Skip to content
Snippets Groups Projects
UserSettingsPage.cpp 60.8 KiB
Newer Older
  • Learn to ignore specific revisions
  • Nicolas Werner's avatar
    Nicolas Werner committed
    // SPDX-FileCopyrightText: 2017 Konstantinos Sideris <siderisk@auth.gr>
    // SPDX-FileCopyrightText: 2021 Nheko Contributors
    
    // SPDX-FileCopyrightText: 2022 Nheko Contributors
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    //
    // SPDX-License-Identifier: GPL-3.0-or-later
    
    #include <QApplication>
    
    #include <QCoreApplication>
    
    #include <QFontDatabase>
    
    #include <QInputDialog>
    #include <QMessageBox>
    
    #include <QStandardPaths>
    
    #include <QTextStream>
    
    #include <mtx/secret_storage.hpp>
    
    #include "Config.h"
    
    #include "MainWindow.h"
    
    #include "UserSettingsPage.h"
    
    #include "Utils.h"
    
    #include "encryption/Olm.h"
    
    #include "ui/Theme.h"
    
    #include "voip/CallDevices.h"
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
    #include "config/nheko.h"
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    QSharedPointer<UserSettings> UserSettings::instance_;
    
    UserSettings::UserSettings()
    {
    
        connect(
          QCoreApplication::instance(), &QCoreApplication::aboutToQuit, []() { instance_.clear(); });
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    }
    
    QSharedPointer<UserSettings>
    UserSettings::instance()
    {
    
        return instance_;
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    }
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    UserSettings::initialize(std::optional<QString> profile)
    {
    
        instance_.reset(new UserSettings());
        instance_->load(profile);
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    }
    
    void
    UserSettings::load(std::optional<QString> profile)
    
        tray_        = settings.value(QStringLiteral("user/window/tray"), false).toBool();
        startInTray_ = settings.value(QStringLiteral("user/window/start_in_tray"), false).toBool();
    
        roomListWidth_ = settings.value(QStringLiteral("user/sidebar/room_list_width"), -1).toInt();
        communityListWidth_ =
          settings.value(QStringLiteral("user/sidebar/community_list_width"), -1).toInt();
    
        hasDesktopNotifications_ =
          settings.value(QStringLiteral("user/desktop_notifications"), true).toBool();
        hasAlertOnNotification_ =
          settings.value(QStringLiteral("user/alert_on_notification"), false).toBool();
        groupView_         = settings.value(QStringLiteral("user/group_view"), true).toBool();
        buttonsInTimeline_ = settings.value(QStringLiteral("user/timeline/buttons"), true).toBool();
        timelineMaxWidth_  = settings.value(QStringLiteral("user/timeline/max_width"), 0).toInt();
    
        messageHoverHighlight_ =
    
          settings.value(QStringLiteral("user/timeline/message_hover_highlight"), false).toBool();
    
        enlargeEmojiOnlyMessages_ =
    
          settings.value(QStringLiteral("user/timeline/enlarge_emoji_only_msg"), false).toBool();
    
        markdown_ = settings.value(QStringLiteral("user/markdown_enabled"), true).toBool();
    
        bubbles_  = settings.value(QStringLiteral("user/bubbles_enabled"), true).toBool();
    
        animateImagesOnHover_ =
          settings.value(QStringLiteral("user/animate_images_on_hover"), false).toBool();
        typingNotifications_ =
          settings.value(QStringLiteral("user/typing_notifications"), true).toBool();
        sortByImportance_ = settings.value(QStringLiteral("user/sort_by_unread"), true).toBool();
        readReceipts_     = settings.value(QStringLiteral("user/read_receipts"), true).toBool();
        theme_            = settings.value(QStringLiteral("user/theme"), defaultTheme_).toString();
        font_             = settings.value(QStringLiteral("user/font_family"), "default").toString();
        avatarCircles_    = settings.value(QStringLiteral("user/avatar_circles"), true).toBool();
        useIdenticon_     = settings.value(QStringLiteral("user/use_identicon"), true).toBool();
        decryptSidebar_   = settings.value(QStringLiteral("user/decrypt_sidebar"), true).toBool();
        privacyScreen_    = settings.value(QStringLiteral("user/privacy_screen"), false).toBool();
        privacyScreenTimeout_ =
          settings.value(QStringLiteral("user/privacy_screen_timeout"), 0).toInt();
        mobileMode_ = settings.value(QStringLiteral("user/mobile_mode"), false).toBool();
        emojiFont_  = settings.value(QStringLiteral("user/emoji_font_family"), "default").toString();
        baseFontSize_ =
          settings.value(QStringLiteral("user/font_size"), QFont().pointSizeF()).toDouble();
        auto tempPresence =
          settings.value(QStringLiteral("user/presence"), "").toString().toStdString();
        auto presenceValue = QMetaEnum::fromType<Presence>().keyToValue(tempPresence.c_str());
    
        if (presenceValue < 0)
            presenceValue = 0;
    
        presence_   = static_cast<Presence>(presenceValue);
        ringtone_   = settings.value(QStringLiteral("user/ringtone"), "Default").toString();
        microphone_ = settings.value(QStringLiteral("user/microphone"), QString()).toString();
        camera_     = settings.value(QStringLiteral("user/camera"), QString()).toString();
        cameraResolution_ =
          settings.value(QStringLiteral("user/camera_resolution"), QString()).toString();
        cameraFrameRate_ =
          settings.value(QStringLiteral("user/camera_frame_rate"), QString()).toString();
        screenShareFrameRate_ =
          settings.value(QStringLiteral("user/screen_share_frame_rate"), 5).toInt();
        screenSharePiP_ = settings.value(QStringLiteral("user/screen_share_pip"), true).toBool();
        screenShareRemoteVideo_ =
          settings.value(QStringLiteral("user/screen_share_remote_video"), false).toBool();
        screenShareHideCursor_ =
          settings.value(QStringLiteral("user/screen_share_hide_cursor"), false).toBool();
        useStunServer_ = settings.value(QStringLiteral("user/use_stun_server"), false).toBool();
    
    
        if (profile) // set to "" if it's the default to maintain compatibility
    
            profile_ = (*profile == QLatin1String("default")) ? QLatin1String("") : *profile;
    
            profile_ = settings.value(QStringLiteral("user/currentProfile"), "").toString();
    
        QString prefix = (profile_ != QLatin1String("") && profile_ != QLatin1String("default"))
                           ? "profile/" + profile_ + "/"
                           : QLatin1String("");
    
        accessToken_   = settings.value(prefix + "auth/access_token", "").toString();
        homeserver_    = settings.value(prefix + "auth/home_server", "").toString();
        userId_        = settings.value(prefix + "auth/user_id", "").toString();
        deviceId_      = settings.value(prefix + "auth/device_id", "").toString();
    
        hiddenTags_    = settings.value(prefix + "user/hidden_tags", QStringList{}).toStringList();
    
    Nicolas Werner's avatar
    Nicolas Werner committed
        hiddenPins_    = settings.value(prefix + "user/hidden_pins", QStringList{}).toStringList();
    
        recentReactions_ =
          settings.value(prefix + "user/recent_reactions", QStringList{}).toStringList();
    
    
        collapsedSpaces_.clear();
    
        auto tempSpaces = settings.value(prefix + "user/collapsed_spaces", QList<QVariant>{}).toList();
        for (const auto &e : qAsConst(tempSpaces))
    
            collapsedSpaces_.push_back(e.toStringList());
    
    
        shareKeysWithTrustedUsers_ =
          settings.value(prefix + "user/automatically_share_keys_with_trusted_users", false).toBool();
        onlyShareKeysWithVerifiedUsers_ =
          settings.value(prefix + "user/only_share_keys_with_verified_users", false).toBool();
        useOnlineKeyBackup_ = settings.value(prefix + "user/online_key_backup", false).toBool();
    
        disableCertificateValidation_ =
    
          settings.value(QStringLiteral("disable_certificate_validation"), false).toBool();
    
    
        applyTheme();
    
    void
    UserSettings::setMessageHoverHighlight(bool state)
    {
    
        if (state == messageHoverHighlight_)
            return;
        messageHoverHighlight_ = state;
        emit messageHoverHighlightChanged(state);
        save();
    
    }
    void
    UserSettings::setEnlargeEmojiOnlyMessages(bool state)
    {
    
        if (state == enlargeEmojiOnlyMessages_)
            return;
        enlargeEmojiOnlyMessages_ = state;
        emit enlargeEmojiOnlyMessagesChanged(state);
        save();
    
        if (state == tray_)
            return;
        tray_ = state;
        emit trayChanged(state);
        save();
    
        if (state == startInTray_)
            return;
        startInTray_ = state;
        emit startInTrayChanged(state);
        save();
    
    void
    UserSettings::setMobileMode(bool state)
    {
    
        if (state == mobileMode_)
            return;
        mobileMode_ = state;
        emit mobileModeChanged(state);
        save();
    
        if (groupView_ == state)
            return;
    
        groupView_ = state;
        emit groupViewStateChanged(state);
        save();
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    void
    UserSettings::setHiddenTags(QStringList hiddenTags)
    {
    
        hiddenTags_ = hiddenTags;
        save();
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    void
    UserSettings::setHiddenPins(QStringList hiddenTags)
    {
        hiddenPins_ = hiddenTags;
        save();
        emit hiddenPinsChanged();
    }
    
    
    void
    UserSettings::setRecentReactions(QStringList recent)
    {
        recentReactions_ = recent;
        save();
        emit recentReactionsChanged();
    }
    
    
    void
    UserSettings::setCollapsedSpaces(QList<QStringList> spaces)
    {
        collapsedSpaces_ = spaces;
        save();
    }
    
    
    UserSettings::setMarkdown(bool state)
    
        if (state == markdown_)
            return;
        markdown_ = state;
        emit markdownChanged(state);
        save();
    
    Malte E's avatar
    Malte E committed
    void
    UserSettings::setBubbles(bool state)
    {
        if (state == bubbles_)
            return;
        bubbles_ = state;
        emit bubblesChanged(state);
        save();
    }
    
    
    void
    UserSettings::setAnimateImagesOnHover(bool state)
    {
    
        if (state == animateImagesOnHover_)
            return;
        animateImagesOnHover_ = state;
        emit animateImagesOnHoverChanged(state);
        save();
    
    void
    UserSettings::setReadReceipts(bool state)
    {
    
        if (state == readReceipts_)
            return;
        readReceipts_ = state;
        emit readReceiptsChanged(state);
        save();
    
    }
    
    void
    UserSettings::setTypingNotifications(bool state)
    {
    
        if (state == typingNotifications_)
            return;
        typingNotifications_ = state;
        emit typingNotificationsChanged(state);
        save();
    
    }
    
    void
    UserSettings::setSortByImportance(bool state)
    {
    
        if (state == sortByImportance_)
            return;
        sortByImportance_ = state;
        emit roomSortingChanged(state);
        save();
    
    }
    
    void
    UserSettings::setButtonsInTimeline(bool state)
    {
    
        if (state == buttonsInTimeline_)
            return;
        buttonsInTimeline_ = state;
        emit buttonInTimelineChanged(state);
        save();
    
        if (state == timelineMaxWidth_)
            return;
        timelineMaxWidth_ = state;
        emit timelineMaxWidthChanged(state);
        save();
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    void
    UserSettings::setCommunityListWidth(int state)
    {
    
        if (state == communityListWidth_)
            return;
        communityListWidth_ = state;
        emit communityListWidthChanged(state);
        save();
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    }
    void
    UserSettings::setRoomListWidth(int state)
    {
    
        if (state == roomListWidth_)
            return;
        roomListWidth_ = state;
        emit roomListWidthChanged(state);
        save();
    
    
    void
    UserSettings::setDesktopNotifications(bool state)
    {
    
        if (state == hasDesktopNotifications_)
            return;
        hasDesktopNotifications_ = state;
        emit desktopNotificationsChanged(state);
        save();
    
    void
    UserSettings::setAlertOnNotification(bool state)
    {
    
        if (state == hasAlertOnNotification_)
            return;
        hasAlertOnNotification_ = state;
        emit alertOnNotificationChanged(state);
        save();
    
    void
    UserSettings::setAvatarCircles(bool state)
    {
    
        if (state == avatarCircles_)
            return;
        avatarCircles_ = state;
        emit avatarCirclesChanged(state);
        save();
    
        if (state == decryptSidebar_)
            return;
        decryptSidebar_ = state;
        emit decryptSidebarChanged(state);
        save();
    
    void
    UserSettings::setPrivacyScreen(bool state)
    {
    
        if (state == privacyScreen_) {
            return;
        }
        privacyScreen_ = state;
        emit privacyScreenChanged(state);
        save();
    
    }
    
    void
    UserSettings::setPrivacyScreenTimeout(int state)
    {
    
        if (state == privacyScreenTimeout_) {
            return;
        }
        privacyScreenTimeout_ = state;
        emit privacyScreenTimeoutChanged(state);
        save();
    
    void
    UserSettings::setFontSize(double size)
    {
    
        if (size == baseFontSize_)
            return;
        baseFontSize_ = size;
        emit fontSizeChanged(size);
        save();
    
    Joe Donofry's avatar
    Joe Donofry committed
    void
    UserSettings::setFontFamily(QString family)
    {
    
        if (family == font_)
            return;
        font_ = family;
        emit fontChanged(family);
        save();
    
    void
    UserSettings::setEmojiFontFamily(QString family)
    {
    
        if (family == emojiFont_)
            return;
    
        if (family == tr("Default")) {
    
            emojiFont_ = QStringLiteral("default");
    
        } else {
            emojiFont_ = family;
        }
    
        emit emojiFontChanged(family);
        save();
    
    void
    UserSettings::setPresence(Presence state)
    {
    
        if (state == presence_)
            return;
        presence_ = state;
        emit presenceChanged(state);
        save();
    
    void
    UserSettings::setTheme(QString theme)
    {
    
        if (theme == theme_)
            return;
        theme_ = theme;
        save();
        applyTheme();
        emit themeChanged(theme);
    
    trilene's avatar
    trilene committed
    void
    UserSettings::setUseStunServer(bool useStunServer)
    {
    
        if (useStunServer == useStunServer_)
            return;
        useStunServer_ = useStunServer;
        emit useStunServerChanged(useStunServer);
        save();
    
    trilene's avatar
    trilene committed
    }
    
    
    void
    UserSettings::setOnlyShareKeysWithVerifiedUsers(bool shareKeys)
    {
    
        if (shareKeys == onlyShareKeysWithVerifiedUsers_)
            return;
    
        onlyShareKeysWithVerifiedUsers_ = shareKeys;
        emit onlyShareKeysWithVerifiedUsersChanged(shareKeys);
        save();
    
    void
    UserSettings::setShareKeysWithTrustedUsers(bool shareKeys)
    {
    
        if (shareKeys == shareKeysWithTrustedUsers_)
            return;
    
        shareKeysWithTrustedUsers_ = shareKeys;
        emit shareKeysWithTrustedUsersChanged(shareKeys);
        save();
    
    void
    UserSettings::setUseOnlineKeyBackup(bool useBackup)
    {
    
        if (useBackup == useOnlineKeyBackup_)
            return;
    
        useOnlineKeyBackup_ = useBackup;
        emit useOnlineKeyBackupChanged(useBackup);
        save();
    
    void
    UserSettings::setRingtone(QString ringtone)
    {
    
        if (ringtone == ringtone_)
            return;
        ringtone_ = ringtone;
        emit ringtoneChanged(ringtone);
        save();
    
    void
    
    trilene's avatar
    trilene committed
    UserSettings::setMicrophone(QString microphone)
    
        if (microphone == microphone_)
            return;
        microphone_ = microphone;
        emit microphoneChanged(microphone);
        save();
    
    trilene's avatar
    trilene committed
    }
    
    void
    UserSettings::setCamera(QString camera)
    {
    
        if (camera == camera_)
            return;
        camera_ = camera;
        emit cameraChanged(camera);
        save();
    
    trilene's avatar
    trilene committed
    }
    
    void
    UserSettings::setCameraResolution(QString resolution)
    {
    
        if (resolution == cameraResolution_)
            return;
        cameraResolution_ = resolution;
        emit cameraResolutionChanged(resolution);
        save();
    
    trilene's avatar
    trilene committed
    }
    
    void
    UserSettings::setCameraFrameRate(QString frameRate)
    {
    
        if (frameRate == cameraFrameRate_)
            return;
        cameraFrameRate_ = frameRate;
        emit cameraFrameRateChanged(frameRate);
        save();
    
    void
    UserSettings::setScreenShareFrameRate(int frameRate)
    {
    
        if (frameRate == screenShareFrameRate_)
            return;
        screenShareFrameRate_ = frameRate;
        emit screenShareFrameRateChanged(frameRate);
        save();
    
    void
    UserSettings::setScreenSharePiP(bool state)
    {
    
        if (state == screenSharePiP_)
            return;
        screenSharePiP_ = state;
        emit screenSharePiPChanged(state);
        save();
    
    void
    UserSettings::setScreenShareRemoteVideo(bool state)
    {
    
        if (state == screenShareRemoteVideo_)
            return;
        screenShareRemoteVideo_ = state;
        emit screenShareRemoteVideoChanged(state);
        save();
    
    void
    UserSettings::setScreenShareHideCursor(bool state)
    {
    
        if (state == screenShareHideCursor_)
            return;
        screenShareHideCursor_ = state;
        emit screenShareHideCursorChanged(state);
        save();
    
    void
    UserSettings::setProfile(QString profile)
    {
    
        if (profile == profile_)
            return;
        profile_ = profile;
        emit profileChanged(profile_);
        save();
    
    }
    
    void
    UserSettings::setUserId(QString userId)
    {
    
        if (userId == userId_)
            return;
        userId_ = userId;
        emit userIdChanged(userId_);
        save();
    
    }
    
    void
    UserSettings::setAccessToken(QString accessToken)
    {
    
        if (accessToken == accessToken_)
            return;
        accessToken_ = accessToken;
        emit accessTokenChanged(accessToken_);
        save();
    
    }
    
    void
    UserSettings::setDeviceId(QString deviceId)
    {
    
        if (deviceId == deviceId_)
            return;
        deviceId_ = deviceId;
        emit deviceIdChanged(deviceId_);
        save();
    
    }
    
    void
    UserSettings::setHomeserver(QString homeserver)
    {
    
        if (homeserver == homeserver_)
            return;
        homeserver_ = homeserver;
        emit homeserverChanged(homeserver_);
        save();
    
    void
    UserSettings::setDisableCertificateValidation(bool disabled)
    {
    
        if (disabled == disableCertificateValidation_)
            return;
        disableCertificateValidation_ = disabled;
        http::client()->verify_certificates(!disabled);
        emit disableCertificateValidationChanged(disabled);
    
    Loren Burkholder's avatar
    Loren Burkholder committed
    }
    
    void
    UserSettings::setUseIdenticon(bool state)
    {
    
        if (state == useIdenticon_)
            return;
        useIdenticon_ = state;
        emit useIdenticonChanged(useIdenticon_);
        save();
    
    void
    UserSettings::applyTheme()
    {
    
        QFile stylefile;
    
        if (this->theme() == QLatin1String("light")) {
            stylefile.setFileName(QStringLiteral(":/styles/styles/nheko.qss"));
        } else if (this->theme() == QLatin1String("dark")) {
            stylefile.setFileName(QStringLiteral(":/styles/styles/nheko-dark.qss"));
    
        } else {
    
            stylefile.setFileName(QStringLiteral(":/styles/styles/system.qss"));
    
        QApplication::setPalette(Theme::paletteFromTheme(this->theme()));
    
        stylefile.open(QFile::ReadOnly);
        QString stylesheet = QString(stylefile.readAll());
    
        qobject_cast<QApplication *>(QApplication::instance())->setStyleSheet(stylesheet);
    
    }
    
    void
    UserSettings::save()
    {
    
        settings.beginGroup(QStringLiteral("user"));
    
        settings.beginGroup(QStringLiteral("window"));
        settings.setValue(QStringLiteral("tray"), tray_);
        settings.setValue(QStringLiteral("start_in_tray"), startInTray_);
    
        settings.endGroup(); // window
    
    
        settings.beginGroup(QStringLiteral("sidebar"));
        settings.setValue(QStringLiteral("community_list_width"), communityListWidth_);
        settings.setValue(QStringLiteral("room_list_width"), roomListWidth_);
    
        settings.endGroup(); // window
    
    
        settings.beginGroup(QStringLiteral("timeline"));
        settings.setValue(QStringLiteral("buttons"), buttonsInTimeline_);
        settings.setValue(QStringLiteral("message_hover_highlight"), messageHoverHighlight_);
        settings.setValue(QStringLiteral("enlarge_emoji_only_msg"), enlargeEmojiOnlyMessages_);
        settings.setValue(QStringLiteral("max_width"), timelineMaxWidth_);
    
        settings.endGroup(); // timeline
    
    
        settings.setValue(QStringLiteral("avatar_circles"), avatarCircles_);
        settings.setValue(QStringLiteral("decrypt_sidebar"), decryptSidebar_);
        settings.setValue(QStringLiteral("privacy_screen"), privacyScreen_);
        settings.setValue(QStringLiteral("privacy_screen_timeout"), privacyScreenTimeout_);
        settings.setValue(QStringLiteral("mobile_mode"), mobileMode_);
        settings.setValue(QStringLiteral("font_size"), baseFontSize_);
        settings.setValue(QStringLiteral("typing_notifications"), typingNotifications_);
        settings.setValue(QStringLiteral("sort_by_unread"), sortByImportance_);
        settings.setValue(QStringLiteral("minor_events"), sortByImportance_);
        settings.setValue(QStringLiteral("read_receipts"), readReceipts_);
        settings.setValue(QStringLiteral("group_view"), groupView_);
        settings.setValue(QStringLiteral("markdown_enabled"), markdown_);
    
    Malte E's avatar
    Malte E committed
        settings.setValue(QStringLiteral("bubbles_enabled"), bubbles_);
    
        settings.setValue(QStringLiteral("animate_images_on_hover"), animateImagesOnHover_);
        settings.setValue(QStringLiteral("desktop_notifications"), hasDesktopNotifications_);
        settings.setValue(QStringLiteral("alert_on_notification"), hasAlertOnNotification_);
        settings.setValue(QStringLiteral("theme"), theme());
        settings.setValue(QStringLiteral("font_family"), font_);
        settings.setValue(QStringLiteral("emoji_font_family"), emojiFont_);
    
        settings.setValue(
    
          QStringLiteral("presence"),
    
          QString::fromUtf8(QMetaEnum::fromType<Presence>().valueToKey(static_cast<int>(presence_))));
    
        settings.setValue(QStringLiteral("ringtone"), ringtone_);
        settings.setValue(QStringLiteral("microphone"), microphone_);
        settings.setValue(QStringLiteral("camera"), camera_);
        settings.setValue(QStringLiteral("camera_resolution"), cameraResolution_);
        settings.setValue(QStringLiteral("camera_frame_rate"), cameraFrameRate_);
        settings.setValue(QStringLiteral("screen_share_frame_rate"), screenShareFrameRate_);
        settings.setValue(QStringLiteral("screen_share_pip"), screenSharePiP_);
        settings.setValue(QStringLiteral("screen_share_remote_video"), screenShareRemoteVideo_);
        settings.setValue(QStringLiteral("screen_share_hide_cursor"), screenShareHideCursor_);
        settings.setValue(QStringLiteral("use_stun_server"), useStunServer_);
        settings.setValue(QStringLiteral("currentProfile"), profile_);
        settings.setValue(QStringLiteral("use_identicon"), useIdenticon_);
    
    
        settings.endGroup(); // user
    
    
        QString prefix = (profile_ != QLatin1String("") && profile_ != QLatin1String("default"))
                           ? "profile/" + profile_ + "/"
                           : QLatin1String("");
    
        settings.setValue(prefix + "auth/access_token", accessToken_);
        settings.setValue(prefix + "auth/home_server", homeserver_);
        settings.setValue(prefix + "auth/user_id", userId_);
        settings.setValue(prefix + "auth/device_id", deviceId_);
    
        settings.setValue(prefix + "user/automatically_share_keys_with_trusted_users",
                          shareKeysWithTrustedUsers_);
        settings.setValue(prefix + "user/only_share_keys_with_verified_users",
                          onlyShareKeysWithVerifiedUsers_);
        settings.setValue(prefix + "user/online_key_backup", useOnlineKeyBackup_);
    
        settings.setValue(prefix + "user/hidden_tags", hiddenTags_);
    
    Nicolas Werner's avatar
    Nicolas Werner committed
        settings.setValue(prefix + "user/hidden_pins", hiddenPins_);
    
        settings.setValue(prefix + "user/recent_reactions", recentReactions_);
    
    
        QVariantList v;
    
        v.reserve(collapsedSpaces_.size());
    
        for (const auto &e : qAsConst(collapsedSpaces_))
    
            v.push_back(e);
        settings.setValue(prefix + "user/collapsed_spaces", v);
    
        settings.setValue(QStringLiteral("disable_certificate_validation"),
                          disableCertificateValidation_);
    
    
        settings.sync();
    
    QHash<int, QByteArray>
    UserSettingsModel::roleNames() const
    {
        static QHash<int, QByteArray> roles{
          {Name, "name"},
          {Description, "description"},
          {Value, "value"},
          {Type, "type"},
          {ValueLowerBound, "valueLowerBound"},
          {ValueUpperBound, "valueUpperBound"},
          {ValueStep, "valueStep"},
          {Values, "values"},
          {Good, "good"},
          {Enabled, "enabled"},
        };
    
        return roles;
    }
    
    QVariant
    UserSettingsModel::data(const QModelIndex &index, int role) const
    {
        if (index.row() >= COUNT)
            return {};
    
        auto i = UserSettings::instance();
        if (!i)
            return {};
    
        if (role == Name) {
            switch (index.row()) {
            case Theme:
                return tr("Theme");
            case ScaleFactor:
                return tr("Scale factor");
            case MessageHoverHighlight:
                return tr("Highlight message on hover");
            case EnlargeEmojiOnlyMessages:
                return tr("Large Emoji in timeline");
            case Tray:
                return tr("Minimize to tray");
            case StartInTray:
                return tr("Start in tray");
            case GroupView:
                return tr("Group's sidebar");
            case Markdown:
                return tr("Send messages as Markdown");
    
    Malte E's avatar
    Malte E committed
            case Bubbles:
    
    Malte E's avatar
    Malte E committed
                return tr("Enable message bubbles");
    
            case AnimateImagesOnHover:
                return tr("Play animated images only on hover");
            case TypingNotifications:
                return tr("Typing notifications");
            case SortByImportance:
                return tr("Sort rooms by unreads");
            case ButtonsInTimeline:
                return tr("Show buttons in timeline");
            case TimelineMaxWidth:
                return tr("Limit width of timeline");
            case ReadReceipts:
                return tr("Read receipts");
            case DesktopNotifications:
                return tr("Desktop notifications");
            case AlertOnNotification:
                return tr("Alert on notification");
            case AvatarCircles:
                return tr("Circular Avatars");
            case UseIdenticon:
                return tr("Use identicons");
            case DecryptSidebar:
                return tr("Decrypt messages in sidebar");
            case PrivacyScreen:
                return tr("Privacy Screen");
            case PrivacyScreenTimeout:
                return tr("Privacy screen timeout (in seconds [0 - 3600])");
            case MobileMode:
                return tr("Touchscreen mode");
            case FontSize:
                return tr("Font size");
            case Font:
                return tr("Font Family");
            case EmojiFont:
                return tr("Emoji Font Family");
            case Ringtone:
                return tr("Ringtone");
            case Microphone:
                return tr("Microphone");
            case Camera:
                return tr("Camera");
            case CameraResolution:
                return tr("Camera resolution");
            case CameraFrameRate:
                return tr("Camera frame rate");
            case UseStunServer:
                return tr("Allow fallback call assist server");
            case OnlyShareKeysWithVerifiedUsers:
                return tr("Send encrypted messages to verified users only");
            case ShareKeysWithTrustedUsers:
                return tr("Share keys with verified users and devices");
            case UseOnlineKeyBackup:
                return tr("Online Key Backup");
            case Profile:
                return tr("Profile");
            case UserId:
                return tr("User ID");
            case AccessToken:
                return tr("Accesstoken");
            case DeviceId:
                return tr("Device ID");
            case DeviceFingerprint:
                return tr("Device Fingerprint");
            case Homeserver:
                return tr("Homeserver");
            case Version:
                return tr("Version");
            case Platform:
                return tr("Platform");
            case GeneralSection:
                return tr("GENERAL");
            case TimelineSection:
                return tr("TIMELINE");
            case SidebarSection:
                return tr("SIDEBAR");
            case TraySection:
                return tr("TRAY");
            case NotificationsSection:
                return tr("NOTIFICATIONS");
            case VoipSection:
                return tr("CALLS");
            case EncryptionSection:
                return tr("ENCRYPTION");
            case LoginInfoSection:
                return tr("INFO");
            case SessionKeys:
                return tr("Session Keys");
            case CrossSigningSecrets:
                return tr("Cross Signing Secrets");
            case OnlineBackupKey:
                return tr("Online backup key");
            case SelfSigningKey:
                return tr("Self signing key");
            case UserSigningKey:
                return tr("User signing key");
            case MasterKey:
                return tr("Master signing key");
    
        } else if (role == Value) {
            switch (index.row()) {
            case Theme:
                return QStringList{
                  QStringLiteral("light"),
                  QStringLiteral("dark"),
                  QStringLiteral("system"),
    
                  .indexOf(i->theme());
            case ScaleFactor:
                return utils::scaleFactor();
            case MessageHoverHighlight:
                return i->messageHoverHighlight();
            case EnlargeEmojiOnlyMessages:
                return i->enlargeEmojiOnlyMessages();
            case Tray:
                return i->tray();
            case StartInTray:
                return i->startInTray();
            case GroupView:
                return i->groupView();
            case Markdown:
                return i->markdown();
    
    Malte E's avatar
    Malte E committed
            case Bubbles:
                return i->bubbles();
    
            case AnimateImagesOnHover:
                return i->animateImagesOnHover();
            case TypingNotifications:
                return i->typingNotifications();
            case SortByImportance:
                return i->sortByImportance();
            case ButtonsInTimeline:
                return i->buttonsInTimeline();
            case TimelineMaxWidth:
                return i->timelineMaxWidth();
            case ReadReceipts:
                return i->readReceipts();
            case DesktopNotifications:
                return i->hasDesktopNotifications();
            case AlertOnNotification:
                return i->hasAlertOnNotification();
            case AvatarCircles:
                return i->avatarCircles();
            case UseIdenticon:
                return i->useIdenticon();
            case DecryptSidebar:
                return i->decryptSidebar();
            case PrivacyScreen:
                return i->privacyScreen();
            case PrivacyScreenTimeout:
                return i->privacyScreenTimeout();
            case MobileMode:
                return i->mobileMode();
            case FontSize:
                return i->fontSize();
            case Font:
                return data(index, Values).toStringList().indexOf(i->font());
            case EmojiFont:
                return data(index, Values).toStringList().indexOf(i->emojiFont());
            case Ringtone: {
                auto v = i->ringtone();
                if (v == QStringView(u"Mute"))
                    return 0;
                else if (v == QStringView(u"Default"))
                    return 1;
                else if (v == QStringView(u"Other"))
                    return 2;
                else
                    return 3;
    
            case Microphone:
                return data(index, Values).toStringList().indexOf(i->microphone());
            case Camera:
                return data(index, Values).toStringList().indexOf(i->camera());
            case CameraResolution:
                return data(index, Values).toStringList().indexOf(i->cameraResolution());
            case CameraFrameRate:
                return data(index, Values).toStringList().indexOf(i->cameraFrameRate());
            case UseStunServer:
                return i->useStunServer();
            case OnlyShareKeysWithVerifiedUsers:
                return i->onlyShareKeysWithVerifiedUsers();
            case ShareKeysWithTrustedUsers:
                return i->shareKeysWithTrustedUsers();
            case UseOnlineKeyBackup:
                return i->useOnlineKeyBackup();
            case Profile:
                return i->profile().isEmpty() ? tr("Default") : i->profile();
            case UserId:
                return i->userId();
            case AccessToken: