diff options
author | Nicolas Werner <nicolas.werner@hotmail.de> | 2021-09-18 00:22:33 +0200 |
---|---|---|
committer | Nicolas Werner <nicolas.werner@hotmail.de> | 2021-09-18 00:45:50 +0200 |
commit | cfca7157b98c9dc8e0852fe6484bc3f75008af7d (patch) | |
tree | 32b92340908a9374214ec7b84c1fac7ea338f56d /src/UserSettingsPage.cpp | |
parent | Merge pull request #728 from Thulinma/goto (diff) | |
download | nheko-cfca7157b98c9dc8e0852fe6484bc3f75008af7d.tar.xz |
Change indentation to 4 spaces
Diffstat (limited to 'src/UserSettingsPage.cpp')
-rw-r--r-- | src/UserSettingsPage.cpp | 2301 |
1 files changed, 1143 insertions, 1158 deletions
diff --git a/src/UserSettingsPage.cpp b/src/UserSettingsPage.cpp index 7b01b0b8..cc1f8206 100644 --- a/src/UserSettingsPage.cpp +++ b/src/UserSettingsPage.cpp @@ -41,1499 +41,1484 @@ QSharedPointer<UserSettings> UserSettings::instance_; UserSettings::UserSettings() { - connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, []() { - instance_.clear(); - }); + connect( + QCoreApplication::instance(), &QCoreApplication::aboutToQuit, []() { instance_.clear(); }); } QSharedPointer<UserSettings> UserSettings::instance() { - return instance_; + return instance_; } void UserSettings::initialize(std::optional<QString> profile) { - instance_.reset(new UserSettings()); - instance_->load(profile); + instance_.reset(new UserSettings()); + instance_->load(profile); } void UserSettings::load(std::optional<QString> profile) { - tray_ = settings.value("user/window/tray", false).toBool(); - startInTray_ = settings.value("user/window/start_in_tray", false).toBool(); - - roomListWidth_ = settings.value("user/sidebar/room_list_width", -1).toInt(); - communityListWidth_ = settings.value("user/sidebar/community_list_width", -1).toInt(); - - hasDesktopNotifications_ = settings.value("user/desktop_notifications", true).toBool(); - hasAlertOnNotification_ = settings.value("user/alert_on_notification", false).toBool(); - groupView_ = settings.value("user/group_view", true).toBool(); - hiddenTags_ = settings.value("user/hidden_tags", QStringList{}).toStringList(); - buttonsInTimeline_ = settings.value("user/timeline/buttons", true).toBool(); - timelineMaxWidth_ = settings.value("user/timeline/max_width", 0).toInt(); - messageHoverHighlight_ = - settings.value("user/timeline/message_hover_highlight", false).toBool(); - enlargeEmojiOnlyMessages_ = - settings.value("user/timeline/enlarge_emoji_only_msg", false).toBool(); - markdown_ = settings.value("user/markdown_enabled", true).toBool(); - animateImagesOnHover_ = settings.value("user/animate_images_on_hover", false).toBool(); - typingNotifications_ = settings.value("user/typing_notifications", true).toBool(); - sortByImportance_ = settings.value("user/sort_by_unread", true).toBool(); - readReceipts_ = settings.value("user/read_receipts", true).toBool(); - theme_ = settings.value("user/theme", defaultTheme_).toString(); - font_ = settings.value("user/font_family", "default").toString(); - avatarCircles_ = settings.value("user/avatar_circles", true).toBool(); - useIdenticon_ = settings.value("user/use_identicon", true).toBool(); - decryptSidebar_ = settings.value("user/decrypt_sidebar", true).toBool(); - privacyScreen_ = settings.value("user/privacy_screen", false).toBool(); - privacyScreenTimeout_ = settings.value("user/privacy_screen_timeout", 0).toInt(); - mobileMode_ = settings.value("user/mobile_mode", false).toBool(); - emojiFont_ = settings.value("user/emoji_font_family", "default").toString(); - baseFontSize_ = settings.value("user/font_size", QFont().pointSizeF()).toDouble(); - auto tempPresence = settings.value("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("user/ringtone", "Default").toString(); - microphone_ = settings.value("user/microphone", QString()).toString(); - camera_ = settings.value("user/camera", QString()).toString(); - cameraResolution_ = settings.value("user/camera_resolution", QString()).toString(); - cameraFrameRate_ = settings.value("user/camera_frame_rate", QString()).toString(); - screenShareFrameRate_ = settings.value("user/screen_share_frame_rate", 5).toInt(); - screenSharePiP_ = settings.value("user/screen_share_pip", true).toBool(); - screenShareRemoteVideo_ = settings.value("user/screen_share_remote_video", false).toBool(); - screenShareHideCursor_ = settings.value("user/screen_share_hide_cursor", false).toBool(); - useStunServer_ = settings.value("user/use_stun_server", false).toBool(); - - if (profile) // set to "" if it's the default to maintain compatibility - profile_ = (*profile == "default") ? "" : *profile; - else - profile_ = settings.value("user/currentProfile", "").toString(); - - QString prefix = - (profile_ != "" && profile_ != "default") ? "profile/" + profile_ + "/" : ""; - 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(); - - 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("disable_certificate_validation", false).toBool(); - - applyTheme(); + tray_ = settings.value("user/window/tray", false).toBool(); + startInTray_ = settings.value("user/window/start_in_tray", false).toBool(); + + roomListWidth_ = settings.value("user/sidebar/room_list_width", -1).toInt(); + communityListWidth_ = settings.value("user/sidebar/community_list_width", -1).toInt(); + + hasDesktopNotifications_ = settings.value("user/desktop_notifications", true).toBool(); + hasAlertOnNotification_ = settings.value("user/alert_on_notification", false).toBool(); + groupView_ = settings.value("user/group_view", true).toBool(); + hiddenTags_ = settings.value("user/hidden_tags", QStringList{}).toStringList(); + buttonsInTimeline_ = settings.value("user/timeline/buttons", true).toBool(); + timelineMaxWidth_ = settings.value("user/timeline/max_width", 0).toInt(); + messageHoverHighlight_ = + settings.value("user/timeline/message_hover_highlight", false).toBool(); + enlargeEmojiOnlyMessages_ = + settings.value("user/timeline/enlarge_emoji_only_msg", false).toBool(); + markdown_ = settings.value("user/markdown_enabled", true).toBool(); + animateImagesOnHover_ = settings.value("user/animate_images_on_hover", false).toBool(); + typingNotifications_ = settings.value("user/typing_notifications", true).toBool(); + sortByImportance_ = settings.value("user/sort_by_unread", true).toBool(); + readReceipts_ = settings.value("user/read_receipts", true).toBool(); + theme_ = settings.value("user/theme", defaultTheme_).toString(); + font_ = settings.value("user/font_family", "default").toString(); + avatarCircles_ = settings.value("user/avatar_circles", true).toBool(); + useIdenticon_ = settings.value("user/use_identicon", true).toBool(); + decryptSidebar_ = settings.value("user/decrypt_sidebar", true).toBool(); + privacyScreen_ = settings.value("user/privacy_screen", false).toBool(); + privacyScreenTimeout_ = settings.value("user/privacy_screen_timeout", 0).toInt(); + mobileMode_ = settings.value("user/mobile_mode", false).toBool(); + emojiFont_ = settings.value("user/emoji_font_family", "default").toString(); + baseFontSize_ = settings.value("user/font_size", QFont().pointSizeF()).toDouble(); + auto tempPresence = settings.value("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("user/ringtone", "Default").toString(); + microphone_ = settings.value("user/microphone", QString()).toString(); + camera_ = settings.value("user/camera", QString()).toString(); + cameraResolution_ = settings.value("user/camera_resolution", QString()).toString(); + cameraFrameRate_ = settings.value("user/camera_frame_rate", QString()).toString(); + screenShareFrameRate_ = settings.value("user/screen_share_frame_rate", 5).toInt(); + screenSharePiP_ = settings.value("user/screen_share_pip", true).toBool(); + screenShareRemoteVideo_ = settings.value("user/screen_share_remote_video", false).toBool(); + screenShareHideCursor_ = settings.value("user/screen_share_hide_cursor", false).toBool(); + useStunServer_ = settings.value("user/use_stun_server", false).toBool(); + + if (profile) // set to "" if it's the default to maintain compatibility + profile_ = (*profile == "default") ? "" : *profile; + else + profile_ = settings.value("user/currentProfile", "").toString(); + + QString prefix = (profile_ != "" && profile_ != "default") ? "profile/" + profile_ + "/" : ""; + 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(); + + 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("disable_certificate_validation", false).toBool(); + + applyTheme(); } void UserSettings::setMessageHoverHighlight(bool state) { - if (state == messageHoverHighlight_) - return; - messageHoverHighlight_ = state; - emit messageHoverHighlightChanged(state); - save(); + 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 == enlargeEmojiOnlyMessages_) + return; + enlargeEmojiOnlyMessages_ = state; + emit enlargeEmojiOnlyMessagesChanged(state); + save(); } void UserSettings::setTray(bool state) { - if (state == tray_) - return; - tray_ = state; - emit trayChanged(state); - save(); + if (state == tray_) + return; + tray_ = state; + emit trayChanged(state); + save(); } void UserSettings::setStartInTray(bool state) { - if (state == startInTray_) - return; - startInTray_ = state; - emit startInTrayChanged(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 (state == mobileMode_) + return; + mobileMode_ = state; + emit mobileModeChanged(state); + save(); } void UserSettings::setGroupView(bool state) { - if (groupView_ == state) - return; + if (groupView_ == state) + return; - groupView_ = state; - emit groupViewStateChanged(state); - save(); + groupView_ = state; + emit groupViewStateChanged(state); + save(); } void UserSettings::setHiddenTags(QStringList hiddenTags) { - hiddenTags_ = hiddenTags; - save(); + hiddenTags_ = hiddenTags; + save(); } void UserSettings::setMarkdown(bool state) { - if (state == markdown_) - return; - markdown_ = state; - emit markdownChanged(state); - save(); + if (state == markdown_) + return; + markdown_ = state; + emit markdownChanged(state); + save(); } void UserSettings::setAnimateImagesOnHover(bool state) { - if (state == animateImagesOnHover_) - return; - animateImagesOnHover_ = state; - emit animateImagesOnHoverChanged(state); - save(); + 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(); + 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(); + 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(); + 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 == buttonsInTimeline_) + return; + buttonsInTimeline_ = state; + emit buttonInTimelineChanged(state); + save(); } void UserSettings::setTimelineMaxWidth(int state) { - if (state == timelineMaxWidth_) - return; - timelineMaxWidth_ = state; - emit timelineMaxWidthChanged(state); - save(); + if (state == timelineMaxWidth_) + return; + timelineMaxWidth_ = state; + emit timelineMaxWidthChanged(state); + save(); } void UserSettings::setCommunityListWidth(int state) { - if (state == communityListWidth_) - return; - communityListWidth_ = state; - emit communityListWidthChanged(state); - save(); + if (state == communityListWidth_) + return; + communityListWidth_ = state; + emit communityListWidthChanged(state); + save(); } void UserSettings::setRoomListWidth(int state) { - if (state == roomListWidth_) - return; - roomListWidth_ = state; - emit roomListWidthChanged(state); - save(); + 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(); + 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(); + 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 == avatarCircles_) + return; + avatarCircles_ = state; + emit avatarCirclesChanged(state); + save(); } void UserSettings::setDecryptSidebar(bool state) { - if (state == decryptSidebar_) - return; - decryptSidebar_ = state; - emit decryptSidebarChanged(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(); + 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(); + 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(); + if (size == baseFontSize_) + return; + baseFontSize_ = size; + emit fontSizeChanged(size); + save(); } void UserSettings::setFontFamily(QString family) { - if (family == font_) - return; - font_ = family; - emit fontChanged(family); - save(); + if (family == font_) + return; + font_ = family; + emit fontChanged(family); + save(); } void UserSettings::setEmojiFontFamily(QString family) { - if (family == emojiFont_) - return; + if (family == emojiFont_) + return; - if (family == tr("Default")) { - emojiFont_ = "default"; - } else { - emojiFont_ = family; - } + if (family == tr("Default")) { + emojiFont_ = "default"; + } else { + emojiFont_ = family; + } - emit emojiFontChanged(family); - save(); + emit emojiFontChanged(family); + save(); } void UserSettings::setPresence(Presence state) { - if (state == presence_) - return; - presence_ = state; - emit presenceChanged(state); - save(); + 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); + if (theme == theme_) + return; + theme_ = theme; + save(); + applyTheme(); + emit themeChanged(theme); } void UserSettings::setUseStunServer(bool useStunServer) { - if (useStunServer == useStunServer_) - return; - useStunServer_ = useStunServer; - emit useStunServerChanged(useStunServer); - save(); + if (useStunServer == useStunServer_) + return; + useStunServer_ = useStunServer; + emit useStunServerChanged(useStunServer); + save(); } void UserSettings::setOnlyShareKeysWithVerifiedUsers(bool shareKeys) { - if (shareKeys == onlyShareKeysWithVerifiedUsers_) - return; + if (shareKeys == onlyShareKeysWithVerifiedUsers_) + return; - onlyShareKeysWithVerifiedUsers_ = shareKeys; - emit onlyShareKeysWithVerifiedUsersChanged(shareKeys); - save(); + onlyShareKeysWithVerifiedUsers_ = shareKeys; + emit onlyShareKeysWithVerifiedUsersChanged(shareKeys); + save(); } void UserSettings::setShareKeysWithTrustedUsers(bool shareKeys) { - if (shareKeys == shareKeysWithTrustedUsers_) - return; + if (shareKeys == shareKeysWithTrustedUsers_) + return; - shareKeysWithTrustedUsers_ = shareKeys; - emit shareKeysWithTrustedUsersChanged(shareKeys); - save(); + shareKeysWithTrustedUsers_ = shareKeys; + emit shareKeysWithTrustedUsersChanged(shareKeys); + save(); } void UserSettings::setUseOnlineKeyBackup(bool useBackup) { - if (useBackup == useOnlineKeyBackup_) - return; + if (useBackup == useOnlineKeyBackup_) + return; - useOnlineKeyBackup_ = useBackup; - emit useOnlineKeyBackupChanged(useBackup); - save(); + useOnlineKeyBackup_ = useBackup; + emit useOnlineKeyBackupChanged(useBackup); + save(); } void UserSettings::setRingtone(QString ringtone) { - if (ringtone == ringtone_) - return; - ringtone_ = ringtone; - emit ringtoneChanged(ringtone); - save(); + if (ringtone == ringtone_) + return; + ringtone_ = ringtone; + emit ringtoneChanged(ringtone); + save(); } void UserSettings::setMicrophone(QString microphone) { - if (microphone == microphone_) - return; - microphone_ = microphone; - emit microphoneChanged(microphone); - save(); + if (microphone == microphone_) + return; + microphone_ = microphone; + emit microphoneChanged(microphone); + save(); } void UserSettings::setCamera(QString camera) { - if (camera == camera_) - return; - camera_ = camera; - emit cameraChanged(camera); - save(); + if (camera == camera_) + return; + camera_ = camera; + emit cameraChanged(camera); + save(); } void UserSettings::setCameraResolution(QString resolution) { - if (resolution == cameraResolution_) - return; - cameraResolution_ = resolution; - emit cameraResolutionChanged(resolution); - save(); + if (resolution == cameraResolution_) + return; + cameraResolution_ = resolution; + emit cameraResolutionChanged(resolution); + save(); } void UserSettings::setCameraFrameRate(QString frameRate) { - if (frameRate == cameraFrameRate_) - return; - cameraFrameRate_ = frameRate; - emit cameraFrameRateChanged(frameRate); - save(); + 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(); + 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(); + 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(); + 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(); + 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(); + 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(); + 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(); + 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(); + 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(); + 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); + if (disabled == disableCertificateValidation_) + return; + disableCertificateValidation_ = disabled; + http::client()->verify_certificates(!disabled); + emit disableCertificateValidationChanged(disabled); } void UserSettings::setUseIdenticon(bool state) { - if (state == useIdenticon_) - return; - useIdenticon_ = state; - emit useIdenticonChanged(useIdenticon_); - save(); + if (state == useIdenticon_) + return; + useIdenticon_ = state; + emit useIdenticonChanged(useIdenticon_); + save(); } void UserSettings::applyTheme() { - QFile stylefile; + QFile stylefile; - if (this->theme() == "light") { - stylefile.setFileName(":/styles/styles/nheko.qss"); - } else if (this->theme() == "dark") { - stylefile.setFileName(":/styles/styles/nheko-dark.qss"); - } else { - stylefile.setFileName(":/styles/styles/system.qss"); - } - QApplication::setPalette(Theme::paletteFromTheme(this->theme().toStdString())); + if (this->theme() == "light") { + stylefile.setFileName(":/styles/styles/nheko.qss"); + } else if (this->theme() == "dark") { + stylefile.setFileName(":/styles/styles/nheko-dark.qss"); + } else { + stylefile.setFileName(":/styles/styles/system.qss"); + } + QApplication::setPalette(Theme::paletteFromTheme(this->theme().toStdString())); - stylefile.open(QFile::ReadOnly); - QString stylesheet = QString(stylefile.readAll()); + stylefile.open(QFile::ReadOnly); + QString stylesheet = QString(stylefile.readAll()); - qobject_cast<QApplication *>(QApplication::instance())->setStyleSheet(stylesheet); + qobject_cast<QApplication *>(QApplication::instance())->setStyleSheet(stylesheet); } void UserSettings::save() { - settings.beginGroup("user"); - - settings.beginGroup("window"); - settings.setValue("tray", tray_); - settings.setValue("start_in_tray", startInTray_); - settings.endGroup(); // window - - settings.beginGroup("sidebar"); - settings.setValue("community_list_width", communityListWidth_); - settings.setValue("room_list_width", roomListWidth_); - settings.endGroup(); // window - - settings.beginGroup("timeline"); - settings.setValue("buttons", buttonsInTimeline_); - settings.setValue("message_hover_highlight", messageHoverHighlight_); - settings.setValue("enlarge_emoji_only_msg", enlargeEmojiOnlyMessages_); - settings.setValue("max_width", timelineMaxWidth_); - settings.endGroup(); // timeline - - settings.setValue("avatar_circles", avatarCircles_); - settings.setValue("decrypt_sidebar", decryptSidebar_); - settings.setValue("privacy_screen", privacyScreen_); - settings.setValue("privacy_screen_timeout", privacyScreenTimeout_); - settings.setValue("mobile_mode", mobileMode_); - settings.setValue("font_size", baseFontSize_); - settings.setValue("typing_notifications", typingNotifications_); - settings.setValue("sort_by_unread", sortByImportance_); - settings.setValue("minor_events", sortByImportance_); - settings.setValue("read_receipts", readReceipts_); - settings.setValue("group_view", groupView_); - settings.setValue("hidden_tags", hiddenTags_); - settings.setValue("markdown_enabled", markdown_); - settings.setValue("animate_images_on_hover", animateImagesOnHover_); - settings.setValue("desktop_notifications", hasDesktopNotifications_); - settings.setValue("alert_on_notification", hasAlertOnNotification_); - settings.setValue("theme", theme()); - settings.setValue("font_family", font_); - settings.setValue("emoji_font_family", emojiFont_); - settings.setValue("presence", - QString::fromUtf8(QMetaEnum::fromType<Presence>().valueToKey( - static_cast<int>(presence_)))); - settings.setValue("ringtone", ringtone_); - settings.setValue("microphone", microphone_); - settings.setValue("camera", camera_); - settings.setValue("camera_resolution", cameraResolution_); - settings.setValue("camera_frame_rate", cameraFrameRate_); - settings.setValue("screen_share_frame_rate", screenShareFrameRate_); - settings.setValue("screen_share_pip", screenSharePiP_); - settings.setValue("screen_share_remote_video", screenShareRemoteVideo_); - settings.setValue("screen_share_hide_cursor", screenShareHideCursor_); - settings.setValue("use_stun_server", useStunServer_); - settings.setValue("currentProfile", profile_); - settings.setValue("use_identicon", useIdenticon_); - - settings.endGroup(); // user - - QString prefix = - (profile_ != "" && profile_ != "default") ? "profile/" + profile_ + "/" : ""; - 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("disable_certificate_validation", disableCertificateValidation_); - - settings.sync(); + settings.beginGroup("user"); + + settings.beginGroup("window"); + settings.setValue("tray", tray_); + settings.setValue("start_in_tray", startInTray_); + settings.endGroup(); // window + + settings.beginGroup("sidebar"); + settings.setValue("community_list_width", communityListWidth_); + settings.setValue("room_list_width", roomListWidth_); + settings.endGroup(); // window + + settings.beginGroup("timeline"); + settings.setValue("buttons", buttonsInTimeline_); + settings.setValue("message_hover_highlight", messageHoverHighlight_); + settings.setValue("enlarge_emoji_only_msg", enlargeEmojiOnlyMessages_); + settings.setValue("max_width", timelineMaxWidth_); + settings.endGroup(); // timeline + + settings.setValue("avatar_circles", avatarCircles_); + settings.setValue("decrypt_sidebar", decryptSidebar_); + settings.setValue("privacy_screen", privacyScreen_); + settings.setValue("privacy_screen_timeout", privacyScreenTimeout_); + settings.setValue("mobile_mode", mobileMode_); + settings.setValue("font_size", baseFontSize_); + settings.setValue("typing_notifications", typingNotifications_); + settings.setValue("sort_by_unread", sortByImportance_); + settings.setValue("minor_events", sortByImportance_); + settings.setValue("read_receipts", readReceipts_); + settings.setValue("group_view", groupView_); + settings.setValue("hidden_tags", hiddenTags_); + settings.setValue("markdown_enabled", markdown_); + settings.setValue("animate_images_on_hover", animateImagesOnHover_); + settings.setValue("desktop_notifications", hasDesktopNotifications_); + settings.setValue("alert_on_notification", hasAlertOnNotification_); + settings.setValue("theme", theme()); + settings.setValue("font_family", font_); + settings.setValue("emoji_font_family", emojiFont_); + settings.setValue( + "presence", + QString::fromUtf8(QMetaEnum::fromType<Presence>().valueToKey(static_cast<int>(presence_)))); + settings.setValue("ringtone", ringtone_); + settings.setValue("microphone", microphone_); + settings.setValue("camera", camera_); + settings.setValue("camera_resolution", cameraResolution_); + settings.setValue("camera_frame_rate", cameraFrameRate_); + settings.setValue("screen_share_frame_rate", screenShareFrameRate_); + settings.setValue("screen_share_pip", screenSharePiP_); + settings.setValue("screen_share_remote_video", screenShareRemoteVideo_); + settings.setValue("screen_share_hide_cursor", screenShareHideCursor_); + settings.setValue("use_stun_server", useStunServer_); + settings.setValue("currentProfile", profile_); + settings.setValue("use_identicon", useIdenticon_); + + settings.endGroup(); // user + + QString prefix = (profile_ != "" && profile_ != "default") ? "profile/" + profile_ + "/" : ""; + 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("disable_certificate_validation", disableCertificateValidation_); + + settings.sync(); } HorizontalLine::HorizontalLine(QWidget *parent) : QFrame{parent} { - setFrameShape(QFrame::HLine); - setFrameShadow(QFrame::Sunken); + setFrameShape(QFrame::HLine); + setFrameShadow(QFrame::Sunken); } UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidget *parent) : QWidget{parent} , settings_{settings} { - topLayout_ = new QVBoxLayout{this}; - - QIcon icon; - icon.addFile(":/icons/icons/ui/angle-pointing-to-left.png"); - - auto backBtn_ = new FlatButton{this}; - backBtn_->setMinimumSize(QSize(24, 24)); - backBtn_->setIcon(icon); - backBtn_->setIconSize(QSize(24, 24)); - - QFont font; - font.setPointSizeF(font.pointSizeF() * 1.1); - - auto versionInfo = new QLabel(QString("%1 | %2").arg(nheko::version).arg(nheko::build_os)); - if (QCoreApplication::applicationName() != "nheko") - versionInfo->setText(versionInfo->text() + " | " + - tr("profile: %1").arg(QCoreApplication::applicationName())); - versionInfo->setTextInteractionFlags(Qt::TextBrowserInteraction); - - topBarLayout_ = new QHBoxLayout; - topBarLayout_->setSpacing(0); - topBarLayout_->setMargin(0); - topBarLayout_->addWidget(backBtn_, 1, Qt::AlignLeft | Qt::AlignVCenter); - topBarLayout_->addStretch(1); - - formLayout_ = new QFormLayout; - - formLayout_->setLabelAlignment(Qt::AlignLeft); - formLayout_->setFormAlignment(Qt::AlignRight); - formLayout_->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); - formLayout_->setRowWrapPolicy(QFormLayout::WrapLongRows); - formLayout_->setHorizontalSpacing(0); - - auto general_ = new QLabel{tr("GENERAL"), this}; - general_->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); - general_->setFont(font); - - trayToggle_ = new Toggle{this}; - startInTrayToggle_ = new Toggle{this}; - avatarCircles_ = new Toggle{this}; - useIdenticon_ = new Toggle{this}; - decryptSidebar_ = new Toggle(this); - privacyScreen_ = new Toggle{this}; - onlyShareKeysWithVerifiedUsers_ = new Toggle(this); - shareKeysWithTrustedUsers_ = new Toggle(this); - useOnlineKeyBackup_ = new Toggle(this); - groupViewToggle_ = new Toggle{this}; - timelineButtonsToggle_ = new Toggle{this}; - typingNotifications_ = new Toggle{this}; - messageHoverHighlight_ = new Toggle{this}; - enlargeEmojiOnlyMessages_ = new Toggle{this}; - sortByImportance_ = new Toggle{this}; - readReceipts_ = new Toggle{this}; - markdown_ = new Toggle{this}; - animateImagesOnHover_ = new Toggle{this}; - desktopNotifications_ = new Toggle{this}; - alertOnNotification_ = new Toggle{this}; - useStunServer_ = new Toggle{this}; - mobileMode_ = new Toggle{this}; - scaleFactorCombo_ = new QComboBox{this}; - fontSizeCombo_ = new QComboBox{this}; - fontSelectionCombo_ = new QFontComboBox{this}; - emojiFontSelectionCombo_ = new QComboBox{this}; - ringtoneCombo_ = new QComboBox{this}; - microphoneCombo_ = new QComboBox{this}; - cameraCombo_ = new QComboBox{this}; - cameraResolutionCombo_ = new QComboBox{this}; - cameraFrameRateCombo_ = new QComboBox{this}; - timelineMaxWidthSpin_ = new QSpinBox{this}; - privacyScreenTimeout_ = new QSpinBox{this}; - - trayToggle_->setChecked(settings_->tray()); - startInTrayToggle_->setChecked(settings_->startInTray()); - avatarCircles_->setChecked(settings_->avatarCircles()); - useIdenticon_->setChecked(settings_->useIdenticon()); - decryptSidebar_->setChecked(settings_->decryptSidebar()); - privacyScreen_->setChecked(settings_->privacyScreen()); - onlyShareKeysWithVerifiedUsers_->setChecked(settings_->onlyShareKeysWithVerifiedUsers()); - shareKeysWithTrustedUsers_->setChecked(settings_->shareKeysWithTrustedUsers()); - useOnlineKeyBackup_->setChecked(settings_->useOnlineKeyBackup()); - groupViewToggle_->setChecked(settings_->groupView()); - timelineButtonsToggle_->setChecked(settings_->buttonsInTimeline()); - typingNotifications_->setChecked(settings_->typingNotifications()); - messageHoverHighlight_->setChecked(settings_->messageHoverHighlight()); - enlargeEmojiOnlyMessages_->setChecked(settings_->enlargeEmojiOnlyMessages()); - sortByImportance_->setChecked(settings_->sortByImportance()); - readReceipts_->setChecked(settings_->readReceipts()); - markdown_->setChecked(settings_->markdown()); - animateImagesOnHover_->setChecked(settings_->animateImagesOnHover()); - desktopNotifications_->setChecked(settings_->hasDesktopNotifications()); - alertOnNotification_->setChecked(settings_->hasAlertOnNotification()); - useStunServer_->setChecked(settings_->useStunServer()); - mobileMode_->setChecked(settings_->mobileMode()); - - if (!settings_->tray()) { - startInTrayToggle_->setState(false); - startInTrayToggle_->setDisabled(true); - } - - if (!settings_->privacyScreen()) { - privacyScreenTimeout_->setDisabled(true); - } - - avatarCircles_->setFixedSize(64, 48); - - auto uiLabel_ = new QLabel{tr("INTERFACE"), this}; - uiLabel_->setFixedHeight(uiLabel_->minimumHeight() + LayoutTopMargin); - uiLabel_->setAlignment(Qt::AlignBottom); - uiLabel_->setFont(font); - - for (double option = 1; option <= 3; option += 0.25) - scaleFactorCombo_->addItem(QString::number(option)); - for (double option = 6; option <= 24; option += 0.5) - fontSizeCombo_->addItem(QString("%1 ").arg(QString::number(option))); - - QFontDatabase fontDb; - - // TODO: Is there a way to limit to just emojis, rather than - // all emoji fonts? - auto emojiFamilies = fontDb.families(QFontDatabase::Symbol); - emojiFontSelectionCombo_->addItem(tr("Default")); - for (const auto &family : emojiFamilies) { - emojiFontSelectionCombo_->addItem(family); - } - - QString currentFont = settings_->font(); - if (currentFont != "default" || currentFont != "") { - fontSelectionCombo_->setCurrentIndex(fontSelectionCombo_->findText(currentFont)); + topLayout_ = new QVBoxLayout{this}; + + QIcon icon; + icon.addFile(":/icons/icons/ui/angle-pointing-to-left.png"); + + auto backBtn_ = new FlatButton{this}; + backBtn_->setMinimumSize(QSize(24, 24)); + backBtn_->setIcon(icon); + backBtn_->setIconSize(QSize(24, 24)); + + QFont font; + font.setPointSizeF(font.pointSizeF() * 1.1); + + auto versionInfo = new QLabel(QString("%1 | %2").arg(nheko::version).arg(nheko::build_os)); + if (QCoreApplication::applicationName() != "nheko") + versionInfo->setText(versionInfo->text() + " | " + + tr("profile: %1").arg(QCoreApplication::applicationName())); + versionInfo->setTextInteractionFlags(Qt::TextBrowserInteraction); + + topBarLayout_ = new QHBoxLayout; + topBarLayout_->setSpacing(0); + topBarLayout_->setMargin(0); + topBarLayout_->addWidget(backBtn_, 1, Qt::AlignLeft | Qt::AlignVCenter); + topBarLayout_->addStretch(1); + + formLayout_ = new QFormLayout; + + formLayout_->setLabelAlignment(Qt::AlignLeft); + formLayout_->setFormAlignment(Qt::AlignRight); + formLayout_->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); + formLayout_->setRowWrapPolicy(QFormLayout::WrapLongRows); + formLayout_->setHorizontalSpacing(0); + + auto general_ = new QLabel{tr("GENERAL"), this}; + general_->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); + general_->setFont(font); + + trayToggle_ = new Toggle{this}; + startInTrayToggle_ = new Toggle{this}; + avatarCircles_ = new Toggle{this}; + useIdenticon_ = new Toggle{this}; + decryptSidebar_ = new Toggle(this); + privacyScreen_ = new Toggle{this}; + onlyShareKeysWithVerifiedUsers_ = new Toggle(this); + shareKeysWithTrustedUsers_ = new Toggle(this); + useOnlineKeyBackup_ = new Toggle(this); + groupViewToggle_ = new Toggle{this}; + timelineButtonsToggle_ = new Toggle{this}; + typingNotifications_ = new Toggle{this}; + messageHoverHighlight_ = new Toggle{this}; + enlargeEmojiOnlyMessages_ = new Toggle{this}; + sortByImportance_ = new Toggle{this}; + readReceipts_ = new Toggle{this}; + markdown_ = new Toggle{this}; + animateImagesOnHover_ = new Toggle{this}; + desktopNotifications_ = new Toggle{this}; + alertOnNotification_ = new Toggle{this}; + useStunServer_ = new Toggle{this}; + mobileMode_ = new Toggle{this}; + scaleFactorCombo_ = new QComboBox{this}; + fontSizeCombo_ = new QComboBox{this}; + fontSelectionCombo_ = new QFontComboBox{this}; + emojiFontSelectionCombo_ = new QComboBox{this}; + ringtoneCombo_ = new QComboBox{this}; + microphoneCombo_ = new QComboBox{this}; + cameraCombo_ = new QComboBox{this}; + cameraResolutionCombo_ = new QComboBox{this}; + cameraFrameRateCombo_ = new QComboBox{this}; + timelineMaxWidthSpin_ = new QSpinBox{this}; + privacyScreenTimeout_ = new QSpinBox{this}; + + trayToggle_->setChecked(settings_->tray()); + startInTrayToggle_->setChecked(settings_->startInTray()); + avatarCircles_->setChecked(settings_->avatarCircles()); + useIdenticon_->setChecked(settings_->useIdenticon()); + decryptSidebar_->setChecked(settings_->decryptSidebar()); + privacyScreen_->setChecked(settings_->privacyScreen()); + onlyShareKeysWithVerifiedUsers_->setChecked(settings_->onlyShareKeysWithVerifiedUsers()); + shareKeysWithTrustedUsers_->setChecked(settings_->shareKeysWithTrustedUsers()); + useOnlineKeyBackup_->setChecked(settings_->useOnlineKeyBackup()); + groupViewToggle_->setChecked(settings_->groupView()); + timelineButtonsToggle_->setChecked(settings_->buttonsInTimeline()); + typingNotifications_->setChecked(settings_->typingNotifications()); + messageHoverHighlight_->setChecked(settings_->messageHoverHighlight()); + enlargeEmojiOnlyMessages_->setChecked(settings_->enlargeEmojiOnlyMessages()); + sortByImportance_->setChecked(settings_->sortByImportance()); + readReceipts_->setChecked(settings_->readReceipts()); + markdown_->setChecked(settings_->markdown()); + animateImagesOnHover_->setChecked(settings_->animateImagesOnHover()); + desktopNotifications_->setChecked(settings_->hasDesktopNotifications()); + alertOnNotification_->setChecked(settings_->hasAlertOnNotification()); + useStunServer_->setChecked(settings_->useStunServer()); + mobileMode_->setChecked(settings_->mobileMode()); + + if (!settings_->tray()) { + startInTrayToggle_->setState(false); + startInTrayToggle_->setDisabled(true); + } + + if (!settings_->privacyScreen()) { + privacyScreenTimeout_->setDisabled(true); + } + + avatarCircles_->setFixedSize(64, 48); + + auto uiLabel_ = new QLabel{tr("INTERFACE"), this}; + uiLabel_->setFixedHeight(uiLabel_->minimumHeight() + LayoutTopMargin); + uiLabel_->setAlignment(Qt::AlignBottom); + uiLabel_->setFont(font); + + for (double option = 1; option <= 3; option += 0.25) + scaleFactorCombo_->addItem(QString::number(option)); + for (double option = 6; option <= 24; option += 0.5) + fontSizeCombo_->addItem(QString("%1 ").arg(QString::number(option))); + + QFontDatabase fontDb; + + // TODO: Is there a way to limit to just emojis, rather than + // all emoji fonts? + auto emojiFamilies = fontDb.families(QFontDatabase::Symbol); + emojiFontSelectionCombo_->addItem(tr("Default")); + for (const auto &family : emojiFamilies) { + emojiFontSelectionCombo_->addItem(family); + } + + QString currentFont = settings_->font(); + if (currentFont != "default" || currentFont != "") { + fontSelectionCombo_->setCurrentIndex(fontSelectionCombo_->findText(currentFont)); + } + + emojiFontSelectionCombo_->setCurrentIndex( + emojiFontSelectionCombo_->findText(settings_->emojiFont())); + + themeCombo_ = new QComboBox{this}; + themeCombo_->addItem("Light"); + themeCombo_->addItem("Dark"); + themeCombo_->addItem("System"); + + QString themeStr = settings_->theme(); + themeStr.replace(0, 1, themeStr[0].toUpper()); + int themeIndex = themeCombo_->findText(themeStr); + themeCombo_->setCurrentIndex(themeIndex); + + timelineMaxWidthSpin_->setMinimum(0); + timelineMaxWidthSpin_->setMaximum(100'000'000); + timelineMaxWidthSpin_->setSingleStep(10); + + privacyScreenTimeout_->setMinimum(0); + privacyScreenTimeout_->setMaximum(3600); + privacyScreenTimeout_->setSingleStep(10); + + auto callsLabel = new QLabel{tr("CALLS"), this}; + callsLabel->setFixedHeight(callsLabel->minimumHeight() + LayoutTopMargin); + callsLabel->setAlignment(Qt::AlignBottom); + callsLabel->setFont(font); + + auto encryptionLabel_ = new QLabel{tr("ENCRYPTION"), this}; + encryptionLabel_->setFixedHeight(encryptionLabel_->minimumHeight() + LayoutTopMargin); + encryptionLabel_->setAlignment(Qt::AlignBottom); + encryptionLabel_->setFont(font); + + QFont monospaceFont; + monospaceFont.setFamily("Monospace"); + monospaceFont.setStyleHint(QFont::Monospace); + monospaceFont.setPointSizeF(monospaceFont.pointSizeF() * 0.9); + + deviceIdValue_ = new QLabel{this}; + deviceIdValue_->setTextInteractionFlags(Qt::TextSelectableByMouse); + deviceIdValue_->setFont(monospaceFont); + + deviceFingerprintValue_ = new QLabel{this}; + deviceFingerprintValue_->setTextInteractionFlags(Qt::TextSelectableByMouse); + deviceFingerprintValue_->setFont(monospaceFont); + + deviceFingerprintValue_->setText(utils::humanReadableFingerprint(QString(44, 'X'))); + + backupSecretCached = new QLabel{this}; + masterSecretCached = new QLabel{this}; + selfSigningSecretCached = new QLabel{this}; + userSigningSecretCached = new QLabel{this}; + backupSecretCached->setFont(monospaceFont); + masterSecretCached->setFont(monospaceFont); + selfSigningSecretCached->setFont(monospaceFont); + userSigningSecretCached->setFont(monospaceFont); + + auto sessionKeysLabel = new QLabel{tr("Session Keys"), this}; + sessionKeysLabel->setFont(font); + sessionKeysLabel->setMargin(OptionMargin); + + auto sessionKeysImportBtn = new QPushButton{tr("IMPORT"), this}; + auto sessionKeysExportBtn = new QPushButton{tr("EXPORT"), this}; + + auto sessionKeysLayout = new QHBoxLayout; + sessionKeysLayout->addWidget(new QLabel{"", this}, 1, Qt::AlignRight); + sessionKeysLayout->addWidget(sessionKeysExportBtn, 0, Qt::AlignRight); + sessionKeysLayout->addWidget(sessionKeysImportBtn, 0, Qt::AlignRight); + + auto crossSigningKeysLabel = new QLabel{tr("Cross Signing Keys"), this}; + crossSigningKeysLabel->setFont(font); + crossSigningKeysLabel->setMargin(OptionMargin); + + auto crossSigningRequestBtn = new QPushButton{tr("REQUEST"), this}; + auto crossSigningDownloadBtn = new QPushButton{tr("DOWNLOAD"), this}; + + auto crossSigningKeysLayout = new QHBoxLayout; + crossSigningKeysLayout->addWidget(new QLabel{"", this}, 1, Qt::AlignRight); + crossSigningKeysLayout->addWidget(crossSigningRequestBtn, 0, Qt::AlignRight); + crossSigningKeysLayout->addWidget(crossSigningDownloadBtn, 0, Qt::AlignRight); + + auto boxWrap = [this, &font](QString labelText, QWidget *field, QString tooltipText = "") { + auto label = new QLabel{labelText, this}; + label->setFont(font); + label->setMargin(OptionMargin); + + if (!tooltipText.isEmpty()) { + label->setToolTip(tooltipText); } - emojiFontSelectionCombo_->setCurrentIndex( - emojiFontSelectionCombo_->findText(settings_->emojiFont())); - - themeCombo_ = new QComboBox{this}; - themeCombo_->addItem("Light"); - themeCombo_->addItem("Dark"); - themeCombo_->addItem("System"); - - QString themeStr = settings_->theme(); - themeStr.replace(0, 1, themeStr[0].toUpper()); - int themeIndex = themeCombo_->findText(themeStr); - themeCombo_->setCurrentIndex(themeIndex); - - timelineMaxWidthSpin_->setMinimum(0); - timelineMaxWidthSpin_->setMaximum(100'000'000); - timelineMaxWidthSpin_->setSingleStep(10); - - privacyScreenTimeout_->setMinimum(0); - privacyScreenTimeout_->setMaximum(3600); - privacyScreenTimeout_->setSingleStep(10); - - auto callsLabel = new QLabel{tr("CALLS"), this}; - callsLabel->setFixedHeight(callsLabel->minimumHeight() + LayoutTopMargin); - callsLabel->setAlignment(Qt::AlignBottom); - callsLabel->setFont(font); - - auto encryptionLabel_ = new QLabel{tr("ENCRYPTION"), this}; - encryptionLabel_->setFixedHeight(encryptionLabel_->minimumHeight() + LayoutTopMargin); - encryptionLabel_->setAlignment(Qt::AlignBottom); - encryptionLabel_->setFont(font); - - QFont monospaceFont; - monospaceFont.setFamily("Monospace"); - monospaceFont.setStyleHint(QFont::Monospace); - monospaceFont.setPointSizeF(monospaceFont.pointSizeF() * 0.9); - - deviceIdValue_ = new QLabel{this}; - deviceIdValue_->setTextInteractionFlags(Qt::TextSelectableByMouse); - deviceIdValue_->setFont(monospaceFont); - - deviceFingerprintValue_ = new QLabel{this}; - deviceFingerprintValue_->setTextInteractionFlags(Qt::TextSelectableByMouse); - deviceFingerprintValue_->setFont(monospaceFont); - - deviceFingerprintValue_->setText(utils::humanReadableFingerprint(QString(44, 'X'))); - - backupSecretCached = new QLabel{this}; - masterSecretCached = new QLabel{this}; - selfSigningSecretCached = new QLabel{this}; - userSigningSecretCached = new QLabel{this}; - backupSecretCached->setFont(monospaceFont); - masterSecretCached->setFont(monospaceFont); - selfSigningSecretCached->setFont(monospaceFont); - userSigningSecretCached->setFont(monospaceFont); - - auto sessionKeysLabel = new QLabel{tr("Session Keys"), this}; - sessionKeysLabel->setFont(font); - sessionKeysLabel->setMargin(OptionMargin); - - auto sessionKeysImportBtn = new QPushButton{tr("IMPORT"), this}; - auto sessionKeysExportBtn = new QPushButton{tr("EXPORT"), this}; - - auto sessionKeysLayout = new QHBoxLayout; - sessionKeysLayout->addWidget(new QLabel{"", this}, 1, Qt::AlignRight); - sessionKeysLayout->addWidget(sessionKeysExportBtn, 0, Qt::AlignRight); - sessionKeysLayout->addWidget(sessionKeysImportBtn, 0, Qt::AlignRight); - - auto crossSigningKeysLabel = new QLabel{tr("Cross Signing Keys"), this}; - crossSigningKeysLabel->setFont(font); - crossSigningKeysLabel->setMargin(OptionMargin); - - auto crossSigningRequestBtn = new QPushButton{tr("REQUEST"), this}; - auto crossSigningDownloadBtn = new QPushButton{tr("DOWNLOAD"), this}; - - auto crossSigningKeysLayout = new QHBoxLayout; - crossSigningKeysLayout->addWidget(new QLabel{"", this}, 1, Qt::AlignRight); - crossSigningKeysLayout->addWidget(crossSigningRequestBtn, 0, Qt::AlignRight); - crossSigningKeysLayout->addWidget(crossSigningDownloadBtn, 0, Qt::AlignRight); - - auto boxWrap = [this, &font](QString labelText, QWidget *field, QString tooltipText = "") { - auto label = new QLabel{labelText, this}; - label->setFont(font); - label->setMargin(OptionMargin); - - if (!tooltipText.isEmpty()) { - label->setToolTip(tooltipText); - } - - auto layout = new QHBoxLayout; - layout->addWidget(field, 0, Qt::AlignRight); - - formLayout_->addRow(label, layout); - }; - - formLayout_->addRow(general_); - formLayout_->addRow(new HorizontalLine{this}); - boxWrap( - tr("Minimize to tray"), - trayToggle_, - tr("Keep the application running in the background after closing the client window.")); - boxWrap(tr("Start in tray"), - startInTrayToggle_, - tr("Start the application in the background without showing the client window.")); - formLayout_->addRow(new HorizontalLine{this}); - boxWrap(tr("Circular Avatars"), - avatarCircles_, - tr("Change the appearance of user avatars in chats.\nOFF - square, ON - Circle.")); - boxWrap(tr("Use identicons"), - useIdenticon_, - tr("Display an identicon instead of a letter when a user has not set an avatar.")); - boxWrap(tr("Group's sidebar"), - groupViewToggle_, - tr("Show a column containing groups and tags next to the room list.")); - boxWrap(tr("Decrypt messages in sidebar"), - decryptSidebar_, - tr("Decrypt the messages shown in the sidebar.\nOnly affects messages in " - "encrypted chats.")); - boxWrap(tr("Privacy Screen"), - privacyScreen_, - tr("When the window loses focus, the timeline will\nbe blurred.")); - boxWrap( - tr("Privacy screen timeout (in seconds [0 - 3600])"), - privacyScreenTimeout_, - tr("Set timeout (in seconds) for how long after window loses\nfocus before the screen" - " will be blurred.\nSet to 0 to blur immediately after focus loss. Max value of 1 " - "hour (3600 seconds)")); - boxWrap(tr("Show buttons in timeline"), - timelineButtonsToggle_, - tr("Show buttons to quickly reply, react or access additional options next to each " - "message.")); - boxWrap(tr("Limit width of timeline"), - timelineMaxWidthSpin_, - tr("Set the max width of messages in the timeline (in pixels). This can help " - "readability on wide screen, when Nheko is maximised")); - boxWrap(tr("Typing notifications"), - typingNotifications_, - tr("Show who is typing in a room.\nThis will also enable or disable sending typing " - "notifications to others.")); - boxWrap( - tr("Sort rooms by unreads"), - sortByImportance_, - tr( - "Display rooms with new messages first.\nIf this is off, the list of rooms will only " - "be sorted by the timestamp of the last message in a room.\nIf this is on, rooms which " - "have active notifications (the small circle with a number in it) will be sorted on " - "top. Rooms, that you have muted, will still be sorted by timestamp, since you don't " - "seem to consider them as important as the other rooms.")); - formLayout_->addRow(new HorizontalLine{this}); - boxWrap(tr("Read receipts"), - readReceipts_, - tr("Show if your message was read.\nStatus is displayed next to timestamps.")); - boxWrap( - tr("Send messages as Markdown"), - markdown_, - tr("Allow using markdown in messages.\nWhen disabled, all messages are sent as a plain " - "text.")); - boxWrap(tr("Play animated images only on hover"), - animateImagesOnHover_, - tr("Plays media like GIFs or WEBPs only when explicitly hovering over them.")); - boxWrap(tr("Desktop notifications"), - desktopNotifications_, - tr("Notify about received message when the client is not currently focused.")); - boxWrap(tr("Alert on notification"), - alertOnNotification_, - tr("Show an alert when a message is received.\nThis usually causes the application " - "icon in the task bar to animate in some fashion.")); - boxWrap(tr("Highlight message on hover"), - messageHoverHighlight_, - tr("Change the background color of messages when you hover over them.")); - boxWrap(tr("Large Emoji in timeline"), - enlargeEmojiOnlyMessages_, - tr("Make font size larger if messages with only a few emojis are displayed.")); - formLayout_->addRow(uiLabel_); - formLayout_->addRow(new HorizontalLine{this}); - - boxWrap(tr("Touchscreen mode"), - mobileMode_, - tr("Will prevent text selection in the timeline to make touch scrolling easier.")); + auto layout = new QHBoxLayout; + layout->addWidget(field, 0, Qt::AlignRight); + + formLayout_->addRow(label, layout); + }; + + formLayout_->addRow(general_); + formLayout_->addRow(new HorizontalLine{this}); + boxWrap(tr("Minimize to tray"), + trayToggle_, + tr("Keep the application running in the background after closing the client window.")); + boxWrap(tr("Start in tray"), + startInTrayToggle_, + tr("Start the application in the background without showing the client window.")); + formLayout_->addRow(new HorizontalLine{this}); + boxWrap(tr("Circular Avatars"), + avatarCircles_, + tr("Change the appearance of user avatars in chats.\nOFF - square, ON - Circle.")); + boxWrap(tr("Use identicons"), + useIdenticon_, + tr("Display an identicon instead of a letter when a user has not set an avatar.")); + boxWrap(tr("Group's sidebar"), + groupViewToggle_, + tr("Show a column containing groups and tags next to the room list.")); + boxWrap(tr("Decrypt messages in sidebar"), + decryptSidebar_, + tr("Decrypt the messages shown in the sidebar.\nOnly affects messages in " + "encrypted chats.")); + boxWrap(tr("Privacy Screen"), + privacyScreen_, + tr("When the window loses focus, the timeline will\nbe blurred.")); + boxWrap(tr("Privacy screen timeout (in seconds [0 - 3600])"), + privacyScreenTimeout_, + tr("Set timeout (in seconds) for how long after window loses\nfocus before the screen" + " will be blurred.\nSet to 0 to blur immediately after focus loss. Max value of 1 " + "hour (3600 seconds)")); + boxWrap(tr("Show buttons in timeline"), + timelineButtonsToggle_, + tr("Show buttons to quickly reply, react or access additional options next to each " + "message.")); + boxWrap(tr("Limit width of timeline"), + timelineMaxWidthSpin_, + tr("Set the max width of messages in the timeline (in pixels). This can help " + "readability on wide screen, when Nheko is maximised")); + boxWrap(tr("Typing notifications"), + typingNotifications_, + tr("Show who is typing in a room.\nThis will also enable or disable sending typing " + "notifications to others.")); + boxWrap( + tr("Sort rooms by unreads"), + sortByImportance_, + tr("Display rooms with new messages first.\nIf this is off, the list of rooms will only " + "be sorted by the timestamp of the last message in a room.\nIf this is on, rooms which " + "have active notifications (the small circle with a number in it) will be sorted on " + "top. Rooms, that you have muted, will still be sorted by timestamp, since you don't " + "seem to consider them as important as the other rooms.")); + formLayout_->addRow(new HorizontalLine{this}); + boxWrap(tr("Read receipts"), + readReceipts_, + tr("Show if your message was read.\nStatus is displayed next to timestamps.")); + boxWrap(tr("Send messages as Markdown"), + markdown_, + tr("Allow using markdown in messages.\nWhen disabled, all messages are sent as a plain " + "text.")); + boxWrap(tr("Play animated images only on hover"), + animateImagesOnHover_, + tr("Plays media like GIFs or WEBPs only when explicitly hovering over them.")); + boxWrap(tr("Desktop notifications"), + desktopNotifications_, + tr("Notify about received message when the client is not currently focused.")); + boxWrap(tr("Alert on notification"), + alertOnNotification_, + tr("Show an alert when a message is received.\nThis usually causes the application " + "icon in the task bar to animate in some fashion.")); + boxWrap(tr("Highlight message on hover"), + messageHoverHighlight_, + tr("Change the background color of messages when you hover over them.")); + boxWrap(tr("Large Emoji in timeline"), + enlargeEmojiOnlyMessages_, + tr("Make font size larger if messages with only a few emojis are displayed.")); + formLayout_->addRow(uiLabel_); + formLayout_->addRow(new HorizontalLine{this}); + + boxWrap(tr("Touchscreen mode"), + mobileMode_, + tr("Will prevent text selection in the timeline to make touch scrolling easier.")); #if !defined(Q_OS_MAC) - boxWrap(tr("Scale factor"), - scaleFactorCombo_, - tr("Change the scale factor of the whole user interface.")); + boxWrap(tr("Scale factor"), + scaleFactorCombo_, + tr("Change the scale factor of the whole user interface.")); #else - scaleFactorCombo_->hide(); + scaleFactorCombo_->hide(); #endif - boxWrap(tr("Font size"), fontSizeCombo_); - boxWrap(tr("Font Family"), fontSelectionCombo_); + boxWrap(tr("Font size"), fontSizeCombo_); + boxWrap(tr("Font Family"), fontSelectionCombo_); #if !defined(Q_OS_MAC) - boxWrap(tr("Emoji Font Family"), emojiFontSelectionCombo_); + boxWrap(tr("Emoji Font Family"), emojiFontSelectionCombo_); #else - emojiFontSelectionCombo_->hide(); + emojiFontSelectionCombo_->hide(); #endif - boxWrap(tr("Theme"), themeCombo_); - - formLayout_->addRow(callsLabel); - formLayout_->addRow(new HorizontalLine{this}); - boxWrap(tr("Ringtone"), - ringtoneCombo_, - tr("Set the notification sound to play when a call invite arrives")); - boxWrap(tr("Microphone"), microphoneCombo_); - boxWrap(tr("Camera"), cameraCombo_); - boxWrap(tr("Camera resolution"), cameraResolutionCombo_); - boxWrap(tr("Camera frame rate"), cameraFrameRateCombo_); - - ringtoneCombo_->setSizeAdjustPolicy(QComboBox::AdjustToContents); - ringtoneCombo_->addItem("Mute"); - ringtoneCombo_->addItem("Default"); - ringtoneCombo_->addItem("Other..."); - const QString &ringtone = settings_->ringtone(); - if (!ringtone.isEmpty() && ringtone != "Mute" && ringtone != "Default") - ringtoneCombo_->addItem(ringtone); - microphoneCombo_->setSizeAdjustPolicy(QComboBox::AdjustToContents); - cameraCombo_->setSizeAdjustPolicy(QComboBox::AdjustToContents); - cameraResolutionCombo_->setSizeAdjustPolicy(QComboBox::AdjustToContents); - cameraFrameRateCombo_->setSizeAdjustPolicy(QComboBox::AdjustToContents); - - boxWrap(tr("Allow fallback call assist server"), - useStunServer_, - tr("Will use turn.matrix.org as assist when your home server does not offer one.")); - - formLayout_->addRow(encryptionLabel_); - formLayout_->addRow(new HorizontalLine{this}); - boxWrap(tr("Device ID"), deviceIdValue_); - boxWrap(tr("Device Fingerprint"), deviceFingerprintValue_); - boxWrap(tr("Send encrypted messages to verified users only"), - onlyShareKeysWithVerifiedUsers_, - tr("Requires a user to be verified to send encrypted messages to them. This " - "improves safety but makes E2EE more tedious.")); - boxWrap(tr("Share keys with verified users and devices"), - shareKeysWithTrustedUsers_, - tr("Automatically replies to key requests from other users, if they are verified, " - "even if that device shouldn't have access to those keys otherwise.")); - boxWrap(tr("Online Key Backup"), - useOnlineKeyBackup_, - tr("Download message encryption keys from and upload to the encrypted online key " - "backup.")); - formLayout_->addRow(new HorizontalLine{this}); - formLayout_->addRow(sessionKeysLabel, sessionKeysLayout); - formLayout_->addRow(crossSigningKeysLabel, crossSigningKeysLayout); - - boxWrap(tr("Master signing key"), - masterSecretCached, - tr("Your most important key. You don't need to have it cached, since not caching " - "it makes it less likely it can be stolen and it is only needed to rotate your " - "other signing keys.")); - boxWrap(tr("User signing key"), - userSigningSecretCached, - tr("The key to verify other users. If it is cached, verifying a user will verify " - "all their devices.")); - boxWrap( - tr("Self signing key"), - selfSigningSecretCached, - tr("The key to verify your own devices. If it is cached, verifying one of your devices " - "will mark it verified for all your other devices and for users, that have verified " - "you.")); - boxWrap(tr("Backup key"), - backupSecretCached, - tr("The key to decrypt online key backups. If it is cached, you can enable online " - "key backup to store encryption keys securely encrypted on the server.")); - updateSecretStatus(); - - auto scrollArea_ = new QScrollArea{this}; - scrollArea_->setFrameShape(QFrame::NoFrame); - scrollArea_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - scrollArea_->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); - scrollArea_->setWidgetResizable(true); - scrollArea_->setAlignment(Qt::AlignTop | Qt::AlignVCenter); - - QScroller::grabGesture(scrollArea_, QScroller::TouchGesture); - - auto spacingAroundForm = new QHBoxLayout; - spacingAroundForm->addStretch(1); - spacingAroundForm->addLayout(formLayout_, 0); - spacingAroundForm->addStretch(1); - - auto scrollAreaContents_ = new QWidget{this}; - scrollAreaContents_->setObjectName("UserSettingScrollWidget"); - scrollAreaContents_->setLayout(spacingAroundForm); - - scrollArea_->setWidget(scrollAreaContents_); - topLayout_->addLayout(topBarLayout_); - topLayout_->addWidget(scrollArea_, Qt::AlignTop); - topLayout_->addStretch(1); - topLayout_->addWidget(versionInfo); - - connect(themeCombo_, - static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged), - [this](const QString &text) { - settings_->setTheme(text.toLower()); - emit themeChanged(); - }); - connect(scaleFactorCombo_, - static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged), - [](const QString &factor) { utils::setScaleFactor(factor.toFloat()); }); - connect(fontSizeCombo_, - static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged), - [this](const QString &size) { settings_->setFontSize(size.trimmed().toDouble()); }); - connect(fontSelectionCombo_, - static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged), - [this](const QString &family) { settings_->setFontFamily(family.trimmed()); }); - connect(emojiFontSelectionCombo_, - static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged), - [this](const QString &family) { settings_->setEmojiFontFamily(family.trimmed()); }); - - connect(ringtoneCombo_, - static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged), - [this](const QString &ringtone) { - if (ringtone == "Other...") { - QString homeFolder = - QStandardPaths::writableLocation(QStandardPaths::HomeLocation); - auto filepath = QFileDialog::getOpenFileName( - this, tr("Select a file"), homeFolder, tr("All Files (*)")); - if (!filepath.isEmpty()) { - const auto &oldSetting = settings_->ringtone(); - if (oldSetting != "Mute" && oldSetting != "Default") - ringtoneCombo_->removeItem( - ringtoneCombo_->findText(oldSetting)); - settings_->setRingtone(filepath); - ringtoneCombo_->addItem(filepath); - ringtoneCombo_->setCurrentText(filepath); - } else { - ringtoneCombo_->setCurrentText(settings_->ringtone()); - } - } else if (ringtone == "Mute" || ringtone == "Default") { - const auto &oldSetting = settings_->ringtone(); - if (oldSetting != "Mute" && oldSetting != "Default") - ringtoneCombo_->removeItem( - ringtoneCombo_->findText(oldSetting)); - settings_->setRingtone(ringtone); - } - }); - - connect(microphoneCombo_, - static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged), - [this](const QString µphone) { settings_->setMicrophone(microphone); }); - - connect(cameraCombo_, - static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged), - [this](const QString &camera) { - settings_->setCamera(camera); - std::vector<std::string> resolutions = - CallDevices::instance().resolutions(camera.toStdString()); - cameraResolutionCombo_->clear(); - for (const auto &resolution : resolutions) - cameraResolutionCombo_->addItem(QString::fromStdString(resolution)); - }); - - connect(cameraResolutionCombo_, - static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged), - [this](const QString &resolution) { - settings_->setCameraResolution(resolution); - std::vector<std::string> frameRates = CallDevices::instance().frameRates( - settings_->camera().toStdString(), resolution.toStdString()); - cameraFrameRateCombo_->clear(); - for (const auto &frameRate : frameRates) - cameraFrameRateCombo_->addItem(QString::fromStdString(frameRate)); - }); - - connect(cameraFrameRateCombo_, - static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged), - [this](const QString &frameRate) { settings_->setCameraFrameRate(frameRate); }); - - connect(trayToggle_, &Toggle::toggled, this, [this](bool enabled) { - settings_->setTray(enabled); - if (enabled) { - startInTrayToggle_->setChecked(false); - startInTrayToggle_->setEnabled(true); - startInTrayToggle_->setState(false); - settings_->setStartInTray(false); - } else { - startInTrayToggle_->setChecked(false); - startInTrayToggle_->setState(false); - startInTrayToggle_->setDisabled(true); - settings_->setStartInTray(false); + boxWrap(tr("Theme"), themeCombo_); + + formLayout_->addRow(callsLabel); + formLayout_->addRow(new HorizontalLine{this}); + boxWrap(tr("Ringtone"), + ringtoneCombo_, + tr("Set the notification sound to play when a call invite arrives")); + boxWrap(tr("Microphone"), microphoneCombo_); + boxWrap(tr("Camera"), cameraCombo_); + boxWrap(tr("Camera resolution"), cameraResolutionCombo_); + boxWrap(tr("Camera frame rate"), cameraFrameRateCombo_); + + ringtoneCombo_->setSizeAdjustPolicy(QComboBox::AdjustToContents); + ringtoneCombo_->addItem("Mute"); + ringtoneCombo_->addItem("Default"); + ringtoneCombo_->addItem("Other..."); + const QString &ringtone = settings_->ringtone(); + if (!ringtone.isEmpty() && ringtone != "Mute" && ringtone != "Default") + ringtoneCombo_->addItem(ringtone); + microphoneCombo_->setSizeAdjustPolicy(QComboBox::AdjustToContents); + cameraCombo_->setSizeAdjustPolicy(QComboBox::AdjustToContents); + cameraResolutionCombo_->setSizeAdjustPolicy(QComboBox::AdjustToContents); + cameraFrameRateCombo_->setSizeAdjustPolicy(QComboBox::AdjustToContents); + + boxWrap(tr("Allow fallback call assist server"), + useStunServer_, + tr("Will use turn.matrix.org as assist when your home server does not offer one.")); + + formLayout_->addRow(encryptionLabel_); + formLayout_->addRow(new HorizontalLine{this}); + boxWrap(tr("Device ID"), deviceIdValue_); + boxWrap(tr("Device Fingerprint"), deviceFingerprintValue_); + boxWrap(tr("Send encrypted messages to verified users only"), + onlyShareKeysWithVerifiedUsers_, + tr("Requires a user to be verified to send encrypted messages to them. This " + "improves safety but makes E2EE more tedious.")); + boxWrap(tr("Share keys with verified users and devices"), + shareKeysWithTrustedUsers_, + tr("Automatically replies to key requests from other users, if they are verified, " + "even if that device shouldn't have access to those keys otherwise.")); + boxWrap(tr("Online Key Backup"), + useOnlineKeyBackup_, + tr("Download message encryption keys from and upload to the encrypted online key " + "backup.")); + formLayout_->addRow(new HorizontalLine{this}); + formLayout_->addRow(sessionKeysLabel, sessionKeysLayout); + formLayout_->addRow(crossSigningKeysLabel, crossSigningKeysLayout); + + boxWrap(tr("Master signing key"), + masterSecretCached, + tr("Your most important key. You don't need to have it cached, since not caching " + "it makes it less likely it can be stolen and it is only needed to rotate your " + "other signing keys.")); + boxWrap(tr("User signing key"), + userSigningSecretCached, + tr("The key to verify other users. If it is cached, verifying a user will verify " + "all their devices.")); + boxWrap(tr("Self signing key"), + selfSigningSecretCached, + tr("The key to verify your own devices. If it is cached, verifying one of your devices " + "will mark it verified for all your other devices and for users, that have verified " + "you.")); + boxWrap(tr("Backup key"), + backupSecretCached, + tr("The key to decrypt online key backups. If it is cached, you can enable online " + "key backup to store encryption keys securely encrypted on the server.")); + updateSecretStatus(); + + auto scrollArea_ = new QScrollArea{this}; + scrollArea_->setFrameShape(QFrame::NoFrame); + scrollArea_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + scrollArea_->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); + scrollArea_->setWidgetResizable(true); + scrollArea_->setAlignment(Qt::AlignTop | Qt::AlignVCenter); + + QScroller::grabGesture(scrollArea_, QScroller::TouchGesture); + + auto spacingAroundForm = new QHBoxLayout; + spacingAroundForm->addStretch(1); + spacingAroundForm->addLayout(formLayout_, 0); + spacingAroundForm->addStretch(1); + + auto scrollAreaContents_ = new QWidget{this}; + scrollAreaContents_->setObjectName("UserSettingScrollWidget"); + scrollAreaContents_->setLayout(spacingAroundForm); + + scrollArea_->setWidget(scrollAreaContents_); + topLayout_->addLayout(topBarLayout_); + topLayout_->addWidget(scrollArea_, Qt::AlignTop); + topLayout_->addStretch(1); + topLayout_->addWidget(versionInfo); + + connect(themeCombo_, + static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged), + [this](const QString &text) { + settings_->setTheme(text.toLower()); + emit themeChanged(); + }); + connect(scaleFactorCombo_, + static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged), + [](const QString &factor) { utils::setScaleFactor(factor.toFloat()); }); + connect(fontSizeCombo_, + static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged), + [this](const QString &size) { settings_->setFontSize(size.trimmed().toDouble()); }); + connect(fontSelectionCombo_, + static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged), + [this](const QString &family) { settings_->setFontFamily(family.trimmed()); }); + connect(emojiFontSelectionCombo_, + static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged), + [this](const QString &family) { settings_->setEmojiFontFamily(family.trimmed()); }); + + connect(ringtoneCombo_, + static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged), + [this](const QString &ringtone) { + if (ringtone == "Other...") { + QString homeFolder = + QStandardPaths::writableLocation(QStandardPaths::HomeLocation); + auto filepath = QFileDialog::getOpenFileName( + this, tr("Select a file"), homeFolder, tr("All Files (*)")); + if (!filepath.isEmpty()) { + const auto &oldSetting = settings_->ringtone(); + if (oldSetting != "Mute" && oldSetting != "Default") + ringtoneCombo_->removeItem(ringtoneCombo_->findText(oldSetting)); + settings_->setRingtone(filepath); + ringtoneCombo_->addItem(filepath); + ringtoneCombo_->setCurrentText(filepath); + } else { + ringtoneCombo_->setCurrentText(settings_->ringtone()); + } + } else if (ringtone == "Mute" || ringtone == "Default") { + const auto &oldSetting = settings_->ringtone(); + if (oldSetting != "Mute" && oldSetting != "Default") + ringtoneCombo_->removeItem(ringtoneCombo_->findText(oldSetting)); + settings_->setRingtone(ringtone); } - emit trayOptionChanged(enabled); - }); - - connect(startInTrayToggle_, &Toggle::toggled, this, [this](bool enabled) { - settings_->setStartInTray(enabled); - }); - - connect(mobileMode_, &Toggle::toggled, this, [this](bool enabled) { - settings_->setMobileMode(enabled); - }); + }); + + connect(microphoneCombo_, + static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged), + [this](const QString µphone) { settings_->setMicrophone(microphone); }); + + connect(cameraCombo_, + static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged), + [this](const QString &camera) { + settings_->setCamera(camera); + std::vector<std::string> resolutions = + CallDevices::instance().resolutions(camera.toStdString()); + cameraResolutionCombo_->clear(); + for (const auto &resolution : resolutions) + cameraResolutionCombo_->addItem(QString::fromStdString(resolution)); + }); + + connect(cameraResolutionCombo_, + static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged), + [this](const QString &resolution) { + settings_->setCameraResolution(resolution); + std::vector<std::string> frameRates = CallDevices::instance().frameRates( + settings_->camera().toStdString(), resolution.toStdString()); + cameraFrameRateCombo_->clear(); + for (const auto &frameRate : frameRates) + cameraFrameRateCombo_->addItem(QString::fromStdString(frameRate)); + }); + + connect(cameraFrameRateCombo_, + static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged), + [this](const QString &frameRate) { settings_->setCameraFrameRate(frameRate); }); + + connect(trayToggle_, &Toggle::toggled, this, [this](bool enabled) { + settings_->setTray(enabled); + if (enabled) { + startInTrayToggle_->setChecked(false); + startInTrayToggle_->setEnabled(true); + startInTrayToggle_->setState(false); + settings_->setStartInTray(false); + } else { + startInTrayToggle_->setChecked(false); + startInTrayToggle_->setState(false); + startInTrayToggle_->setDisabled(true); + settings_->setStartInTray(false); + } + emit trayOptionChanged(enabled); + }); - connect(groupViewToggle_, &Toggle::toggled, this, [this](bool enabled) { - settings_->setGroupView(enabled); - }); + connect(startInTrayToggle_, &Toggle::toggled, this, [this](bool enabled) { + settings_->setStartInTray(enabled); + }); - connect(decryptSidebar_, &Toggle::toggled, this, [this](bool enabled) { - settings_->setDecryptSidebar(enabled); - }); + connect(mobileMode_, &Toggle::toggled, this, [this](bool enabled) { + settings_->setMobileMode(enabled); + }); - connect(privacyScreen_, &Toggle::toggled, this, [this](bool enabled) { - settings_->setPrivacyScreen(enabled); - if (enabled) { - privacyScreenTimeout_->setEnabled(true); - } else { - privacyScreenTimeout_->setDisabled(true); - } - }); + connect(groupViewToggle_, &Toggle::toggled, this, [this](bool enabled) { + settings_->setGroupView(enabled); + }); - connect(onlyShareKeysWithVerifiedUsers_, &Toggle::toggled, this, [this](bool enabled) { - settings_->setOnlyShareKeysWithVerifiedUsers(enabled); - }); + connect(decryptSidebar_, &Toggle::toggled, this, [this](bool enabled) { + settings_->setDecryptSidebar(enabled); + }); - connect(shareKeysWithTrustedUsers_, &Toggle::toggled, this, [this](bool enabled) { - settings_->setShareKeysWithTrustedUsers(enabled); - }); + connect(privacyScreen_, &Toggle::toggled, this, [this](bool enabled) { + settings_->setPrivacyScreen(enabled); + if (enabled) { + privacyScreenTimeout_->setEnabled(true); + } else { + privacyScreenTimeout_->setDisabled(true); + } + }); + + connect(onlyShareKeysWithVerifiedUsers_, &Toggle::toggled, this, [this](bool enabled) { + settings_->setOnlyShareKeysWithVerifiedUsers(enabled); + }); + + connect(shareKeysWithTrustedUsers_, &Toggle::toggled, this, [this](bool enabled) { + settings_->setShareKeysWithTrustedUsers(enabled); + }); + + connect(useOnlineKeyBackup_, &Toggle::toggled, this, [this](bool enabled) { + if (enabled) { + if (QMessageBox::question( + this, + tr("Enable online key backup"), + tr("The Nheko authors recommend not enabling online key backup until " + "symmetric online key backup is available. Enable anyway?")) != + QMessageBox::StandardButton::Yes) { + useOnlineKeyBackup_->setState(false); + return; + } + } + settings_->setUseOnlineKeyBackup(enabled); + }); - connect(useOnlineKeyBackup_, &Toggle::toggled, this, [this](bool enabled) { - if (enabled) { - if (QMessageBox::question( - this, - tr("Enable online key backup"), - tr("The Nheko authors recommend not enabling online key backup until " - "symmetric online key backup is available. Enable anyway?")) != - QMessageBox::StandardButton::Yes) { - useOnlineKeyBackup_->setState(false); - return; - } - } - settings_->setUseOnlineKeyBackup(enabled); - }); + connect(avatarCircles_, &Toggle::toggled, this, [this](bool enabled) { + settings_->setAvatarCircles(enabled); + }); - connect(avatarCircles_, &Toggle::toggled, this, [this](bool enabled) { - settings_->setAvatarCircles(enabled); + if (JdenticonProvider::isAvailable()) + connect(useIdenticon_, &Toggle::toggled, this, [this](bool enabled) { + settings_->setUseIdenticon(enabled); }); + else + useIdenticon_->setDisabled(true); - if (JdenticonProvider::isAvailable()) - connect(useIdenticon_, &Toggle::toggled, this, [this](bool enabled) { - settings_->setUseIdenticon(enabled); - }); - else - useIdenticon_->setDisabled(true); + connect( + markdown_, &Toggle::toggled, this, [this](bool enabled) { settings_->setMarkdown(enabled); }); - connect(markdown_, &Toggle::toggled, this, [this](bool enabled) { - settings_->setMarkdown(enabled); - }); + connect(animateImagesOnHover_, &Toggle::toggled, this, [this](bool enabled) { + settings_->setAnimateImagesOnHover(enabled); + }); - connect(animateImagesOnHover_, &Toggle::toggled, this, [this](bool enabled) { - settings_->setAnimateImagesOnHover(enabled); - }); + connect(typingNotifications_, &Toggle::toggled, this, [this](bool enabled) { + settings_->setTypingNotifications(enabled); + }); - connect(typingNotifications_, &Toggle::toggled, this, [this](bool enabled) { - settings_->setTypingNotifications(enabled); - }); + connect(sortByImportance_, &Toggle::toggled, this, [this](bool enabled) { + settings_->setSortByImportance(enabled); + }); - connect(sortByImportance_, &Toggle::toggled, this, [this](bool enabled) { - settings_->setSortByImportance(enabled); - }); + connect(timelineButtonsToggle_, &Toggle::toggled, this, [this](bool enabled) { + settings_->setButtonsInTimeline(enabled); + }); - connect(timelineButtonsToggle_, &Toggle::toggled, this, [this](bool enabled) { - settings_->setButtonsInTimeline(enabled); - }); + connect(readReceipts_, &Toggle::toggled, this, [this](bool enabled) { + settings_->setReadReceipts(enabled); + }); - connect(readReceipts_, &Toggle::toggled, this, [this](bool enabled) { - settings_->setReadReceipts(enabled); - }); + connect(desktopNotifications_, &Toggle::toggled, this, [this](bool enabled) { + settings_->setDesktopNotifications(enabled); + }); - connect(desktopNotifications_, &Toggle::toggled, this, [this](bool enabled) { - settings_->setDesktopNotifications(enabled); - }); - - connect(alertOnNotification_, &Toggle::toggled, this, [this](bool enabled) { - settings_->setAlertOnNotification(enabled); - }); + connect(alertOnNotification_, &Toggle::toggled, this, [this](bool enabled) { + settings_->setAlertOnNotification(enabled); + }); - connect(messageHoverHighlight_, &Toggle::toggled, this, [this](bool enabled) { - settings_->setMessageHoverHighlight(enabled); - }); + connect(messageHoverHighlight_, &Toggle::toggled, this, [this](bool enabled) { + settings_->setMessageHoverHighlight(enabled); + }); - connect(enlargeEmojiOnlyMessages_, &Toggle::toggled, this, [this](bool enabled) { - settings_->setEnlargeEmojiOnlyMessages(enabled); - }); + connect(enlargeEmojiOnlyMessages_, &Toggle::toggled, this, [this](bool enabled) { + settings_->setEnlargeEmojiOnlyMessages(enabled); + }); - connect(useStunServer_, &Toggle::toggled, this, [this](bool enabled) { - settings_->setUseStunServer(enabled); - }); + connect(useStunServer_, &Toggle::toggled, this, [this](bool enabled) { + settings_->setUseStunServer(enabled); + }); - connect(timelineMaxWidthSpin_, - qOverload<int>(&QSpinBox::valueChanged), - this, - [this](int newValue) { settings_->setTimelineMaxWidth(newValue); }); + connect(timelineMaxWidthSpin_, + qOverload<int>(&QSpinBox::valueChanged), + this, + [this](int newValue) { settings_->setTimelineMaxWidth(newValue); }); - connect(privacyScreenTimeout_, - qOverload<int>(&QSpinBox::valueChanged), - this, - [this](int newValue) { settings_->setPrivacyScreenTimeout(newValue); }); + connect(privacyScreenTimeout_, + qOverload<int>(&QSpinBox::valueChanged), + this, + [this](int newValue) { settings_->setPrivacyScreenTimeout(newValue); }); - connect( - sessionKeysImportBtn, &QPushButton::clicked, this, &UserSettingsPage::importSessionKeys); + connect( + sessionKeysImportBtn, &QPushButton::clicked, this, &UserSettingsPage::importSessionKeys); - connect( - sessionKeysExportBtn, &QPushButton::clicked, this, &UserSettingsPage::exportSessionKeys); + connect( + sessionKeysExportBtn, &QPushButton::clicked, this, &UserSettingsPage::exportSessionKeys); - connect(crossSigningRequestBtn, &QPushButton::clicked, this, []() { - olm::request_cross_signing_keys(); - }); + connect(crossSigningRequestBtn, &QPushButton::clicked, this, []() { + olm::request_cross_signing_keys(); + }); - connect(crossSigningDownloadBtn, &QPushButton::clicked, this, []() { - olm::download_cross_signing_keys(); - }); + connect(crossSigningDownloadBtn, &QPushButton::clicked, this, []() { + olm::download_cross_signing_keys(); + }); - connect(backBtn_, &QPushButton::clicked, this, [this]() { - settings_->save(); - emit moveBack(); - }); + connect(backBtn_, &QPushButton::clicked, this, [this]() { + settings_->save(); + emit moveBack(); + }); } void UserSettingsPage::showEvent(QShowEvent *) { - // FIXME macOS doesn't show the full option unless a space is added. - utils::restoreCombobox(fontSizeCombo_, QString::number(settings_->fontSize()) + " "); - utils::restoreCombobox(scaleFactorCombo_, QString::number(utils::scaleFactor())); - utils::restoreCombobox(themeCombo_, settings_->theme()); - utils::restoreCombobox(ringtoneCombo_, settings_->ringtone()); - - trayToggle_->setState(settings_->tray()); - startInTrayToggle_->setState(settings_->startInTray()); - groupViewToggle_->setState(settings_->groupView()); - decryptSidebar_->setState(settings_->decryptSidebar()); - privacyScreen_->setState(settings_->privacyScreen()); - onlyShareKeysWithVerifiedUsers_->setState(settings_->onlyShareKeysWithVerifiedUsers()); - shareKeysWithTrustedUsers_->setState(settings_->shareKeysWithTrustedUsers()); - useOnlineKeyBackup_->setState(settings_->useOnlineKeyBackup()); - avatarCircles_->setState(settings_->avatarCircles()); - typingNotifications_->setState(settings_->typingNotifications()); - sortByImportance_->setState(settings_->sortByImportance()); - timelineButtonsToggle_->setState(settings_->buttonsInTimeline()); - mobileMode_->setState(settings_->mobileMode()); - readReceipts_->setState(settings_->readReceipts()); - markdown_->setState(settings_->markdown()); - desktopNotifications_->setState(settings_->hasDesktopNotifications()); - alertOnNotification_->setState(settings_->hasAlertOnNotification()); - messageHoverHighlight_->setState(settings_->messageHoverHighlight()); - enlargeEmojiOnlyMessages_->setState(settings_->enlargeEmojiOnlyMessages()); - deviceIdValue_->setText(QString::fromStdString(http::client()->device_id())); - timelineMaxWidthSpin_->setValue(settings_->timelineMaxWidth()); - privacyScreenTimeout_->setValue(settings_->privacyScreenTimeout()); - - auto mics = CallDevices::instance().names(false, settings_->microphone().toStdString()); - microphoneCombo_->clear(); - for (const auto &m : mics) - microphoneCombo_->addItem(QString::fromStdString(m)); - - auto cameraResolution = settings_->cameraResolution(); - auto cameraFrameRate = settings_->cameraFrameRate(); - - auto cameras = CallDevices::instance().names(true, settings_->camera().toStdString()); - cameraCombo_->clear(); - for (const auto &c : cameras) - cameraCombo_->addItem(QString::fromStdString(c)); - - utils::restoreCombobox(cameraResolutionCombo_, cameraResolution); - utils::restoreCombobox(cameraFrameRateCombo_, cameraFrameRate); - - useStunServer_->setState(settings_->useStunServer()); - - deviceFingerprintValue_->setText( - utils::humanReadableFingerprint(olm::client()->identity_keys().ed25519)); + // FIXME macOS doesn't show the full option unless a space is added. + utils::restoreCombobox(fontSizeCombo_, QString::number(settings_->fontSize()) + " "); + utils::restoreCombobox(scaleFactorCombo_, QString::number(utils::scaleFactor())); + utils::restoreCombobox(themeCombo_, settings_->theme()); + utils::restoreCombobox(ringtoneCombo_, settings_->ringtone()); + + trayToggle_->setState(settings_->tray()); + startInTrayToggle_->setState(settings_->startInTray()); + groupViewToggle_->setState(settings_->groupView()); + decryptSidebar_->setState(settings_->decryptSidebar()); + privacyScreen_->setState(settings_->privacyScreen()); + onlyShareKeysWithVerifiedUsers_->setState(settings_->onlyShareKeysWithVerifiedUsers()); + shareKeysWithTrustedUsers_->setState(settings_->shareKeysWithTrustedUsers()); + useOnlineKeyBackup_->setState(settings_->useOnlineKeyBackup()); + avatarCircles_->setState(settings_->avatarCircles()); + typingNotifications_->setState(settings_->typingNotifications()); + sortByImportance_->setState(settings_->sortByImportance()); + timelineButtonsToggle_->setState(settings_->buttonsInTimeline()); + mobileMode_->setState(settings_->mobileMode()); + readReceipts_->setState(settings_->readReceipts()); + markdown_->setState(settings_->markdown()); + desktopNotifications_->setState(settings_->hasDesktopNotifications()); + alertOnNotification_->setState(settings_->hasAlertOnNotification()); + messageHoverHighlight_->setState(settings_->messageHoverHighlight()); + enlargeEmojiOnlyMessages_->setState(settings_->enlargeEmojiOnlyMessages()); + deviceIdValue_->setText(QString::fromStdString(http::client()->device_id())); + timelineMaxWidthSpin_->setValue(settings_->timelineMaxWidth()); + privacyScreenTimeout_->setValue(settings_->privacyScreenTimeout()); + + auto mics = CallDevices::instance().names(false, settings_->microphone().toStdString()); + microphoneCombo_->clear(); + for (const auto &m : mics) + microphoneCombo_->addItem(QString::fromStdString(m)); + + auto cameraResolution = settings_->cameraResolution(); + auto cameraFrameRate = settings_->cameraFrameRate(); + + auto cameras = CallDevices::instance().names(true, settings_->camera().toStdString()); + cameraCombo_->clear(); + for (const auto &c : cameras) + cameraCombo_->addItem(QString::fromStdString(c)); + + utils::restoreCombobox(cameraResolutionCombo_, cameraResolution); + utils::restoreCombobox(cameraFrameRateCombo_, cameraFrameRate); + + useStunServer_->setState(settings_->useStunServer()); + + deviceFingerprintValue_->setText( + utils::humanReadableFingerprint(olm::client()->identity_keys().ed25519)); } void UserSettingsPage::paintEvent(QPaintEvent *) { - QStyleOption opt; - opt.init(this); - QPainter p(this); - style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); + QStyleOption opt; + opt.init(this); + QPainter p(this); + style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } void UserSettingsPage::importSessionKeys() { - const QString homeFolder = QStandardPaths::writableLocation(QStandardPaths::HomeLocation); - const QString fileName = - QFileDialog::getOpenFileName(this, tr("Open Sessions File"), homeFolder, ""); - - QFile file(fileName); - if (!file.open(QIODevice::ReadOnly)) { - QMessageBox::warning(this, tr("Error"), file.errorString()); - return; - } - - auto bin = file.peek(file.size()); - auto payload = std::string(bin.data(), bin.size()); - - bool ok; - auto password = QInputDialog::getText(this, - tr("File Password"), - tr("Enter the passphrase to decrypt the file:"), - QLineEdit::Password, - "", - &ok); - if (!ok) - return; - - if (password.isEmpty()) { - QMessageBox::warning(this, tr("Error"), tr("The password cannot be empty")); - return; - } - - try { - auto sessions = - mtx::crypto::decrypt_exported_sessions(payload, password.toStdString()); - cache::importSessionKeys(std::move(sessions)); - } catch (const std::exception &e) { - QMessageBox::warning(this, tr("Error"), e.what()); - } + const QString homeFolder = QStandardPaths::writableLocation(QStandardPaths::HomeLocation); + const QString fileName = + QFileDialog::getOpenFileName(this, tr("Open Sessions File"), homeFolder, ""); + + QFile file(fileName); + if (!file.open(QIODevice::ReadOnly)) { + QMessageBox::warning(this, tr("Error"), file.errorString()); + return; + } + + auto bin = file.peek(file.size()); + auto payload = std::string(bin.data(), bin.size()); + + bool ok; + auto password = QInputDialog::getText(this, + tr("File Password"), + tr("Enter the passphrase to decrypt the file:"), + QLineEdit::Password, + "", + &ok); + if (!ok) + return; + + if (password.isEmpty()) { + QMessageBox::warning(this, tr("Error"), tr("The password cannot be empty")); + return; + } + + try { + auto sessions = mtx::crypto::decrypt_exported_sessions(payload, password.toStdString()); + cache::importSessionKeys(std::move(sessions)); + } catch (const std::exception &e) { + QMessageBox::warning(this, tr("Error"), e.what()); + } } void UserSettingsPage::exportSessionKeys() { - // Open password dialog. - bool ok; - auto password = QInputDialog::getText(this, - tr("File Password"), - tr("Enter passphrase to encrypt your session keys:"), - QLineEdit::Password, - "", - &ok); - if (!ok) - return; - - if (password.isEmpty()) { - QMessageBox::warning(this, tr("Error"), tr("The password cannot be empty")); - return; - } - - // Open file dialog to save the file. - const QString homeFolder = QStandardPaths::writableLocation(QStandardPaths::HomeLocation); - const QString fileName = - QFileDialog::getSaveFileName(this, tr("File to save the exported session keys"), "", ""); - - QFile file(fileName); - if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { - QMessageBox::warning(this, tr("Error"), file.errorString()); - return; - } - - // Export sessions & save to file. - try { - auto encrypted_blob = mtx::crypto::encrypt_exported_sessions( - cache::exportSessionKeys(), password.toStdString()); - - QString b64 = QString::fromStdString(mtx::crypto::bin2base64(encrypted_blob)); - - QString prefix("-----BEGIN MEGOLM SESSION DATA-----"); - QString suffix("-----END MEGOLM SESSION DATA-----"); - QString newline("\n"); - QTextStream out(&file); - out << prefix << newline << b64 << newline << suffix << newline; - file.close(); - } catch (const std::exception &e) { - QMessageBox::warning(this, tr("Error"), e.what()); - } + // Open password dialog. + bool ok; + auto password = QInputDialog::getText(this, + tr("File Password"), + tr("Enter passphrase to encrypt your session keys:"), + QLineEdit::Password, + "", + &ok); + if (!ok) + return; + + if (password.isEmpty()) { + QMessageBox::warning(this, tr("Error"), tr("The password cannot be empty")); + return; + } + + // Open file dialog to save the file. + const QString homeFolder = QStandardPaths::writableLocation(QStandardPaths::HomeLocation); + const QString fileName = + QFileDialog::getSaveFileName(this, tr("File to save the exported session keys"), "", ""); + + QFile file(fileName); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + QMessageBox::warning(this, tr("Error"), file.errorString()); + return; + } + + // Export sessions & save to file. + try { + auto encrypted_blob = mtx::crypto::encrypt_exported_sessions(cache::exportSessionKeys(), + password.toStdString()); + + QString b64 = QString::fromStdString(mtx::crypto::bin2base64(encrypted_blob)); + + QString prefix("-----BEGIN MEGOLM SESSION DATA-----"); + QString suffix("-----END MEGOLM SESSION DATA-----"); + QString newline("\n"); + QTextStream out(&file); + out << prefix << newline << b64 << newline << suffix << newline; + file.close(); + } catch (const std::exception &e) { + QMessageBox::warning(this, tr("Error"), e.what()); + } } void UserSettingsPage::updateSecretStatus() { - QString ok = "QLabel { color : #00cc66; }"; - QString notSoOk = "QLabel { color : #ff9933; }"; - - auto updateLabel = [&ok, ¬SoOk](QLabel *label, const std::string &secretName) { - if (cache::secret(secretName)) { - label->setStyleSheet(ok); - label->setText(tr("CACHED")); - } else { - if (secretName == mtx::secret_storage::secrets::cross_signing_master) - label->setStyleSheet(ok); - else - label->setStyleSheet(notSoOk); - label->setText(tr("NOT CACHED")); - } - }; - - updateLabel(masterSecretCached, mtx::secret_storage::secrets::cross_signing_master); - updateLabel(userSigningSecretCached, - mtx::secret_storage::secrets::cross_signing_user_signing); - updateLabel(selfSigningSecretCached, - mtx::secret_storage::secrets::cross_signing_self_signing); - updateLabel(backupSecretCached, mtx::secret_storage::secrets::megolm_backup_v1); + QString ok = "QLabel { color : #00cc66; }"; + QString notSoOk = "QLabel { color : #ff9933; }"; + + auto updateLabel = [&ok, ¬SoOk](QLabel *label, const std::string &secretName) { + if (cache::secret(secretName)) { + label->setStyleSheet(ok); + label->setText(tr("CACHED")); + } else { + if (secretName == mtx::secret_storage::secrets::cross_signing_master) + label->setStyleSheet(ok); + else + label->setStyleSheet(notSoOk); + label->setText(tr("NOT CACHED")); + } + }; + + updateLabel(masterSecretCached, mtx::secret_storage::secrets::cross_signing_master); + updateLabel(userSigningSecretCached, mtx::secret_storage::secrets::cross_signing_user_signing); + updateLabel(selfSigningSecretCached, mtx::secret_storage::secrets::cross_signing_self_signing); + updateLabel(backupSecretCached, mtx::secret_storage::secrets::megolm_backup_v1); } |