UserSettings.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. #include "UserSettings.h"
  2. #include "AppConfig.h"
  3. #include <QCoreApplication>
  4. #include <QDir>
  5. #include <QFileInfo>
  6. #include <QRect>
  7. #include <QSettings>
  8. #include <QtGlobal>
  9. namespace
  10. {
  11. const char kXor[] = "IM-Client-local";
  12. QString encodeSecret(const QString &plain)
  13. {
  14. if (plain.isEmpty())
  15. return QString();
  16. QByteArray raw = plain.toUtf8();
  17. const int kn = static_cast<int>(sizeof(kXor) - 1);
  18. for (int i = 0; i < raw.size(); ++i)
  19. raw[i] = raw[i] ^ kXor[i % kn];
  20. return QString::fromLatin1(raw.toBase64());
  21. }
  22. QString decodeSecret(const QString &stored)
  23. {
  24. if (stored.isEmpty())
  25. return QString();
  26. QByteArray raw = QByteArray::fromBase64(stored.toLatin1());
  27. const int kn = static_cast<int>(sizeof(kXor) - 1);
  28. for (int i = 0; i < raw.size(); ++i)
  29. raw[i] = raw[i] ^ kXor[i % kn];
  30. return QString::fromUtf8(raw);
  31. }
  32. void applyIniCodec(QSettings &ini)
  33. {
  34. #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
  35. ini.setIniCodec("UTF-8");
  36. #else
  37. Q_UNUSED(ini);
  38. #endif
  39. }
  40. }
  41. UserSettings &UserSettings::instance()
  42. {
  43. static UserSettings s;
  44. return s;
  45. }
  46. bool UserSettings::load()
  47. {
  48. QString dir;
  49. if (AppConfig::instance().loaded())
  50. dir = QFileInfo(AppConfig::instance().path()).absolutePath();
  51. else
  52. dir = QDir::cleanPath(QCoreApplication::applicationDirPath() + QStringLiteral("/config"));
  53. QDir().mkpath(dir);
  54. m_path = dir + QStringLiteral("/user.ini");
  55. QSettings ini(m_path, QSettings::IniFormat);
  56. applyIniCodec(ini);
  57. m_account = ini.value(QStringLiteral("login/account")).toString().trimmed();
  58. m_nickname = ini.value(QStringLiteral("login/nickname")).toString().trimmed();
  59. m_rememberPassword = ini.value(QStringLiteral("login/remember_password"), false).toBool();
  60. m_autoLogin = ini.value(QStringLiteral("login/auto_login"), false).toBool();
  61. if (m_rememberPassword)
  62. m_password = decodeSecret(ini.value(QStringLiteral("login/password")).toString());
  63. else
  64. m_password.clear();
  65. if (!m_rememberPassword)
  66. m_autoLogin = false;
  67. m_fontPreset = ini.value(QStringLiteral("ui/font_preset")).toString().trimmed();
  68. if (m_fontPreset.isEmpty())
  69. {
  70. QSettings legacyNim(QStringLiteral("NIM"), QStringLiteral("Client"));
  71. m_fontPreset = legacyNim.value(QStringLiteral("ui/fontPreset")).toString();
  72. if (m_fontPreset.isEmpty())
  73. {
  74. QSettings legacyIm(QStringLiteral("IM"), QStringLiteral("Client"));
  75. m_fontPreset = legacyIm.value(QStringLiteral("ui/fontPreset"), QStringLiteral("system")).toString();
  76. }
  77. if (m_fontPreset.isEmpty())
  78. m_fontPreset = QStringLiteral("system");
  79. persist();
  80. }
  81. const int x = ini.value(QStringLiteral("window/x"), -1).toInt();
  82. const int y = ini.value(QStringLiteral("window/y"), -1).toInt();
  83. const int w = ini.value(QStringLiteral("window/w"), 0).toInt();
  84. const int h = ini.value(QStringLiteral("window/h"), 0).toInt();
  85. if (w > 0 && h > 0)
  86. m_windowRect = QRect(x, y, w, h);
  87. m_windowMaximized = ini.value(QStringLiteral("window/maximized"), false).toBool();
  88. const QString closeAct = ini.value(QStringLiteral("window/close_action")).toString().trimmed();
  89. if (closeAct == QLatin1String("tray"))
  90. m_closeAction = 1;
  91. else if (closeAct == QLatin1String("quit"))
  92. m_closeAction = 2;
  93. else
  94. m_closeAction = 0;
  95. return true;
  96. }
  97. void UserSettings::persist() const
  98. {
  99. if (m_path.isEmpty())
  100. return;
  101. QSettings ini(m_path, QSettings::IniFormat);
  102. applyIniCodec(ini);
  103. ini.setValue(QStringLiteral("login/account"), m_account);
  104. ini.setValue(QStringLiteral("login/nickname"), m_nickname);
  105. ini.setValue(QStringLiteral("login/remember_password"), m_rememberPassword);
  106. ini.setValue(QStringLiteral("login/auto_login"), m_autoLogin && m_rememberPassword);
  107. ini.setValue(QStringLiteral("login/password"),
  108. m_rememberPassword ? encodeSecret(m_password) : QString());
  109. ini.setValue(QStringLiteral("ui/font_preset"), m_fontPreset);
  110. if (m_windowRect.isValid())
  111. {
  112. ini.setValue(QStringLiteral("window/x"), m_windowRect.x());
  113. ini.setValue(QStringLiteral("window/y"), m_windowRect.y());
  114. ini.setValue(QStringLiteral("window/w"), m_windowRect.width());
  115. ini.setValue(QStringLiteral("window/h"), m_windowRect.height());
  116. }
  117. ini.setValue(QStringLiteral("window/maximized"), m_windowMaximized);
  118. if (m_closeAction == 1)
  119. ini.setValue(QStringLiteral("window/close_action"), QStringLiteral("tray"));
  120. else if (m_closeAction == 2)
  121. ini.setValue(QStringLiteral("window/close_action"), QStringLiteral("quit"));
  122. else
  123. ini.remove(QStringLiteral("window/close_action"));
  124. ini.sync();
  125. }
  126. void UserSettings::saveLogin(const QString &account, const QString &nickname,
  127. const QString &password, bool rememberPassword, bool autoLogin)
  128. {
  129. m_account = account.trimmed();
  130. m_nickname = nickname.trimmed();
  131. m_rememberPassword = rememberPassword && !password.isEmpty();
  132. m_autoLogin = autoLogin && m_rememberPassword;
  133. m_password = m_rememberPassword ? password : QString();
  134. persist();
  135. }
  136. void UserSettings::setFontPreset(const QString &key)
  137. {
  138. m_fontPreset = key.isEmpty() ? QStringLiteral("system") : key;
  139. persist();
  140. }
  141. void UserSettings::saveWindow(const QRect &rect, bool maximized)
  142. {
  143. if (rect.width() > 0 && rect.height() > 0)
  144. m_windowRect = rect;
  145. m_windowMaximized = maximized;
  146. persist();
  147. }
  148. void UserSettings::setCloseAction(int action)
  149. {
  150. m_closeAction = (action == 1 || action == 2) ? action : 0;
  151. persist();
  152. }