tdesktop/Telegram/SourceFiles/settings/settings_advanced.cpp

958 lines
27 KiB
C++
Raw Normal View History

2018-09-05 19:05:49 +00:00
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
2018-09-20 16:47:02 +00:00
#include "settings/settings_advanced.h"
2018-09-05 19:05:49 +00:00
#include "settings/settings_common.h"
#include "settings/settings_chat.h"
#include "settings/settings_experimental.h"
2023-02-21 12:31:55 +00:00
#include "settings/settings_power_saving.h"
2018-09-05 19:05:49 +00:00
#include "ui/wrap/vertical_layout.h"
2018-09-07 09:40:25 +00:00
#include "ui/wrap/slide_wrap.h"
#include "ui/widgets/labels.h"
2018-09-13 20:09:26 +00:00
#include "ui/widgets/checkbox.h"
#include "ui/widgets/buttons.h"
2021-07-01 07:47:29 +00:00
#include "ui/gl/gl_detection.h"
2019-06-17 16:59:43 +00:00
#include "ui/text/text_utilities.h" // Ui::Text::ToUpper
#include "ui/text/format_values.h"
2021-07-01 07:47:29 +00:00
#include "ui/boxes/single_choice_box.h"
#include "ui/painter.h"
2018-09-07 09:40:25 +00:00
#include "boxes/connection_box.h"
#include "boxes/about_box.h"
2021-10-18 21:36:55 +00:00
#include "ui/boxes/confirm_box.h"
2018-09-07 09:40:25 +00:00
#include "platform/platform_specific.h"
2021-07-25 21:30:56 +00:00
#include "ui/platform/ui_platform_window.h"
#include "base/platform/base_platform_custom_app_icon.h"
2019-09-17 16:13:12 +00:00
#include "base/platform/base_platform_info.h"
#include "window/window_controller.h"
2019-07-24 14:00:30 +00:00
#include "window/window_session_controller.h"
2018-09-05 19:05:49 +00:00
#include "lang/lang_keys.h"
2018-09-07 09:40:25 +00:00
#include "core/update_checker.h"
#include "core/application.h"
#include "tray.h"
2018-09-07 09:40:25 +00:00
#include "storage/localstorage.h"
#include "storage/storage_domain.h"
#include "data/data_session.h"
#include "main/main_account.h"
#include "main/main_domain.h"
2019-07-24 11:45:24 +00:00
#include "main/main_session.h"
#include "mtproto/facade.h"
2018-09-05 19:05:49 +00:00
#include "styles/style_settings.h"
2022-01-31 21:43:20 +00:00
#ifdef Q_OS_MAC
#include "base/platform/mac/base_confirm_quit.h"
#endif // Q_OS_MAC
2019-11-13 06:52:44 +00:00
#ifndef TDESKTOP_DISABLE_SPELLCHECK
#include "boxes/dictionaries_manager.h"
#include "chat_helpers/spellchecker_common.h"
2019-11-13 06:52:44 +00:00
#include "spellcheck/platform/platform_spellcheck.h"
#endif // !TDESKTOP_DISABLE_SPELLCHECK
2018-09-05 19:05:49 +00:00
namespace Settings {
namespace {
[[nodiscard]] const QImage &IconMacRound() {
static const auto result = QImage(u":/gui/art/icon_round512@2x.png"_q);
return result;
}
} // namespace
2018-09-11 18:07:04 +00:00
2020-06-10 14:52:44 +00:00
void SetupConnectionType(
not_null<Window::Controller*> controller,
2020-06-10 14:52:44 +00:00
not_null<Main::Account*> account,
not_null<Ui::VerticalLayout*> container) {
const auto connectionType = [=] {
const auto transport = account->mtp().dctransport();
if (!Core::App().settings().proxy().isEnabled()) {
2018-09-07 09:40:25 +00:00
return transport.isEmpty()
2019-06-19 15:09:03 +00:00
? tr::lng_connection_auto_connecting(tr::now)
: tr::lng_connection_auto(tr::now, lt_transport, transport);
2018-09-07 09:40:25 +00:00
} else {
return transport.isEmpty()
2019-06-19 15:09:03 +00:00
? tr::lng_connection_proxy_connecting(tr::now)
: tr::lng_connection_proxy(tr::now, lt_transport, transport);
2018-09-07 09:40:25 +00:00
}
};
const auto button = AddButtonWithLabel(
container,
2019-06-18 12:16:43 +00:00
tr::lng_settings_connection_type(),
rpl::merge(
Core::App().settings().proxy().connectionTypeChanges(),
// Handle language switch.
tr::lng_connection_auto_connecting() | rpl::to_empty
) | rpl::map(connectionType),
2022-02-18 16:26:57 +00:00
st::settingsButton,
{ &st::settingsIconArrows, kIconGreen });
2020-06-10 14:52:44 +00:00
button->addClickHandler([=] {
controller->show(ProxiesBoxController::CreateOwningBox(account));
2018-09-07 09:40:25 +00:00
});
}
2018-09-11 18:07:04 +00:00
bool HasUpdate() {
return !Core::UpdaterDisabled();
}
void SetupUpdate(
not_null<Ui::VerticalLayout*> container,
Fn<void(Type)> showOther) {
2018-09-11 18:07:04 +00:00
if (!HasUpdate()) {
2018-09-07 09:40:25 +00:00
return;
}
2018-11-21 10:09:46 +00:00
const auto texts = Ui::CreateChild<rpl::event_stream<QString>>(
container.get());
const auto downloading = Ui::CreateChild<rpl::event_stream<bool>>(
container.get());
const auto version = tr::lng_settings_current_version(
tr::now,
2018-09-07 09:40:25 +00:00
lt_version,
currentVersionText());
const auto toggle = AddButton(
container,
2019-06-18 12:16:43 +00:00
tr::lng_settings_update_automatically(),
2018-09-07 09:40:25 +00:00
st::settingsUpdateToggle);
const auto label = Ui::CreateChild<Ui::FlatLabel>(
toggle.get(),
texts->events(),
st::settingsUpdateState);
const auto options = container->add(
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
2018-09-07 09:40:25 +00:00
container,
object_ptr<Ui::VerticalLayout>(container)));
const auto inner = options->entity();
const auto install = cAlphaVersion() ? nullptr : AddButton(
inner,
2019-06-18 12:16:43 +00:00
tr::lng_settings_install_beta(),
st::settingsButtonNoIcon).get();
if (showOther) {
const auto experimental = inner->add(
object_ptr<Ui::SlideWrap<Button>>(
inner,
CreateButton(
inner,
tr::lng_settings_experimental(),
st::settingsButtonNoIcon)));
if (!install) {
experimental->toggle(true, anim::type::instant);
} else {
experimental->toggleOn(install->toggledValue());
}
experimental->entity()->setClickedCallback([=] {
showOther(Experimental::Id());
});
}
const auto check = AddButton(
inner,
2019-06-18 12:16:43 +00:00
tr::lng_settings_check_now(),
st::settingsButtonNoIcon);
2018-09-07 09:40:25 +00:00
const auto update = Ui::CreateChild<Button>(
check.get(),
2019-06-18 12:16:43 +00:00
tr::lng_update_telegram() | Ui::Text::ToUpper(),
2018-09-07 09:40:25 +00:00
st::settingsUpdate);
update->hide();
check->widthValue() | rpl::start_with_next([=](int width) {
2018-09-07 09:40:25 +00:00
update->resizeToWidth(width);
update->moveToLeft(0, 0);
2018-09-07 12:19:56 +00:00
}, update->lifetime());
2018-09-07 09:40:25 +00:00
rpl::combine(
toggle->widthValue(),
label->widthValue()
) | rpl::start_with_next([=] {
label->moveToLeft(
st::settingsUpdateStatePosition.x(),
st::settingsUpdateStatePosition.y());
}, label->lifetime());
label->setAttribute(Qt::WA_TransparentForMouseEvents);
const auto showDownloadProgress = [=](int64 ready, int64 total) {
texts->fire(tr::lng_settings_downloading_update(
tr::now,
2018-09-07 09:40:25 +00:00
lt_progress,
Ui::FormatDownloadText(ready, total)));
2018-09-07 09:40:25 +00:00
downloading->fire(true);
};
const auto setDefaultStatus = [=](const Core::UpdateChecker &checker) {
using State = Core::UpdateChecker::State;
const auto state = checker.state();
switch (state) {
case State::Download:
showDownloadProgress(checker.already(), checker.size());
break;
case State::Ready:
2019-06-19 15:09:03 +00:00
texts->fire(tr::lng_settings_update_ready(tr::now));
2018-09-07 09:40:25 +00:00
update->show();
break;
default:
texts->fire_copy(version);
break;
}
};
toggle->toggleOn(rpl::single(cAutoUpdate()));
toggle->toggledValue(
) | rpl::filter([](bool toggled) {
return (toggled != cAutoUpdate());
}) | rpl::start_with_next([=](bool toggled) {
cSetAutoUpdate(toggled);
Local::writeSettings();
Core::UpdateChecker checker;
if (cAutoUpdate()) {
checker.start();
} else {
checker.stop();
setDefaultStatus(checker);
2018-09-07 09:40:25 +00:00
}
2018-09-07 12:19:56 +00:00
}, toggle->lifetime());
2018-09-07 09:40:25 +00:00
if (install) {
install->toggleOn(rpl::single(cInstallBetaVersion()));
install->toggledValue(
) | rpl::filter([](bool toggled) {
return (toggled != cInstallBetaVersion());
}) | rpl::start_with_next([=](bool toggled) {
cSetInstallBetaVersion(toggled);
Core::App().writeInstallBetaVersionsSetting();
Core::UpdateChecker checker;
checker.stop();
if (toggled) {
cSetLastUpdateCheck(0);
}
checker.start();
}, toggle->lifetime());
}
2018-09-07 09:40:25 +00:00
Core::UpdateChecker checker;
options->toggleOn(rpl::combine(
2018-09-07 09:40:25 +00:00
toggle->toggledValue(),
downloading->events_starting_with(
checker.state() == Core::UpdateChecker::State::Download)
) | rpl::map([](bool check, bool downloading) {
return check && !downloading;
}));
checker.checking() | rpl::start_with_next([=] {
options->setAttribute(Qt::WA_TransparentForMouseEvents);
2019-06-19 15:09:03 +00:00
texts->fire(tr::lng_settings_update_checking(tr::now));
2018-09-07 09:40:25 +00:00
downloading->fire(false);
}, options->lifetime());
2018-09-07 09:40:25 +00:00
checker.isLatest() | rpl::start_with_next([=] {
options->setAttribute(Qt::WA_TransparentForMouseEvents, false);
2019-06-19 15:09:03 +00:00
texts->fire(tr::lng_settings_latest_installed(tr::now));
2018-09-07 09:40:25 +00:00
downloading->fire(false);
}, options->lifetime());
2018-09-07 09:40:25 +00:00
checker.progress(
) | rpl::start_with_next([=](Core::UpdateChecker::Progress progress) {
showDownloadProgress(progress.already, progress.size);
}, options->lifetime());
2018-09-07 09:40:25 +00:00
checker.failed() | rpl::start_with_next([=] {
options->setAttribute(Qt::WA_TransparentForMouseEvents, false);
2019-06-19 15:09:03 +00:00
texts->fire(tr::lng_settings_update_fail(tr::now));
2018-09-07 09:40:25 +00:00
downloading->fire(false);
}, options->lifetime());
2018-09-07 09:40:25 +00:00
checker.ready() | rpl::start_with_next([=] {
options->setAttribute(Qt::WA_TransparentForMouseEvents, false);
2019-06-19 15:09:03 +00:00
texts->fire(tr::lng_settings_update_ready(tr::now));
2018-09-07 09:40:25 +00:00
update->show();
downloading->fire(false);
}, options->lifetime());
2018-09-07 09:40:25 +00:00
setDefaultStatus(checker);
check->addClickHandler([] {
2018-09-07 09:40:25 +00:00
Core::UpdateChecker checker;
cSetLastUpdateCheck(0);
checker.start();
});
update->addClickHandler([] {
if (!Core::UpdaterDisabled()) {
Core::checkReadyUpdate();
}
Core::Restart();
2018-09-07 09:40:25 +00:00
});
}
bool HasSystemSpellchecker() {
#ifdef TDESKTOP_DISABLE_SPELLCHECK
return false;
#endif // TDESKTOP_DISABLE_SPELLCHECK
return true;
}
void SetupSpellchecker(
not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container) {
#ifndef TDESKTOP_DISABLE_SPELLCHECK
const auto session = &controller->session();
const auto settings = &Core::App().settings();
const auto isSystem = Platform::Spellchecker::IsSystemSpellchecker();
const auto button = AddButton(
container,
isSystem
? tr::lng_settings_system_spellchecker()
: tr::lng_settings_custom_spellchecker(),
st::settingsButtonNoIcon
)->toggleOn(
rpl::single(settings->spellcheckerEnabled())
);
button->toggledValue(
) | rpl::filter([=](bool enabled) {
return (enabled != settings->spellcheckerEnabled());
}) | rpl::start_with_next([=](bool enabled) {
settings->setSpellcheckerEnabled(enabled);
Core::App().saveSettingsDelayed();
}, container->lifetime());
if (isSystem) {
return;
}
const auto sliding = container->add(
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
container,
object_ptr<Ui::VerticalLayout>(container)));
AddButton(
sliding->entity(),
tr::lng_settings_auto_download_dictionaries(),
st::settingsButtonNoIcon
)->toggleOn(
rpl::single(settings->autoDownloadDictionaries())
)->toggledValue(
) | rpl::filter([=](bool enabled) {
return (enabled != settings->autoDownloadDictionaries());
}) | rpl::start_with_next([=](bool enabled) {
settings->setAutoDownloadDictionaries(enabled);
Core::App().saveSettingsDelayed();
}, sliding->entity()->lifetime());
AddButtonWithLabel(
sliding->entity(),
tr::lng_settings_manage_dictionaries(),
Spellchecker::ButtonManageDictsState(session),
st::settingsButtonNoIcon
)->addClickHandler([=] {
controller->show(
Box<Ui::ManageDictionariesBox>(&controller->session()));
});
button->toggledValue(
) | rpl::start_with_next([=](bool enabled) {
sliding->toggle(enabled, anim::type::normal);
}, container->lifetime());
#endif // !TDESKTOP_DISABLE_SPELLCHECK
}
void SetupWindowTitleContent(
Window::SessionController *controller,
not_null<Ui::VerticalLayout*> container) {
const auto checkbox = [&](rpl::producer<QString> &&label, bool checked) {
return object_ptr<Ui::Checkbox>(
container,
std::move(label),
checked,
st::settingsCheckbox);
};
const auto addCheckbox = [&](
rpl::producer<QString> &&label,
bool checked) {
return container->add(
checkbox(std::move(label), checked),
st::settingsCheckboxPadding);
};
const auto settings = &Core::App().settings();
if (controller) {
const auto content = [=] {
return settings->windowTitleContent();
};
const auto showChatName = addCheckbox(
tr::lng_settings_title_chat_name(),
!content().hideChatName);
showChatName->checkedChanges(
) | rpl::filter([=](bool checked) {
return (checked == content().hideChatName);
}) | rpl::start_with_next([=](bool checked) {
auto updated = content();
updated.hideChatName = !checked;
settings->setWindowTitleContent(updated);
Core::App().saveSettingsDelayed();
}, showChatName->lifetime());
if (Core::App().domain().accountsAuthedCount() > 1) {
const auto showAccountName = addCheckbox(
tr::lng_settings_title_account_name(),
!content().hideAccountName);
showAccountName->checkedChanges(
) | rpl::filter([=](bool checked) {
return (checked == content().hideAccountName);
}) | rpl::start_with_next([=](bool checked) {
auto updated = content();
updated.hideAccountName = !checked;
settings->setWindowTitleContent(updated);
Core::App().saveSettingsDelayed();
}, showAccountName->lifetime());
}
const auto showTotalUnread = addCheckbox(
tr::lng_settings_title_total_count(),
!content().hideTotalUnread);
showTotalUnread->checkedChanges(
) | rpl::filter([=](bool checked) {
return (checked == content().hideTotalUnread);
}) | rpl::start_with_next([=](bool checked) {
auto updated = content();
updated.hideTotalUnread = !checked;
settings->setWindowTitleContent(updated);
Core::App().saveSettingsDelayed();
}, showTotalUnread->lifetime());
}
if (Ui::Platform::NativeWindowFrameSupported()) {
const auto nativeFrame = addCheckbox(
tr::lng_settings_native_frame(),
Core::App().settings().nativeWindowFrame());
nativeFrame->checkedChanges(
) | rpl::filter([](bool checked) {
return (checked != Core::App().settings().nativeWindowFrame());
}) | rpl::start_with_next([=](bool checked) {
Core::App().settings().setNativeWindowFrame(checked);
Core::App().saveSettingsDelayed();
}, nativeFrame->lifetime());
}
}
void SetupSystemIntegrationContent(
Window::SessionController *controller,
not_null<Ui::VerticalLayout*> container) {
2021-05-27 22:11:16 +00:00
using WorkMode = Core::Settings::WorkMode;
const auto checkbox = [&](rpl::producer<QString> &&label, bool checked) {
2018-09-13 20:09:26 +00:00
return object_ptr<Ui::Checkbox>(
container,
std::move(label),
2018-09-13 20:09:26 +00:00
checked,
st::settingsCheckbox);
};
const auto addCheckbox = [&](
rpl::producer<QString> &&label,
bool checked) {
2018-09-13 20:09:26 +00:00
return container->add(
checkbox(std::move(label), checked),
2018-09-13 20:09:26 +00:00
st::settingsCheckboxPadding);
};
const auto addSlidingCheckbox = [&](
rpl::producer<QString> &&label,
bool checked) {
2018-09-13 20:09:26 +00:00
return container->add(
object_ptr<Ui::SlideWrap<Ui::Checkbox>>(
container,
checkbox(std::move(label), checked),
2018-09-13 20:09:26 +00:00
st::settingsCheckboxPadding));
};
2021-09-12 23:13:13 +00:00
if (Platform::TrayIconSupported()) {
const auto trayEnabled = [] {
const auto workMode = Core::App().settings().workMode();
2021-05-27 22:11:16 +00:00
return (workMode == WorkMode::TrayOnly)
|| (workMode == WorkMode::WindowAndTray);
};
const auto tray = addCheckbox(
tr::lng_settings_workmode_tray(),
trayEnabled());
const auto taskbarEnabled = [] {
const auto workMode = Core::App().settings().workMode();
2021-05-27 22:11:16 +00:00
return (workMode == WorkMode::WindowOnly)
|| (workMode == WorkMode::WindowAndTray);
};
const auto taskbar = Platform::SkipTaskbarSupported()
? addCheckbox(
tr::lng_settings_workmode_window(),
taskbarEnabled())
: nullptr;
const auto updateWorkmode = [=] {
const auto newMode = tray->checked()
? ((!taskbar || taskbar->checked())
2021-05-27 22:11:16 +00:00
? WorkMode::WindowAndTray
: WorkMode::TrayOnly)
: WorkMode::WindowOnly;
if ((newMode == WorkMode::WindowAndTray
|| newMode == WorkMode::TrayOnly)
&& Core::App().settings().workMode() != newMode) {
cSetSeenTrayTooltip(false);
}
Core::App().settings().setWorkMode(newMode);
2022-01-31 21:43:20 +00:00
Core::App().saveSettingsDelayed();
};
2018-09-07 09:40:25 +00:00
tray->checkedChanges(
2018-09-07 09:40:25 +00:00
) | rpl::filter([=](bool checked) {
return (checked != trayEnabled());
2018-09-07 09:40:25 +00:00
}) | rpl::start_with_next([=](bool checked) {
if (!checked && taskbar && !taskbar->checked()) {
taskbar->setChecked(true);
2018-09-07 09:40:25 +00:00
} else {
updateWorkmode();
}
}, tray->lifetime());
if (taskbar) {
taskbar->checkedChanges(
) | rpl::filter([=](bool checked) {
return (checked != taskbarEnabled());
}) | rpl::start_with_next([=](bool checked) {
if (!checked && !tray->checked()) {
tray->setChecked(true);
} else {
updateWorkmode();
}
}, taskbar->lifetime());
}
2018-09-07 09:40:25 +00:00
}
2021-09-12 23:13:13 +00:00
2022-01-31 21:43:20 +00:00
#ifdef Q_OS_MAC
const auto warnBeforeQuit = addCheckbox(
tr::lng_settings_mac_warn_before_quit(
lt_text,
rpl::single(Platform::ConfirmQuit::QuitKeysString())),
Core::App().settings().macWarnBeforeQuit());
warnBeforeQuit->checkedChanges(
) | rpl::filter([=](bool checked) {
return (checked != Core::App().settings().macWarnBeforeQuit());
}) | rpl::start_with_next([=](bool checked) {
Core::App().settings().setMacWarnBeforeQuit(checked);
Core::App().saveSettingsDelayed();
}, warnBeforeQuit->lifetime());
#ifndef OS_MAC_STORE
const auto enabled = [] {
const auto digest = base::Platform::CurrentCustomAppIconDigest();
return digest && (Core::App().settings().macRoundIconDigest() == digest);
};
const auto roundIcon = addCheckbox(
tr::lng_settings_mac_round_icon(),
enabled());
roundIcon->checkedChanges(
) | rpl::filter([=](bool checked) {
return (checked != enabled());
}) | rpl::start_with_next([=](bool checked) {
const auto digest = checked
? base::Platform::SetCustomAppIcon(IconMacRound())
: std::optional<uint64>();
if (!checked) {
base::Platform::ClearCustomAppIcon();
}
Window::OverrideApplicationIcon(checked ? IconMacRound() : QImage());
Core::App().refreshApplicationIcon();
Core::App().settings().setMacRoundIconDigest(digest);
Core::App().saveSettings();
}, roundIcon->lifetime());
#endif // OS_MAC_STORE
2022-01-31 21:43:20 +00:00
#else // Q_OS_MAC
const auto closeToTaskbar = addSlidingCheckbox(
tr::lng_settings_close_to_taskbar(),
Core::App().settings().closeToTaskbar());
const auto closeToTaskbarShown = std::make_shared<rpl::variable<bool>>(false);
Core::App().settings().workModeValue(
) | rpl::start_with_next([=](WorkMode workMode) {
*closeToTaskbarShown = !Core::App().tray().has();
2022-01-31 21:43:20 +00:00
}, closeToTaskbar->lifetime());
closeToTaskbar->toggleOn(closeToTaskbarShown->value());
closeToTaskbar->entity()->checkedChanges(
) | rpl::filter([=](bool checked) {
return (checked != Core::App().settings().closeToTaskbar());
}) | rpl::start_with_next([=](bool checked) {
Core::App().settings().setCloseToTaskbar(checked);
Local::writeSettings();
}, closeToTaskbar->lifetime());
#endif // Q_OS_MAC
2021-09-12 23:13:13 +00:00
if (Platform::AutostartSupported() && controller) {
const auto minimizedToggled = [=] {
return cStartMinimized()
&& !controller->session().domain().local().hasLocalPasscode();
2018-09-07 09:40:25 +00:00
};
2018-09-13 20:09:26 +00:00
const auto autostart = addCheckbox(
tr::lng_settings_auto_start(),
2018-09-13 20:09:26 +00:00
cAutoStart());
const auto minimized = addSlidingCheckbox(
tr::lng_settings_start_min(),
2018-09-13 20:09:26 +00:00
minimizedToggled());
autostart->checkedChanges(
2018-09-07 09:40:25 +00:00
) | rpl::filter([](bool checked) {
return (checked != cAutoStart());
}) | rpl::start_with_next([=](bool checked) {
const auto weak = base::make_weak(controller);
2018-09-07 09:40:25 +00:00
cSetAutoStart(checked);
Platform::AutostartToggle(checked, crl::guard(autostart, [=](
bool enabled) {
if (checked && !enabled && weak) {
weak->window().showToast(
Lang::Hard::AutostartEnableError());
}
Ui::PostponeCall(autostart, [=] {
autostart->setChecked(enabled);
});
if (enabled || !minimized->entity()->checked()) {
Local::writeSettings();
} else {
minimized->entity()->setChecked(false);
}
}));
2018-09-07 12:19:56 +00:00
}, autostart->lifetime());
2018-09-07 09:40:25 +00:00
Platform::AutostartRequestStateFromSystem(crl::guard(
controller,
[=](bool enabled) { autostart->setChecked(enabled); }));
minimized->toggleOn(autostart->checkedValue());
minimized->entity()->checkedChanges(
2018-09-07 09:40:25 +00:00
) | rpl::filter([=](bool checked) {
return (checked != minimizedToggled());
}) | rpl::start_with_next([=](bool checked) {
if (controller->session().domain().local().hasLocalPasscode()) {
2018-09-13 20:09:26 +00:00
minimized->entity()->setChecked(false);
controller->show(Ui::MakeInformBox(
tr::lng_error_start_minimized_passcoded()));
2018-09-07 09:40:25 +00:00
} else {
cSetStartMinimized(checked);
Local::writeSettings();
}
2018-09-07 12:19:56 +00:00
}, minimized->lifetime());
2018-09-07 09:40:25 +00:00
controller->session().domain().local().localPasscodeChanged(
2018-09-07 09:40:25 +00:00
) | rpl::start_with_next([=] {
2018-09-13 20:09:26 +00:00
minimized->entity()->setChecked(minimizedToggled());
2018-09-07 12:19:56 +00:00
}, minimized->lifetime());
2020-01-21 00:10:10 +00:00
}
if (Platform::IsWindows() && !Platform::IsWindowsStoreBuild()) {
2020-01-21 00:10:10 +00:00
const auto sendto = addCheckbox(
tr::lng_settings_add_sendto(),
2020-01-21 00:10:10 +00:00
cSendToMenu());
2018-09-07 09:40:25 +00:00
sendto->checkedChanges(
2018-09-07 09:40:25 +00:00
) | rpl::filter([](bool checked) {
return (checked != cSendToMenu());
}) | rpl::start_with_next([](bool checked) {
cSetSendToMenu(checked);
psSendToMenu(checked);
Local::writeSettings();
2018-09-07 12:19:56 +00:00
}, sendto->lifetime());
2018-09-07 09:40:25 +00:00
}
}
template <typename Fill>
void CheckNonEmptyOptions(
not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container,
Fill fill) {
2018-09-13 20:09:26 +00:00
auto wrap = object_ptr<Ui::VerticalLayout>(container);
fill(controller, wrap.data());
if (wrap->count() > 0) {
container->add(object_ptr<Ui::OverrideMargins>(
container,
std::move(wrap)));
AddSkip(container, st::settingsCheckboxesSkip);
}
2018-09-13 20:09:26 +00:00
}
void SetupSystemIntegrationOptions(
not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container) {
CheckNonEmptyOptions(
controller,
container,
SetupSystemIntegrationContent);
}
void SetupWindowTitleOptions(
not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container) {
CheckNonEmptyOptions(
controller,
container,
SetupWindowTitleContent);
}
2023-02-21 12:31:55 +00:00
void SetupAnimations(
not_null<Window::Controller*> window,
not_null<Ui::VerticalLayout*> container) {
AddButton(
container,
tr::lng_settings_power_menu(),
st::settingsButtonNoIcon
2023-02-21 12:31:55 +00:00
)->setClickedCallback([=] {
window->show(Box(PowerSavingBox));
});
}
void SetupHardwareAcceleration(not_null<Ui::VerticalLayout*> container) {
const auto settings = &Core::App().settings();
AddButton(
container,
tr::lng_settings_enable_hwaccel(),
st::settingsButtonNoIcon
)->toggleOn(
rpl::single(settings->hardwareAcceleratedVideo())
)->toggledValue(
) | rpl::filter([=](bool enabled) {
return (enabled != settings->hardwareAcceleratedVideo());
}) | rpl::start_with_next([=](bool enabled) {
settings->setHardwareAcceleratedVideo(enabled);
Core::App().saveSettingsDelayed();
}, container->lifetime());
}
#ifdef Q_OS_WIN
2021-07-01 07:47:29 +00:00
void SetupANGLE(
not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container) {
using ANGLE = Ui::GL::ANGLE;
const auto options = std::vector{
tr::lng_settings_angle_backend_auto(tr::now),
tr::lng_settings_angle_backend_d3d11(tr::now),
tr::lng_settings_angle_backend_d3d9(tr::now),
tr::lng_settings_angle_backend_d3d11on12(tr::now),
tr::lng_settings_angle_backend_opengl(tr::now),
tr::lng_settings_angle_backend_disabled(tr::now),
};
const auto backendIndex = [] {
if (Core::App().settings().disableOpenGL()) {
return 5;
} else switch (Ui::GL::CurrentANGLE()) {
case ANGLE::Auto: return 0;
case ANGLE::D3D11: return 1;
case ANGLE::D3D9: return 2;
case ANGLE::D3D11on12: return 3;
case ANGLE::OpenGL: return 4;
}
Unexpected("Ui::GL::CurrentANGLE value in SetupANGLE.");
}();
const auto button = AddButtonWithLabel(
container,
tr::lng_settings_angle_backend(),
rpl::single(options[backendIndex]),
st::settingsButtonNoIcon);
2021-07-01 07:47:29 +00:00
button->addClickHandler([=] {
controller->show(Box([=](not_null<Ui::GenericBox*> box) {
const auto save = [=](int index) {
if (index == backendIndex) {
return;
}
const auto confirmed = crl::guard(button, [=] {
const auto nowDisabled = (index == 5);
if (!nowDisabled) {
Ui::GL::ChangeANGLE([&] {
switch (index) {
case 0: return ANGLE::Auto;
case 1: return ANGLE::D3D11;
case 2: return ANGLE::D3D9;
case 3: return ANGLE::D3D11on12;
case 4: return ANGLE::OpenGL;
}
Unexpected("Index in SetupANGLE.");
}());
}
const auto wasDisabled = (backendIndex == 5);
if (nowDisabled != wasDisabled) {
Core::App().settings().setDisableOpenGL(nowDisabled);
Local::writeSettings();
}
Core::Restart();
2021-07-01 07:47:29 +00:00
});
controller->show(Ui::MakeConfirmBox({
.text = tr::lng_settings_need_restart(),
.confirmed = confirmed,
.confirmText = tr::lng_settings_restart_now(),
}));
2021-07-01 07:47:29 +00:00
};
SingleChoiceBox(box, {
.title = tr::lng_settings_angle_backend(),
.options = options,
.initialSelection = backendIndex,
.callback = save,
});
}));
});
}
#endif // Q_OS_WIN
2021-07-01 07:47:29 +00:00
void SetupOpenGL(
not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container) {
2021-05-20 12:07:53 +00:00
const auto toggles = container->lifetime().make_state<
rpl::event_stream<bool>
>();
const auto button = AddButton(
container,
tr::lng_settings_enable_opengl(),
st::settingsButtonNoIcon
2021-05-20 12:07:53 +00:00
)->toggleOn(
toggles->events_starting_with_copy(
!Core::App().settings().disableOpenGL())
);
button->toggledValue(
) | rpl::filter([](bool enabled) {
return (enabled == Core::App().settings().disableOpenGL());
}) | rpl::start_with_next([=](bool enabled) {
const auto confirmed = crl::guard(button, [=] {
Core::App().settings().setDisableOpenGL(!enabled);
Local::writeSettings();
Core::Restart();
2021-05-20 12:07:53 +00:00
});
const auto cancelled = crl::guard(button, [=](Fn<void()> close) {
2021-05-20 12:07:53 +00:00
toggles->fire(!enabled);
close();
2021-05-20 12:07:53 +00:00
});
controller->show(Ui::MakeConfirmBox({
.text = tr::lng_settings_need_restart(),
.confirmed = confirmed,
.cancelled = cancelled,
.confirmText = tr::lng_settings_restart_now(),
}));
2021-05-20 12:07:53 +00:00
}, container->lifetime());
}
2019-07-24 14:00:30 +00:00
void SetupPerformance(
not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container) {
2023-02-21 12:31:55 +00:00
SetupAnimations(&controller->window(), container);
SetupHardwareAcceleration(container);
#ifdef Q_OS_WIN
SetupANGLE(controller, container);
#else // Q_OS_WIN
if constexpr (!Platform::IsMac()) {
SetupOpenGL(controller, container);
2021-05-20 12:07:53 +00:00
}
#endif // Q_OS_WIN
}
void SetupWindowTitle(
not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container) {
AddDivider(container);
AddSkip(container);
AddSubsectionTitle(container, tr::lng_settings_window_system());
SetupWindowTitleOptions(controller, container);
AddSkip(container);
}
void SetupSystemIntegration(
not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container) {
AddDivider(container);
AddSkip(container);
2019-06-18 12:16:43 +00:00
AddSubsectionTitle(container, tr::lng_settings_system_integration());
SetupSystemIntegrationOptions(controller, container);
AddSkip(container);
}
2019-07-24 14:00:30 +00:00
Advanced::Advanced(
QWidget *parent,
not_null<Window::SessionController*> controller)
: Section(parent) {
2019-07-24 14:00:30 +00:00
setupContent(controller);
2018-09-05 19:05:49 +00:00
}
rpl::producer<QString> Advanced::title() {
return tr::lng_settings_advanced();
}
rpl::producer<Type> Advanced::sectionShowOther() {
return _showOther.events();
}
2019-07-24 14:00:30 +00:00
void Advanced::setupContent(not_null<Window::SessionController*> controller) {
2018-09-05 19:05:49 +00:00
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
2018-09-17 10:52:34 +00:00
auto empty = true;
const auto addDivider = [&] {
if (empty) {
empty = false;
} else {
AddDivider(content);
}
};
const auto addUpdate = [&] {
if (HasUpdate()) {
addDivider();
AddSkip(content);
2019-06-18 12:16:43 +00:00
AddSubsectionTitle(content, tr::lng_settings_version_info());
SetupUpdate(content, [=](Type type) {
_showOther.fire_copy(type);
});
AddSkip(content);
}
};
if (!cAutoUpdate()) {
addUpdate();
}
addDivider();
2019-07-24 14:00:30 +00:00
SetupDataStorage(controller, content);
SetupAutoDownload(controller, content);
SetupWindowTitle(controller, content);
SetupSystemIntegration(controller, content);
2022-02-25 13:11:49 +00:00
empty = false;
AddDivider(content);
AddSkip(content);
2019-06-18 12:16:43 +00:00
AddSubsectionTitle(content, tr::lng_settings_performance());
2019-07-24 14:00:30 +00:00
SetupPerformance(controller, content);
AddSkip(content);
if (HasSystemSpellchecker()) {
AddDivider(content);
AddSkip(content);
AddSubsectionTitle(content, tr::lng_settings_spellchecker());
SetupSpellchecker(controller, content);
AddSkip(content);
}
if (cAutoUpdate()) {
addUpdate();
}
if (!HasUpdate()) {
AddSkip(content);
AddDivider(content);
AddSkip(content);
content->add(
CreateButton(
content,
tr::lng_settings_experimental(),
st::settingsButtonNoIcon)
)->setClickedCallback([=] {
_showOther.fire_copy(Experimental::Id());
});
}
2018-09-05 19:05:49 +00:00
2022-02-18 16:26:57 +00:00
AddSkip(content);
AddDivider(content);
AddSkip(content);
SetupExport(controller, content);
2018-09-05 19:05:49 +00:00
Ui::ResizeFitChild(this, content);
}
} // namespace Settings