main.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. #include <QDebug>
  2. #include <QTextCodec>
  3. #include <QSslSocket>
  4. #include <QLocale>
  5. #include <QTranslator>
  6. #include <QScopedPointer>
  7. #include <QOpenGLContext>
  8. #include <QDateTime>
  9. #include <QSysInfo>
  10. #include <QProcess>
  11. #include <QWebEngineSettings>
  12. #include <QWindow>
  13. #include <QAccessible>
  14. #include <core/configmgr.h>
  15. #include <core/mainconfig.h>
  16. #include <core/coreconfig.h>
  17. #include <core/sessionconfig.h>
  18. #include <core/singleinstanceguard.h>
  19. #include <core/vnotex.h>
  20. #include <core/logger.h>
  21. #include <widgets/mainwindow.h>
  22. #include <core/exception.h>
  23. #include <utils/widgetutils.h>
  24. #include <widgets/messageboxhelper.h>
  25. #include "commandlineoptions.h"
  26. #include "application.h"
  27. #include "fakeaccessible.h"
  28. using namespace vnotex;
  29. void loadTranslators(QApplication &p_app);
  30. void showMessageOnCommandLineIfAvailable(const QString &p_msg);
  31. int main(int argc, char *argv[])
  32. {
  33. QTextCodec *codec = QTextCodec::codecForName("UTF8");
  34. if (codec) {
  35. QTextCodec::setCodecForLocale(codec);
  36. }
  37. QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
  38. // This only takes effect on Win, X11 and Android.
  39. QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
  40. // Set OpenGL option on Windows.
  41. // Set environment QT_OPENGL to "angle/desktop/software".
  42. #if defined(Q_OS_WIN)
  43. {
  44. auto option = SessionConfig::getOpenGLAtBootstrap();
  45. qDebug() << "OpenGL option" << SessionConfig::openGLToString(option);
  46. switch (option) {
  47. case SessionConfig::OpenGL::Desktop:
  48. QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL);
  49. break;
  50. case SessionConfig::OpenGL::Angle:
  51. QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
  52. break;
  53. case SessionConfig::OpenGL::Software:
  54. QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
  55. break;
  56. default:
  57. break;
  58. }
  59. }
  60. #endif
  61. #if defined(Q_OS_LINUX)
  62. // Disable sandbox on Linux.
  63. qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--no-sandbox");
  64. #endif
  65. Application app(argc, argv);
  66. QAccessible::installFactory(&FakeAccessible::accessibleFactory);
  67. {
  68. const QString iconPath = ":/vnotex/data/core/icons/vnote.ico";
  69. // Make sense only on Windows.
  70. app.setWindowIcon(QIcon(iconPath));
  71. app.setApplicationName(ConfigMgr::c_appName);
  72. app.setOrganizationName(ConfigMgr::c_orgName);
  73. app.setApplicationVersion(ConfigMgr::getApplicationVersion());
  74. }
  75. CommandLineOptions cmdOptions;
  76. switch (cmdOptions.parse(app.arguments())) {
  77. case CommandLineOptions::Ok:
  78. break;
  79. case CommandLineOptions::Error:
  80. fprintf(stderr, "%s\n", qPrintable(cmdOptions.m_errorMsg));
  81. // Arguments to WebEngineView will be unknown ones. So just let it go.
  82. break;
  83. case CommandLineOptions::VersionRequested:
  84. {
  85. auto versionStr = QString("%1 %2").arg(app.applicationName()).arg(app.applicationVersion());
  86. showMessageOnCommandLineIfAvailable(versionStr);
  87. return 0;
  88. }
  89. case CommandLineOptions::HelpRequested:
  90. Q_FALLTHROUGH();
  91. default:
  92. showMessageOnCommandLineIfAvailable(cmdOptions.m_helpText);
  93. return 0;
  94. }
  95. // Guarding.
  96. SingleInstanceGuard guard;
  97. bool canRun = guard.tryRun();
  98. if (!canRun) {
  99. guard.requestOpenFiles(cmdOptions.m_pathsToOpen);
  100. guard.requestShow();
  101. return 0;
  102. }
  103. try {
  104. ConfigMgr::getInst();
  105. } catch (Exception &e) {
  106. MessageBoxHelper::notify(MessageBoxHelper::Critical,
  107. MainWindow::tr("%1 failed to start.").arg(ConfigMgr::c_appName),
  108. MainWindow::tr("Failed to initialize configuration manager. "
  109. "Please check if all the files are intact or reinstall the application."),
  110. e.what());
  111. return -1;
  112. }
  113. // Init logger after app info is set.
  114. Logger::init(cmdOptions.m_verbose);
  115. qInfo() << QString("%1 (v%2) started at %3 (%4)").arg(ConfigMgr::c_appName,
  116. app.applicationVersion(),
  117. QDateTime::currentDateTime().toString(),
  118. QSysInfo::productType());
  119. qInfo() << "OpenSSL build version:" << QSslSocket::sslLibraryBuildVersionString()
  120. << "link version:" << QSslSocket::sslLibraryVersionString();
  121. if (QSslSocket::sslLibraryBuildVersionNumber() != QSslSocket::sslLibraryVersionNumber()) {
  122. qWarning() << "versions of the built and linked OpenSSL mismatch, network may not work";
  123. }
  124. // Should set the correct locale before VNoteX::getInst().
  125. loadTranslators(app);
  126. MainWindow window;
  127. window.show();
  128. QObject::connect(&guard, &SingleInstanceGuard::showRequested,
  129. &window, &MainWindow::showMainWindow);
  130. QObject::connect(&guard, &SingleInstanceGuard::openFilesRequested,
  131. &window, &MainWindow::openFiles);
  132. QObject::connect(&app, &Application::openFileRequested,
  133. &window, [&window](const QString &p_filePath) {
  134. window.openFiles(QStringList() << p_filePath);
  135. });
  136. // Let MainWindow show first to decide the screen on which app is running.
  137. WidgetUtils::calculateScaleFactor(window.windowHandle()->screen());
  138. if (app.styleSheet().isEmpty()) {
  139. auto style = VNoteX::getInst().getThemeMgr().fetchQtStyleSheet();
  140. if (!style.isEmpty()) {
  141. app.setStyleSheet(style);
  142. WidgetUtils::updateStyle(&window);
  143. }
  144. }
  145. VNoteX::getInst().getThemeMgr().setBaseBackground(window.palette().color(QPalette::Base));
  146. window.kickOffOnStart(cmdOptions.m_pathsToOpen);
  147. int ret = app.exec();
  148. if (ret == RESTART_EXIT_CODE) {
  149. // Asked to restart VNote.
  150. guard.exit();
  151. QProcess::startDetached(QCoreApplication::applicationFilePath(), QStringList());
  152. // Must use exit() in Linux to quit the parent process in Qt 5.12.
  153. // Thanks to @ygcaicn.
  154. exit(0);
  155. return 0;
  156. }
  157. return ret;
  158. }
  159. void loadTranslators(QApplication &p_app)
  160. {
  161. auto localeName = ConfigMgr::getInst().getCoreConfig().getLocale();
  162. if (!localeName.isEmpty()) {
  163. QLocale::setDefault(QLocale(localeName));
  164. }
  165. QLocale locale;
  166. qInfo() << "locale:" << locale.name();
  167. const QString resourceTranslationFolder(QStringLiteral(":/vnotex/data/core/translations"));
  168. const QString envTranslationFolder(QStringLiteral("translations"));
  169. // For QTextEdit/QTextBrowser and other basic widgets.
  170. QScopedPointer<QTranslator> qtbaseTranslator(new QTranslator(&p_app));
  171. if (qtbaseTranslator->load(locale, "qtbase", "_", resourceTranslationFolder)) {
  172. p_app.installTranslator(qtbaseTranslator.take());
  173. }
  174. // qt_zh_CN.ts does not cover the real QDialogButtonBox which uses QPlatformTheme.
  175. QScopedPointer<QTranslator> dialogButtonBoxTranslator(new QTranslator(&p_app));
  176. if (dialogButtonBoxTranslator->load(locale, "qdialogbuttonbox", "_", resourceTranslationFolder)) {
  177. p_app.installTranslator(dialogButtonBoxTranslator.take());
  178. }
  179. QScopedPointer<QTranslator> webengineTranslator(new QTranslator(&p_app));
  180. if (webengineTranslator->load(locale, "qwebengine", "_", resourceTranslationFolder)) {
  181. p_app.installTranslator(webengineTranslator.take());
  182. }
  183. // Load translation for Qt from resource.
  184. QScopedPointer<QTranslator> qtTranslator(new QTranslator(&p_app));
  185. if (qtTranslator->load(locale, "qt", "_", resourceTranslationFolder)) {
  186. p_app.installTranslator(qtTranslator.take());
  187. }
  188. // Load translation for Qt from env.
  189. QScopedPointer<QTranslator> qtEnvTranslator(new QTranslator(&p_app));
  190. if (qtEnvTranslator->load(locale, "qt", "_", envTranslationFolder)) {
  191. p_app.installTranslator(qtEnvTranslator.take());
  192. }
  193. // Load translation for vnote from resource.
  194. QScopedPointer<QTranslator> vnoteTranslator(new QTranslator(&p_app));
  195. if (vnoteTranslator->load(locale, "vnote", "_", resourceTranslationFolder)) {
  196. p_app.installTranslator(vnoteTranslator.take());
  197. }
  198. // Load translation for vtextedit from resource.
  199. QScopedPointer<QTranslator> vtexteditTranslator(new QTranslator(&p_app));
  200. if (vtexteditTranslator->load(locale, "vtextedit", "_", resourceTranslationFolder)) {
  201. p_app.installTranslator(vtexteditTranslator.take());
  202. }
  203. }
  204. void showMessageOnCommandLineIfAvailable(const QString &p_msg)
  205. {
  206. #if defined(Q_OS_WIN)
  207. MessageBoxHelper::notify(MessageBoxHelper::Information,
  208. QString("<pre>%1</pre>").arg(p_msg));
  209. #else
  210. fprintf(stderr, "%s\n", qPrintable(p_msg));
  211. #endif
  212. }