#include "UserSettings.h" #include "AppConfig.h" #include #include #include #include #include #include namespace { const char kXor[] = "IM-Client-local"; QString encodeSecret(const QString &plain) { if (plain.isEmpty()) return QString(); QByteArray raw = plain.toUtf8(); const int kn = static_cast(sizeof(kXor) - 1); for (int i = 0; i < raw.size(); ++i) raw[i] = raw[i] ^ kXor[i % kn]; return QString::fromLatin1(raw.toBase64()); } QString decodeSecret(const QString &stored) { if (stored.isEmpty()) return QString(); QByteArray raw = QByteArray::fromBase64(stored.toLatin1()); const int kn = static_cast(sizeof(kXor) - 1); for (int i = 0; i < raw.size(); ++i) raw[i] = raw[i] ^ kXor[i % kn]; return QString::fromUtf8(raw); } void applyIniCodec(QSettings &ini) { #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) ini.setIniCodec("UTF-8"); #else Q_UNUSED(ini); #endif } } UserSettings &UserSettings::instance() { static UserSettings s; return s; } bool UserSettings::load() { QString dir; if (AppConfig::instance().loaded()) dir = QFileInfo(AppConfig::instance().path()).absolutePath(); else dir = QDir::cleanPath(QCoreApplication::applicationDirPath() + QStringLiteral("/config")); QDir().mkpath(dir); m_path = dir + QStringLiteral("/user.ini"); QSettings ini(m_path, QSettings::IniFormat); applyIniCodec(ini); m_account = ini.value(QStringLiteral("login/account")).toString().trimmed(); m_nickname = ini.value(QStringLiteral("login/nickname")).toString().trimmed(); m_rememberPassword = ini.value(QStringLiteral("login/remember_password"), false).toBool(); m_autoLogin = ini.value(QStringLiteral("login/auto_login"), false).toBool(); if (m_rememberPassword) m_password = decodeSecret(ini.value(QStringLiteral("login/password")).toString()); else m_password.clear(); if (!m_rememberPassword) m_autoLogin = false; m_fontPreset = ini.value(QStringLiteral("ui/font_preset")).toString().trimmed(); if (m_fontPreset.isEmpty()) { QSettings legacyNim(QStringLiteral("NIM"), QStringLiteral("Client")); m_fontPreset = legacyNim.value(QStringLiteral("ui/fontPreset")).toString(); if (m_fontPreset.isEmpty()) { QSettings legacyIm(QStringLiteral("IM"), QStringLiteral("Client")); m_fontPreset = legacyIm.value(QStringLiteral("ui/fontPreset"), QStringLiteral("system")).toString(); } if (m_fontPreset.isEmpty()) m_fontPreset = QStringLiteral("system"); persist(); } const int x = ini.value(QStringLiteral("window/x"), -1).toInt(); const int y = ini.value(QStringLiteral("window/y"), -1).toInt(); const int w = ini.value(QStringLiteral("window/w"), 0).toInt(); const int h = ini.value(QStringLiteral("window/h"), 0).toInt(); if (w > 0 && h > 0) m_windowRect = QRect(x, y, w, h); m_windowMaximized = ini.value(QStringLiteral("window/maximized"), false).toBool(); const QString closeAct = ini.value(QStringLiteral("window/close_action")).toString().trimmed(); if (closeAct == QLatin1String("tray")) m_closeAction = 1; else if (closeAct == QLatin1String("quit")) m_closeAction = 2; else m_closeAction = 0; return true; } void UserSettings::persist() const { if (m_path.isEmpty()) return; QSettings ini(m_path, QSettings::IniFormat); applyIniCodec(ini); ini.setValue(QStringLiteral("login/account"), m_account); ini.setValue(QStringLiteral("login/nickname"), m_nickname); ini.setValue(QStringLiteral("login/remember_password"), m_rememberPassword); ini.setValue(QStringLiteral("login/auto_login"), m_autoLogin && m_rememberPassword); ini.setValue(QStringLiteral("login/password"), m_rememberPassword ? encodeSecret(m_password) : QString()); ini.setValue(QStringLiteral("ui/font_preset"), m_fontPreset); if (m_windowRect.isValid()) { ini.setValue(QStringLiteral("window/x"), m_windowRect.x()); ini.setValue(QStringLiteral("window/y"), m_windowRect.y()); ini.setValue(QStringLiteral("window/w"), m_windowRect.width()); ini.setValue(QStringLiteral("window/h"), m_windowRect.height()); } ini.setValue(QStringLiteral("window/maximized"), m_windowMaximized); if (m_closeAction == 1) ini.setValue(QStringLiteral("window/close_action"), QStringLiteral("tray")); else if (m_closeAction == 2) ini.setValue(QStringLiteral("window/close_action"), QStringLiteral("quit")); else ini.remove(QStringLiteral("window/close_action")); ini.sync(); } void UserSettings::saveLogin(const QString &account, const QString &nickname, const QString &password, bool rememberPassword, bool autoLogin) { m_account = account.trimmed(); m_nickname = nickname.trimmed(); m_rememberPassword = rememberPassword && !password.isEmpty(); m_autoLogin = autoLogin && m_rememberPassword; m_password = m_rememberPassword ? password : QString(); persist(); } void UserSettings::setFontPreset(const QString &key) { m_fontPreset = key.isEmpty() ? QStringLiteral("system") : key; persist(); } void UserSettings::saveWindow(const QRect &rect, bool maximized) { if (rect.width() > 0 && rect.height() > 0) m_windowRect = rect; m_windowMaximized = maximized; persist(); } void UserSettings::setCloseAction(int action) { m_closeAction = (action == 1 || action == 2) ? action : 0; persist(); }