From c83fcf6ce9494f96cf1d39ee0635d0d4caf0dc34 Mon Sep 17 00:00:00 2001 From: Le Tan Date: Sun, 12 Feb 2017 22:39:40 +0800 Subject: [PATCH] add settings dialog and language setting Add VSettingsDialog to show a settings dialog. For now, VNote supports setting of language. Add imcomplete Chinese support. Signed-off-by: Le Tan --- src/dialog/vsettingsdialog.cpp | 143 ++++ src/dialog/vsettingsdialog.h | 51 ++ src/main.cpp | 27 + src/resources/icons/settings.svg | 18 + src/resources/vnote.ini | 1 + src/src.pro | 13 +- src/translations.qrc | 5 + src/translations/vnote_zh_CN.qm | Bin 0 -> 7411 bytes src/translations/vnote_zh_CN.ts | 1054 ++++++++++++++++++++++++++++++ src/utils/vutils.cpp | 19 + src/utils/vutils.h | 6 + src/vconfigmanager.cpp | 2 + src/vconfigmanager.h | 21 + src/vdirectory.cpp | 2 +- src/vmainwindow.cpp | 34 +- src/vmainwindow.h | 1 + src/vnote.cpp | 3 +- src/vnote.qrc | 1 + 18 files changed, 1384 insertions(+), 17 deletions(-) create mode 100644 src/dialog/vsettingsdialog.cpp create mode 100644 src/dialog/vsettingsdialog.h create mode 100644 src/resources/icons/settings.svg create mode 100644 src/translations.qrc create mode 100644 src/translations/vnote_zh_CN.qm create mode 100644 src/translations/vnote_zh_CN.ts diff --git a/src/dialog/vsettingsdialog.cpp b/src/dialog/vsettingsdialog.cpp new file mode 100644 index 00000000..c945488a --- /dev/null +++ b/src/dialog/vsettingsdialog.cpp @@ -0,0 +1,143 @@ +#include "vsettingsdialog.h" +#include +#include "vconfigmanager.h" +#include "utils/vutils.h" + +extern VConfigManager vconfig; + +VSettingsDialog::VSettingsDialog(QWidget *p_parent) + : QDialog(p_parent) +{ + m_tabs = new QTabWidget; + m_tabs->addTab(new VGeneralTab(), tr("General")); + + m_btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + connect(m_btnBox, &QDialogButtonBox::accepted, this, &VSettingsDialog::saveConfiguration); + connect(m_btnBox, &QDialogButtonBox::rejected, this, &QDialog::reject); + + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addWidget(m_tabs); + mainLayout->addWidget(m_btnBox); + setLayout(mainLayout); + + setWindowTitle(tr("Settings")); + + loadConfiguration(); +} + +void VSettingsDialog::loadConfiguration() +{ + // General Tab. + VGeneralTab *generalTab = dynamic_cast(m_tabs->widget(0)); + Q_ASSERT(generalTab); + bool ret = generalTab->loadConfiguration(); + if (!ret) { + goto err; + } + + return; +err: + VUtils::showMessage(QMessageBox::Warning, tr("Warning"), + QString("Failed to load configuration."), "", + QMessageBox::Ok, QMessageBox::Ok, NULL); + QMetaObject::invokeMethod(this, "reject", Qt::QueuedConnection); +} + +void VSettingsDialog::saveConfiguration() +{ + // General Tab. + VGeneralTab *generalTab = dynamic_cast(m_tabs->widget(0)); + Q_ASSERT(generalTab); + bool ret = generalTab->saveConfiguration(); + if (!ret) { + goto err; + } + + accept(); + return; +err: + VUtils::showMessage(QMessageBox::Warning, tr("Warning"), + QString("Failed to save configuration. Please try it again."), "", + QMessageBox::Ok, QMessageBox::Ok, NULL); +} + +const QVector VGeneralTab::c_availableLangs = { "System", "English", "Chinese" }; + +VGeneralTab::VGeneralTab(QWidget *p_parent) + : QWidget(p_parent), m_langChanged(false) +{ + QLabel *langLabel = new QLabel(tr("Language:")); + m_langCombo = new QComboBox(this); + m_langCombo->addItem(tr("System"), "System"); + auto langs = VUtils::getAvailableLanguages(); + for (auto lang : langs) { + m_langCombo->addItem(lang.second, lang.first); + } + connect(m_langCombo, SIGNAL(currentIndexChanged(int)), + this, SLOT(handleIndexChange(int))); + + QFormLayout *optionLayout = new QFormLayout(); + optionLayout->addRow(langLabel, m_langCombo); + + QVBoxLayout *mainLayout = new QVBoxLayout(); + mainLayout->addLayout(optionLayout); + + setLayout(mainLayout); +} + +bool VGeneralTab::loadConfiguration() +{ + if (!loadLanguage()) { + return false; + } + return true; +} + +bool VGeneralTab::saveConfiguration() +{ + if (!saveLanguage()) { + return false; + } + return true; +} + +bool VGeneralTab::loadLanguage() +{ + QString lang = vconfig.getLanguage(); + if (lang.isNull()) { + return false; + } else if (lang == "System") { + m_langCombo->setCurrentIndex(0); + return true; + } + bool found = false; + // Lang is the value, not name. + for (int i = 0; i < m_langCombo->count(); ++i) { + if (m_langCombo->itemData(i).toString() == lang) { + found = true; + m_langCombo->setCurrentIndex(i); + break; + } + } + if (!found) { + qWarning() << "invalid language configuration (use default value)"; + m_langCombo->setCurrentIndex(0); + } + return true; +} + +bool VGeneralTab::saveLanguage() +{ + if (m_langChanged) { + vconfig.setLanguage(m_langCombo->currentData().toString()); + } + return true; +} + +void VGeneralTab::handleIndexChange(int p_index) +{ + if (p_index == -1) { + return; + } + m_langChanged = true; +} diff --git a/src/dialog/vsettingsdialog.h b/src/dialog/vsettingsdialog.h new file mode 100644 index 00000000..692949da --- /dev/null +++ b/src/dialog/vsettingsdialog.h @@ -0,0 +1,51 @@ +#ifndef VSETTINGSDIALOG_H +#define VSETTINGSDIALOG_H + +#include +#include +#include + +class QDialogButtonBox; +class QTabWidget; +class QComboBox; + +class VGeneralTab : public QWidget +{ + Q_OBJECT +public: + explicit VGeneralTab(QWidget *p_parent = 0); + bool loadConfiguration(); + bool saveConfiguration(); + +private slots: + void handleIndexChange(int p_index); + +private: + bool loadLanguage(); + bool saveLanguage(); + + // Language + QComboBox *m_langCombo; + // Whether language changes. + bool m_langChanged; + + static const QVector c_availableLangs; +}; + +class VSettingsDialog : public QDialog +{ + Q_OBJECT +public: + explicit VSettingsDialog(QWidget *p_parent = 0); + +private slots: + void saveConfiguration(); + +private: + void loadConfiguration(); + + QTabWidget *m_tabs; + QDialogButtonBox *m_btnBox; +}; + +#endif // VSETTINGSDIALOG_H diff --git a/src/main.cpp b/src/main.cpp index ae55733f..0449e93f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,9 +1,15 @@ #include "vmainwindow.h" #include +#include +#include +#include #include #include #include "utils/vutils.h" #include "vsingleinstanceguard.h" +#include "vconfigmanager.h" + +VConfigManager vconfig; void VLogger(QtMsgType type, const QMessageLogContext &context, const QString &msg) { @@ -37,6 +43,27 @@ int main(int argc, char *argv[]) } QApplication app(argc, argv); + vconfig.initialize(); + + QString locale = vconfig.getLanguage(); + if (locale == "System" || !VUtils::isValidLanguage(locale)) { + locale = QLocale::system().name(); + } + qDebug() << "use locale" << locale; + + // load translation for Qt + QTranslator qtTranslator; + if (!qtTranslator.load("qt_" + locale, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { + qtTranslator.load("qt_" + locale, "translations"); + } + app.installTranslator(&qtTranslator); + + // load translation for vnote + QTranslator translator; + if (translator.load("vnote_" + locale, ":/translations")) { + qDebug() << "install VNote translator"; + app.installTranslator(&translator); + } QTextCodec *codec = QTextCodec::codecForName("UTF8"); if (codec) { diff --git a/src/resources/icons/settings.svg b/src/resources/icons/settings.svg new file mode 100644 index 00000000..49c969a9 --- /dev/null +++ b/src/resources/icons/settings.svg @@ -0,0 +1,18 @@ + + + + + + diff --git a/src/resources/vnote.ini b/src/resources/vnote.ini index 597150d2..d15545aa 100644 --- a/src/resources/vnote.ini +++ b/src/resources/vnote.ini @@ -12,6 +12,7 @@ highlight_selected_word=1 highlight_searched_word=1 current_background_color=System current_render_background_color=System +language=System [predefined_colors] 1\name=White diff --git a/src/src.pro b/src/src.pro index 1c9a7b9b..4134b0c9 100644 --- a/src/src.pro +++ b/src/src.pro @@ -13,8 +13,10 @@ TEMPLATE = app RC_ICONS = resources/icons/vnote.ico +TRANSLATIONS += translations/vnote_zh_CN.ts + SOURCES += main.cpp\ - vmainwindow.cpp \ + vmainwindow.cpp \ vdirectorytree.cpp \ vnote.cpp \ vnotebook.cpp \ @@ -49,7 +51,8 @@ SOURCES += main.cpp\ vnofocusitemdelegate.cpp \ vavatar.cpp \ vmdedit.cpp \ - dialog/vfindreplacedialog.cpp + dialog/vfindreplacedialog.cpp \ + dialog/vsettingsdialog.cpp HEADERS += vmainwindow.h \ vdirectorytree.h \ @@ -87,10 +90,12 @@ HEADERS += vmainwindow.h \ vnofocusitemdelegate.h \ vavatar.h \ vmdedit.h \ - dialog/vfindreplacedialog.h + dialog/vfindreplacedialog.h \ + dialog/vsettingsdialog.h RESOURCES += \ - vnote.qrc + vnote.qrc \ + translations.qrc win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../hoedown/release/ -lhoedown else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../hoedown/debug/ -lhoedown diff --git a/src/translations.qrc b/src/translations.qrc new file mode 100644 index 00000000..1effdca7 --- /dev/null +++ b/src/translations.qrc @@ -0,0 +1,5 @@ + + + translations/vnote_zh_CN.qm + + diff --git a/src/translations/vnote_zh_CN.qm b/src/translations/vnote_zh_CN.qm new file mode 100644 index 0000000000000000000000000000000000000000..b9dd5e0b9bee9c0833f4f536834df2c8c0262ed0 GIT binary patch literal 7411 zcmcIpdvH|M89xcTo89atfshwS>j7mUND>UT#pqaGK~!>av&%*rOT4>#cK0^B_ipdr zYz$f+HddTCLIzQ^R!2c?X{%@*#@5%2Q?yn^sXBG0b)=nPe6-3RSRAoHzwh3?XCJvY z!i=3v=H%XczTfva=X>VzXJRdXK6d}EH)hXz@rH+_b zkT~Cbg^-qGWWlozLMl#@1#iuTebPsq zLrBB<<-^seI`4 z9|`eIt$gfmSSv2B{Ngn1ueo>1iWQdvy>rSfo4N_9ia4CoUZ8){;ab*7$n<+1tm1P* zJkL2Y*E@l4-0@~|CG309*>X)1o{u<}j6V%}Eq3;txB%qc>D+jL0q!B^qZ^}yIIe;9 zr||w?u$@lJT(?ff`& zkdPTac7FWOI6POlzI_Dn9gn*%+X{MlA9wwF+)GGZo9l^}{to&daJ`&rfbTcCURwnE z*S%fU@stAceN{E~)-8bBU-cOK58yRdy}8v#$kd3twV@U4+vDy_&IS7@?$oY&u>S?_ zO!s=w<6`&tFFu3kPuzbvbuS^#58bcK19`~1##(pU{l@AbeBbB(;4YA>;$@HL!tcPo zUwST@1JAY0^S!At(0{H+=)N56*64{{2Jh>mo`>JL75E+ZJpJTBkYiVM<2xgOON_Pl zZts#AkHAyH+jYPRtKa+JnJgi02J241ISlLX;Q2gX^9}C;*=}R4{*5oSa}?~*;Cr?L z_D?@rY-Cw7#ORh8 zUW<6dgE|BVDLc=nk|;Z}Ya~J(0v_j@t^jkR?WFMA4E|OR^%1BMY<>h4^LTf%U>cWMBz> zo(ZkUsSzFeYruS{^@Nj~hT)cHLfdomVeAdu+W-4tSKkL*J(m%DEf24u5Uqu-2_D~6 z2-{RsXeZ6u`+q4?c`PVHy5#JU%A-UX(vr!Lnozs#I|D2?YGfp#t0bb$%IgQ^1yh-x zo>0$8w47>M7>}vM$_;reygvGM6rqr@wE2aJ1zS#;>FJCwcx=n5ct`k%&=sob?+ZM& zajWpNMV0*Y7OxT^NyShu$;e-EOj9i)luqiX2Z#Q7zkU$yTqC1TR)x z9NdEy5f#{t)&bNYsV*U@(MhgVSx!=htW!ZPR%6I%y(4fkTd3`(>!dPpqe>Kl5R;9< zY(kVY0D$k{>=J-x9UznE{WTzGRTEBRecyY+L zHLIv}jU-!#8y`ZT2}*+3%mP4=iE1qq!I*1;sX? z^eJl0^2D2p1<8#@mL@zU=3H0+6H}>zIkQxW)2u0EW)dNF4yKS699k#mkXK;XPJwz< z0E3~$fqbg~ZRRsr@nBMR2UAN{LnXi_)N@s<6=q+}nV!nepvk(9v^;{D!XYd|g*HUd zGsGg)rzF3&=kYMCXK5VkQp3e18C=^`ju!!zeB9B$1X%dAdL@^#<|;W0EdYh8S4>!6 z)LEu*CULJW9EvHlaiG>bkSId{0;qz7<>iQ_WIkR-gW)--3oB@5eQn*?7@`n-w?}U= z1-o+PT)NT;4(}-8u|bXu9X*35|=0Ack4WGO;^ zDbxD4r`Nv26Z!b|tr&fCqZo9PTWITt9J@pJ~6M#Zdtw2{KJCyLV^8ZTl=p;|H~ z2$mch432mN;bd+Urw>J3{9nff3s#%)k^_;sUEF}A!AQcU@WVa`JM`RWNu-<+Oe(_= zjXm@Nz0>f{P1XCm{T}IijuOn*41k_56v$wN$`G@-x;_?`TI)f8TUQp z_O0V@u>F`T(D{;8H*MNIRCI5Jby-I9?HFZ~xo2HRUEp zb@=%$N5QiCfOlS&PH<7|xunF9YTW8`aM%{1%W&3msW|8Fo-5}`ocKP%y(!*-?OgD$ z@J1r(P)G3a7T*8~9?p&8`*K@g5ZGJ1nQT`_M?%t)Ly`8VlJ3yNbV?cQ$YG9X zhxd9|O)Dz?bAbmW>z286Sn9BymA2qeHFO8&s)C`%dy3-b9HiAVxseW`y)xpcE{%QY p(nnXJJMgNQ6;4THE#T@i2h<3gH`A$Y^Wr2?y)JCV`27D!{s(mN&DH<_ literal 0 HcmV?d00001 diff --git a/src/translations/vnote_zh_CN.ts b/src/translations/vnote_zh_CN.ts new file mode 100644 index 00000000..11de0fb6 --- /dev/null +++ b/src/translations/vnote_zh_CN.ts @@ -0,0 +1,1054 @@ + + + + + VDirInfoDialog + + + &Name: + + + + + &OK + + + + + &Cancel + + + + + VDirectory + + + Warning + + + + + Please check if there already exists a file with the same name and manually copy it. + + + + + VDirectoryTree + + + New &Root Directory + 新建根目录 + + + + Create a new root directory in current notebook + + + + + &New Sub-Directory + + + + + Create a new sub-directory + + + + + &Delete + + + + + Delete selected directory + + + + + &Info + + + + + View and edit current directory's information + + + + + &Copy + + + + + Copy selected directories + + + + + &Cut + + + + + Cut selected directories + + + + + &Paste + + + + + Paste directories + + + + + + + + + + + Warning + + + + + Create Directory + + + + + Create Root Directory + + + + + This will delete any files under this directory. + + + + + Directory Information + + + + + VEditTab + + + Information + + + + + Do you want to save your changes? + + + + + + Warning + + + + + + Fail to save note + + + + + VEditWindow + + + Locate + + + + + Locate the directory of current note + + + + + Move One Split Left + + + + + Move current tab to the split on the left + + + + + Move One Split Right + + + + + Move current tab to the split on the right + + + + + Split + + + + + Split current window vertically + + + + + Remove split + + + + + Remove current split window + + + + + VFileInfoDialog + + + &Name: + + + + + &OK + + + + + &Cancel + + + + + VFileList + + + &New Note + + + + + Create a note in current directory + 在当前目录下新建一个笔记 + + + + &Delete + + + + + Delete selected note + + + + + &Info + + + + + View and edit current note's information + + + + + &Copy + + + + + Copy selected notes + + + + + &Cut + + + + + Cut selected notes + + + + + &Paste + + + + + Paste notes + + + + + Note Information + + + + + + + Warning + + + + + This may be unrecoverable! + + + + + VFindReplaceDialog + + + Find/Replace + 查找/替换 + + + + Find: + + + + + Enter text to search + + + + + Find &Next + + + + + Find &Previous + + + + + &Replace with: + + + + + Enter text to replace with + + + + + Replace + 替换 + + + + Replace && Fin&d + + + + + Replace A&ll + + + + + &Advanced >> + + + + + &Case sensitive + + + + + &Whole word only + + + + + Re&gular expression + + + + + &Incremental search + + + + + VGeneralTab + + + Language: + + + + + System + 默认 + + + + VInsertImageDialog + + + &From: + + + + + &Browse + + + + + &Image title: + + + + + &OK + + + + + &Cancel + + + + + Select the image to be inserted + + + + + Images (*.png *.xpm *.jpg *.bmp *.gif) + + + + + VMainWindow + + + Notebook + 笔记本 + + + + Directory + 目录 + + + + View + 查看 + + + + &Single Panel + 单列 + + + + Display only the note panel + 仅显示笔记列表面板 + + + + &Two Panels + 双列 + + + + Display both the directory and note panel + 显示目录和笔记列表面板 + + + + Expand + 扩展内容区域 + + + + Expand the edit area + 扩展内容编辑区域 + + + + Note + 笔记 + + + + New &Root Directory + 新建根目录 + + + + Create a root directory in current notebook + 在当前笔记本下新建一个根目录 + + + + New &Note + 新建笔记 + + + + Create a note in current directory + 在当前目录下新建一个笔记 + + + + Note &Info + 笔记信息 + + + + View and edit info of current note + 显示和编辑当前笔记信息 + + + + &Delete Note + 删除笔记 + + + + Delete current note + 删除当前笔记 + + + + + &Edit + 编辑 + + + + Edit current note + 编辑当前笔记 + + + + Discard Changes And Exit + 放弃更改并退出 + + + + Discard changes and exit edit mode + 放弃当前更改并退出编辑模式 + + + + Save Changes And Exit + 保存更改并退出 + + + + Save changes and exit edit mode + 保存当前更改并退出编辑模式 + + + + Save + 保存 + + + + Save changes of current note + 保存当前笔记的更改 + + + + &Help + 帮助 + + + + &About + 关于 + + + + Show information about VNote + 显示VNote的信息 + + + + About &Qt + 关于&Qt + + + + Show information about Qt + 显示Qt的信息 + + + + &Markdown + &Markdown + + + + &Converter + 渲染引擎 + + + + Marked + Marked + + + + Use Marked to convert Markdown to HTML (re-open current tabs to make it work) + 使用Marked渲染Markdown为HTML (需要重新打开当前标签页) + + + + Hoedown + Hoedown + + + + Use Hoedown to convert Markdown to HTML (re-open current tabs to make it work) + 使用Hoedow渲染Markdown为HTML (需要重新打开当前标签页) + + + + &View + 查看 + + + + &File + 文件 + + + + &Import Notes From Files + 导入文件 + + + + Import notes from files into current directory + 从文件中导入笔记到当前目录 + + + + Settings + 设置 + + + + View and change settings for VNote + 查看和更改VNote配置 + + + + Insert &Image + 插入图片 + + + + Insert an image from file in current note + 从文件中插入图片到当前笔记中 + + + + + Find/Replace + 查找/替换 + + + + Open Find/Replace dialog to search in current note + 打开查找/替换对话框以在当前笔记中查找 + + + + Find Next + 查找下一个 + + + + Find next occurence + 查找下一处出现 + + + + Find Previous + 查找上一个 + + + + Find previous occurence + 查找上一次出现 + + + + Replace + 替换 + + + + Replace current occurence + 替换当前出现 + + + + Replace && Find + 替换并查找 + + + + Replace current occurence and find the next one + 替换当前出现并查找下一个 + + + + Replace All + 替换全部 + + + + Replace all occurences in current note + 替换当前笔记中的所有出现 + + + + Highlight Searched Pattern + 高亮查找模式 + + + + Highlight all occurences of searched pattern + 高亮查找模式的所有出现 + + + + &Expand Tab + 扩展Tab + + + + Expand entered Tab to spaces + 扩展输入的Tab为空格 + + + + Expand Tab to 2 spaces + 扩展Tab为2个空格 + + + + Expand Tab to 4 spaces + 扩展Tab为4个空格 + + + + Expand Tab to 8 spaces + 扩展Tab为8个空格 + + + + Import Notes From File + 导入文件 + + + + Failed to import files maybe due to name conflicts. + 未能导入文件,可能是因为名字冲突了。 + + + + Use system's background color configuration for Markdown rendering + 使用系统的背景色设置进行Markdown渲染 + + + + Set as the background color for Markdown rendering + 设置为Markdown渲染背景色 + + + + 2 Spaces + 2个空格 + + + + 4 Spaces + 4个空格 + + + + 8 Spaces + 8个空格 + + + + Highlight Cursor Line + 高亮光标所在行 + + + + Highlight current cursor line + 高亮当前光标所在行 + + + + Highlight Selected Word + 高亮所选文本 + + + + Highlight all occurences of selected word + 高亮所选文本的所有出现 + + + + Tab Stop Width + Tab Stop 宽度 + + + + Tools + 工具 + + + + Outline + 大纲 + + + + Select Files(HTML or Markdown) To Import + 选择要导入的文件(HTML或Markdown) + + + + About VNote + 关于VNote + + + + VNote is a Vim-inspired note taking application for Markdown. +Visit https://github.com/tamlok/vnote.git for more information. + VNote是一个受Vim启发而开发的一个Markdown笔记软件。更多信息请访问 https://github.com/tamlok/vnote.git。 + + + + &Rendering Background + 渲染背景 + + + + + System + 默认 + + + + &Background Color + 背景颜色 + + + + Use system's background color configuration for editor + 为编辑器使用系统的背景色 + + + + Set as the background color for editor + 设置为编辑器的背景色 + + + + VMdEditOperations + + + Insert Image From Clipboard + + + + + + Warning + + + + + Insert Image From File + + + + + VNewDirDialog + + + &OK + + + + + &Cancel + + + + + VNewFileDialog + + + &OK + + + + + &Cancel + + + + + VNewNotebookDialog + + + Notebook &name: + + + + + Notebook &path: + + + + + &Browse + + + + + Import existing notebook + + + + + When checked, VNote won't create a new config file if there already exists one. + + + + + &OK + + + + + &Cancel + + + + + Select a directory as the path of the notebook + + + + + VNotebookInfoDialog + + + Notebook &name: + + + + + Notebook &path: + + + + + &OK + + + + + &Cancel + + + + + VNotebookSelector + + + &Delete + + + + + Delete current notebook + + + + + &Info + + + + + View and edit current notebook's information + + + + + Create or import a notebook. + + + + + Create Notebook + + + + + Warning + + + + + Notebook Information + + + + + VSettingsDialog + + + General + + + + + Settings + 设置 + + + + + Warning + + + + diff --git a/src/utils/vutils.cpp b/src/utils/vutils.cpp index aebacec9..d601ff0c 100644 --- a/src/utils/vutils.cpp +++ b/src/utils/vutils.cpp @@ -9,6 +9,10 @@ #include #include #include + +const QVector> VUtils::c_availableLanguages = {QPair("en_US", "Englisth (US)"), + QPair("zh_CN", "Chinese")}; + VUtils::VUtils() { } @@ -302,3 +306,18 @@ QString VUtils::generateCopiedDirName(const QString &p_parentDirPath, const QStr } return name; } + +const QVector>& VUtils::getAvailableLanguages() +{ + return c_availableLanguages; +} + +bool VUtils::isValidLanguage(const QString &p_lang) +{ + for (auto lang : c_availableLanguages) { + if (lang.first == p_lang) { + return true; + } + } + return false; +} diff --git a/src/utils/vutils.h b/src/utils/vutils.h index 709f0ef6..aa49cc96 100644 --- a/src/utils/vutils.h +++ b/src/utils/vutils.h @@ -35,6 +35,12 @@ public: static int showMessage(QMessageBox::Icon p_icon, const QString &p_title, const QString &p_text, const QString &p_infoText, QMessageBox::StandardButtons p_buttons, QMessageBox::StandardButton p_defaultBtn, QWidget *p_parent); + static const QVector > &getAvailableLanguages(); + static bool isValidLanguage(const QString &p_lang); + +private: + // + static const QVector> c_availableLanguages; }; inline QString VUtils::directoryNameFromPath(const QString &path) diff --git a/src/vconfigmanager.cpp b/src/vconfigmanager.cpp index 5c1a10c7..25845304 100644 --- a/src/vconfigmanager.cpp +++ b/src/vconfigmanager.cpp @@ -79,6 +79,8 @@ void VConfigManager::initialize() "find_regular_expression").toBool(); m_findIncrementalSearch = getConfigFromSettings("global", "find_incremental_search").toBool(); + + m_language = getConfigFromSettings("global", "language").toString(); } void VConfigManager::readPredefinedColorsFromSettings() diff --git a/src/vconfigmanager.h b/src/vconfigmanager.h index 04b6e820..5af1bbf1 100644 --- a/src/vconfigmanager.h +++ b/src/vconfigmanager.h @@ -117,6 +117,9 @@ public: inline bool getFindIncrementalSearch() const; inline void setFindIncrementalSearch(bool p_enabled); + inline QString getLanguage() const; + inline void setLanguage(const QString &p_language); + private: void updateMarkdownEditStyle(); QVariant getConfigFromSettings(const QString §ion, const QString &key); @@ -174,6 +177,9 @@ private: bool m_findRegularExpression; bool m_findIncrementalSearch; + // Language + QString m_language; + // The name of the config file in each directory static const QString dirConfigFileName; // The name of the default configuration file @@ -491,4 +497,19 @@ inline void VConfigManager::setFindIncrementalSearch(bool p_enabled) m_findIncrementalSearch); } +inline QString VConfigManager::getLanguage() const +{ + return m_language; +} + +inline void VConfigManager::setLanguage(const QString &p_language) +{ + if (m_language == p_language) { + return; + } + m_language = p_language; + setConfigToSettings("global", "language", + m_language); +} + #endif // VCONFIGMANAGER_H diff --git a/src/vdirectory.cpp b/src/vdirectory.cpp index 8b4b6af9..e680d2cd 100644 --- a/src/vdirectory.cpp +++ b/src/vdirectory.cpp @@ -523,7 +523,7 @@ VFile *VDirectory::copyFile(VDirectory *p_destDir, const QString &p_destName, } else { VUtils::showMessage(QMessageBox::Warning, tr("Warning"), QString("Failed to copy image %1.").arg(images[i]), - tr("Please check if there already exists a file with the same name and manually copy it"), + tr("Please check if there already exists a file with the same name and manually copy it."), QMessageBox::Ok, QMessageBox::Ok, NULL); } } diff --git a/src/vmainwindow.cpp b/src/vmainwindow.cpp index a6a85a84..e4234ba7 100644 --- a/src/vmainwindow.cpp +++ b/src/vmainwindow.cpp @@ -11,6 +11,7 @@ #include "vnotebookselector.h" #include "vavatar.h" #include "dialog/vfindreplacedialog.h" +#include "dialog/vsettingsdialog.h" extern VConfigManager vconfig; @@ -20,7 +21,6 @@ VMainWindow::VMainWindow(QWidget *parent) : QMainWindow(parent) { setWindowIcon(QIcon(":/resources/icons/vnote.ico")); - // Must be called before those who uses VConfigManager vnote = new VNote(this); g_vnote = vnote; vnote->initPalette(palette()); @@ -174,7 +174,7 @@ void VMainWindow::initFileToolBar() fileToolBar->setMovable(false); newRootDirAct = new QAction(QIcon(":/resources/icons/create_rootdir_tb.svg"), - tr("New &Rood Directory"), this); + tr("New &Root Directory"), this); newRootDirAct->setStatusTip(tr("Create a root directory in current notebook")); connect(newRootDirAct, &QAction::triggered, directoryTree, &VDirectoryTree::newRootDirectory); @@ -321,7 +321,16 @@ void VMainWindow::initFileMenu() connect(importNoteAct, &QAction::triggered, this, &VMainWindow::importNoteFromFile); + // Settings. + QAction *settingsAct = new QAction(QIcon(":/resources/icons/settings.svg"), + tr("Settings"), this); + settingsAct->setStatusTip(tr("View and change settings for VNote")); + connect(settingsAct, &QAction::triggered, + this, &VMainWindow::viewSettings); + fileMenu->addAction(importNoteAct); + fileMenu->addSeparator(); + fileMenu->addAction(settingsAct); } void VMainWindow::initEditMenu() @@ -379,7 +388,7 @@ void VMainWindow::initEditMenu() // Expand Tab into spaces. QAction *expandTabAct = new QAction(tr("&Expand Tab"), this); - expandTabAct->setStatusTip(tr("Expand entered tab to spaces")); + expandTabAct->setStatusTip(tr("Expand entered Tab to spaces")); expandTabAct->setCheckable(true); connect(expandTabAct, &QAction::triggered, this, &VMainWindow::changeExpandTab); @@ -387,15 +396,15 @@ void VMainWindow::initEditMenu() // Tab stop width. QActionGroup *tabStopWidthAct = new QActionGroup(this); QAction *twoSpaceTabAct = new QAction(tr("2 Spaces"), tabStopWidthAct); - twoSpaceTabAct->setStatusTip(tr("Expand tab to 2 spaces")); + twoSpaceTabAct->setStatusTip(tr("Expand Tab to 2 spaces")); twoSpaceTabAct->setCheckable(true); twoSpaceTabAct->setData(2); QAction *fourSpaceTabAct = new QAction(tr("4 Spaces"), tabStopWidthAct); - fourSpaceTabAct->setStatusTip(tr("Expand tab to 4 spaces")); + fourSpaceTabAct->setStatusTip(tr("Expand Tab to 4 spaces")); fourSpaceTabAct->setCheckable(true); fourSpaceTabAct->setData(4); QAction *eightSpaceTabAct = new QAction(tr("8 Spaces"), tabStopWidthAct); - eightSpaceTabAct->setStatusTip(tr("Expand tab to 8 spaces")); + eightSpaceTabAct->setStatusTip(tr("Expand Tab to 8 spaces")); eightSpaceTabAct->setCheckable(true); eightSpaceTabAct->setData(8); connect(tabStopWidthAct, &QActionGroup::triggered, @@ -530,12 +539,12 @@ void VMainWindow::importNoteFromFile() failedFiles.append(files[i]); } } - QMessageBox msgBox(QMessageBox::Information, tr("Import note from file"), + QMessageBox msgBox(QMessageBox::Information, tr("Import Notes From File"), QString("Imported notes: %1 succeed, %2 failed.") .arg(files.size() - failedFiles.size()).arg(failedFiles.size()), QMessageBox::Ok, this); if (!failedFiles.isEmpty()) { - msgBox.setInformativeText(tr("Failed to import files may be due to name conflicts.")); + msgBox.setInformativeText(tr("Failed to import files maybe due to name conflicts.")); } msgBox.exec(); } @@ -617,7 +626,7 @@ void VMainWindow::initRenderBackgroundMenu(QMenu *menu) QMenu *renderBgMenu = menu->addMenu(tr("&Rendering Background")); const QString &curBgColor = vconfig.getCurRenderBackgroundColor(); QAction *tmpAct = new QAction(tr("System"), renderBackgroundAct); - tmpAct->setStatusTip(tr("Use system's background color configuration for markdown rendering")); + tmpAct->setStatusTip(tr("Use system's background color configuration for Markdown rendering")); tmpAct->setCheckable(true); tmpAct->setData("System"); if (curBgColor == "System") { @@ -628,7 +637,7 @@ void VMainWindow::initRenderBackgroundMenu(QMenu *menu) const QVector &bgColors = vconfig.getPredefinedColors(); for (int i = 0; i < bgColors.size(); ++i) { tmpAct = new QAction(bgColors[i].name, renderBackgroundAct); - tmpAct->setStatusTip(tr("Set as the background color for markdown rendering")); + tmpAct->setStatusTip(tr("Set as the background color for Markdown rendering")); tmpAct->setCheckable(true); tmpAct->setData(bgColors[i].name); tmpAct->setIcon(QIcon(predefinedColorPixmaps[i])); @@ -943,3 +952,8 @@ void VMainWindow::openFindDialog() m_findReplaceDialog->openDialog(editArea->getSelectedText()); } +void VMainWindow::viewSettings() +{ + VSettingsDialog settingsDialog(this); + settingsDialog.exec(); +} diff --git a/src/vmainwindow.h b/src/vmainwindow.h index 13266064..d09c9b0c 100644 --- a/src/vmainwindow.h +++ b/src/vmainwindow.h @@ -40,6 +40,7 @@ public: private slots: void importNoteFromFile(); + void viewSettings(); void changeMarkdownConverter(QAction *action); void aboutMessage(); void changeExpandTab(bool checked); diff --git a/src/vnote.cpp b/src/vnote.cpp index 4715260f..648a5449 100644 --- a/src/vnote.cpp +++ b/src/vnote.cpp @@ -8,7 +8,7 @@ #include "vconfigmanager.h" #include "vmainwindow.h" -VConfigManager vconfig; +extern VConfigManager vconfig; QString VNote::templateHtml; QString VNote::preTemplateHtml; @@ -17,7 +17,6 @@ QString VNote::postTemplateHtml; VNote::VNote(QObject *parent) : QObject(parent), m_mainWindow(dynamic_cast(parent)) { - vconfig.initialize(); initTemplate(); vconfig.getNotebooks(m_notebooks, this); } diff --git a/src/vnote.qrc b/src/vnote.qrc index b0d2d2b5..98e507ae 100644 --- a/src/vnote.qrc +++ b/src/vnote.qrc @@ -84,5 +84,6 @@ resources/icons/close.svg resources/icons/find_replace.svg resources/icons/search_wrap.svg + resources/icons/settings.svg