1 /*
2 This file is part of Telegram Desktop,
3 the official desktop application for the Telegram messaging service.
4
5 For license and copyright information please follow this link:
6 https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
7 */
8 #include "settings/settings_advanced.h"
9
10 #include "settings/settings_common.h"
11 #include "settings/settings_chat.h"
12 #include "ui/wrap/vertical_layout.h"
13 #include "ui/wrap/slide_wrap.h"
14 #include "ui/widgets/labels.h"
15 #include "ui/widgets/checkbox.h"
16 #include "ui/widgets/buttons.h"
17 #include "ui/gl/gl_detection.h"
18 #include "ui/text/text_utilities.h" // Ui::Text::ToUpper
19 #include "ui/text/format_values.h"
20 #include "ui/boxes/single_choice_box.h"
21 #include "boxes/connection_box.h"
22 #include "boxes/about_box.h"
23 #include "ui/boxes/confirm_box.h"
24 #include "platform/platform_specific.h"
25 #include "ui/platform/ui_platform_window.h"
26 #include "base/platform/base_platform_info.h"
27 #include "window/window_controller.h"
28 #include "window/window_session_controller.h"
29 #include "lang/lang_keys.h"
30 #include "core/update_checker.h"
31 #include "core/application.h"
32 #include "storage/localstorage.h"
33 #include "storage/storage_domain.h"
34 #include "data/data_session.h"
35 #include "main/main_account.h"
36 #include "main/main_domain.h"
37 #include "main/main_session.h"
38 #include "mtproto/facade.h"
39 #include "app.h"
40 #include "styles/style_settings.h"
41
42 #ifndef TDESKTOP_DISABLE_SPELLCHECK
43 #include "boxes/dictionaries_manager.h"
44 #include "chat_helpers/spellchecker_common.h"
45 #include "spellcheck/platform/platform_spellcheck.h"
46 #endif // !TDESKTOP_DISABLE_SPELLCHECK
47
48 namespace Settings {
49
SetupConnectionType(not_null<Window::Controller * > controller,not_null<Main::Account * > account,not_null<Ui::VerticalLayout * > container)50 void SetupConnectionType(
51 not_null<Window::Controller*> controller,
52 not_null<Main::Account*> account,
53 not_null<Ui::VerticalLayout*> container) {
54 const auto connectionType = [=] {
55 const auto transport = account->mtp().dctransport();
56 if (!Core::App().settings().proxy().isEnabled()) {
57 return transport.isEmpty()
58 ? tr::lng_connection_auto_connecting(tr::now)
59 : tr::lng_connection_auto(tr::now, lt_transport, transport);
60 } else {
61 return transport.isEmpty()
62 ? tr::lng_connection_proxy_connecting(tr::now)
63 : tr::lng_connection_proxy(tr::now, lt_transport, transport);
64 }
65 };
66 const auto button = AddButtonWithLabel(
67 container,
68 tr::lng_settings_connection_type(),
69 rpl::merge(
70 Core::App().settings().proxy().connectionTypeChanges(),
71 // Handle language switch.
72 tr::lng_connection_auto_connecting() | rpl::to_empty
73 ) | rpl::map(connectionType),
74 st::settingsButton);
75 button->addClickHandler([=] {
76 controller->show(ProxiesBoxController::CreateOwningBox(account));
77 });
78 }
79
HasUpdate()80 bool HasUpdate() {
81 return !Core::UpdaterDisabled();
82 }
83
SetupUpdate(not_null<Ui::VerticalLayout * > container)84 void SetupUpdate(not_null<Ui::VerticalLayout*> container) {
85 if (!HasUpdate()) {
86 return;
87 }
88
89 const auto texts = Ui::CreateChild<rpl::event_stream<QString>>(
90 container.get());
91 const auto downloading = Ui::CreateChild<rpl::event_stream<bool>>(
92 container.get());
93 const auto version = tr::lng_settings_current_version(
94 tr::now,
95 lt_version,
96 currentVersionText());
97 const auto toggle = AddButton(
98 container,
99 tr::lng_settings_update_automatically(),
100 st::settingsUpdateToggle);
101 const auto label = Ui::CreateChild<Ui::FlatLabel>(
102 toggle.get(),
103 texts->events(),
104 st::settingsUpdateState);
105
106 const auto options = container->add(
107 object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
108 container,
109 object_ptr<Ui::VerticalLayout>(container)));
110 const auto inner = options->entity();
111 const auto install = cAlphaVersion() ? nullptr : AddButton(
112 inner,
113 tr::lng_settings_install_beta(),
114 st::settingsButton).get();
115
116 const auto check = AddButton(
117 inner,
118 tr::lng_settings_check_now(),
119 st::settingsButton);
120 const auto update = Ui::CreateChild<Button>(
121 check.get(),
122 tr::lng_update_telegram() | Ui::Text::ToUpper(),
123 st::settingsUpdate);
124 update->hide();
125 check->widthValue() | rpl::start_with_next([=](int width) {
126 update->resizeToWidth(width);
127 update->moveToLeft(0, 0);
128 }, update->lifetime());
129
130 rpl::combine(
131 toggle->widthValue(),
132 label->widthValue()
133 ) | rpl::start_with_next([=] {
134 label->moveToLeft(
135 st::settingsUpdateStatePosition.x(),
136 st::settingsUpdateStatePosition.y());
137 }, label->lifetime());
138 label->setAttribute(Qt::WA_TransparentForMouseEvents);
139
140 const auto showDownloadProgress = [=](int64 ready, int64 total) {
141 texts->fire(tr::lng_settings_downloading_update(
142 tr::now,
143 lt_progress,
144 Ui::FormatDownloadText(ready, total)));
145 downloading->fire(true);
146 };
147 const auto setDefaultStatus = [=](const Core::UpdateChecker &checker) {
148 using State = Core::UpdateChecker::State;
149 const auto state = checker.state();
150 switch (state) {
151 case State::Download:
152 showDownloadProgress(checker.already(), checker.size());
153 break;
154 case State::Ready:
155 texts->fire(tr::lng_settings_update_ready(tr::now));
156 update->show();
157 break;
158 default:
159 texts->fire_copy(version);
160 break;
161 }
162 };
163
164 toggle->toggleOn(rpl::single(cAutoUpdate()));
165 toggle->toggledValue(
166 ) | rpl::filter([](bool toggled) {
167 return (toggled != cAutoUpdate());
168 }) | rpl::start_with_next([=](bool toggled) {
169 cSetAutoUpdate(toggled);
170
171 Local::writeSettings();
172 Core::UpdateChecker checker;
173 if (cAutoUpdate()) {
174 checker.start();
175 } else {
176 checker.stop();
177 setDefaultStatus(checker);
178 }
179 }, toggle->lifetime());
180
181 if (install) {
182 install->toggleOn(rpl::single(cInstallBetaVersion()));
183 install->toggledValue(
184 ) | rpl::filter([](bool toggled) {
185 return (toggled != cInstallBetaVersion());
186 }) | rpl::start_with_next([=](bool toggled) {
187 cSetInstallBetaVersion(toggled);
188 Core::App().writeInstallBetaVersionsSetting();
189
190 Core::UpdateChecker checker;
191 checker.stop();
192 if (toggled) {
193 cSetLastUpdateCheck(0);
194 }
195 checker.start();
196 }, toggle->lifetime());
197 }
198
199 Core::UpdateChecker checker;
200 options->toggleOn(rpl::combine(
201 toggle->toggledValue(),
202 downloading->events_starting_with(
203 checker.state() == Core::UpdateChecker::State::Download)
204 ) | rpl::map([](bool check, bool downloading) {
205 return check && !downloading;
206 }));
207
208 checker.checking() | rpl::start_with_next([=] {
209 options->setAttribute(Qt::WA_TransparentForMouseEvents);
210 texts->fire(tr::lng_settings_update_checking(tr::now));
211 downloading->fire(false);
212 }, options->lifetime());
213 checker.isLatest() | rpl::start_with_next([=] {
214 options->setAttribute(Qt::WA_TransparentForMouseEvents, false);
215 texts->fire(tr::lng_settings_latest_installed(tr::now));
216 downloading->fire(false);
217 }, options->lifetime());
218 checker.progress(
219 ) | rpl::start_with_next([=](Core::UpdateChecker::Progress progress) {
220 showDownloadProgress(progress.already, progress.size);
221 }, options->lifetime());
222 checker.failed() | rpl::start_with_next([=] {
223 options->setAttribute(Qt::WA_TransparentForMouseEvents, false);
224 texts->fire(tr::lng_settings_update_fail(tr::now));
225 downloading->fire(false);
226 }, options->lifetime());
227 checker.ready() | rpl::start_with_next([=] {
228 options->setAttribute(Qt::WA_TransparentForMouseEvents, false);
229 texts->fire(tr::lng_settings_update_ready(tr::now));
230 update->show();
231 downloading->fire(false);
232 }, options->lifetime());
233
234 setDefaultStatus(checker);
235
236 check->addClickHandler([] {
237 Core::UpdateChecker checker;
238
239 cSetLastUpdateCheck(0);
240 checker.start();
241 });
242 update->addClickHandler([] {
243 if (!Core::UpdaterDisabled()) {
244 Core::checkReadyUpdate();
245 }
246 App::restart();
247 });
248 }
249
HasSystemSpellchecker()250 bool HasSystemSpellchecker() {
251 #ifdef TDESKTOP_DISABLE_SPELLCHECK
252 return false;
253 #endif // TDESKTOP_DISABLE_SPELLCHECK
254 return true;
255 }
256
SetupSpellchecker(not_null<Window::SessionController * > controller,not_null<Ui::VerticalLayout * > container)257 void SetupSpellchecker(
258 not_null<Window::SessionController*> controller,
259 not_null<Ui::VerticalLayout*> container) {
260 #ifndef TDESKTOP_DISABLE_SPELLCHECK
261 const auto session = &controller->session();
262 const auto settings = &Core::App().settings();
263 const auto isSystem = Platform::Spellchecker::IsSystemSpellchecker();
264 const auto button = AddButton(
265 container,
266 isSystem
267 ? tr::lng_settings_system_spellchecker()
268 : tr::lng_settings_custom_spellchecker(),
269 st::settingsButton
270 )->toggleOn(
271 rpl::single(settings->spellcheckerEnabled())
272 );
273
274 button->toggledValue(
275 ) | rpl::filter([=](bool enabled) {
276 return (enabled != settings->spellcheckerEnabled());
277 }) | rpl::start_with_next([=](bool enabled) {
278 settings->setSpellcheckerEnabled(enabled);
279 Core::App().saveSettingsDelayed();
280 }, container->lifetime());
281
282 if (isSystem) {
283 return;
284 }
285
286 const auto sliding = container->add(
287 object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
288 container,
289 object_ptr<Ui::VerticalLayout>(container)));
290
291 AddButton(
292 sliding->entity(),
293 tr::lng_settings_auto_download_dictionaries(),
294 st::settingsButton
295 )->toggleOn(
296 rpl::single(settings->autoDownloadDictionaries())
297 )->toggledValue(
298 ) | rpl::filter([=](bool enabled) {
299 return (enabled != settings->autoDownloadDictionaries());
300 }) | rpl::start_with_next([=](bool enabled) {
301 settings->setAutoDownloadDictionaries(enabled);
302 Core::App().saveSettingsDelayed();
303 }, sliding->entity()->lifetime());
304
305 AddButtonWithLabel(
306 sliding->entity(),
307 tr::lng_settings_manage_dictionaries(),
308 Spellchecker::ButtonManageDictsState(session),
309 st::settingsButton
310 )->addClickHandler([=] {
311 controller->show(Box<Ui::ManageDictionariesBox>(controller));
312 });
313
314 button->toggledValue(
315 ) | rpl::start_with_next([=](bool enabled) {
316 sliding->toggle(enabled, anim::type::normal);
317 }, container->lifetime());
318 #endif // !TDESKTOP_DISABLE_SPELLCHECK
319 }
320
SetupSystemIntegrationContent(Window::SessionController * controller,not_null<Ui::VerticalLayout * > container)321 void SetupSystemIntegrationContent(
322 Window::SessionController *controller,
323 not_null<Ui::VerticalLayout*> container) {
324 using WorkMode = Core::Settings::WorkMode;
325
326 const auto checkbox = [&](rpl::producer<QString> &&label, bool checked) {
327 return object_ptr<Ui::Checkbox>(
328 container,
329 std::move(label),
330 checked,
331 st::settingsCheckbox);
332 };
333 const auto addCheckbox = [&](
334 rpl::producer<QString> &&label,
335 bool checked) {
336 return container->add(
337 checkbox(std::move(label), checked),
338 st::settingsCheckboxPadding);
339 };
340 const auto addSlidingCheckbox = [&](
341 rpl::producer<QString> &&label,
342 bool checked) {
343 return container->add(
344 object_ptr<Ui::SlideWrap<Ui::Checkbox>>(
345 container,
346 checkbox(std::move(label), checked),
347 st::settingsCheckboxPadding));
348 };
349
350 if (Platform::TrayIconSupported()) {
351 const auto trayEnabled = [] {
352 const auto workMode = Core::App().settings().workMode();
353 return (workMode == WorkMode::TrayOnly)
354 || (workMode == WorkMode::WindowAndTray);
355 };
356 const auto tray = addCheckbox(
357 tr::lng_settings_workmode_tray(),
358 trayEnabled());
359
360 const auto taskbarEnabled = [] {
361 const auto workMode = Core::App().settings().workMode();
362 return (workMode == WorkMode::WindowOnly)
363 || (workMode == WorkMode::WindowAndTray);
364 };
365 const auto taskbar = Platform::SkipTaskbarSupported()
366 ? addCheckbox(
367 tr::lng_settings_workmode_window(),
368 taskbarEnabled())
369 : nullptr;
370
371 const auto updateWorkmode = [=] {
372 const auto newMode = tray->checked()
373 ? ((!taskbar || taskbar->checked())
374 ? WorkMode::WindowAndTray
375 : WorkMode::TrayOnly)
376 : WorkMode::WindowOnly;
377 if ((newMode == WorkMode::WindowAndTray
378 || newMode == WorkMode::TrayOnly)
379 && Core::App().settings().workMode() != newMode) {
380 cSetSeenTrayTooltip(false);
381 }
382 Core::App().settings().setWorkMode(newMode);
383 Local::writeSettings();
384 };
385
386 tray->checkedChanges(
387 ) | rpl::filter([=](bool checked) {
388 return (checked != trayEnabled());
389 }) | rpl::start_with_next([=](bool checked) {
390 if (!checked && taskbar && !taskbar->checked()) {
391 taskbar->setChecked(true);
392 } else {
393 updateWorkmode();
394 }
395 }, tray->lifetime());
396
397 if (taskbar) {
398 taskbar->checkedChanges(
399 ) | rpl::filter([=](bool checked) {
400 return (checked != taskbarEnabled());
401 }) | rpl::start_with_next([=](bool checked) {
402 if (!checked && !tray->checked()) {
403 tray->setChecked(true);
404 } else {
405 updateWorkmode();
406 }
407 }, taskbar->lifetime());
408 }
409 }
410
411 if (!Platform::IsMac()) {
412 const auto closeToTaskbar = addSlidingCheckbox(
413 tr::lng_settings_close_to_taskbar(),
414 Core::App().settings().closeToTaskbar());
415
416 const auto closeToTaskbarShown = std::make_shared<rpl::variable<bool>>(false);
417 Core::App().settings().workModeValue(
418 ) | rpl::start_with_next([=](WorkMode workMode) {
419 *closeToTaskbarShown = (workMode == WorkMode::WindowOnly)
420 || !Platform::TrayIconSupported();
421 }, closeToTaskbar->lifetime());
422
423 closeToTaskbar->toggleOn(closeToTaskbarShown->value());
424 closeToTaskbar->entity()->checkedChanges(
425 ) | rpl::filter([=](bool checked) {
426 return (checked != Core::App().settings().closeToTaskbar());
427 }) | rpl::start_with_next([=](bool checked) {
428 Core::App().settings().setCloseToTaskbar(checked);
429 Local::writeSettings();
430 }, closeToTaskbar->lifetime());
431 }
432
433 if (Ui::Platform::NativeWindowFrameSupported()) {
434 const auto nativeFrame = addCheckbox(
435 tr::lng_settings_native_frame(),
436 Core::App().settings().nativeWindowFrame());
437
438 nativeFrame->checkedChanges(
439 ) | rpl::filter([](bool checked) {
440 return (checked != Core::App().settings().nativeWindowFrame());
441 }) | rpl::start_with_next([=](bool checked) {
442 Core::App().settings().setNativeWindowFrame(checked);
443 Core::App().saveSettingsDelayed();
444 }, nativeFrame->lifetime());
445 }
446
447 if (Platform::AutostartSupported() && controller) {
448 const auto minimizedToggled = [=] {
449 return cStartMinimized()
450 && !controller->session().domain().local().hasLocalPasscode();
451 };
452
453 const auto autostart = addCheckbox(
454 tr::lng_settings_auto_start(),
455 cAutoStart());
456 const auto minimized = addSlidingCheckbox(
457 tr::lng_settings_start_min(),
458 minimizedToggled());
459
460 autostart->checkedChanges(
461 ) | rpl::filter([](bool checked) {
462 return (checked != cAutoStart());
463 }) | rpl::start_with_next([=](bool checked) {
464 cSetAutoStart(checked);
465 Platform::AutostartToggle(checked, crl::guard(autostart, [=](
466 bool enabled) {
467 autostart->setChecked(enabled);
468 if (enabled || !minimized->entity()->checked()) {
469 Local::writeSettings();
470 } else {
471 minimized->entity()->setChecked(false);
472 }
473 }));
474 }, autostart->lifetime());
475
476 Platform::AutostartRequestStateFromSystem(crl::guard(
477 controller,
478 [=](bool enabled) { autostart->setChecked(enabled); }));
479
480 minimized->toggleOn(autostart->checkedValue());
481 minimized->entity()->checkedChanges(
482 ) | rpl::filter([=](bool checked) {
483 return (checked != minimizedToggled());
484 }) | rpl::start_with_next([=](bool checked) {
485 if (controller->session().domain().local().hasLocalPasscode()) {
486 minimized->entity()->setChecked(false);
487 controller->show(Box<Ui::InformBox>(
488 tr::lng_error_start_minimized_passcoded(tr::now)));
489 } else {
490 cSetStartMinimized(checked);
491 Local::writeSettings();
492 }
493 }, minimized->lifetime());
494
495 controller->session().domain().local().localPasscodeChanged(
496 ) | rpl::start_with_next([=] {
497 minimized->entity()->setChecked(minimizedToggled());
498 }, minimized->lifetime());
499 }
500
501 if (Platform::IsWindows() && !Platform::IsWindowsStoreBuild()) {
502 const auto sendto = addCheckbox(
503 tr::lng_settings_add_sendto(),
504 cSendToMenu());
505
506 sendto->checkedChanges(
507 ) | rpl::filter([](bool checked) {
508 return (checked != cSendToMenu());
509 }) | rpl::start_with_next([](bool checked) {
510 cSetSendToMenu(checked);
511 psSendToMenu(checked);
512 Local::writeSettings();
513 }, sendto->lifetime());
514 }
515 }
516
SetupSystemIntegrationOptions(not_null<Window::SessionController * > controller,not_null<Ui::VerticalLayout * > container)517 void SetupSystemIntegrationOptions(
518 not_null<Window::SessionController*> controller,
519 not_null<Ui::VerticalLayout*> container) {
520 auto wrap = object_ptr<Ui::VerticalLayout>(container);
521 SetupSystemIntegrationContent(controller, wrap.data());
522 if (wrap->count() > 0) {
523 container->add(object_ptr<Ui::OverrideMargins>(
524 container,
525 std::move(wrap)));
526
527 AddSkip(container, st::settingsCheckboxesSkip);
528 }
529 }
530
SetupAnimations(not_null<Ui::VerticalLayout * > container)531 void SetupAnimations(not_null<Ui::VerticalLayout*> container) {
532 AddButton(
533 container,
534 tr::lng_settings_enable_animations(),
535 st::settingsButton
536 )->toggleOn(
537 rpl::single(!anim::Disabled())
538 )->toggledValue(
539 ) | rpl::filter([](bool enabled) {
540 return (enabled == anim::Disabled());
541 }) | rpl::start_with_next([](bool enabled) {
542 anim::SetDisabled(!enabled);
543 Local::writeSettings();
544 }, container->lifetime());
545 }
546
547 #ifdef Q_OS_WIN
SetupANGLE(not_null<Window::SessionController * > controller,not_null<Ui::VerticalLayout * > container)548 void SetupANGLE(
549 not_null<Window::SessionController*> controller,
550 not_null<Ui::VerticalLayout*> container) {
551 using ANGLE = Ui::GL::ANGLE;
552 const auto options = std::vector{
553 tr::lng_settings_angle_backend_auto(tr::now),
554 tr::lng_settings_angle_backend_d3d11(tr::now),
555 tr::lng_settings_angle_backend_d3d9(tr::now),
556 tr::lng_settings_angle_backend_d3d11on12(tr::now),
557 tr::lng_settings_angle_backend_opengl(tr::now),
558 tr::lng_settings_angle_backend_disabled(tr::now),
559 };
560 const auto backendIndex = [] {
561 if (Core::App().settings().disableOpenGL()) {
562 return 5;
563 } else switch (Ui::GL::CurrentANGLE()) {
564 case ANGLE::Auto: return 0;
565 case ANGLE::D3D11: return 1;
566 case ANGLE::D3D9: return 2;
567 case ANGLE::D3D11on12: return 3;
568 case ANGLE::OpenGL: return 4;
569 }
570 Unexpected("Ui::GL::CurrentANGLE value in SetupANGLE.");
571 }();
572 const auto button = AddButtonWithLabel(
573 container,
574 tr::lng_settings_angle_backend(),
575 rpl::single(options[backendIndex]),
576 st::settingsButton);
577 button->addClickHandler([=] {
578 controller->show(Box([=](not_null<Ui::GenericBox*> box) {
579 const auto save = [=](int index) {
580 if (index == backendIndex) {
581 return;
582 }
583 const auto confirmed = crl::guard(button, [=] {
584 const auto nowDisabled = (index == 5);
585 if (!nowDisabled) {
586 Ui::GL::ChangeANGLE([&] {
587 switch (index) {
588 case 0: return ANGLE::Auto;
589 case 1: return ANGLE::D3D11;
590 case 2: return ANGLE::D3D9;
591 case 3: return ANGLE::D3D11on12;
592 case 4: return ANGLE::OpenGL;
593 }
594 Unexpected("Index in SetupANGLE.");
595 }());
596 }
597 const auto wasDisabled = (backendIndex == 5);
598 if (nowDisabled != wasDisabled) {
599 Core::App().settings().setDisableOpenGL(nowDisabled);
600 Local::writeSettings();
601 }
602 App::restart();
603 });
604 controller->show(Box<Ui::ConfirmBox>(
605 tr::lng_settings_need_restart(tr::now),
606 tr::lng_settings_restart_now(tr::now),
607 confirmed));
608 };
609 SingleChoiceBox(box, {
610 .title = tr::lng_settings_angle_backend(),
611 .options = options,
612 .initialSelection = backendIndex,
613 .callback = save,
614 });
615 }));
616 });
617 }
618 #endif // Q_OS_WIN
619
SetupOpenGL(not_null<Window::SessionController * > controller,not_null<Ui::VerticalLayout * > container)620 void SetupOpenGL(
621 not_null<Window::SessionController*> controller,
622 not_null<Ui::VerticalLayout*> container) {
623 const auto toggles = container->lifetime().make_state<
624 rpl::event_stream<bool>
625 >();
626 const auto button = AddButton(
627 container,
628 tr::lng_settings_enable_opengl(),
629 st::settingsButton
630 )->toggleOn(
631 toggles->events_starting_with_copy(
632 !Core::App().settings().disableOpenGL())
633 );
634 button->toggledValue(
635 ) | rpl::filter([](bool enabled) {
636 return (enabled == Core::App().settings().disableOpenGL());
637 }) | rpl::start_with_next([=](bool enabled) {
638 const auto confirmed = crl::guard(button, [=] {
639 Core::App().settings().setDisableOpenGL(!enabled);
640 Local::writeSettings();
641 App::restart();
642 });
643 const auto cancelled = crl::guard(button, [=] {
644 toggles->fire(!enabled);
645 });
646 controller->show(Box<Ui::ConfirmBox>(
647 tr::lng_settings_need_restart(tr::now),
648 tr::lng_settings_restart_now(tr::now),
649 confirmed,
650 cancelled));
651 }, container->lifetime());
652 }
653
SetupPerformance(not_null<Window::SessionController * > controller,not_null<Ui::VerticalLayout * > container)654 void SetupPerformance(
655 not_null<Window::SessionController*> controller,
656 not_null<Ui::VerticalLayout*> container) {
657 SetupAnimations(container);
658 #ifdef Q_OS_WIN
659 SetupANGLE(controller, container);
660 #else // Q_OS_WIN
661 if constexpr (!Platform::IsMac()) {
662 SetupOpenGL(controller, container);
663 }
664 #endif // Q_OS_WIN
665 }
666
SetupSystemIntegration(not_null<Window::SessionController * > controller,not_null<Ui::VerticalLayout * > container,Fn<void (Type)> showOther)667 void SetupSystemIntegration(
668 not_null<Window::SessionController*> controller,
669 not_null<Ui::VerticalLayout*> container,
670 Fn<void(Type)> showOther) {
671 AddDivider(container);
672 AddSkip(container);
673 AddSubsectionTitle(container, tr::lng_settings_system_integration());
674 AddButton(
675 container,
676 tr::lng_settings_section_call_settings(),
677 st::settingsButton
678 )->addClickHandler([=] {
679 showOther(Type::Calls);
680 });
681 SetupSystemIntegrationOptions(controller, container);
682 AddSkip(container);
683 }
684
Advanced(QWidget * parent,not_null<Window::SessionController * > controller)685 Advanced::Advanced(
686 QWidget *parent,
687 not_null<Window::SessionController*> controller)
688 : Section(parent) {
689 setupContent(controller);
690 }
691
sectionShowOther()692 rpl::producer<Type> Advanced::sectionShowOther() {
693 return _showOther.events();
694 }
695
setupContent(not_null<Window::SessionController * > controller)696 void Advanced::setupContent(not_null<Window::SessionController*> controller) {
697 const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
698
699 auto empty = true;
700 const auto addDivider = [&] {
701 if (empty) {
702 empty = false;
703 } else {
704 AddDivider(content);
705 }
706 };
707 const auto addUpdate = [&] {
708 if (HasUpdate()) {
709 addDivider();
710 AddSkip(content);
711 AddSubsectionTitle(content, tr::lng_settings_version_info());
712 SetupUpdate(content);
713 AddSkip(content);
714 }
715 };
716 if (!cAutoUpdate()) {
717 addUpdate();
718 }
719 addDivider();
720 AddSkip(content);
721 AddSubsectionTitle(content, tr::lng_settings_network_proxy());
722 SetupConnectionType(
723 &controller->window(),
724 &controller->session().account(),
725 content);
726 AddSkip(content);
727 SetupDataStorage(controller, content);
728 SetupAutoDownload(controller, content);
729 SetupSystemIntegration(controller, content, [=](Type type) {
730 _showOther.fire_copy(type);
731 });
732
733 AddDivider(content);
734 AddSkip(content);
735 AddSubsectionTitle(content, tr::lng_settings_performance());
736 SetupPerformance(controller, content);
737 AddSkip(content);
738
739 if (HasSystemSpellchecker()) {
740 AddDivider(content);
741 AddSkip(content);
742 AddSubsectionTitle(content, tr::lng_settings_spellchecker());
743 SetupSpellchecker(controller, content);
744 AddSkip(content);
745 }
746
747 if (cAutoUpdate()) {
748 addUpdate();
749 }
750
751 Ui::ResizeFitChild(this, content);
752 }
753
754 } // namespace Settings
755