From ecf1f8dbbe468519c407ed639f64ef7a784408f4 Mon Sep 17 00:00:00 2001 From: Le Tan Date: Wed, 17 Nov 2021 20:50:26 +0800 Subject: [PATCH] support print --- README_zh_CN.md | 42 +- src/core/coreconfig.cpp | 2 +- src/core/coreconfig.h | 2 +- src/core/editorconfig.h | 1 + src/core/notebook/notebookdatabaseaccess.cpp | 14 + src/core/notebook/notebookdatabaseaccess.h | 2 + src/core/notebook/notebooktagmgr.cpp | 4 +- src/data/core/core.qrc | 2 +- src/data/core/icons/debug_editor.svg | 2 +- src/data/core/icons/find_replace_editor.svg | 11 +- src/data/core/icons/print_editor.svg | 1 + src/data/core/icons/quick_access_menu.svg | 8 +- src/data/core/icons/search.svg | 11 +- src/data/core/icons/search_dock.svg | 11 +- src/data/core/icons/settings.svg | 19 +- src/data/core/icons/settings_menu.svg | 19 +- src/data/core/icons/snippet_dock.svg | 2 +- src/data/core/icons/split_window_list.svg | 5 +- src/data/core/icons/whatsthis.svg | 14 - src/data/core/translations/vnote_ja.ts | 123 ++-- src/data/core/translations/vnote_zh_CN.qm | Bin 90869 -> 89758 bytes src/data/core/translations/vnote_zh_CN.ts | 523 +++++++++--------- src/data/core/vnotex.json | 5 +- src/data/extra/docs/en/shortcuts.md | 14 +- src/data/extra/docs/zh_CN/about_vnotex.txt | 4 +- .../extra/docs/zh_CN/external_programs.md | 14 +- src/data/extra/docs/zh_CN/features_tips.txt | 10 +- src/data/extra/docs/zh_CN/markdown_guide.md | 34 +- src/data/extra/docs/zh_CN/shortcuts.md | 28 +- src/data/extra/docs/zh_CN/welcome.md | 16 +- src/export/exporter.cpp | 2 +- src/utils/printutils.cpp | 22 + src/utils/printutils.h | 21 + src/utils/utils.pri | 2 + src/widgets/dialogs/importnotebookdialog.cpp | 2 +- .../dialogs/settings/settingsdialog.cpp | 5 + src/widgets/markdownviewwindow.cpp | 21 +- src/widgets/markdownviewwindow.h | 2 + src/widgets/textviewwindow.cpp | 13 +- src/widgets/textviewwindow.h | 2 + src/widgets/toolbarhelper.cpp | 453 ++++++++------- src/widgets/toolbarhelper.h | 6 + src/widgets/viewsplit.cpp | 2 +- src/widgets/viewwindow.cpp | 15 +- src/widgets/viewwindow.h | 2 + src/widgets/viewwindowtoolbarhelper.cpp | 7 + src/widgets/viewwindowtoolbarhelper.h | 3 +- .../test_notebook/testnotebookdatabase.cpp | 14 + 48 files changed, 808 insertions(+), 729 deletions(-) create mode 100644 src/data/core/icons/print_editor.svg delete mode 100644 src/data/core/icons/whatsthis.svg create mode 100644 src/utils/printutils.cpp create mode 100644 src/utils/printutils.h diff --git a/README_zh_CN.md b/README_zh_CN.md index ef1d1c57..19aabb10 100644 --- a/README_zh_CN.md +++ b/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) -**支付宝**: `tamlokveer@gmail.com` +**支付宝**:`tamlokveer@gmail.com` @@ -51,7 +51,7 @@ VNote 不是一个简单的 Markdown 编辑器。通过提供强大的笔记管 -感谢这些 [捐赠用户](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项目使用。 diff --git a/src/core/coreconfig.cpp b/src/core/coreconfig.cpp index 1a5b2808..e90ca838 100644 --- a/src/core/coreconfig.cpp +++ b/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")); diff --git a/src/core/coreconfig.h b/src/core/coreconfig.h index 4ec556de..30b976ec 100644 --- a/src/core/coreconfig.h +++ b/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; diff --git a/src/core/editorconfig.h b/src/core/editorconfig.h index 1031c57e..62b39906 100644 --- a/src/core/editorconfig.h +++ b/src/core/editorconfig.h @@ -60,6 +60,7 @@ namespace vnotex ApplySnippet, Tag, Debug, + Print, MaxShortcut }; Q_ENUM(Shortcut) diff --git a/src/core/notebook/notebookdatabaseaccess.cpp b/src/core/notebook/notebookdatabaseaccess.cpp index f291009f..a6bac152 100644 --- a/src/core/notebook/notebookdatabaseaccess.cpp +++ b/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::queryNode(ID p_id) { auto db = getDatabase(); diff --git a/src/core/notebook/notebookdatabaseaccess.h b/src/core/notebook/notebookdatabaseaccess.h index 60eb50aa..c67291c6 100644 --- a/src/core/notebook/notebookdatabaseaccess.h +++ b/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); diff --git a/src/core/notebook/notebooktagmgr.cpp b/src/core/notebook/notebooktagmgr.cpp index 617a0a7c..9aa1d837 100644 --- a/src/core/notebook/notebooktagmgr.cpp +++ b/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; } diff --git a/src/data/core/core.qrc b/src/data/core/core.qrc index 2bfdf372..ce546a87 100644 --- a/src/data/core/core.qrc +++ b/src/data/core/core.qrc @@ -26,7 +26,6 @@ icons/inplace_preview_editor.svg icons/image_host_editor.svg icons/settings_menu.svg - icons/whatsthis.svg icons/help_menu.svg icons/import_menu.svg icons/export_menu.svg @@ -79,6 +78,7 @@ icons/close.svg icons/delete.svg icons/debug_editor.svg + icons/print_editor.svg icons/stay_on_top.svg icons/outline_editor.svg icons/find_replace_editor.svg diff --git a/src/data/core/icons/debug_editor.svg b/src/data/core/icons/debug_editor.svg index 515d0583..8f355f18 100644 --- a/src/data/core/icons/debug_editor.svg +++ b/src/data/core/icons/debug_editor.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/data/core/icons/find_replace_editor.svg b/src/data/core/icons/find_replace_editor.svg index 0927bfb2..ff5769c3 100644 --- a/src/data/core/icons/find_replace_editor.svg +++ b/src/data/core/icons/find_replace_editor.svg @@ -1,10 +1 @@ - - - - - - + \ No newline at end of file diff --git a/src/data/core/icons/print_editor.svg b/src/data/core/icons/print_editor.svg new file mode 100644 index 00000000..199f7e6b --- /dev/null +++ b/src/data/core/icons/print_editor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/data/core/icons/quick_access_menu.svg b/src/data/core/icons/quick_access_menu.svg index 349a2bdc..1e635891 100644 --- a/src/data/core/icons/quick_access_menu.svg +++ b/src/data/core/icons/quick_access_menu.svg @@ -1,7 +1 @@ - - - - - - + \ No newline at end of file diff --git a/src/data/core/icons/search.svg b/src/data/core/icons/search.svg index 0927bfb2..ff5769c3 100644 --- a/src/data/core/icons/search.svg +++ b/src/data/core/icons/search.svg @@ -1,10 +1 @@ - - - - - - + \ No newline at end of file diff --git a/src/data/core/icons/search_dock.svg b/src/data/core/icons/search_dock.svg index 0927bfb2..ff5769c3 100644 --- a/src/data/core/icons/search_dock.svg +++ b/src/data/core/icons/search_dock.svg @@ -1,10 +1 @@ - - - - - - + \ No newline at end of file diff --git a/src/data/core/icons/settings.svg b/src/data/core/icons/settings.svg index 734a2747..64aeeb44 100644 --- a/src/data/core/icons/settings.svg +++ b/src/data/core/icons/settings.svg @@ -1,18 +1 @@ - - - - - - + \ No newline at end of file diff --git a/src/data/core/icons/settings_menu.svg b/src/data/core/icons/settings_menu.svg index 734a2747..64aeeb44 100644 --- a/src/data/core/icons/settings_menu.svg +++ b/src/data/core/icons/settings_menu.svg @@ -1,18 +1 @@ - - - - - - + \ No newline at end of file diff --git a/src/data/core/icons/snippet_dock.svg b/src/data/core/icons/snippet_dock.svg index 339038eb..fc940ec9 100644 --- a/src/data/core/icons/snippet_dock.svg +++ b/src/data/core/icons/snippet_dock.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/data/core/icons/split_window_list.svg b/src/data/core/icons/split_window_list.svg index fb334a0b..2d221a2e 100644 --- a/src/data/core/icons/split_window_list.svg +++ b/src/data/core/icons/split_window_list.svg @@ -1,4 +1 @@ - - - - + \ No newline at end of file diff --git a/src/data/core/icons/whatsthis.svg b/src/data/core/icons/whatsthis.svg deleted file mode 100644 index 8494d36f..00000000 --- a/src/data/core/icons/whatsthis.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - diff --git a/src/data/core/translations/vnote_ja.ts b/src/data/core/translations/vnote_ja.ts index 4ba3ed13..14528427 100644 --- a/src/data/core/translations/vnote_ja.ts +++ b/src/data/core/translations/vnote_ja.ts @@ -109,7 +109,7 @@ - Keep dock widgets when expanding content area: + Dock widgets kept when expanding content area: @@ -690,9 +690,8 @@ ファイルベースのないバッファ(%1)をスキップしました。 - Failed to create output folder %1. - 出力フォルダ%1の作成に失敗しました。 + 出力フォルダ%1の作成に失敗しました。 @@ -701,6 +700,7 @@ + Failed to create output folder (%1). @@ -1503,8 +1503,12 @@ + Not a valid (%1) root folder (%2). + + + Not a valid %1 root folder (%2). - 有効な%1ルートフォルダ(%2)ではありません。 + 有効な%1ルートフォルダ(%2)ではありません。 @@ -1700,7 +1704,7 @@ Remove them from the configuration? - + Quit 終了 @@ -1803,49 +1807,59 @@ Remove them from the configuration? - + + Menu + メニュー + + + + Home Page + + + + Contributors - + Configuration - + Edit User Configuration File - + Edit Markdown User Styles - + Edit the user styles of Markdown editor read mode - + Quick Access Not Set - - + + Settings 設定 - + Expand Content Area コンテンツ領域の拡大 - + Press %1 To Exit Full Screen %1 を押して全画面表示を終了する @@ -1860,88 +1874,81 @@ Remove them from the configuration? - + Stay on Top - + Windows ウインドウ - + Open User Configuration Folder ユーザー設定フォルダを開く - + Open Default Configuration Folder 既定の設定フォルダを開く - + Reset Main Window Layout メインウィンドウのレイアウトをリセット - + Restart 再起動 - + Help ヘルプ - What's This? - これは何ですか? + これは何ですか? - Enter WhatsThis mode and click somewhere to show help information - [これは何]モードに入り、ヘルプ情報を表示する場所をクリックします + [これは何]モードに入り、ヘルプ情報を表示する場所をクリックします - + Shortcuts Help ショートカットヘルプ - + Markdown Guide Markdown ガイド - + View Logs ログの表示 - - %1 Home Page - - - - + Feedback and Discussions - + Check for Updates - - + + About バージョン情報 - + <h3>%1</h3> <span>%2</span> @@ -1950,7 +1957,7 @@ Remove them from the configuration? - + About Qt Qtについて @@ -2520,66 +2527,66 @@ Remove them from the configuration? vnotex::MarkdownViewWindow - + Markdown Viewer Markdownビューア - - + + Clear Obsolete Images 古いイメージをクリア - + These images seems to be not in use anymore. Please confirm the deletion of them. - + Deleted local images could be found in the recycle bin of notebook if it is from a bundle notebook. - + Clearing obsolete images... - + Abort 中止 - + Clear image (%1) - + Cleared %n obsolete images - + View Mode Not Supported In Read Mode - + Edit Only - + Edit with Preview - - + + Replace is not supported in read mode 置換は読み取りモードではサポートされていません @@ -4732,9 +4739,13 @@ Description: %3 ウインドウリスト - Workspaces and Splits - ワークスペースと分割 + ワークスペースと分割 + + + + Menu + メニュー diff --git a/src/data/core/translations/vnote_zh_CN.qm b/src/data/core/translations/vnote_zh_CN.qm index f2f398c853244e1d5e406067b65f9fb1c0fa051d..9a6f8af24c7e29fe632f8c4906daa732b262bf4a 100644 GIT binary patch delta 13177 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

FHA?qMjxLOVIwKMp6seRqzd|E{Z)1;BXyfx zB_nq?y8Tp3+I;RqnK5IjFaAa==n@Q0^xE&A1(&=D4bp{1vlDBp=KV#i9ZKri z1;U@I>OU9SW`kDkFXt+Z(-R{dm@@S_y`5gTip0@bi+ULRgCl4UELzAnR~Fw(Dbumh zFP@T(zQTG+*77>4g-X&-$u6fIup)$*T4a?mfu?E~+M{GQ>hCLwrK?xY)Hf>&WOy00 z!Q!8V|5a-HukzvQTQHn=+*tfD02w&Lc+1!Fh^1$w!w=hkb5!SbHuRNsG&X>N=)&>H z##135%~F8sAH9AlCI7a!)@s8Ij!>H79LbQvrcGVjdyd4KndP2x8Tagu6h0o0lZU%! zGIV}m)AZE*B6c(cV-?4)fKIB6wsdPY>&H!hsT^UzaOwYuC~ef{RRoh#sJ10Kq1I?? zB{8-A%#?pz2TCnnngEi<1OvjQO)^&vk_T4Q@eI& z94^wK@L-B8Y(;|c1pfEBV^&R3|C_dHs%ki<^l?@8=!QQiM7ym@#GzVb@e2w*yV>Dt zHRm7o++mLkud_c}hra}q?x3G}G{8} z%A5ez9P)GgH@ZK}CPnj|da>SBT;~u;i%vW06u>Z@oWS&|=BL&6IIC`^pH$)4LiA_txd7gmW`O>9v4?9% zMpysNOS#^KYj0>4f0rB z{nQHY*UC*>Gwo0~Kf)=};rk|ne)OWyNyi4GWMSUle`B~FGw-ujb$&?~zszFkHPe?T z7>{{hp0r?0enWH3fAeD6tTCCr>IlR3@kg21hLYh?+AWO-i440>hN-ZxwWD9#@vYq= z9T=v_c)hA!%v)BdZ#!tK-|G=fo-t9zWe;EodgFx;J(y=^CFWUc_L1hZ9>x-D))Brb z{>x=cHG1|1DO;8`#w8b3_j8!ixPi8;xU3+~#IanD7*Wl$4HFKodSsq{OQupKS&Y}U z!OZPO#U(w`mf>+z>lkPkZUxrc*=^GW9U&J^qd&K~8C|VvC1mC3uxb*T{v8P=wx8@6xhWai){T9| zB)D*6=7WyEp%Bci2E^f27;ePWxQf}PB)P47^WiBX)yIDwZe&J=*}KHH4hxC-P>y#c zy0Z*NZpbJo4&1P5{<5--IWef%Zbm}wT{2dri2r5AcjM7%zAZgip=Pr@v#i_KWmlS$ z+zKaaylMJwz?WU!EXc?oY8f~ke0-}sPu=Q-dsP=D1ej(TmVYOgp{^wO#g_|o` zVCfAp5U%Skk};N@bljV{PR?O6QT07n;wPpIAqKmp1-dt`KBNW--s&G?m?R-Eoi9vE5R^>4P02Ie4UKs$U^Rvhysoy~1O6Y75&VA75F z3+32Cq~U?$x{)SM^~|2ckw?jg)b|@)P@u~u2YZpsc3)pa%uF~QCivPD7)561q~{Kg zPgLjXx}fmk8EJVHdV!?DK1gYi?5eb6=$ooGN{Cj~W$n0xDA^~e(juZY^R2=)`sYTu#Un72%d)cGn?wD2CSx*?cYa9GuRsm?gpB!u+FDuK&R--KphQf+z& z2{W)@UPU^LKAiuns-4O<3a=R}YD36*o1WnpbGI=cKQFE;V);d14u>1HhSz?9W)5hRRQT9v$Ey0d0;bq8av$V;x$bKaU(?;JoT5+l1WeNXe_SM-V`*VtN; zP#EU+If=I&L_D|#4!TAQ@2JBcmAq%=uFi}hGdPy5nHv1%-naR3Uusl^O)MGz{{Xqc BqXGZ` diff --git a/src/data/core/translations/vnote_zh_CN.ts b/src/data/core/translations/vnote_zh_CN.ts index f2e7a835..738748db 100644 --- a/src/data/core/translations/vnote_zh_CN.ts +++ b/src/data/core/translations/vnote_zh_CN.ts @@ -49,12 +49,12 @@ VNoteX Notebook Configuration - VNoteX 笔记本配置 + VNoteX笔记本配置 Built-in VNoteX notebook configuration - 内建的 VNoteX 笔记本配置 + 内建的VNoteX笔记本配置 @@ -109,8 +109,12 @@ + Dock widgets kept when expanding content area: + 扩展内容区时保留的停靠部件: + + Keep dock widgets when expanding content area: - 扩展内容区时保留停靠部件: + 扩展内容区时保留停靠部件: @@ -164,7 +168,7 @@ Failed to rename attachment (%1) to (%2). - 无法将附件 (%1) 重命名为 (%2)。 + 无法将附件(%1)重命名为(%2)。 @@ -205,7 +209,7 @@ %1/%2 Items - %1/%2 项 + %1/%2项 @@ -291,12 +295,12 @@ LF (Linux/macOS) - LF (Linux/macOS) + LF(Linux/macOS) CR LF (Windows) - CR LF (Windows) + CR LF(Windows) @@ -331,12 +335,12 @@ VNote uses [Hunspell](http://hunspell.github.io/) for spell check. - VNote 使用 [Hunspell](http://hunspell.github.io/) 进行拼写检查。 + VNote使用[Hunspell](http://hunspell.github.io/)进行拼写检查。 Please download Hunspell's dictionaries, put them under (%1) and restart VNote. - 请下载 Hunspell 的词典,放置于 (%1) 并重启 VNote。 + 请下载Hunspell的词典,放置于(%1)并重启VNote。 @@ -365,22 +369,22 @@ Current Buffer (%1) - 当前缓冲区 (%1) + 当前缓冲区(%1) Current Note (%1) - 当前笔记 (%1) + 当前笔记(%1) Current Folder (%1) - 当前文件夹 (%1) + 当前文件夹(%1) Current Notebook (%1) - 当前笔记本 (%1) + 当前笔记本(%1) @@ -450,7 +454,7 @@ Use wkhtmltopdf (outline supported) - 使用 wkhtmltopdf (支持大纲) + 使用wkhtmltopdf(支持大纲) @@ -496,7 +500,7 @@ Delete scheme (%1)? - 删除方案 (%1)? + 删除方案(%1)? @@ -553,7 +557,7 @@ Please specify a valid wkhtmltopdf executable file (%1) - 请指定一个有效的 wkhtmltopdf 可执行文件 (%1) + 请指定一个有效的wkhtmltopdf可执行文件(%1) @@ -578,7 +582,7 @@ Mime HTML format - Mime HTML 格式 + Mime HTML格式 @@ -609,17 +613,17 @@ Select wkhtmltopdf Executable - 选择 wkhtmltopdf 可执行文件 + 选择wkhtmltopdf可执行文件 Wkhtmltopdf path: - Wkhtmltopdf 路径: + Wkhtmltopdf路径: Wkhtmltopdf arguments: - Wkhtmltopdf 参数: + Wkhtmltopdf参数: @@ -639,7 +643,7 @@ Suffix of the target file like docs/pdf/epub - 目标文件的后缀,如 docs/pdf/epub + 目标文件的后缀,如docs/pdf/epub @@ -659,12 +663,12 @@ Use HTML format as input - 使用 HTML 格式作为输入 + 使用HTML格式作为输入 Convert to HTMl format first as the input of the custom export command - 首先转换为 HTML 格式然后作为自定义输出命令的输入 + 首先转换为HTML格式然后作为自定义输出命令的输入 @@ -692,22 +696,18 @@ Skipped buffer (%1) without file base. - 跳过非基于文件的缓冲区 (%1)。 + 跳过非基于文件的缓冲区(%1)。 + - Failed to create output folder %1. - 无法创建输出文件夹 %1。 + Failed to create output folder (%1). + 无法创建输出文件夹(%1)。 Format %1 is not supported to export as Markdown. - 格式 %1 不支持导出为 Markdown。 - - - - Failed to create output folder (%1). - 无法创建输出文件夹 (%1)。 + 格式%1不支持导出为Markdown。 @@ -716,7 +716,7 @@ Failed to create output folder under (%1). - 无法在 (%1) 中创建输出文件夹。 + 无法在(%1)中创建输出文件夹。 @@ -728,27 +728,27 @@ Exported to (%1). - 输出到 (%1)。 + 输出到(%1)。 Failed to load node (%1) (%2). - 无法加载节点 (%1) (%2)。 + 无法加载节点(%1)(%2)。 Unknown target format %1. - 未知的目标格式 %1。 + 未知的目标格式%1。 File (%1) exported to (%2) - 文件 (%1) 已导出为 (%2) + 文件(%1)已导出为(%2) Failed to export file (%1) - 无法导出文件 (%1) + 无法导出文件(%1) @@ -767,22 +767,22 @@ Failed to create temporary directory to hold HTML files. - 无法创建临时目录存放 HTML 文件。 + 无法创建临时目录存放HTML文件。 Format %1 is not supported to export as HTML. - 格式 %1 不支持导出为 HTML。 + 格式%1不支持导出为HTML。 Asked to stop. Aborting. - 用户取消。 正在终止。 + 用户取消。正在终止。 Format %1 is not supported to export as PDF. - 格式 %1 不支持导出为 PDF。 + 格式%1不支持导出为PDF。 @@ -805,7 +805,7 @@ %1 Bytes - %1 字节 + %1字节 @@ -818,7 +818,7 @@ Skip binary file (%1) - 跳过二进制文件 (%1) + 跳过二进制文件(%1) @@ -889,7 +889,7 @@ \1, \2 for back reference in regular expression - 在正则表达式中使用 \1, \2 来后向引用 + 在正则表达式中使用\1和\2来后向引用 @@ -980,7 +980,7 @@ Failed to save folder (%1) in (%2) (%3). - 无法保存笔记本 (%2) 中的文件夹 (%1) (%3)。 + 无法保存笔记本(%2)中的文件夹(%1)(%3)。 @@ -1061,7 +1061,7 @@ Recover last session (like buffers) on start of VNote - 启动 VNote 时恢复上次会话(如缓冲区) + 启动VNote时恢复上次会话(如缓冲区) @@ -1071,7 +1071,7 @@ Check for updates on start of VNote - VNote 启动时检查更新 + VNote启动时检查更新 @@ -1095,33 +1095,33 @@ Invalid GitHub image host configuration. - 无效的 GitHub 图床配置。 + 无效的GitHub图床配置。 The resource already exists at the image host (%1). - 该资源已经存在于图床 (%1)。 + 该资源已经存在于图床(%1)。 Failed to query the resource at the image host (%1) (%2) (%3). - 无法在图床查询资源 (%1) (%2) (%3)。 + 无法在图床查询资源(%1)(%2)(%3)。 Failed to create resource at the image host (%1) (%2) (%3). - 无法在图床创建资源 (%1) (%2) (%3)。 + 无法在图床创建资源(%1)(%2)(%3)。 Failed to fetch SHA about the resource (%1) (%2). - 无法获取该资源的 SHA 值 (%1) (%2)。 + 无法获取该资源的SHA值(%1)(%2)。 Failed to delete resource (%1) (%2). - 无法删除资源 (%1) (%2)。 + 无法删除资源(%1)(%2)。 @@ -1145,33 +1145,33 @@ The resource already exists at the image host (%1). - 该资源已经存在于图床 (%1)。 + 该资源已经存在于图床(%1)。 Failed to query the resource at the image host (%1) (%2) (%3). - 无法在图床查询资源 (%1) (%2) (%3)。 + 无法在图床查询资源(%1)(%2)(%3)。 Failed to create resource at the image host (%1) (%2) (%3). - 无法在图床创建资源 (%1) (%2) (%3)。 + 无法在图床创建资源(%1)(%2)(%3)。 Failed to fetch information about the resource (%1). - 无法获取该资源的信息 (%1)。 + 无法获取该资源的信息(%1)。 Failed to fetch SHA about the resource (%1) (%2). - 无法获取该资源的 SHA 值 (%1) (%2)。 + 无法获取该资源的SHA值(%1)(%2)。 Failed to delete resource (%1) (%2). - 无法删除资源 (%1) (%2)。 + 无法删除资源(%1)(%2)。 @@ -1214,7 +1214,7 @@ Last 7 Days - 过去 7 天 + 过去7天 @@ -1279,7 +1279,7 @@ Failed to rename image host (%1) to (%2). - 无法重命名图床 (%1) 为 (%2)。 + 无法重命名图床(%1)为(%2)。 @@ -1314,12 +1314,12 @@ Delete image host (%1)? - 删除图床 (%1)? + 删除图床(%1)? Test %1. - 测试 %1。 + 测试%1。 @@ -1372,7 +1372,7 @@ Images (*.png *.xpm *.jpg *.bmp *.gif *.svg *.webp);;All (*.*) - 图片 (*.png *.xpm *.jpg *.bmp *.gif *.svg *.webp);;全部文件 (*.*) + 图片(*.png *.xpm *.jpg *.bmp *.gif *.svg *.webp);;全部文件(*.*) @@ -1380,7 +1380,7 @@ Import folder into (%1). - 导入文件夹至 (%1)。 + 导入文件夹至(%1)。 @@ -1395,12 +1395,12 @@ Failed to add folder (%1) as node under (%2). - 无法在 (%2) 下将文件夹 (%1) 添加为节点。 + 无法在(%2)下将文件夹(%1)添加为节点。 Failed to add folder (%1) as node (%2). - 无法添加文件夹 (%1) 为节点 (%2)。 + 无法添加文件夹(%1)为节点(%2)。 @@ -1409,38 +1409,38 @@ Failed to add folder (%1) as node (%2). - 无法添加文件夹 (%1) 为节点 (%2)。 + 无法添加文件夹(%1)为节点(%2)。 Failed to add file (%1) as node (%2). - 无法添加文件 (%1) 为节点 (%2)。 + 无法添加文件(%1)为节点(%2)。 Failed to read folder config (%1) (%2). - 无法读取文件夹配置 (%1) (%2)。 + 无法读取文件夹配置(%1)(%2)。 Folder (%1) does not exist. - 文件夹 (%1) 不存在。 + 文件夹(%1)不存在。 Folder (%1) conflicts with built-in folder. - 文件夹 (%1) 和内建文件夹冲突。 + 文件夹(%1)和内建文件夹冲突。 File (%1) does not exist. - 文件 (%1) 不存在。 + 文件(%1)不存在。 File (%1) conflicts with built-in file. - 文件 (%1) 和内建文件冲突。 + 文件(%1)和内建文件冲突。 @@ -1458,7 +1458,7 @@ Once opened, the legacy notebook could no longer be recognized by legacy VNote! - 一旦打开,该遗留笔记本将无法被旧版本的 VNote 所识别! + 一旦打开,该遗留笔记本将无法被旧版本的VNote所识别! @@ -1473,22 +1473,22 @@ There already exists a notebook (%1) with the same root folder. - 已经存在一个使用相同根文件夹的笔记本 (%1)。 + 已经存在一个使用相同根文件夹的笔记本(%1)。 Failed to read legacy notebook configuration in (%1) (%2). - 在 (%1) 中无法读取遗留笔记本配置 (%2)。 + 在(%1)中无法读取遗留笔记本配置(%2)。 Failed to create notebook in (%1) (%2). - 无法在 (%1) 创建笔记本 (%2)。 + 无法在(%1)创建笔记本(%2)。 Failed to import folder contents by legacy config in (%1) (%2). - 无法在 (%1) 中根据遗留配置导入文件夹内容 (%2)。 + 无法在(%1)中根据遗留配置导入文件夹内容(%2)。 @@ -1506,17 +1506,17 @@ There already exists a notebook (%1) with the same root folder. - 已经存在一个使用相同根文件夹的笔记本 (%1)。 + 已经存在一个使用相同根文件夹的笔记本(%1)。 - Not a valid %1 root folder (%2). - 无效的%1根文件夹 (%2)。 + Not a valid (%1) root folder (%2). + 无效的(%1)根文件夹(%2)。 Failed to create notebook from root folder (%1) (%2). - 无法从根文件夹 (%1) 创建笔记本 (%2)。 + 无法从根文件夹(%1)创建笔记本(%2)。 @@ -1526,7 +1526,7 @@ Failed to open notebook (%1). - 无法打开笔记本 (%1)。 + 无法打开笔记本(%1)。 @@ -1555,7 +1555,7 @@ Snippet is supported via "%name%" - 支持通过 "%名字%" 使用片段 + 支持通过"%名字%"使用片段 @@ -1614,7 +1614,7 @@ Failed to check for updates (%1) - 无法检查更新 (%1) + 无法检查更新(%1) @@ -1629,7 +1629,7 @@ Do you want to minimize %1 to system tray instead of quitting when closed? - 关闭时,是否将 %1 最小化到系统托盘而非退出? + 关闭时,是否将%1最小化到系统托盘而非退出? @@ -1639,7 +1639,7 @@ %1 is still running here. - %1 仍然在此运行。 + %1仍然在此运行。 @@ -1673,7 +1673,7 @@ Remove them from the configuration? - + Quit 退出 @@ -1732,12 +1732,12 @@ Remove them from the configuration? Open Legacy Notebooks Of VNote 2 - 打开 VNote 2 的遗留笔记本 + 打开VNote 2的遗留笔记本 Export (Convert Format) - 导出 (转换格式) + 导出(转换格式) @@ -1776,51 +1776,56 @@ Remove them from the configuration? 可以在设置对话框中管理快速访问。 - + + Menu + 菜单 + + + Contributors 贡献者 - + Configuration 配置 - + Edit User Configuration File 编辑用户配置文件 - + Edit Markdown User Styles - 编辑 Markdown 用户样式 + 编辑Markdown用户样式 - + Edit the user styles of Markdown editor read mode - 编辑 Markdown 编辑器阅读模式的用户样式 + 编辑Markdown编辑器阅读模式的用户样式 - + Quick Access Not Set 快速访问未设置 - - + + Settings 设置 - + Expand Content Area 扩展内容区 - + Press %1 To Exit Full Screen - 按 %1 退出全屏 + 按%1退出全屏 @@ -1833,88 +1838,86 @@ Remove them from the configuration? 导入 - + Stay on Top 置顶 - + Windows 窗口 - + Open User Configuration Folder 打开用户配置文件夹 - + Open Default Configuration Folder 打开默认配置文件夹 - + Reset Main Window Layout 重置主窗口布局 - + Restart 重启 - + Help 帮助 - What's This? - 这是什么? + 这是什么? - Enter WhatsThis mode and click somewhere to show help information - 进入 WhatsThis 模式,点击某处以显示帮助信息 + 进入WhatsThis模式,点击某处以显示帮助信息 - + Shortcuts Help 快捷键帮助 - + Markdown Guide - Markdown 指南 + Markdown指南 - + View Logs 查看日志 - - %1 Home Page - %1 主页 + + Home Page + 主页 - + Feedback and Discussions 反馈和讨论 - + Check for Updates 检查更新 - - + + About 关于 - + <h3>%1</h3> <span>%2</span> @@ -1923,14 +1926,14 @@ Remove them from the configuration? - + About Qt - 关于 Qt + 关于Qt %1 failed to start. - %1 无法启动。 + %1无法启动。 @@ -1955,12 +1958,12 @@ Remove them from the configuration? WebEngine remote debugging port. - WebEngine 远程调试端口。 + WebEngine远程调试端口。 WebEngine without sandbox. - 在非沙盒下运行 WebEngine。 + 在非沙盒下运行WebEngine。 @@ -1988,12 +1991,12 @@ Remove them from the configuration? Close notebook (%1)? - 关闭笔记本 (%1)? + 关闭笔记本(%1)? The notebook could be opened by VNote again. - 该笔记本可以使用 VNote 重新打开。 + 该笔记本可以使用VNote重新打开。 @@ -2009,12 +2012,12 @@ Remove them from the configuration? Failed to close notebook (%1) - 无法关闭笔记本 (%1) + 无法关闭笔记本(%1) Please close the notebook in VNote first and delete the notebook root folder files manually. - 请先在 VNote 中关闭该笔记本,然后手动删除该笔记本的根文件夹等文件。 + 请先在VNote中关闭该笔记本,然后手动删除该笔记本的根文件夹等文件。 @@ -2043,7 +2046,7 @@ Remove them from the configuration? For advanced paste, try the "Rich Paste" and "Parse to Markdown and Paste" on the editor's context menu - 更多高级粘贴,请尝试编辑器上下文菜单中的“多功能粘贴”和“解析为 Markdown 并粘贴”功能 + 更多高级粘贴,请尝试编辑器上下文菜单中的“多功能粘贴”和“解析为Markdown并粘贴”功能 @@ -2129,7 +2132,7 @@ Remove them from the configuration? Parse to Markdown and Paste - 解析为 Markodwn 并粘贴 + 解析为Markodwn并粘贴 @@ -2185,7 +2188,7 @@ Remove them from the configuration? Fetching image (%1) - 正在获取图片 (%1) + 正在获取图片(%1) @@ -2206,7 +2209,7 @@ Remove them from the configuration? Upload image (%1) - 上传图片 (%1) + 上传图片(%1) @@ -2260,12 +2263,12 @@ Remove them from the configuration? HTML tag - HTML 标签 + HTML标签 Allow HTML tags in source - 源文件中允许 HTML 标签 + 源文件中允许HTML标签 @@ -2275,7 +2278,7 @@ Remove them from the configuration? Automatically break a line with '\n' - 遇到 '\n' 则自动换行 + 遇到'\n'则自动换行 @@ -2285,7 +2288,7 @@ Remove them from the configuration? Convert URL-like text to links - 转换类 URL 的文本为链接 + 转换类URL的文本为链接 @@ -2341,7 +2344,7 @@ Remove them from the configuration? Fetch images to local in Parse To Markdown And Paste - 在解析为 Markdown 并粘贴时,获取图片到本地 + 在解析为Markdown并粘贴时,获取图片到本地 @@ -2412,7 +2415,7 @@ Remove them from the configuration? Use online service or local JAR file to render PlantUml graphs - 使用在线服务或者本地 JAR 文件来渲染 PlantUml 图表 + 使用在线服务或者本地JAR文件来渲染PlantUml图表 @@ -2423,7 +2426,7 @@ Remove them from the configuration? Local JAR - 本地 JAR + 本地JAR @@ -2433,12 +2436,12 @@ Remove them from the configuration? Local JAR file to render PlantUml graphs - 用于渲染 PlantUml 图表的本地 JAR 文件 + 用于渲染PlantUml图表的本地JAR文件 Select PlantUml JAR File - 选择 PlantUml JAR 文件 + 选择PlantUml JAR文件 @@ -2449,18 +2452,18 @@ Remove them from the configuration? Test PlantUml JAR and Java Runtime Environment - 测试 PlantUml JAR 以及 Java 运行时环境 + 测试PlantUml JAR以及Java运行时环境 The JAR file (%1) specified does not exist. - 指定的 JAR 文件 (%1) 不存在。 + 指定的JAR文件(%1)不存在。 Test %1. - 测试 %1。 + 测试%1。 @@ -2477,12 +2480,12 @@ Remove them from the configuration? PlantUml JAR file: - PlantUml JAR 文件: + PlantUml JAR文件: Use online service or local executable file to render Graphviz graphs - 使用在线服务或者本地可执行文件来渲染 Graphviz 图表 + 使用在线服务或者本地可执行文件来渲染Graphviz图表 @@ -2497,97 +2500,97 @@ Remove them from the configuration? Local executable file to render Graphviz graphs - 用于渲染 Graphviz 图表的本地可执行文件 + 用于渲染Graphviz图表的本地可执行文件 Select Graphviz Executable File - 选择 Graphviz 可执行文件 + 选择Graphviz可执行文件 Test Graphviz executable file - 测试 Graphviz 可执行文件 + 测试Graphviz可执行文件 The executable file (%1) specified does not exist. - 指定的可执行文件 (%1) 不存在。 + 指定的可执行文件(%1)不存在。 Graphviz executable file: - Graphviz 可执行文件: + Graphviz可执行文件: Markdown Editor - Markdown 编辑器 + Markdown编辑器 vnotex::MarkdownViewWindow - + Markdown Viewer - Markdown 查看器 + Markdown查看器 - - + + Clear Obsolete Images 清空无用图片 - + These images seems to be not in use anymore. Please confirm the deletion of them. 这些图片似乎已经不再使用。请确认并删除。 - + Deleted local images could be found in the recycle bin of notebook if it is from a bundle notebook. 如果这是一个自包含笔记本,已删除的本地图片可以在笔记本回收站中找回。 - + Clearing obsolete images... 正在清空无用图片... - + Abort 终止 - + Clear image (%1) - 清空图片 (%1) + 清空图片(%1) - + Cleared %n obsolete images 清空 %n 无用图片 - + View Mode Not Supported In Read Mode 阅读模式不支持查看模式 - + Edit Only 纯编辑 - + Edit with Preview 预览辅助的编辑 - - + + Replace is not supported in read mode 阅读模式不支持替换 @@ -2666,7 +2669,7 @@ Remove them from the configuration? Failed to create folder under (%1) in (%2) (%3). - 无法在笔记本 (%2) 中文件夹 (%1) 下创建文件夹 (%3)。 + 无法在笔记本(%2)中文件夹(%1)下创建文件夹(%3)。 @@ -2699,7 +2702,7 @@ Remove them from the configuration? Failed to create image host (%1). - 无法创建图床 (%1)。 + 无法创建图床(%1)。 @@ -2732,7 +2735,7 @@ Remove them from the configuration? Failed to create note under (%1) in (%2) (%3). - 无法在笔记本 (%2) 中文件夹 (%1) 下创建笔记 (%3)。 + 无法在笔记本(%2)中文件夹(%1)下创建笔记(%3)。 @@ -2747,7 +2750,7 @@ Remove them from the configuration? Failed to load template (%1) (%2). - 无法加载模板 (%1) (%2)。 + 无法加载模板(%1)(%2)。 @@ -2760,7 +2763,7 @@ Remove them from the configuration? <br/>Both absolute and relative paths are supported. ~ and environment variable are not supported now. - <br/>支持绝对路径和相对路径。~ 和环境变量暂时不支持。 + <br/>支持绝对路径和相对路径。~和环境变量暂时不支持。 @@ -2785,12 +2788,12 @@ Remove them from the configuration? There already exists a notebook (%1) with the same root folder. - 已经存在一个使用相同根文件夹的笔记本 (%1)。 + 已经存在一个使用相同根文件夹的笔记本(%1)。 Failed to create notebook in (%1) (%2). - 无法在 (%1) 创建笔记本 (%2)。 + 无法在(%1)创建笔记本(%2)。 @@ -2818,12 +2821,12 @@ Remove them from the configuration? There already exists a notebook (%1) with the same root folder. - 已经存在一个使用相同根文件夹的笔记本 (%1)。 + 已经存在一个使用相同根文件夹的笔记本(%1)。 Failed to create notebook in %1 (%2). - 无法在 (%1) 创建笔记本 (%2)。 + 无法在(%1)创建笔记本(%2)。 @@ -2836,7 +2839,7 @@ Remove them from the configuration? Failed to add snippet (%1) (%2). - 无法添加片段 (%1) (%2)。 + 无法添加片段(%1)(%2)。 @@ -2879,7 +2882,7 @@ Remove them from the configuration? Failed to create tag (%1). - 无法创建标签 (%1)。 + 无法创建标签(%1)。 @@ -2938,7 +2941,7 @@ Remove them from the configuration? %1 Properties - %1 属性 + %1属性 @@ -2953,7 +2956,7 @@ Remove them from the configuration? Failed to save note (%1) in (%2) (%3). - 无法保存笔记本 (%2) 中的笔记 (%1) (%3)。 + 无法保存笔记本(%2)中的笔记(%1)(%3)。 @@ -3001,17 +3004,17 @@ Remove them from the configuration? Scan the whole notebook (%1) and import external files automatically? - 扫描整个笔记本 (%1) 并自动导入外部文件? + 扫描整个笔记本(%1)并自动导入外部文件? This operation helps importing external files that are added outside from VNote. It may import unexpected files. - 该操作帮助导入在 VNote 外添加的外部文件。可能会导入不想要的文件。 + 该操作帮助导入在VNote外添加的外部文件。可能会导入不想要的文件。 It is recommended to always manage files within VNote. - 推荐总是在 VNote 中管理文件。 + 推荐总是在VNote中管理文件。 @@ -3110,7 +3113,7 @@ Remove them from the configuration? Empty the recycle bin of notebook (%1)? - 清空笔记本 (%1) 的回收站? + 清空笔记本(%1)的回收站? @@ -3125,7 +3128,7 @@ Remove them from the configuration? Rebuild the database of notebook (%1)? - 重建笔记本 (%1) 的数据库? + 重建笔记本(%1)的数据库? @@ -3221,7 +3224,7 @@ Remove them from the configuration? <b>Notebook Root Folder</b> is the folder containing all data of one notebook in %1. - <b>笔记本根文件夹</b>是在 %1 中包含一个笔记本的全部数据。 + <b>笔记本根文件夹</b>是在%1中包含一个笔记本的全部数据。 @@ -3289,17 +3292,17 @@ Remove them from the configuration? Failed to load nodes of notebook (%1) (%2). - 无法加载笔记本 (%1) 节点 (%2)。 + 无法加载笔记本(%1)节点(%2)。 [Invalid] %1 - [无效] %1 + [无效]%1 [External] %1 - [外部] %1 + [外部]%1 @@ -3369,7 +3372,7 @@ Remove them from the configuration? Failed to copy source (%1) to destination (%2) (%3). - 无法复制源 (%1) 至 目标 (%2) (%3)。 + 无法复制源(%1)至目标(%2)(%3)。 @@ -3384,7 +3387,7 @@ Remove them from the configuration? Sort nodes under %1 (%2) in the configuration file. - 在配置文件中对%1 (%2) 下的节点进行排序。 + 在配置文件中对%1(%2)下的节点进行排序。 @@ -3414,7 +3417,7 @@ Remove them from the configuration? Invalid node (%1). - 无效的节点 (%1)。 + 无效的节点(%1)。 @@ -3471,7 +3474,7 @@ Remove them from the configuration? Destination is detected in sources (%1). Operation is cancelled. - 目标包含在源 (%1) 中。操作取消。 + 目标包含在源(%1)中。操作取消。 @@ -3498,7 +3501,7 @@ Remove them from the configuration? Failed to delete/remove item (%1) (%2) (%3). - 无法删除或移除项目 (%1) (%2) (%3)。 + 无法删除或移除项目(%1)(%2)(%3)。 @@ -3677,7 +3680,7 @@ Description: %3 Failed to rename tag (%1) to (%2). - 无法重命名标签 (%1) 为 (%2)。 + 无法重命名标签(%1)为(%2)。 @@ -3918,22 +3921,22 @@ Description: %3 Searching folder (%1) - 正在搜索文件夹 (%1) + 正在搜索文件夹(%1) Searching notebook (%1) - 正在搜索笔记本 (%1) + 正在搜索笔记本(%1) Failed to compile tokens (%1) - 无法编译令牌 (%1) + 无法编译令牌(%1) Failed to load node to search (%1) (%2). - 无法加载节点进行搜索 (%1) (%2)。 + 无法加载节点进行搜索(%1)(%2)。 @@ -4014,7 +4017,7 @@ Description: %3 Nested snippet is supported, like `%time%` to embed the snippet `time` - 支持嵌套的片段,如 `%time%` 会内嵌片段 `time` + 支持嵌套的片段,如`%time%`会内嵌片段`time` @@ -4042,47 +4045,47 @@ Description: %3 the day as number without a leading zero (`1` to `31`) - 没有前导零的日期数字 (`1` 到 `31`) + 没有前导零的日期数字(`1`到`31`) the day as number with a leading zero (`01` to `31`) - 带前导零的日期数字 (`01` 到 `31`) + 带前导零的日期数字(`01`到`31`) the abbreviated localized day name (e.g. `Mon` to `Sun`) - 缩写的本地化日期名字 (如 `一` 到 `日`) + 缩写的本地化日期名字(如`一`到`日`) the long localized day name (e.g. `Monday` to `Sunday`) - 本地化日期名字 (如 `星期一` 到 `星期日`) + 本地化日期名字(如`星期一`到`星期日`) the month as number without a leading zero (`1` to `12`) - 没有前导零的月份数字 (如 `1` 到 `12`) + 没有前导零的月份数字(如`1`到`12`) the month as number with a leading zero (`01` to `12`) - 带前导零的月份数字 (`01` 到 `12`) + 带前导零的月份数字(`01`到`12`) the abbreviated localized month name (e.g. `Jan` to `Dec`) - 缩写的本地化月份名字 (如 `一` 到 `十二`) + 缩写的本地化月份名字(如`一`到`十二`) the long localized month name (e.g. `January` to `December`) - 本地化月份名字 (如 `一月` 到 `十二月`) + 本地化月份名字(如`一月`到`十二月`) the year as two digit numbers (`00` to `99`) - 两位数的年份数字 (`00` 到 `99`) + 两位数的年份数字(`00`到`99`) @@ -4092,62 +4095,62 @@ Description: %3 the week number without a leading zero (`1` to `53`) - 没有前导零的星期数字 (`1` 到 `53`) + 没有前导零的星期数字(`1`到`53`) the week number with a leading zero (`01` to `53`) - 带前导零的星期数字 (`1` 到 `53`) + 带前导零的星期数字(`1`到`53`) the hour without a leading zero (`0` to `23` even with AM/PM display) - 没有前导零的小时 (`0` 到 `23`) + 没有前导零的小时(`0`到`23`) the hour with a leading zero (`00` to `23` even with AM/PM display) - 带前导零的小时 (`00` 到 `23`) + 带前导零的小时(`00`到`23`) the minute without a leading zero (`0` to `59`) - 没有前导零的分 (`0` 到 `59`) + 没有前导零的分(`0`到`59`) the minute with a leading zero (`00` to `59`) - 带前导零的分 (`00` 到 `59`) + 带前导零的分(`00`到`59`) the second without a leading zero (`0` to `59`) - 没有前导零的秒 (`0` 到 `59`) + 没有前导零的秒(`0`到`59`) the second with a leading zero (`00` to `59`) - 带前导零的秒 (`00` 到 `59`) + 带前导零的秒(`00`到`59`) date (`2021-02-24`) - 日期 (`2021-02-24`) + 日期(`2021-02-24`) the abbreviated date (`20210224`) - 缩写的日期 (`20210224`) + 缩写的日期(`20210224`) time (`16:51:02`) - 时间 (`16:51:02`) + 时间(`16:51:02`) date and time (`2021-02-24_16:51:02`) - 日期时间 (`2021-02-24_16:51:02`) + 日期时间(`2021-02-24_16:51:02`) @@ -4228,7 +4231,7 @@ Description: %3 Failed to remove snippet (%1) (%2). - 无法删除片段 (%1) (%2)。 + 无法删除片段(%1)(%2)。 @@ -4236,7 +4239,7 @@ Description: %3 %1 Properties - %1 属性 + %1属性 @@ -4251,7 +4254,7 @@ Description: %3 Failed to update snippet (%1) (%2). - 无法更新片段 (%1) (%2)。 + 无法更新片段(%1)(%2)。 @@ -4385,7 +4388,7 @@ Description: %3 Failed to move tag (%1). - 无法移动标签 (%1)。 + 无法移动标签(%1)。 @@ -4398,7 +4401,7 @@ Description: %3 [Shift+Enter] to add current selected tag in the list - [Shift+Enter] 以添加列表中当前选择的标签 + [Shift+Enter]以添加列表中当前选择的标签 @@ -4408,7 +4411,7 @@ Description: %3 Failed to update tags of node (%1). - 无法更新节点 (%1) 的标签。 + 无法更新节点(%1)的标签。 @@ -4589,7 +4592,7 @@ Description: %3 [Theme] %1 %2 - [主题] %1 %2 + [主题]%1 %2 @@ -4697,7 +4700,7 @@ Description: %3 Failed to fetch information (%1). - 无法获取信息 (%1)。 + 无法获取信息(%1)。 @@ -4705,7 +4708,7 @@ Description: %3 Failed to load HTML template. Check the logs for details. Try deleting the user configuration file and the default configuration file. - 无法加载 HTML 模板。详情请查看日志。可以尝试删除用户配置文件以及默认配置文件。 + 无法加载HTML模板。详情请查看日志。可以尝试删除用户配置文件以及默认配置文件。 @@ -4713,17 +4716,17 @@ Description: %3 Control-C to copy - Control-C 进行复制 + Control-C进行复制 Use Control-C to copy text - 使用 Control-C 复制文本 + 使用Control-C复制文本 Vi Input Mode - Vi 输入模式 + Vi输入模式 @@ -4742,9 +4745,13 @@ Description: %3 窗口列表 - Workspaces and Splits - 工作空间和拆分 + 工作空间和拆分 + + + + Menu + 菜单 @@ -4759,7 +4766,7 @@ Description: %3 Workspace %1 - 工作空间 %1 + 工作空间%1 @@ -4913,28 +4920,28 @@ Description: %3 Save changes before closing note (%1)? - 关闭笔记 (%1) 前是否保存更改? + 关闭笔记(%1)前是否保存更改? Note path (%1). - 笔记路径 (%1)。 + 笔记路径(%1)。 Discard changes to note (%1)? - 放弃对笔记 (%1) 的更改? + 放弃对笔记(%1)的更改? Found backup file (%1) of file (%2). Do you want to recover from backup file? - 发现文件 (%2) 的备份文件 (%1)。是否要从备份文件中恢复? + 发现文件(%2)的备份文件(%1)。是否要从备份文件中恢复? 'Yes' to recover from backup file, 'No' to discard it, and 'Cancel' to exit. - “是” 以从备份文件中恢复,“否” 以放弃该备份文件,“取消” 以退出。 + “是”以从备份文件中恢复,“否”以放弃该备份文件,“取消”以退出。 @@ -4955,7 +4962,7 @@ Backup file last modified time: %2 File is missing on disk (%1). - 文件在磁盘中丢失 (%1)。 + 文件在磁盘中丢失(%1)。 @@ -4970,7 +4977,7 @@ Backup file last modified time: %2 File is changed from outside (%1). - 文件被更改 (%1)。 + 文件被更改(%1)。 @@ -5005,7 +5012,7 @@ Backup file last modified time: %2 This is a read-only note (%1), on which modification is not allowed. - 这是一个只读笔记 (%1),不支持修改。 + 这是一个只读笔记(%1),不支持修改。 @@ -5015,12 +5022,12 @@ Backup file last modified time: %2 Failed to save note (%1). - 无法保存笔记 (%1)。 + 无法保存笔记(%1)。 Please check the file (%1) and try it again. - 请检查文件 (%1) 并重试。 + 请检查文件(%1)并重试。 @@ -5262,7 +5269,7 @@ Backup file last modified time: %2 Snippet (%1) not found - 无法找到片段 (%1) + 无法找到片段(%1) @@ -5285,7 +5292,7 @@ Backup file last modified time: %2 Copy output file (%1) to (%2). - 复制输出文件 (%1) 为 (%2)。 + 复制输出文件(%1)为(%2)。 diff --git a/src/data/core/vnotex.json b/src/data/core/vnotex.json index 8c60d36b..d5123b8d 100644 --- a/src/data/core/vnotex.json +++ b/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", diff --git a/src/data/extra/docs/en/shortcuts.md b/src/data/extra/docs/en/shortcuts.md index f5bccfd8..96b8c510 100644 --- a/src/data/extra/docs/en/shortcuts.md +++ b/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. diff --git a/src/data/extra/docs/zh_CN/about_vnotex.txt b/src/data/extra/docs/zh_CN/about_vnotex.txt index 2363c50a..970f5e13 100644 --- a/src/data/extra/docs/zh_CN/about_vnotex.txt +++ b/src/data/extra/docs/zh_CN/about_vnotex.txt @@ -1,7 +1,7 @@

-VNoteX 致力于成为一个舒适的笔记平台。VNoteX 重构自 VNote,后者是一个始于2016年的专注于 Markdown 的开源笔记软件。VNote 在版本3之后会和 VNoteX 共享大部分源代码,并继续开源。 +VNoteX致力于成为一个舒适的笔记平台。VNoteX重构自VNote,后者是一个始于2016年的专注于Markdown的开源笔记软件。VNote在版本3之后会和VNoteX共享大部分源代码,并继续开源。

-VNote 源代码可以在 GitHub 获取。 +VNote源代码可以在GitHub获取。

详情请访问主页

diff --git a/src/data/extra/docs/zh_CN/external_programs.md b/src/data/extra/docs/zh_CN/external_programs.md index afa0ccd6..7809cb91 100644 --- a/src/data/extra/docs/zh_CN/external_programs.md +++ b/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**。 diff --git a/src/data/extra/docs/zh_CN/features_tips.txt b/src/data/extra/docs/zh_CN/features_tips.txt index e89041db..e6a76b9f 100644 --- a/src/data/extra/docs/zh_CN/features_tips.txt +++ b/src/data/extra/docs/zh_CN/features_tips.txt @@ -1,7 +1,7 @@ -

VNote 中一些不容错过的特性:

-

Markdown 编辑器

+

VNote中一些不容错过的特性:

+

Markdown编辑器

    -
  • 上下文菜单中的 解析为 Markdown 并粘贴: 解析富文本为 Markdown 文本,并按需获取图片到本地。
  • -
  • 上下文菜单中的 多功能粘贴: 粘贴为图片、附件或者连接。
  • -
  • 上下文菜单中的 交叉复制: 将所选文本复制为富文本。
  • +
  • 上下文菜单中的解析为Markdown并粘贴:解析富文本为Markdown文本,并按需获取图片到本地。
  • +
  • 上下文菜单中的多功能粘贴:粘贴为图片、附件或者连接。
  • +
  • 上下文菜单中的交叉复制:将所选文本复制为富文本。
diff --git a/src/data/extra/docs/zh_CN/markdown_guide.md b/src/data/extra/docs/zh_CN/markdown_guide.md index 179bd904..d0dd5d33 100644 --- a/src/data/extra/docs/zh_CN/markdown_guide.md +++ b/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/)。 diff --git a/src/data/extra/docs/zh_CN/shortcuts.md b/src/data/extra/docs/zh_CN/shortcuts.md index d3c76963..cf83ef66 100644 --- a/src/data/extra/docs/zh_CN/shortcuts.md +++ b/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`个高一层级的标题; @@ -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会在一些主要部件中显示最多两个字母,按下这些字母可以跳转到对应的部件。 diff --git a/src/data/extra/docs/zh_CN/welcome.md b/src/data/extra/docs/zh_CN/welcome.md index a59c1225..f2acd8e1 100644 --- a/src/data/extra/docs/zh_CN/welcome.md +++ b/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)。 +* 请关闭*有道词典*或者禁用其取词翻译功能。 diff --git a/src/export/exporter.cpp b/src/export/exporter.cpp index 9edb3da7..abbc2c41 100644 --- a/src/export/exporter.cpp +++ b/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; } diff --git a/src/utils/printutils.cpp b/src/utils/printutils.cpp new file mode 100644 index 00000000..72e48a13 --- /dev/null +++ b/src/utils/printutils.cpp @@ -0,0 +1,22 @@ +#include "printutils.h" + +#include +#include + +using namespace vnotex; + +QSharedPointer PrintUtils::promptForPrint(bool p_printSelectionEnabled, QWidget *p_parent) +{ + auto printer = QSharedPointer::create(); + + QPrintDialog dialog(printer.data(), p_parent); + if (p_printSelectionEnabled) { + dialog.addEnabledOption(QAbstractPrintDialog::PrintSelection); + } + + if (dialog.exec() == QDialog::Accepted) { + return printer; + } + + return nullptr; +} diff --git a/src/utils/printutils.h b/src/utils/printutils.h new file mode 100644 index 00000000..af1701e6 --- /dev/null +++ b/src/utils/printutils.h @@ -0,0 +1,21 @@ +#ifndef PRINTUTILS_H +#define PRINTUTILS_H + +#include + +class QPrinter; +class QWidget; + +namespace vnotex +{ + class PrintUtils + { + public: + PrintUtils() = delete; + + // Return null if user cancel the print. + static QSharedPointer promptForPrint(bool p_printSelectionEnabled, QWidget *p_parent); + }; +} + +#endif // PRINTUTILS_H diff --git a/src/utils/utils.pri b/src/utils/utils.pri index f9dd9429..d92cb069 100644 --- a/src/utils/utils.pri +++ b/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 \ diff --git a/src/widgets/dialogs/importnotebookdialog.cpp b/src/widgets/dialogs/importnotebookdialog.cpp index 4d6ceab9..b53c4bed 100644 --- a/src/widgets/dialogs/importnotebookdialog.cpp +++ b/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; } diff --git a/src/widgets/dialogs/settings/settingsdialog.cpp b/src/widgets/dialogs/settings/settingsdialog.cpp index b46890b0..695fe83c 100644 --- a/src/widgets/dialogs/settings/settingsdialog.cpp +++ b/src/widgets/dialogs/settings/settingsdialog.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -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); diff --git a/src/widgets/markdownviewwindow.cpp b/src/widgets/markdownviewwindow.cpp index f6de5fc8..474bd4b9 100644 --- a/src/widgets/markdownviewwindow.cpp +++ b/src/widgets/markdownviewwindow.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -21,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -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(); + }); + } +} diff --git a/src/widgets/markdownviewwindow.h b/src/widgets/markdownviewwindow.h index 830a522d..a0e306dd 100644 --- a/src/widgets/markdownviewwindow.h +++ b/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; diff --git a/src/widgets/textviewwindow.cpp b/src/widgets/textviewwindow.cpp index 89054e9c..c5af5358 100644 --- a/src/widgets/textviewwindow.cpp +++ b/src/widgets/textviewwindow.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -15,6 +16,7 @@ #include #include "editors/statuswidget.h" #include +#include 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 &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()); + } +} diff --git a/src/widgets/textviewwindow.h b/src/widgets/textviewwindow.h index 7b241689..a8e90ceb 100644 --- a/src/widgets/textviewwindow.h +++ b/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; diff --git a/src/widgets/toolbarhelper.cpp b/src/widgets/toolbarhelper.cpp index c84ebcfb..7f3af67b 100644 --- a/src/widgets/toolbarhelper.cpp +++ b/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(); + setupExpandButton(p_win, tb); - auto btn = WidgetsFactory::createToolButton(tb); + setupSettingsButton(p_win, 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(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(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::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::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::create(); - paras->m_readOnly = true; - emit VNoteX::getInst().openFileRequested(file, paras); - } - }); - - 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("

%1

\n%2\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 = 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(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(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::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::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::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("

%1

\n%2\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); + } +} diff --git a/src/widgets/toolbarhelper.h b/src/widgets/toolbarhelper.h index 029ef383..045721a3 100644 --- a/src/widgets/toolbarhelper.h +++ b/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 diff --git a/src/widgets/viewsplit.cpp b/src/widgets/viewsplit.cpp index 335753bf..a5fca64f 100644 --- a/src/widgets/viewsplit.cpp +++ b/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); diff --git a/src/widgets/viewwindow.cpp b/src/widgets/viewwindow.cpp index 2396b407..39d57313 100644 --- a/src/widgets/viewwindow.cpp +++ b/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"; +} diff --git a/src/widgets/viewwindow.h b/src/widgets/viewwindow.h index 32fe2188..60af1f3e 100644 --- a/src/widgets/viewwindow.h +++ b/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; diff --git a/src/widgets/viewwindowtoolbarhelper.cpp b/src/widgets/viewwindowtoolbarhelper.cpp index b1eeecee..c935d4f6 100644 --- a/src/widgets/viewwindowtoolbarhelper.cpp +++ b/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; diff --git a/src/widgets/viewwindowtoolbarhelper.h b/src/widgets/viewwindowtoolbarhelper.h index e91ab546..f260ec8e 100644 --- a/src/widgets/viewwindowtoolbarhelper.h +++ b/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); diff --git a/tests/test_core/test_notebook/testnotebookdatabase.cpp b/tests/test_core/test_notebook/testnotebookdatabase.cpp index 4fa40871..e935ca8b 100644 --- a/tests/test_core/test_notebook/testnotebookdatabase.cpp +++ b/tests/test_core/test_notebook/testnotebookdatabase.cpp @@ -83,6 +83,20 @@ void TestNotebookDatabase::testNode() QScopedPointer 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 node7(new DummyNode(Node::Flag::Content, 55, "caba", m_notebook.data(), node6.data())); + QScopedPointer 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());