Implement chat settings section.

This commit is contained in:
John Preston 2018-09-07 15:19:56 +03:00
parent 38f788f545
commit b8c2c3991f
12 changed files with 767 additions and 47 deletions

View File

@ -324,7 +324,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_bg_use_default" = "Use default color theme";
"lng_settings_bg_from_gallery" = "Choose from gallery";
"lng_settings_bg_from_file" = "Choose from file";
"lng_settings_bg_edit_theme" = "Edit theme";
"lng_settings_bg_edit_theme" = "Launch theme editor";
"lng_settings_bg_tile" = "Tile background";
"lng_settings_adaptive_wide" = "Adaptive layout for wide screens";
@ -334,6 +334,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_local_storage" = "Local storage";
"lng_settings_connection_type" = "Connection type";
"lng_settings_downloading_update" = "Downloading update {progress}...";
"lng_settings_use_night_mode" = "Use night mode";
"lng_backgrounds_header" = "Choose your new chat background";
"lng_theme_sure_keep" = "Keep this theme?";

View File

@ -1440,7 +1440,7 @@ void EditPeerInfoBox::prepare() {
) | rpl::start_with_next([this](int height) {
setDimensions(st::boxWideWidth, height);
}, content->lifetime());
setInnerWidget(object_ptr<Ui::IgnoreMargins>(
setInnerWidget(object_ptr<Ui::OverrideMargins>(
this,
std::move(content)));
Ui::AttachAsChild(this, std::move(controller));

View File

@ -93,9 +93,10 @@ void SettingsWidget::setupContent() {
const auto scroll = Ui::CreateChild<Ui::ScrollArea>(
this,
st::boxLayerScroll);
const auto wrap = scroll->setOwnedWidget(object_ptr<Ui::IgnoreMargins>(
scroll,
object_ptr<Ui::VerticalLayout>(scroll)));
const auto wrap = scroll->setOwnedWidget(
object_ptr<Ui::OverrideMargins>(
scroll,
object_ptr<Ui::VerticalLayout>(scroll)));
const auto content = static_cast<Ui::VerticalLayout*>(wrap->entity());
const auto buttons = setupButtons(scroll, wrap);

View File

@ -16,6 +16,9 @@ settingsSectionButton: InfoProfileButton(infoProfileButton) {
settingsButton: InfoProfileButton(settingsSectionButton) {
padding: margins(28px, 10px, 8px, 8px);
}
settingsChatButton: InfoProfileButton(settingsSectionButton) {
padding: margins(22px, 10px, 8px, 8px);
}
settingsSectionSkip: infoProfileSkip;
settingsButtonRightPosition: point(28px, 10px);
settingsButtonRight: FlatLabel(defaultFlatLabel) {
@ -37,7 +40,30 @@ settingsUpdate: InfoProfileButton(infoMainButton, settingsButton) {
}
settingsUpdateStatePosition: point(28px, 30px);
settingsNotificationsCheckbox: defaultBoxCheckbox;
settingsNotificationsCheckboxPadding: margins(22px, 10px, 10px, 10px);
settingsSendType: defaultBoxCheckbox;
settingsSendTypePadding: margins(22px, 5px, 10px, 5px);
settingsSendTypeSkip: 5px;
settingsCheckbox: defaultBoxCheckbox;
settingsCheckboxPadding: margins(22px, 10px, 10px, 10px);
settingsLink: boxLinkButton;
settingsAdvancedNotificationsPadding: margins(22px, 20px, 10px, 10px);
settingsLinkLabel: defaultFlatLabel;
settingsAskPathPadding: margins(22px, 10px, 10px, 0px);
settingsDownloadPathPadding: margins(22px, 1px, 10px, 0px);
settingsBackgroundThumb: 76px;
settingsThumbSkip: 16px;
settingsBackgroundTitle: FlatLabel(defaultFlatLabel) {
style: TextStyle(semiboldTextStyle) {
font: font(boxFontSize semibold);
linkFont: font(boxFontSize semibold);
linkFontOver: font(boxFontSize semibold underline);
}
textFg: windowActiveTextFg;
}
settingsBackgroundTitlePadding: margins(22px, 7px, 10px, 9px);
settingsBackgroundPadding: margins(22px, 8px, 10px, 8px);
settingsFromGalleryTop: 2px;
settingsFromFileTop: 14px;

View File

@ -8,12 +8,686 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "settings/settings_chat.h"
#include "settings/settings_common.h"
#include "boxes/abstract_box.h"
#include "boxes/connection_box.h"
#include "boxes/stickers_box.h"
#include "boxes/background_box.h"
#include "boxes/download_path_box.h"
#include "ui/wrap/vertical_layout.h"
#include "ui/wrap/slide_wrap.h"
#include "ui/widgets/checkbox.h"
#include "ui/widgets/labels.h"
#include "ui/effects/radial_animation.h"
#include "lang/lang_keys.h"
#include "window/themes/window_theme_editor.h"
#include "window/themes/window_theme.h"
#include "info/profile/info_profile_button.h"
#include "storage/localstorage.h"
#include "core/file_utilities.h"
#include "mainwidget.h"
#include "styles/style_settings.h"
namespace Settings {
namespace {
class BackgroundRow : public Ui::RpWidget {
public:
BackgroundRow(QWidget *parent);
protected:
void paintEvent(QPaintEvent *e) override;
int resizeGetHeight(int newWidth) override;
private:
void updateImage();
float64 radialProgress() const;
bool radialLoading() const;
QRect radialRect() const;
void radialStart();
TimeMs radialTimeShift() const;
void step_radial(TimeMs ms, bool timer);
QPixmap _background;
object_ptr<Ui::LinkButton> _chooseFromGallery;
object_ptr<Ui::LinkButton> _chooseFromFile;
Ui::RadialAnimation _radial;
};
#ifndef OS_WIN_STORE
class DownloadPathRow : public Ui::RpWidget {
public:
DownloadPathRow(QWidget *parent);
private:
void setupControls();
};
#endif // OS_WIN_STORE
void ChooseFromFile(not_null<QWidget*> parent);
BackgroundRow::BackgroundRow(QWidget *parent) : RpWidget(parent)
, _chooseFromGallery(
this,
lang(lng_settings_bg_from_gallery),
st::settingsLink)
, _chooseFromFile(this, lang(lng_settings_bg_from_file), st::settingsLink)
, _radial(animation(this, &BackgroundRow::step_radial)) {
updateImage();
_chooseFromGallery->addClickHandler([] {
Ui::show(Box<BackgroundBox>());
});
_chooseFromFile->addClickHandler([=] {
ChooseFromFile(this);
});
using Update = const Window::Theme::BackgroundUpdate;
base::ObservableViewer(
*Window::Theme::Background()
) | rpl::filter([](const Update &update) {
return (update.type == Update::Type::New
|| update.type == Update::Type::Start
|| update.type == Update::Type::Changed);
}) | rpl::start_with_next([=] {
updateImage();
}, lifetime());
}
void BackgroundRow::paintEvent(QPaintEvent *e) {
Painter p(this);
bool radial = false;
float64 radialOpacity = 0;
if (_radial.animating()) {
_radial.step(getms());
radial = _radial.animating();
radialOpacity = _radial.opacity();
}
if (radial) {
const auto backThumb = App::main()->newBackgroundThumb();
if (backThumb->isNull()) {
p.drawPixmap(0, 0, _background);
} else {
const auto &pix = backThumb->pixBlurred(
Data::FileOrigin(),
st::settingsBackgroundThumb);
const auto factor = cIntRetinaFactor();
p.drawPixmap(
0,
0,
st::settingsBackgroundThumb,
st::settingsBackgroundThumb,
pix,
0,
(pix.height() - st::settingsBackgroundThumb * factor) / 2,
st::settingsBackgroundThumb * factor,
st::settingsBackgroundThumb * factor);
}
const auto outer = radialRect();
const auto inner = QRect(
QPoint(
outer.x() + (outer.width() - st::radialSize.width()) / 2,
outer.y() + (outer.height() - st::radialSize.height()) / 2),
st::radialSize);
p.setPen(Qt::NoPen);
p.setOpacity(radialOpacity);
p.setBrush(st::radialBg);
{
PainterHighQualityEnabler hq(p);
p.drawEllipse(inner);
}
p.setOpacity(1);
const auto arc = inner.marginsRemoved(QMargins(
st::radialLine,
st::radialLine,
st::radialLine,
st::radialLine));
_radial.draw(p, arc, st::radialLine, st::radialFg);
} else {
p.drawPixmap(0, 0, _background);
}
}
int BackgroundRow::resizeGetHeight(int newWidth) {
auto linkTop = st::settingsFromGalleryTop;
auto linkLeft = st::settingsBackgroundThumb + st::settingsThumbSkip;
auto linkWidth = newWidth - linkLeft;
_chooseFromGallery->resizeToWidth(
qMin(linkWidth, _chooseFromGallery->naturalWidth()));
_chooseFromFile->resizeToWidth(
qMin(linkWidth, _chooseFromFile->naturalWidth()));
_chooseFromGallery->moveToLeft(linkLeft, linkTop, newWidth);
linkTop += _chooseFromGallery->height() + st::settingsFromFileTop;
_chooseFromFile->moveToLeft(linkLeft, linkTop, newWidth);
return st::settingsBackgroundThumb;
}
float64 BackgroundRow::radialProgress() const {
return App::main()->chatBackgroundProgress();
}
bool BackgroundRow::radialLoading() const {
const auto main = App::main();
if (main->chatBackgroundLoading()) {
main->checkChatBackground();
if (main->chatBackgroundLoading()) {
return true;
} else {
const_cast<BackgroundRow*>(this)->updateImage();
}
}
return false;
}
QRect BackgroundRow::radialRect() const {
return QRect(
0,
0,
st::settingsBackgroundThumb,
st::settingsBackgroundThumb);
}
void BackgroundRow::radialStart() {
if (radialLoading() && !_radial.animating()) {
_radial.start(radialProgress());
if (const auto shift = radialTimeShift()) {
_radial.update(
radialProgress(),
!radialLoading(),
getms() + shift);
}
}
}
TimeMs BackgroundRow::radialTimeShift() const {
return st::radialDuration;
}
void BackgroundRow::step_radial(TimeMs ms, bool timer) {
_radial.update(
radialProgress(),
!radialLoading(),
ms + radialTimeShift());
if (timer && _radial.animating()) {
rtlupdate(radialRect());
}
}
void BackgroundRow::updateImage() {
int32 size = st::settingsBackgroundThumb * cIntRetinaFactor();
QImage back(size, size, QImage::Format_ARGB32_Premultiplied);
back.setDevicePixelRatio(cRetinaFactor());
{
Painter p(&back);
PainterHighQualityEnabler hq(p);
const auto &pix = Window::Theme::Background()->pixmap();
const auto sx = (pix.width() > pix.height())
? ((pix.width() - pix.height()) / 2)
: 0;
const auto sy = (pix.height() > pix.width())
? ((pix.height() - pix.width()) / 2)
: 0;
const auto s = (pix.width() > pix.height())
? pix.height()
: pix.width();
p.drawPixmap(
0,
0,
st::settingsBackgroundThumb,
st::settingsBackgroundThumb,
pix,
sx,
sy,
s,
s);
}
Images::prepareRound(back, ImageRoundRadius::Small);
_background = App::pixmapFromImageInPlace(std::move(back));
_background.setDevicePixelRatio(cRetinaFactor());
rtlupdate(radialRect());
if (radialLoading()) {
radialStart();
}
}
void ChooseFromFile(not_null<QWidget*> parent) {
const auto imgExtensions = cImgExtensions();
auto filters = QStringList(
qsl("Theme files (*.tdesktop-theme *.tdesktop-palette *")
+ imgExtensions.join(qsl(" *"))
+ qsl(")"));
filters.push_back(FileDialog::AllFilesFilter());
const auto callback = [=](const FileDialog::OpenResult &result) {
if (result.paths.isEmpty() && result.remoteContent.isEmpty()) {
return;
}
if (!result.paths.isEmpty()) {
const auto filePath = result.paths.front();
const auto hasExtension = [&](QLatin1String extension) {
return filePath.endsWith(extension, Qt::CaseInsensitive);
};
if (hasExtension(qstr(".tdesktop-theme"))
|| hasExtension(qstr(".tdesktop-palette"))) {
Window::Theme::Apply(filePath);
return;
}
}
auto image = result.remoteContent.isEmpty()
? App::readImage(result.paths.front())
: App::readImage(result.remoteContent);
if (image.isNull() || image.width() <= 0 || image.height() <= 0) {
return;
} else if (image.width() > 4096 * image.height()) {
image = image.copy(
(image.width() - 4096 * image.height()) / 2,
0,
4096 * image.height(),
image.height());
} else if (image.height() > 4096 * image.width()) {
image = image.copy(
0,
(image.height() - 4096 * image.width()) / 2,
image.width(),
4096 * image.width());
}
Window::Theme::Background()->setImage(
Window::Theme::kCustomBackground,
std::move(image));
Window::Theme::Background()->setTile(false);
};
FileDialog::GetOpenPath(
parent.get(),
lang(lng_choose_image),
filters.join(qsl(";;")),
crl::guard(parent, callback));
}
#ifndef OS_WIN_STORE
QString DownloadPathText() {
if (Global::DownloadPath().isEmpty()) {
return lang(lng_download_path_default);
} else if (Global::DownloadPath() == qsl("tmp")) {
return lang(lng_download_path_temp);
}
return QDir::toNativeSeparators(Global::DownloadPath());
}
DownloadPathRow::DownloadPathRow(QWidget *parent) : RpWidget(parent) {
setupControls();
}
void DownloadPathRow::setupControls() {
const auto label = Ui::CreateChild<Ui::FlatLabel>(
this,
Lang::Viewer(lng_download_path_label),
st::settingsLinkLabel);
const auto link = Ui::CreateChild<Ui::LinkButton>(
this,
DownloadPathText(),
st::settingsLink);
base::ObservableViewer(
Global::RefDownloadPathChanged()
) | rpl::map([] {
return DownloadPathText();
}) | rpl::start_with_next([=](const QString &text) {
link->setText(text);
}, link->lifetime());
link->addClickHandler([] {
Ui::show(Box<DownloadPathBox>());
});
rpl::combine(
widthValue(),
label->sizeValue(),
link->widthValue()
) | rpl::start_with_next([=](int width, QSize labelSize, int possible) {
const auto space = st::settingsLinkLabel.style.font->spacew;
link->resizeToNaturalWidth(width - labelSize.width() - space);
if (link->width() == possible) {
label->moveToLeft(0, 0);
link->moveToLeft(labelSize.width() + space, 0);
resize(width, labelSize.height());
}
}, link->lifetime());
}
#endif // OS_WIN_STORE
void SetupChatOptions(not_null<Ui::VerticalLayout*> container) {
AddDivider(container);
AddSkip(container);
auto wrap = object_ptr<Ui::VerticalLayout>(container);
const auto inner = wrap.data();
container->add(object_ptr<Ui::OverrideMargins>(
container,
std::move(wrap),
QMargins(0, 0, 0, st::settingsCheckbox.margin.bottom())));
const auto checkbox = [&](LangKey label, bool checked) {
return object_ptr<Ui::Checkbox>(
container,
lang(label),
checked,
st::settingsCheckbox);
};
const auto add = [&](LangKey label, bool checked, auto &&handle) {
base::ObservableViewer(
inner->add(
checkbox(label, checked),
st::settingsCheckboxPadding
)->checkedChanged
) | rpl::start_with_next(
std::move(handle),
inner->lifetime());
};
add(
lng_settings_replace_emojis,
Global::ReplaceEmoji(),
[](bool checked) {
Global::SetReplaceEmoji(checked);
Global::RefReplaceEmojiChanged().notify();
Local::writeUserSettings();
});
add(
lng_settings_suggest_emoji,
Global::SuggestEmoji(),
[](bool checked) {
Global::SetSuggestEmoji(checked);
Local::writeUserSettings();
});
add(
lng_settings_suggest_by_emoji,
Global::SuggestStickersByEmoji(),
[](bool checked) {
Global::SetSuggestStickersByEmoji(checked);
Local::writeUserSettings();
});
const auto dontask = inner->add(
checkbox(
lng_download_path_dont_ask,
!Global::AskDownloadPath()),
#ifndef OS_WIN_STORE
st::settingsAskPathPadding);
#else // OS_WIN_STORE
st::settingsCheckboxPadding);
#endif // OS_WIN_STORE
#ifndef OS_WIN_STORE
const auto showpath = Ui::AttachAsChild(
dontask,
rpl::event_stream<bool>());
const auto padding = st::settingsDownloadPathPadding;
const auto path = container->add(
object_ptr<Ui::SlideWrap<DownloadPathRow>>(
container,
object_ptr<DownloadPathRow>(container),
QMargins(
(padding.left()
+ st::settingsCheckbox.checkPosition.x()
+ st::defaultCheck.diameter
+ st::settingsCheckbox.textPosition.x()
- st::settingsCheckbox.margin.left()),
padding.top(),
padding.right(),
padding.bottom())));
AddSkip(container, st::settingsCheckboxPadding.bottom());
path->toggleOn(
showpath->events_starting_with(!Global::AskDownloadPath()));
#endif // OS_WIN_STORE
base::ObservableViewer(
dontask->checkedChanged
) | rpl::start_with_next([=](bool checked) {
Global::SetAskDownloadPath(!checked);
Local::writeUserSettings();
#ifndef OS_WIN_STORE
showpath->fire_copy(checked);
#endif // OS_WIN_STORE
}, inner->lifetime());
AddSkip(container);
}
void SetupSendKey(not_null<Ui::VerticalLayout*> container) {
AddDivider(container);
const auto skip = st::settingsSendTypeSkip;
const auto full = st::settingsSectionSkip + skip;
AddSkip(container, full);
enum class SendByType {
Enter,
CtrlEnter,
};
const auto group = std::make_shared<Ui::RadioenumGroup<SendByType>>(
cCtrlEnter() ? SendByType::CtrlEnter : SendByType::Enter);
auto wrap = object_ptr<Ui::VerticalLayout>(container);
const auto inner = wrap.data();
container->add(
object_ptr<Ui::OverrideMargins>(
container,
std::move(wrap),
QMargins(0, skip, 0, skip)));
AddSkip(container, full);
const auto add = [&](
SendByType value,
LangKey key,
style::margins padding) {
inner->add(
object_ptr<Ui::Radioenum<SendByType>>(
inner,
group,
value,
lang(key),
st::settingsSendType),
st::settingsSendTypePadding);
};
const auto small = st::settingsSendTypePadding;
const auto top = skip;
add(
SendByType::Enter,
lng_settings_send_enter,
{ small.left(), small.top() + top, small.right(), small.bottom() });
add(
SendByType::CtrlEnter,
((cPlatform() == dbipMac || cPlatform() == dbipMacOld)
? lng_settings_send_cmdenter
: lng_settings_send_ctrlenter),
{ small.left(), small.top(), small.right(), small.bottom() + top });
group->setChangedCallback([](SendByType value) {
cSetCtrlEnter(value == SendByType::CtrlEnter);
if (App::main()) {
App::main()->ctrlEnterSubmitUpdated();
}
Local::writeUserSettings();
});
}
void SetupMediaOptions(not_null<Ui::VerticalLayout*> container) {
AddDivider(container);
AddSkip(container);
AddButton(
container,
lng_media_auto_settings,
st::settingsChatButton
)->addClickHandler([] {
Ui::show(Box<AutoDownloadBox>());
});
AddButton(
container,
lng_stickers_you_have,
st::settingsChatButton
)->addClickHandler([] {
Ui::show(Box<StickersBox>(StickersBox::Section::Installed));
});
AddSkip(container);
}
void SetupChatBackground(not_null<Ui::VerticalLayout*> container) {
AddDivider(container);
AddSkip(container);
container->add(
object_ptr<Ui::FlatLabel>(
container,
Lang::Viewer(lng_settings_section_background),
st::settingsBackgroundTitle),
st::settingsBackgroundTitlePadding);
container->add(
object_ptr<BackgroundRow>(container),
st::settingsBackgroundPadding);
const auto skipTop = st::settingsCheckbox.margin.top();
const auto skipBottom = st::settingsCheckbox.margin.bottom();
auto wrap = object_ptr<Ui::VerticalLayout>(container);
const auto inner = wrap.data();
container->add(
object_ptr<Ui::OverrideMargins>(
container,
std::move(wrap),
QMargins(0, skipTop, 0, skipBottom)));
AddSkip(container);
const auto tile = inner->add(
object_ptr<Ui::Checkbox>(
inner,
lang(lng_settings_bg_tile),
Window::Theme::Background()->tile(),
st::settingsCheckbox),
st::settingsSendTypePadding);
const auto adaptive = inner->add(
object_ptr<Ui::SlideWrap<Ui::Checkbox>>(
inner,
object_ptr<Ui::Checkbox>(
inner,
lang(lng_settings_adaptive_wide),
Global::AdaptiveForWide(),
st::settingsCheckbox),
st::settingsSendTypePadding));
base::ObservableViewer(
tile->checkedChanged
) | rpl::start_with_next([](bool checked) {
Window::Theme::Background()->setTile(checked);
}, tile->lifetime());
using Update = const Window::Theme::BackgroundUpdate;
base::ObservableViewer(
*Window::Theme::Background()
) | rpl::filter([](const Update &update) {
return (update.type == Update::Type::Changed);
}) | rpl::map([] {
return Window::Theme::Background()->tile();
}) | rpl::start_with_next([=](bool tiled) {
tile->setChecked(tiled);
}, tile->lifetime());
adaptive->toggleOn(rpl::single(
rpl::empty_value()
) | rpl::then(base::ObservableViewer(
Adaptive::Changed()
)) | rpl::map([] {
return (Global::AdaptiveChatLayout() == Adaptive::ChatLayout::Wide);
}));
base::ObservableViewer(
adaptive->entity()->checkedChanged
) | rpl::start_with_next([](bool checked) {
Global::SetAdaptiveForWide(checked);
Adaptive::Changed().notify();
Local::writeUserSettings();
}, adaptive->lifetime());
}
void SetupThemeOptions(not_null<Ui::VerticalLayout*> container) {
AddDivider(container);
AddSkip(container);
const auto calling = Ui::AttachAsChild(container, 0);
AddButton(
container,
lng_settings_use_night_mode,
st::settingsChatButton
)->toggleOn(
rpl::single(Window::Theme::IsNightMode())
)->toggledValue(
) | rpl::start_with_next([=](bool toggled) {
++*calling;
const auto change = [=] {
if (!--*calling && toggled != Window::Theme::IsNightMode()) {
Window::Theme::ToggleNightMode();
}
};
App::CallDelayed(
st::settingsButton.toggle.duration,
container,
change);
}, container->lifetime());
AddButton(
container,
lng_settings_bg_edit_theme,
st::settingsChatButton
)->addClickHandler(App::LambdaDelayed(
st::settingsChatButton.ripple.hideDuration,
container,
[] { Window::Theme::Editor::Start(); }));
using Update = const Window::Theme::BackgroundUpdate;
container->add(
object_ptr<Ui::SlideWrap<Button>>(
container,
object_ptr<Button>(
container,
Lang::Viewer(lng_settings_bg_use_default),
st::settingsChatButton))
)->toggleOn(rpl::single(
Window::Theme::SuggestThemeReset()
) | rpl::then(base::ObservableViewer(
*Window::Theme::Background()
) | rpl::filter([](const Update &update) {
return (update.type == Update::Type::ApplyingTheme
|| update.type == Update::Type::New);
}) | rpl::map([] {
return Window::Theme::SuggestThemeReset();
})))->entity()->addClickHandler([] {
Window::Theme::ApplyDefault();
});
AddSkip(container);
}
} // namespace
Chat::Chat(QWidget *parent, not_null<UserData*> self)
: Section(parent)
@ -24,7 +698,11 @@ Chat::Chat(QWidget *parent, not_null<UserData*> self)
void Chat::setupContent() {
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
content->add(object_ptr<BoxContentDivider>(content));
SetupChatOptions(content);
SetupSendKey(content);
SetupMediaOptions(content);
SetupChatBackground(content);
SetupThemeOptions(content);
Ui::ResizeFitChild(this, content);
}

View File

@ -47,9 +47,13 @@ object_ptr<Section> CreateSection(
}
void AddSkip(not_null<Ui::VerticalLayout*> container) {
AddSkip(container, st::settingsSectionSkip);
}
void AddSkip(not_null<Ui::VerticalLayout*> container, int skip) {
container->add(object_ptr<Ui::FixedHeightWidget>(
container,
st::settingsSectionSkip));
skip));
}
void AddDivider(not_null<Ui::VerticalLayout*> container) {

View File

@ -59,6 +59,7 @@ object_ptr<Section> CreateSection(
UserData *self = nullptr);
void AddSkip(not_null<Ui::VerticalLayout*> container);
void AddSkip(not_null<Ui::VerticalLayout*> container, int skip);
void AddDivider(not_null<Ui::VerticalLayout*> container);
not_null<Button*> AddButton(
not_null<Ui::VerticalLayout*> container,

View File

@ -82,7 +82,6 @@ void SetupUpdate(not_null<Ui::VerticalLayout*> container) {
AddDivider(container);
AddSkip(container);
const auto lifetime = Ui::AttachAsChild(container, rpl::lifetime());
const auto texts = Ui::AttachAsChild(
container,
rpl::event_stream<QString>());
@ -115,7 +114,7 @@ void SetupUpdate(not_null<Ui::VerticalLayout*> container) {
check->entity()->widthValue() | rpl::start_with_next([=](int width) {
update->resizeToWidth(width);
update->moveToLeft(0, 0);
}, *lifetime);
}, update->lifetime());
AddSkip(container);
@ -167,7 +166,7 @@ void SetupUpdate(not_null<Ui::VerticalLayout*> container) {
checker.stop();
}
setDefaultStatus(checker);
}, *lifetime);
}, toggle->lifetime());
Core::UpdateChecker checker;
check->toggleOn(rpl::combine(
@ -182,26 +181,26 @@ void SetupUpdate(not_null<Ui::VerticalLayout*> container) {
check->setAttribute(Qt::WA_TransparentForMouseEvents);
texts->fire(lang(lng_settings_update_checking));
downloading->fire(false);
}, *lifetime);
}, check->lifetime());
checker.isLatest() | rpl::start_with_next([=] {
check->setAttribute(Qt::WA_TransparentForMouseEvents, false);
texts->fire(lang(lng_settings_latest_installed));
downloading->fire(false);
}, *lifetime);
}, check->lifetime());
checker.progress(
) | rpl::start_with_next([=](Core::UpdateChecker::Progress progress) {
showDownloadProgress(progress.already, progress.size);
}, *lifetime);
}, check->lifetime());
checker.failed() | rpl::start_with_next([=] {
check->setAttribute(Qt::WA_TransparentForMouseEvents, false);
texts->fire(lang(lng_settings_update_fail));
downloading->fire(false);
}, *lifetime);
}, check->lifetime());
checker.ready() | rpl::start_with_next([=] {
texts->fire(lang(lng_settings_update_ready));
update->show();
downloading->fire(false);
}, *lifetime);
}, check->lifetime());
setDefaultStatus(checker);
@ -227,7 +226,6 @@ void SetupTray(not_null<Ui::VerticalLayout*> container) {
AddDivider(container);
AddSkip(container);
const auto lifetime = Ui::AttachAsChild(container, rpl::lifetime());
const auto trayEnabler = Ui::AttachAsChild(
container,
rpl::event_stream<bool>());
@ -281,7 +279,7 @@ void SetupTray(not_null<Ui::VerticalLayout*> container) {
} else {
updateWorkmode();
}
}, *lifetime);
}, tray->lifetime());
if (taskbar) {
taskbar->toggledValue(
@ -293,7 +291,7 @@ void SetupTray(not_null<Ui::VerticalLayout*> container) {
} else {
updateWorkmode();
}
}, *lifetime);
}, taskbar->lifetime());
}
#ifndef OS_WIN_STORE
@ -336,7 +334,7 @@ void SetupTray(not_null<Ui::VerticalLayout*> container) {
} else {
Local::writeSettings();
}
}, *lifetime);
}, autostart->lifetime());
minimized->entity()->toggleOn(
minimizedToggler->events_starting_with(minimizedToggled()));
@ -353,13 +351,13 @@ void SetupTray(not_null<Ui::VerticalLayout*> container) {
cSetStartMinimized(checked);
Local::writeSettings();
}
}, *lifetime);
}, minimized->lifetime());
base::ObservableViewer(
Global::RefLocalPasscodeChanged()
) | rpl::start_with_next([=] {
minimizedToggler->fire(minimizedToggled());
}, *lifetime);
}, minimized->lifetime());
sendto->toggledValue(
) | rpl::filter([](bool checked) {
@ -368,7 +366,7 @@ void SetupTray(not_null<Ui::VerticalLayout*> container) {
cSetSendToMenu(checked);
psSendToMenu(checked);
Local::writeSettings();
}, *lifetime);
}, sendto->lifetime());
}
#endif // OS_WIN_STORE

View File

@ -30,19 +30,19 @@ void SetupNotificationsContent(not_null<Ui::VerticalLayout*> container) {
container,
lang(label),
checked,
st::settingsNotificationsCheckbox);
st::settingsCheckbox);
};
const auto addCheckbox = [&](LangKey label, bool checked) {
return container->add(
checkbox(label, checked),
st::settingsNotificationsCheckboxPadding);
st::settingsCheckboxPadding);
};
const auto addSlidingCheckbox = [&](LangKey label, bool checked) {
return container->add(
object_ptr<Ui::SlideWrap<Ui::Checkbox>>(
container,
checkbox(label, checked),
st::settingsNotificationsCheckboxPadding));
st::settingsCheckboxPadding));
};
const auto desktop = addCheckbox(
lng_settings_desktop_notify,
@ -96,8 +96,6 @@ void SetupNotificationsContent(not_null<Ui::VerticalLayout*> container) {
advanced->hide(anim::type::instant);
}
const auto lifetime = Ui::AttachAsChild(container, rpl::lifetime());
using Change = Window::Notifications::ChangeType;
const auto changed = [](Change change) {
Local::writeUserSettings();
@ -110,7 +108,7 @@ void SetupNotificationsContent(not_null<Ui::VerticalLayout*> container) {
}) | rpl::start_with_next([=](bool checked) {
Global::SetDesktopNotify(checked);
changed(Change::DesktopEnabled);
}, *lifetime);
}, desktop->lifetime());
base::ObservableViewer(
name->entity()->checkedChanged
@ -126,7 +124,7 @@ void SetupNotificationsContent(not_null<Ui::VerticalLayout*> container) {
}) | rpl::start_with_next([=](DBINotifyView value) {
Global::SetNotifyView(value);
changed(Change::ViewParams);
}, *lifetime);
}, name->lifetime());
base::ObservableViewer(
preview->entity()->checkedChanged
@ -142,7 +140,7 @@ void SetupNotificationsContent(not_null<Ui::VerticalLayout*> container) {
}) | rpl::start_with_next([=](DBINotifyView value) {
Global::SetNotifyView(value);
changed(Change::ViewParams);
}, *lifetime);
}, preview->lifetime());
base::ObservableViewer(
sound->checkedChanged
@ -151,7 +149,7 @@ void SetupNotificationsContent(not_null<Ui::VerticalLayout*> container) {
}) | rpl::start_with_next([=](bool checked) {
Global::SetSoundNotify(checked);
changed(Change::SoundEnabled);
}, *lifetime);
}, sound->lifetime());
base::ObservableViewer(
muted->checkedChanged
@ -160,7 +158,7 @@ void SetupNotificationsContent(not_null<Ui::VerticalLayout*> container) {
}) | rpl::start_with_next([=](bool checked) {
Global::SetIncludeMuted(checked);
changed(Change::IncludeMuted);
}, *lifetime);
}, muted->lifetime());
base::ObservableViewer(
Auth().notifications().settingsChanged()
@ -176,7 +174,7 @@ void SetupNotificationsContent(not_null<Ui::VerticalLayout*> container) {
} else if (change == Change::SoundEnabled) {
sound->setChecked(Global::SoundNotify());
}
}, *lifetime);
}, desktop->lifetime());
if (native) {
base::ObservableViewer(
@ -194,7 +192,7 @@ void SetupNotificationsContent(not_null<Ui::VerticalLayout*> container) {
!Global::NativeNotifications(),
anim::type::normal);
}
}, *lifetime);
}, native->lifetime());
}
if (advanced) {
advanced->entity()->addClickHandler([=] {
@ -210,7 +208,7 @@ void SetupNotifications(not_null<Ui::VerticalLayout*> container) {
auto wrap = object_ptr<Ui::VerticalLayout>(container);
SetupNotificationsContent(wrap.data());
container->add(object_ptr<Ui::IgnoreMargins>(
container->add(object_ptr<Ui::OverrideMargins>(
container,
std::move(wrap)));

View File

@ -45,7 +45,7 @@ void LinkButton::paintEvent(QPaintEvent *e) {
p.setPen(pen);
const auto left = _st.padding.left();
const auto top = _st.padding.top() + font->ascent;
if (width() > naturalWidth()) {
if (width() < naturalWidth()) {
const auto available = width() - left - _st.padding.right();
p.drawText(left, top, font->elided(_text, available));
} else {

View File

@ -62,7 +62,7 @@ int VerticalLayout::resizeGetHeight(int newWidth) {
+ row.widget->heightNoMargins()
+ row.margin.bottom();
}
return result - margins.bottom();
return result;
}
void VerticalLayout::visibleTopBottomUpdated(

View File

@ -145,12 +145,15 @@ public:
};
class IgnoreMargins : public Wrap<RpWidget> {
class OverrideMargins : public Wrap<RpWidget> {
using Parent = Wrap<RpWidget>;
public:
IgnoreMargins(QWidget *parent, object_ptr<RpWidget> &&child)
: Parent(parent, std::move(child)) {
OverrideMargins(
QWidget *parent,
object_ptr<RpWidget> &&child,
QMargins margins = QMargins())
: Parent(parent, std::move(child)), _margins(margins) {
if (auto weak = wrapped()) {
auto margins = weak->getMargins();
resizeToWidth(weak->width()
@ -160,14 +163,14 @@ public:
}
QMargins getMargins() const override {
return QMargins();
return _margins;
}
protected:
int resizeGetHeight(int newWidth) override {
if (auto weak = wrapped()) {
weak->resizeToWidth(newWidth);
weak->moveToLeft(0, 0);
weak->moveToLeft(_margins.left(), _margins.top());
return weak->heightNoMargins();
}
return height();
@ -177,10 +180,20 @@ private:
void wrappedSizeUpdated(QSize size) override {
auto margins = wrapped()->getMargins();
resize(
size.width() - margins.left() - margins.right(),
size.height() - margins.top() - margins.bottom());
(size.width()
- margins.left()
- margins.right()
+ _margins.left()
+ _margins.right()),
(size.height()
- margins.top()
- margins.bottom()
+ _margins.top()
+ _margins.bottom()));
}
QMargins _margins;
};
} // namespace Ui