Use rpl in some widgets and effects.

This commit is contained in:
John Preston 2017-09-13 19:57:44 +03:00
parent 21d136e224
commit c302219f9e
120 changed files with 2119 additions and 671 deletions

View file

@ -78,6 +78,8 @@ slideDuration: 240;
slideShift: 100px;
slideShadow: icon {{ "slide_shadow", slideFadeOutShadowFg }};
slideWrapDuration: 150;
linkCropLimit: 360px;
linkFont: normalFont;
linkOverFont: font(fsize underline);

View file

@ -365,9 +365,14 @@ public:
}
}
inline Return operator()(Args... args) {
template <
typename ...OtherArgs,
typename = std::enable_if_t<(sizeof...(Args) == sizeof...(OtherArgs))>>
inline Return operator()(OtherArgs&&... args) {
Assert(data_.vtable != nullptr);
return data_.vtable->call(data_.storage, std::forward<Args>(args)...);
return data_.vtable->call(
data_.storage,
std::forward<OtherArgs>(args)...);
}
explicit operator bool() const {
@ -437,9 +442,14 @@ public:
return *this;
}
inline Return operator()(Args... args) const {
template <
typename ...OtherArgs,
typename = std::enable_if_t<(sizeof...(Args) == sizeof...(OtherArgs))>>
inline Return operator()(OtherArgs&&... args) const {
Assert(this->data_.vtable != nullptr);
return this->data_.vtable->const_call(this->data_.storage, std::forward<Args>(args)...);
return this->data_.vtable->const_call(
this->data_.storage,
std::forward<OtherArgs>(args)...);
}
void swap(lambda &other) {

View file

@ -22,6 +22,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include <vector>
#include <deque>
#include <rpl/producer.h>
#include "base/type_traits.h"
namespace base {
@ -460,4 +461,31 @@ private:
void HandleObservables();
template <
typename Type,
typename = std::enable_if_t<!std::is_same_v<Type, void>>>
inline rpl::producer<Type> ObservableViewer(
base::Observable<Type> &observable) {
return [&observable](const rpl::consumer<Type> &consumer) {
auto lifetime = rpl::lifetime();
lifetime.make_state<base::Subscription>(
observable.add_subscription([consumer](auto &&update) {
consumer.put_next_copy(update);
}));
return lifetime;
};
}
inline rpl::producer<> ObservableViewer(
base::Observable<void> &observable) {
return [&observable](const rpl::consumer<> &consumer) {
auto lifetime = rpl::lifetime();
lifetime.make_state<base::Subscription>(
observable.add_subscription([consumer]() {
consumer.put_next({});
}));
return lifetime;
};
}
} // namespace base

View file

@ -20,6 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include <gsl/gsl_assert>
#include "base/variant.h"
namespace base {

View file

@ -21,6 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#pragma once
#include "layerwidget.h"
#include "ui/rp_widget.h"
#include "ui/widgets/shadow.h"
namespace Ui {
@ -58,7 +59,7 @@ public:
};
class BoxContent : public TWidget, protected base::Subscriber {
class BoxContent : public Ui::RpWidget, protected base::Subscriber {
Q_OBJECT
public:

View file

@ -24,7 +24,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "ui/widgets/checkbox.h"
#include "ui/widgets/labels.h"
#include "ui/widgets/buttons.h"
#include "ui/effects/widget_slide_wrap.h"
#include "ui/wrap/slide_wrap.h"
#include "boxes/peer_list_controllers.h"
#include "apiwrap.h"
#include "auth_session.h"
@ -252,7 +252,7 @@ std::vector<not_null<UserData*>> &EditPrivacyBox::exceptionUsers(Exception excep
Unexpected("Invalid exception value.");
}
object_ptr<Ui::WidgetSlideWrap<Ui::LinkButton>> &EditPrivacyBox::exceptionLink(Exception exception) {
object_ptr<Ui::SlideWrap<Ui::LinkButton>> &EditPrivacyBox::exceptionLink(Exception exception) {
switch (exception) {
case Exception::Always: return _alwaysLink;
case Exception::Never: return _neverLink;
@ -284,9 +284,10 @@ void EditPrivacyBox::createWidgets() {
widget.create(this, text, Ui::FlatLabel::InitType::Simple, st);
};
auto createExceptionLink = [this](Exception exception) {
exceptionLink(exception).create(this, object_ptr<Ui::LinkButton>(this, exceptionLinkText(exception)), exceptionLinkMargins(), [this] {
resizeGetHeight(width());
});
exceptionLink(exception).create(this, object_ptr<Ui::LinkButton>(this, exceptionLinkText(exception)), exceptionLinkMargins());
exceptionLink(exception)->heightValue()
| rpl::on_next([this](int) { resizeToWidth(width()); })
| rpl::start(lifetime());
exceptionLink(exception)->entity()->setClickedCallback([this, exception] { editExceptionUsers(exception); });
};

View file

@ -31,7 +31,7 @@ class RadioenumGroup;
template <typename Enum>
class Radioenum;
template <typename Widget>
class WidgetSlideWrap;
class SlideWrap;
} // namespace Ui
class EditPrivacyBox : public BoxContent, private MTP::Sender {
@ -103,7 +103,7 @@ private:
void editExceptionUsers(Exception exception);
QString exceptionLinkText(Exception exception);
std::vector<not_null<UserData*>> &exceptionUsers(Exception exception);
object_ptr<Ui::WidgetSlideWrap<Ui::LinkButton>> &exceptionLink(Exception exception);
object_ptr<Ui::SlideWrap<Ui::LinkButton>> &exceptionLink(Exception exception);
std::unique_ptr<Controller> _controller;
Option _option = Option::Everyone;
@ -116,8 +116,8 @@ private:
object_ptr<Ui::Radioenum<Option>> _nobody = { nullptr };
object_ptr<Ui::FlatLabel> _warning = { nullptr };
object_ptr<Ui::FlatLabel> _exceptionsTitle = { nullptr };
object_ptr<Ui::WidgetSlideWrap<Ui::LinkButton>> _alwaysLink = { nullptr };
object_ptr<Ui::WidgetSlideWrap<Ui::LinkButton>> _neverLink = { nullptr };
object_ptr<Ui::SlideWrap<Ui::LinkButton>> _alwaysLink = { nullptr };
object_ptr<Ui::SlideWrap<Ui::LinkButton>> _neverLink = { nullptr };
object_ptr<Ui::FlatLabel> _exceptionsDescription = { nullptr };
std::vector<not_null<UserData*>> _alwaysUsers;

View file

@ -127,7 +127,9 @@ void NotificationsBox::prepare() {
_sampleOpacities.push_back(Animation());
}
_countSlider->setActiveSectionFast(_oldCount - 1);
_countSlider->setSectionActivatedCallback([this] { countChanged(); });
_countSlider->sectionActivated()
| rpl::on_next([this](int) { countChanged(); })
| rpl::start(lifetime());
setMouseTracking(true);

View file

@ -28,7 +28,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "ui/widgets/labels.h"
#include "ui/effects/round_checkbox.h"
#include "ui/effects/ripple_animation.h"
#include "ui/effects/widget_slide_wrap.h"
#include "ui/wrap/slide_wrap.h"
#include "lang/lang_keys.h"
#include "observer_peer.h"
#include "storage/file_download.h"
@ -44,9 +44,10 @@ void PeerListBox::createMultiSelect() {
Expects(_select == nullptr);
auto entity = object_ptr<Ui::MultiSelect>(this, st::contactsMultiSelect, langFactory(lng_participant_filter));
auto margins = style::margins(0, 0, 0, 0);
auto callback = [this] { updateScrollSkips(); };
_select.create(this, std::move(entity), margins, std::move(callback));
_select.create(this, std::move(entity));
_select->heightValue()
| rpl::on_next([this](int) { updateScrollSkips(); })
| rpl::start(lifetime());
_select->entity()->setSubmittedCallback([this](bool chtrlShiftEnter) { _inner->submitted(); });
_select->entity()->setQueryChangedCallback([this](const QString &query) { searchQueryChanged(query); });
_select->entity()->setItemRemovedCallback([this](uint64 itemId) {
@ -86,7 +87,7 @@ void PeerListBox::prepare() {
setDimensions(st::boxWideWidth, st::boxMaxListHeight);
if (_select) {
_select->finishAnimation();
_select->finishAnimations();
_scrollBottomFixed = true;
onScrollToY(0);
}
@ -1158,7 +1159,9 @@ void PeerListBox::Inner::submitted() {
}
}
void PeerListBox::Inner::setVisibleTopBottom(int visibleTop, int visibleBottom) {
void PeerListBox::Inner::visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) {
_visibleTop = visibleTop;
_visibleBottom = visibleBottom;
loadProfilePhotos();

View file

@ -29,7 +29,7 @@ class RippleAnimation;
class RoundImageCheckbox;
class MultiSelect;
template <typename Widget>
class WidgetSlideWrap;
class SlideWrap;
class FlatLabel;
} // namespace Ui
@ -378,7 +378,7 @@ private:
void updateScrollSkips();
void searchQueryChanged(const QString &query);
object_ptr<Ui::WidgetSlideWrap<Ui::MultiSelect>> _select = { nullptr };
object_ptr<Ui::SlideWrap<Ui::MultiSelect>> _select = { nullptr };
class Inner;
QPointer<Inner> _inner;
@ -401,8 +401,6 @@ public:
void clearSelection();
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
void searchQueryChanged(QString query);
void submitted();
@ -441,10 +439,11 @@ public:
signals:
void mustScrollTo(int ymin, int ymax);
public slots:
protected:
int resizeGetHeight(int newWidth) override;
void visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) override;
void paintEvent(QPaintEvent *e) override;
void enterEventHook(QEvent *e) override;

View file

@ -311,7 +311,9 @@ void ShareBox::Inner::invalidateCache() {
}
}
void ShareBox::Inner::setVisibleTopBottom(int visibleTop, int visibleBottom) {
void ShareBox::Inner::visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) {
loadProfilePhotos(visibleTop);
}

View file

@ -125,7 +125,6 @@ public:
void activateSkipRow(int direction);
void activateSkipColumn(int direction);
void activateSkipPage(int pageHeight, int direction);
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
void updateFilter(QString filter = QString());
~Inner();
@ -138,6 +137,10 @@ signals:
void searchByUsername();
protected:
void visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) override;
void paintEvent(QPaintEvent *e) override;
void enterEventHook(QEvent *e) override;
void leaveEventHook(QEvent *e) override;

View file

@ -401,11 +401,6 @@ void StickerSetBox::Inner::paintEvent(QPaintEvent *e) {
}
}
void StickerSetBox::Inner::setVisibleTopBottom(int visibleTop, int visibleBottom) {
_visibleTop = visibleTop;
_visibleBottom = visibleBottom;
}
bool StickerSetBox::Inner::loaded() const {
return _loaded && !_pack.isEmpty();
}

View file

@ -73,7 +73,6 @@ public:
base::lambda<TextWithEntities()> title() const;
QString shortName() const;
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
void install();
~Inner();
@ -119,8 +118,6 @@ private:
int32 _setHash = 0;
MTPDstickerSet::Flags _setFlags = 0;
int _visibleTop = 0;
int _visibleBottom = 0;
MTPInputStickerSet _input;
mtpRequestId _installRequest = 0;

View file

@ -243,9 +243,9 @@ void StickersBox::prepare() {
preloadArchivedSets();
}
setNoContentMargin(true);
_tabs->setSectionActivatedCallback([this] {
switchTab();
});
_tabs->sectionActivated()
| rpl::on_next([this](int) { switchTab(); })
| rpl::start(lifetime());
refreshTabs();
}
if (_installed.widget() && _section != Section::Installed) _installed.widget()->hide();
@ -1532,7 +1532,9 @@ void StickersBox::Inner::setRemovedSets(const Stickers::Order &removed) {
}
}
void StickersBox::Inner::setVisibleTopBottom(int visibleTop, int visibleBottom) {
void StickersBox::Inner::visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) {
_visibleTop = visibleTop;
_visibleBottom = visibleBottom;
updateScrollbarWidth();

View file

@ -173,7 +173,6 @@ public:
_loadMoreCallback = std::move(callback);
}
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
void setMinHeight(int newWidth, int minHeight);
int getVisibleTop() const {
@ -183,6 +182,10 @@ public:
~Inner();
protected:
void visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) override;
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;

View file

@ -75,7 +75,10 @@ void DebugInfoBox::updateText() {
} // namespace
TopBar::TopBar(QWidget *parent, const base::weak_unique_ptr<Call> &call) : TWidget(parent)
TopBar::TopBar(
QWidget *parent,
const base::weak_unique_ptr<Call> &call)
: RpWidget(parent)
, _call(call)
, _durationLabel(this, st::callBarLabel)
, _fullInfoLabel(this, st::callBarInfoLabel)

View file

@ -22,6 +22,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "base/weak_unique_ptr.h"
#include "base/timer.h"
#include "ui/rp_widget.h"
namespace Ui {
class IconButton;
@ -34,7 +35,7 @@ namespace Calls {
class Call;
class TopBar : public TWidget, private base::Subscriber {
class TopBar : public Ui::RpWidget, private base::Subscriber {
public:
TopBar(QWidget *parent, const base::weak_unique_ptr<Call> &call);

View file

@ -323,8 +323,10 @@ EmojiListWidget::EmojiListWidget(QWidget *parent, not_null<Window::Controller*>
connect(_picker, SIGNAL(hidden()), this, SLOT(onPickerHidden()));
}
void EmojiListWidget::setVisibleTopBottom(int visibleTop, int visibleBottom) {
Inner::setVisibleTopBottom(visibleTop, visibleBottom);
void EmojiListWidget::visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) {
Inner::visibleTopBottomUpdated(visibleTop, visibleBottom);
if (_footer) {
_footer->setCurrentSectionIcon(currentSection(visibleTop));
}

View file

@ -92,7 +92,6 @@ public:
using Section = Ui::Emoji::Section;
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
void refreshRecent() override;
void clearSelection() override;
object_ptr<TabbedSelector::InnerFooter> createFooter() override;
@ -112,6 +111,10 @@ signals:
void switchToStickers();
protected:
void visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) override;
void mousePressEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override;
@ -136,6 +139,7 @@ private:
int rowsTop = 0;
int rowsBottom = 0;
};
template <typename Callback>
bool enumerateSections(Callback callback) const;
SectionInfo sectionInfo(int section) const;

View file

@ -156,9 +156,11 @@ object_ptr<TabbedSelector::InnerFooter> GifsListWidget::createFooter() {
return std::move(result);
}
void GifsListWidget::setVisibleTopBottom(int visibleTop, int visibleBottom) {
void GifsListWidget::visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) {
auto top = getVisibleTop();
Inner::setVisibleTopBottom(visibleTop, visibleBottom);
Inner::visibleTopBottomUpdated(visibleTop, visibleBottom);
if (top != getVisibleTop()) {
_lastScrolled = getms();
}

View file

@ -51,8 +51,6 @@ public:
void clearSelection() override;
object_ptr<TabbedSelector::InnerFooter> createFooter() override;
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
void inlineItemLayoutChanged(const InlineBots::Layout::ItemBase *layout) override;
void inlineItemRepaint(const InlineBots::Layout::ItemBase *layout) override;
bool inlineItemVisible(const InlineBots::Layout::ItemBase *layout) override;
@ -69,6 +67,10 @@ public:
~GifsListWidget();
protected:
void visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) override;
void mousePressEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override;

View file

@ -468,9 +468,11 @@ object_ptr<TabbedSelector::InnerFooter> StickersListWidget::createFooter() {
return std::move(result);
}
void StickersListWidget::setVisibleTopBottom(int visibleTop, int visibleBottom) {
void StickersListWidget::visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) {
auto top = getVisibleTop();
Inner::setVisibleTopBottom(visibleTop, visibleBottom);
Inner::visibleTopBottomUpdated(visibleTop, visibleBottom);
if (_section == Section::Featured) {
readVisibleSets();
}

View file

@ -54,8 +54,6 @@ public:
void fillIcons(QList<StickerIcon> &icons);
bool preventAutoHide();
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
uint64 currentSet(int yOffset) const;
void installedLocally(uint64 setId);
@ -65,6 +63,10 @@ public:
~StickersListWidget();
protected:
void visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) override;
void mousePressEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override;

View file

@ -77,7 +77,7 @@ bool TabbedSection::wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn
return _selector->wheelEventFromFloatPlayer(e);
}
QRect TabbedSection::rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) {
QRect TabbedSection::rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) const {
return _selector->rectForFloatPlayer();
}

View file

@ -44,7 +44,7 @@ public:
// Float player interface.
bool wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Window::Column playerColumn) override;
QRect rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) override;
QRect rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) const override;
protected:
void resizeEvent(QResizeEvent *e) override;

View file

@ -285,7 +285,7 @@ void TabbedSelector::Tab::saveScrollTop() {
_scrollTop = widget()->getVisibleTop();
}
TabbedSelector::TabbedSelector(QWidget *parent, not_null<Window::Controller*> controller) : TWidget(parent)
TabbedSelector::TabbedSelector(QWidget *parent, not_null<Window::Controller*> controller) : RpWidget(parent)
, _tabsSlider(this, st::emojiTabs)
, _topShadow(this, st::shadowFg)
, _bottomShadow(this, st::shadowFg)
@ -472,7 +472,7 @@ bool TabbedSelector::wheelEventFromFloatPlayer(QEvent *e) {
return _scroll->viewportEvent(e);
}
QRect TabbedSelector::rectForFloatPlayer() {
QRect TabbedSelector::rectForFloatPlayer() const {
return mapToGlobal(_scroll->geometry());
}
@ -602,9 +602,9 @@ void TabbedSelector::createTabsSlider() {
_tabsSlider->setSections(sections);
_tabsSlider->setActiveSectionFast(static_cast<int>(_currentTabType));
_tabsSlider->setSectionActivatedCallback([this] {
switchTab();
});
_tabsSlider->sectionActivated()
| rpl::on_next([this](int) { switchTab(); })
| rpl::start(lifetime());
_tabsSlider->resizeToWidth(width());
_tabsSlider->moveToLeft(0, 0);
@ -701,7 +701,7 @@ TabbedSelector::Inner::Inner(QWidget *parent, not_null<Window::Controller*> cont
, _controller(controller) {
}
void TabbedSelector::Inner::setVisibleTopBottom(int visibleTop, int visibleBottom) {
void TabbedSelector::Inner::visibleTopBottomUpdated(int visibleTop, int visibleBottom) {
auto oldVisibleHeight = getVisibleBottom() - getVisibleTop();
_visibleTop = visibleTop;
_visibleBottom = visibleBottom;

View file

@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "ui/twidget.h"
#include "ui/rp_widget.h"
#include "ui/effects/panel_animation.h"
#include "mtproto/sender.h"
#include "auth_session.h"
@ -52,7 +52,7 @@ class EmojiListWidget;
class StickersListWidget;
class GifsListWidget;
class TabbedSelector : public TWidget, private base::Subscriber {
class TabbedSelector : public Ui::RpWidget, private base::Subscriber {
Q_OBJECT
public:
@ -86,7 +86,7 @@ public:
// Float player interface.
bool wheelEventFromFloatPlayer(QEvent *e);
QRect rectForFloatPlayer();
QRect rectForFloatPlayer() const;
~TabbedSelector();
@ -207,8 +207,6 @@ class TabbedSelector::Inner : public TWidget {
public:
Inner(QWidget *parent, not_null<Window::Controller*> controller);
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
int getVisibleTop() const {
return _visibleTop;
}
@ -235,6 +233,10 @@ signals:
void disableScroll(bool disabled);
protected:
void visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) override;
not_null<Window::Controller*> controller() const {
return _controller;
}

View file

@ -127,7 +127,7 @@ constexpr auto kTagsCount = " << langpack_.tags.size() << ";\n\
}
header_->stream() << "\
\n\
enum LangKey {\n";
enum LangKey : int {\n";
for (auto &entry : langpack_.entries) {
header_->stream() << "\t" << getFullKey(entry) << ",\n";
}

View file

@ -1423,7 +1423,9 @@ PeerData *DialogsInner::updateFromParentDrag(QPoint globalPos) {
return nullptr;
}
void DialogsInner::setVisibleTopBottom(int visibleTop, int visibleBottom) {
void DialogsInner::visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) {
_visibleTop = visibleTop;
_visibleBottom = visibleBottom;
loadPeerPhotos();

View file

@ -107,7 +107,6 @@ public:
void setLoadMoreCallback(base::lambda<void()> callback) {
_loadMoreCallback = std::move(callback);
}
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
base::Observable<UserData*> searchFromUserChanged;
@ -133,6 +132,10 @@ signals:
void refreshHashtags();
protected:
void visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) override;
void paintRegion(Painter &p, const QRegion &region, bool paintingOther) override;
void mouseMoveEvent(QMouseEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;

View file

@ -271,7 +271,7 @@ bool DialogsWidget::wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn
return _scroll->viewportEvent(e);
}
QRect DialogsWidget::rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) {
QRect DialogsWidget::rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) const {
return mapToGlobal(_scroll->geometry());
}

View file

@ -99,7 +99,7 @@ public:
// Float player interface.
bool wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Window::Column playerColumn) override;
QRect rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) override;
QRect rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) const override;
void notify_userIsContactChanged(UserData *user, bool fromThisApp);
void notify_historyMuteUpdated(History *history);

View file

@ -18,6 +18,8 @@ to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "facades.h"
#include "profile/profile_section_memento.h"
#include "core/click_handler_types.h"
#include "media/media_clip_reader.h"

View file

@ -233,7 +233,9 @@ InnerWidget::InnerWidget(QWidget *parent, not_null<Window::Controller*> controll
requestAdmins();
}
void InnerWidget::setVisibleTopBottom(int visibleTop, int visibleBottom) {
void InnerWidget::visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) {
auto scrolledUp = (visibleTop < _visibleTop);
_visibleTop = visibleTop;
_visibleBottom = visibleBottom;

View file

@ -50,9 +50,6 @@ public:
return _channel;
}
// Updates the area that is visible inside the scroll container.
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
// Set the correct scroll position after being resized.
void restoreScrollPosition();
@ -76,6 +73,10 @@ public:
~InnerWidget();
protected:
void visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) override;
void paintEvent(QPaintEvent *e) override;
void keyPressEvent(QKeyEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;

View file

@ -431,7 +431,7 @@ bool Widget::wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Windo
return _scroll->viewportEvent(e);
}
QRect Widget::rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) {
QRect Widget::rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) const {
return mapToGlobal(_scroll->geometry());
}

View file

@ -102,7 +102,7 @@ public:
// Float player interface.
bool wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Window::Column playerColumn) override;
QRect rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) override;
QRect rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) const override;
void applyFilter(FilterValue &&value);

View file

@ -3515,7 +3515,7 @@ bool HistoryWidget::wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn
return _scroll->viewportEvent(e);
}
QRect HistoryWidget::rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) {
QRect HistoryWidget::rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) const {
if (playerColumn == Window::Column::Third && _tabbedSection) {
auto tabbedColumn = (myColumn == Window::Column::First) ? Window::Column::Second : Window::Column::Third;
return _tabbedSection->rectForFloatPlayer(tabbedColumn, playerColumn);

View file

@ -348,7 +348,7 @@ public:
// Float player interface.
bool wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Window::Column playerColumn) override;
QRect rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) override;
QRect rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) const override;
void app_sendBotCallback(const HistoryMessageReplyMarkup::Button *button, not_null<const HistoryItem*> msg, int row, int col);

View file

@ -80,7 +80,9 @@ Inner::Inner(QWidget *parent, not_null<Window::Controller*> controller) : TWidge
}));
}
void Inner::setVisibleTopBottom(int visibleTop, int visibleBottom) {
void Inner::visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) {
_visibleBottom = visibleBottom;
if (_visibleTop != visibleTop) {
_visibleTop = visibleTop;

View file

@ -74,7 +74,6 @@ public:
void hideInlineRowsPanel();
void clearInlineRowsPanel();
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
void preloadImages();
void inlineItemLayoutChanged(const ItemBase *layout) override;
@ -90,6 +89,10 @@ public:
~Inner();
protected:
void visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) override;
void mousePressEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override;

View file

@ -499,4 +499,14 @@ Instance &Current() {
return Messenger::Instance().langpack();
}
rpl::producer<QString> Viewer(LangKey key) {
return
rpl::single(Current().getValue(key))
| then(
base::ObservableViewer(Current().updated())
| rpl::map([=](auto&&) {
return Current().getValue(key);
}));
}
} // namespace Lang

View file

@ -20,6 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include <rpl/producer.h>
#include "lang_auto.h"
#include "base/weak_unique_ptr.h"
@ -48,6 +49,8 @@ QString DefaultLanguageId();
class Instance;
Instance &Current();
rpl::producer<QString> Viewer(LangKey key);
class Instance {
public:
Instance() {
@ -84,15 +87,20 @@ public:
return _updated;
}
QString getValue(LangKey key) {
QString getValue(LangKey key) const {
Expects(key >= 0 && key < kLangKeysCount);
Expects(_values.size() == kLangKeysCount);
return _values[key];
}
bool isNonDefaultPlural(LangKey key) {
bool isNonDefaultPlural(LangKey key) const {
Expects(key >= 0 && key < kLangKeysCount);
Expects(_nonDefaultSet.size() == kLangKeysCount);
return _nonDefaultSet[key] || _nonDefaultSet[key + 1] || _nonDefaultSet[key + 2] || _nonDefaultSet[key + 3] || _nonDefaultSet[key + 4] || _nonDefaultSet[key + 5];
return _nonDefaultSet[key]
|| _nonDefaultSet[key + 1]
|| _nonDefaultSet[key + 2]
|| _nonDefaultSet[key + 3]
|| _nonDefaultSet[key + 4]
|| _nonDefaultSet[key + 5];
}
private:

View file

@ -388,6 +388,7 @@ void LayerStackWidget::setCacheImages() {
auto bodyCache = QPixmap(), mainMenuCache = QPixmap();
auto specialLayerCache = QPixmap();
if (_specialLayer) {
myEnsureResized(_specialLayer);
auto sides = RectPart::Left | RectPart::Right;
if (_specialLayer->y() > 0) {
sides |= RectPart::Top;
@ -673,6 +674,7 @@ void LayerStackWidget::initChildLayer(LayerWidget *layer) {
layer->setClosedCallback([this, layer] { onLayerClosed(layer); });
layer->setResizedCallback([this] { onLayerResized(); });
connect(layer, SIGNAL(destroyed(QObject*)), this, SLOT(onLayerDestroyed(QObject*)));
myEnsureResized(layer);
layer->parentResized();
}

View file

@ -20,16 +20,16 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "ui/rp_widget.h"
namespace Window {
class MainMenu;
class Controller;
} // namespace Window
class LayerWidget : public TWidget {
Q_OBJECT
class LayerWidget : public Ui::RpWidget {
public:
using TWidget::TWidget;
using RpWidget::RpWidget;
virtual void parentResized() = 0;
virtual void showFinished() {

View file

@ -119,7 +119,10 @@ MainWidget::Float::Float(QWidget *parent, HistoryItem *item, ToggleCallback togg
}) {
}
MainWidget::MainWidget(QWidget *parent, not_null<Window::Controller*> controller) : TWidget(parent)
MainWidget::MainWidget(
QWidget *parent,
not_null<Window::Controller*> controller)
: RpWidget(parent)
, _controller(controller)
, _dialogsWidth(st::dialogsWidthMin)
, _sideShadow(this, st::shadowFg)
@ -1813,7 +1816,10 @@ void MainWidget::createPlayer() {
return;
}
if (!_player) {
_player.create(this, [this] { playerHeightUpdated(); });
_player.create(this);
_player->heightValue()
| rpl::on_next([this](int) { playerHeightUpdated(); })
| rpl::start(lifetime());
_player->entity()->setCloseCallback([this] { closeBothPlayers(); });
_playerVolume.create(this);
_player->entity()->volumeWidgetCreated(_playerVolume);
@ -1870,7 +1876,12 @@ void MainWidget::setCurrentCall(Calls::Call *call) {
void MainWidget::createCallTopBar() {
Expects(_currentCall != nullptr);
_callTopBar.create(this, object_ptr<Calls::TopBar>(this, _currentCall), style::margins(0, 0, 0, 0), [this] { callTopBarHeightUpdated(); });
_callTopBar.create(this, object_ptr<Calls::TopBar>(this, _currentCall));
_callTopBar->heightValue()
| rpl::on_next([this](int value) {
callTopBarHeightUpdated(value);
})
| rpl::start(lifetime());
orderWidgets();
if (_a_show.animating()) {
_callTopBar->showFast();
@ -1889,8 +1900,7 @@ void MainWidget::destroyCallTopBar() {
}
}
void MainWidget::callTopBarHeightUpdated() {
auto callTopBarHeight = _callTopBar ? _callTopBar->height() : 0;
void MainWidget::callTopBarHeightUpdated(int callTopBarHeight) {
if (!callTopBarHeight && !_currentCall) {
_callTopBar.destroyDelayed();
}

View file

@ -24,6 +24,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "history/history_common.h"
#include "core/single_timer.h"
#include "base/weak_unique_ptr.h"
#include "ui/rp_widget.h"
namespace Notify {
struct PeerUpdate;
@ -46,7 +47,7 @@ namespace Ui {
class PlainShadow;
class DropdownMenu;
template <typename Widget>
class WidgetSlideWrap;
class SlideWrap;
} // namespace Ui
namespace Window {
@ -149,7 +150,7 @@ class ItemBase;
} // namespace Layout
} // namespace InlineBots
class MainWidget : public TWidget, public RPCSender, private base::Subscriber {
class MainWidget : public Ui::RpWidget, public RPCSender, private base::Subscriber {
Q_OBJECT
public:
@ -506,7 +507,7 @@ private:
void setCurrentCall(Calls::Call *call);
void createCallTopBar();
void destroyCallTopBar();
void callTopBarHeightUpdated();
void callTopBarHeightUpdated(int callTopBarHeight);
void sendReadRequest(PeerData *peer, MsgId upTo);
void channelReadDone(PeerData *peer, const MTPBool &result);
@ -620,7 +621,7 @@ private:
object_ptr<OverviewWidget> _overview = { nullptr };
base::weak_unique_ptr<Calls::Call> _currentCall;
object_ptr<Ui::WidgetSlideWrap<Calls::TopBar>> _callTopBar = { nullptr };
object_ptr<Ui::SlideWrap<Calls::TopBar>> _callTopBar = { nullptr };
object_ptr<Window::PlayerWrapWidget> _player = { nullptr };
object_ptr<Media::Player::VolumeWidget> _playerVolume = { nullptr };

View file

@ -84,7 +84,7 @@ QPoint Widget::PlayButton::prepareRippleStartPosition() const {
return QPoint(mapFromGlobal(QCursor::pos()) - st::mediaPlayerButton.rippleAreaPosition);
}
Widget::Widget(QWidget *parent) : TWidget(parent)
Widget::Widget(QWidget *parent) : RpWidget(parent)
, _nameLabel(this, st::mediaPlayerName)
, _timeLabel(this, st::mediaPlayerTime)
, _playPause(this)

View file

@ -20,6 +20,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "ui/rp_widget.h"
class AudioMsgId;
namespace Ui {
@ -41,7 +43,7 @@ class PlayButton;
class VolumeWidget;
struct TrackState;
class Widget : public TWidget, private base::Subscriber {
class Widget : public Ui::RpWidget, private base::Subscriber {
public:
Widget(QWidget *parent);

View file

@ -2149,7 +2149,7 @@ bool OverviewWidget::wheelEventFromFloatPlayer(QEvent *e, Window::Column myColum
return _scroll->viewportEvent(e);
}
QRect OverviewWidget::rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) {
QRect OverviewWidget::rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) const {
return mapToGlobal(_scroll->geometry());
}

View file

@ -350,7 +350,7 @@ public:
// Float player interface.
bool wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Window::Column playerColumn) override;
QRect rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) override;
QRect rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) const override;
void ui_repaintHistoryItem(not_null<const HistoryItem*> item);

View file

@ -23,7 +23,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "styles/style_profile.h"
#include "ui/widgets/labels.h"
#include "ui/widgets/buttons.h"
#include "ui/effects/widget_slide_wrap.h"
#include "ui/wrap/slide_wrap.h"
#include "core/click_handler_types.h"
#include "mainwidget.h"
#include "observer_peer.h"

View file

@ -50,7 +50,7 @@ int PeerListWidget::resizeGetHeight(int newWidth) {
return newHeight + _st.bottom;
}
void PeerListWidget::setVisibleTopBottom(int visibleTop, int visibleBottom) {
void PeerListWidget::visibleTopBottomUpdated(int visibleTop, int visibleBottom) {
_visibleTop = visibleTop;
_visibleBottom = visibleBottom;

View file

@ -38,8 +38,6 @@ class PeerListWidget : public BlockWidget {
public:
PeerListWidget(QWidget *parent, PeerData *peer, const QString &title, const style::ProfilePeerListItem &st = st::profileMemberItem, const QString &removeText = QString());
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
struct Item {
explicit Item(PeerData *peer);
~Item();
@ -100,12 +98,14 @@ public:
}
protected:
int resizeGetHeight(int newWidth) override;
void visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) override;
void paintOutlinedRect(Painter &p, int x, int y, int w, int h) const;
void refreshVisibility();
// Resizes content and counts natural widget height for the desired width.
int resizeGetHeight(int newWidth) override;
void paintContents(Painter &p) override;
void mouseMoveEvent(QMouseEvent *e) override;

View file

@ -105,7 +105,9 @@ InnerWidget::InnerWidget(QWidget *parent, not_null<UserData*> user) : TWidget(pa
_contentTop = st::profileCommonGroupsSkip;
}
void InnerWidget::setVisibleTopBottom(int visibleTop, int visibleBottom) {
void InnerWidget::visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) {
_visibleTop = visibleTop;
_visibleBottom = visibleBottom;
@ -449,7 +451,7 @@ bool Widget::wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Windo
return _scroll->viewportEvent(e);
}
QRect Widget::rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) {
QRect Widget::rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) const {
return mapToGlobal(_scroll->geometry());
}

View file

@ -102,9 +102,6 @@ public:
return _user;
}
// Updates the area that is visible inside the scroll container.
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
void resizeToWidth(int newWidth, int minHeight) {
_minHeight = minHeight;
return TWidget::resizeToWidth(newWidth);
@ -119,15 +116,17 @@ signals:
void cancelled();
protected:
int resizeGetHeight(int newWidth) override;
void visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) override;
void paintEvent(QPaintEvent *e) override;
void keyPressEvent(QKeyEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
// Resizes content and counts natural widget height for the desired width.
int resizeGetHeight(int newWidth) override;
private:
void updateSelected(QPoint localPos);
void updateRow(int index);
@ -191,7 +190,7 @@ public:
// Float player interface.
bool wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Window::Column playerColumn) override;
QRect rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) override;
QRect rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) const override;
protected:
void resizeEvent(QResizeEvent *e) override;

View file

@ -70,7 +70,7 @@ void InnerWidget::createBlocks() {
}
}
void InnerWidget::setVisibleTopBottom(int visibleTop, int visibleBottom) {
void InnerWidget::visibleTopBottomUpdated(int visibleTop, int visibleBottom) {
_visibleTop = visibleTop;
_visibleBottom = visibleBottom;

View file

@ -41,9 +41,6 @@ public:
return TWidget::resizeToWidth(newWidth);
}
// Updates the area that is visible inside the scroll container.
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
// Profile fixed top bar should use this flag to decide
// if it shows "Share contact" button or not.
// It should show it only if it is hidden in the cover.
@ -61,12 +58,14 @@ private slots:
void onBlockHeightUpdated();
protected:
int resizeGetHeight(int newWidth) override;
void visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) override;
void paintEvent(QPaintEvent *e) override;
void keyPressEvent(QKeyEvent *e) override;
// Resizes content and counts natural widget height for the desired width.
int resizeGetHeight(int newWidth) override;
private:
void createBlocks();

View file

@ -26,7 +26,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
namespace Profile {
UserpicButton::UserpicButton(QWidget *parent, PeerData *peer, int size) : AbstractButton(parent)
UserpicButton::UserpicButton(QWidget *parent, not_null<PeerData*> peer, int size) : AbstractButton(parent)
, _size(size ? size : st::profilePhotoSize)
, _peer(peer) {
resize(_size, _size);

View file

@ -31,7 +31,7 @@ namespace Profile {
class UserpicButton : public Ui::AbstractButton, private base::Subscriber {
public:
UserpicButton(QWidget *parent, PeerData *peer, int size = 0);
UserpicButton(QWidget *parent, not_null<PeerData*> peer, int size = 0);
// If at the first moment the _userpic was not loaded,
// we need to show it animated after the profile is fully shown.
@ -51,7 +51,7 @@ private:
bool _notShownYet;
int _size = 0;
PeerData *_peer;
not_null<PeerData*> _peer;
bool _waiting = false;
QPixmap _userpic, _oldUserpic;
Animation _a_appearance;

View file

@ -165,7 +165,7 @@ bool Widget::wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Windo
return _scroll->viewportEvent(e);
}
QRect Widget::rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) {
QRect Widget::rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) const {
return mapToGlobal(_scroll->geometry());
}

View file

@ -56,7 +56,7 @@ public:
// Float player interface.
bool wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Window::Column playerColumn) override;
QRect rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) override;
QRect rectForFloatPlayer(Window::Column myColumn, Window::Column playerColumn) const override;
protected:
void resizeEvent(QResizeEvent *e) override;

View file

@ -143,8 +143,8 @@ std::weak_ptr<std::vector<consumer<Value, no_error>>> event_stream<Value>::weak(
template <typename Value>
event_stream<Value>::~event_stream() {
if (_consumers) {
for (auto &consumer : *_consumers) {
if (auto consumers = base::take(_consumers)) {
for (auto &consumer : *consumers) {
consumer.put_done();
}
}

View file

@ -28,7 +28,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "boxes/local_storage_box.h"
#include "mainwindow.h"
#include "ui/widgets/buttons.h"
#include "ui/effects/widget_slide_wrap.h"
#include "ui/wrap/slide_wrap.h"
#include "storage/localstorage.h"
#include "window/themes/window_theme.h"
@ -62,31 +62,31 @@ void AdvancedWidget::createControls() {
#endif // TDESKTOP_DISABLE_NETWORK_PROXY
})();
if (self()) {
addChildRow(_manageLocalStorage, marginLocalStorage, lang(lng_settings_manage_local_storage), SLOT(onManageLocalStorage()));
createChildRow(_manageLocalStorage, marginLocalStorage, lang(lng_settings_manage_local_storage), SLOT(onManageLocalStorage()));
}
#ifndef TDESKTOP_DISABLE_NETWORK_PROXY
addChildRow(_connectionType, marginLarge, lang(lng_connection_type), lang(lng_connection_auto_connecting), LabeledLink::Type::Primary, SLOT(onConnectionType()));
createChildRow(_connectionType, marginLarge, lang(lng_connection_type), lang(lng_connection_auto_connecting), LabeledLink::Type::Primary, SLOT(onConnectionType()));
connectionTypeUpdated();
#endif // !TDESKTOP_DISABLE_NETWORK_PROXY
if (self()) {
addChildRow(_askQuestion, marginSmall, lang(lng_settings_ask_question), SLOT(onAskQuestion()));
createChildRow(_askQuestion, marginSmall, lang(lng_settings_ask_question), SLOT(onAskQuestion()));
} else {
style::margins slidedPadding(0, marginLarge.bottom() / 2, 0, marginLarge.bottom() - (marginLarge.bottom() / 2));
addChildRow(_useDefaultTheme, marginLarge, slidedPadding, lang(lng_settings_bg_use_default), SLOT(onUseDefaultTheme()));
createChildRow(_useDefaultTheme, marginLarge, slidedPadding, lang(lng_settings_bg_use_default), SLOT(onUseDefaultTheme()));
if (!Window::Theme::IsNonDefaultUsed()) {
_useDefaultTheme->hideFast();
}
addChildRow(_toggleNightTheme, marginLarge, slidedPadding, getNightThemeToggleText(), SLOT(onToggleNightTheme()));
createChildRow(_toggleNightTheme, marginLarge, slidedPadding, getNightThemeToggleText(), SLOT(onToggleNightTheme()));
if (Window::Theme::IsNonDefaultUsed()) {
_toggleNightTheme->hideFast();
}
}
addChildRow(_telegramFAQ, marginLarge, lang(lng_settings_faq), SLOT(onTelegramFAQ()));
createChildRow(_telegramFAQ, marginLarge, lang(lng_settings_faq), SLOT(onTelegramFAQ()));
if (self()) {
style::margins marginLogout(0, 0, 0, 2 * st::settingsLargeSkip);
addChildRow(_logOut, marginLogout, lang(lng_settings_logout), SLOT(onLogOut()));
createChildRow(_logOut, marginLogout, lang(lng_settings_logout), SLOT(onLogOut()));
}
}

View file

@ -52,15 +52,15 @@ private:
void supportGot(const MTPhelp_Support &support);
QString getNightThemeToggleText() const;
object_ptr<Ui::LinkButton> _manageLocalStorage = { nullptr };
Ui::LinkButton *_manageLocalStorage = nullptr;
#ifndef TDESKTOP_DISABLE_NETWORK_PROXY
object_ptr<LabeledLink> _connectionType = { nullptr };
LabeledLink *_connectionType = nullptr;
#endif // !TDESKTOP_DISABLE_NETWORK_PROXY
object_ptr<Ui::WidgetSlideWrap<Ui::LinkButton>> _useDefaultTheme = { nullptr };
object_ptr<Ui::WidgetSlideWrap<Ui::LinkButton>> _toggleNightTheme = { nullptr };
object_ptr<Ui::LinkButton> _askQuestion = { nullptr };
object_ptr<Ui::LinkButton> _telegramFAQ = { nullptr };
object_ptr<Ui::LinkButton> _logOut = { nullptr };
Ui::SlideWrap<Ui::LinkButton> *_useDefaultTheme = nullptr;
Ui::SlideWrap<Ui::LinkButton> *_toggleNightTheme = nullptr;
Ui::LinkButton *_askQuestion = nullptr;
Ui::LinkButton *_telegramFAQ = nullptr;
Ui::LinkButton *_logOut = nullptr;
mtpRequestId _supportGetRequest = 0;

View file

@ -24,7 +24,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "lang/lang_keys.h"
#include "mainwidget.h"
#include "boxes/background_box.h"
#include "ui/effects/widget_slide_wrap.h"
#include "ui/wrap/slide_wrap.h"
#include "ui/widgets/checkbox.h"
#include "ui/widgets/buttons.h"
#include "storage/localstorage.h"
@ -35,7 +35,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
namespace Settings {
BackgroundRow::BackgroundRow(QWidget *parent) : TWidget(parent)
BackgroundRow::BackgroundRow(QWidget *parent) : RpWidget(parent)
, _chooseFromGallery(this, lang(lng_settings_bg_from_gallery), st::boxLinkButton)
, _chooseFromFile(this, lang(lng_settings_bg_from_file), st::boxLinkButton)
, _editTheme(this, lang(lng_settings_bg_edit_theme), st::boxLinkButton)
@ -216,14 +216,14 @@ void BackgroundWidget::createControls() {
style::margins margin(0, 0, 0, st::settingsSmallSkip);
style::margins slidedPadding(0, margin.bottom() / 2, 0, margin.bottom() - (margin.bottom() / 2));
addChildRow(_background, margin);
createChildRow(_background, margin);
connect(_background, SIGNAL(chooseFromGallery()), this, SLOT(onChooseFromGallery()));
connect(_background, SIGNAL(chooseFromFile()), this, SLOT(onChooseFromFile()));
connect(_background, SIGNAL(editTheme()), this, SLOT(onEditTheme()));
connect(_background, SIGNAL(useDefault()), this, SLOT(onUseDefaultTheme()));
addChildRow(_tile, margin, lang(lng_settings_bg_tile), [this](bool) { onTile(); }, Window::Theme::Background()->tile());
addChildRow(_adaptive, margin, slidedPadding, lang(lng_settings_adaptive_wide), [this](bool) { onAdaptive(); }, Global::AdaptiveForWide());
createChildRow(_tile, margin, lang(lng_settings_bg_tile), [this](bool) { onTile(); }, Window::Theme::Background()->tile());
createChildRow(_adaptive, margin, slidedPadding, lang(lng_settings_adaptive_wide), [this](bool) { onAdaptive(); }, Global::AdaptiveForWide());
if (Global::AdaptiveChatLayout() != Adaptive::ChatLayout::Wide) {
_adaptive->hideFast();
}

View file

@ -22,10 +22,11 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "settings/settings_block_widget.h"
#include "ui/effects/radial_animation.h"
#include "ui/rp_widget.h"
namespace Settings {
class BackgroundRow : public TWidget, private base::Subscriber {
class BackgroundRow : public Ui::RpWidget, private base::Subscriber {
Q_OBJECT
public:
@ -82,9 +83,9 @@ private:
void createControls();
void needBackgroundUpdate(bool tile);
object_ptr<BackgroundRow> _background = { nullptr };
object_ptr<Ui::Checkbox> _tile = { nullptr };
object_ptr<Ui::WidgetSlideWrap<Ui::Checkbox>> _adaptive = { nullptr };
BackgroundRow *_background = nullptr;
Ui::Checkbox *_tile = nullptr;
Ui::SlideWrap<Ui::Checkbox> *_adaptive = nullptr;
};

View file

@ -23,12 +23,19 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "styles/style_settings.h"
#include "ui/widgets/checkbox.h"
#include "ui/widgets/buttons.h"
#include "ui/wrap/vertical_layout.h"
namespace Settings {
BlockWidget::BlockWidget(QWidget *parent, UserData *self, const QString &title) : TWidget(parent)
BlockWidget::BlockWidget(QWidget *parent, UserData *self, const QString &title) : RpWidget(parent)
, _self(self)
, _title(title) {
, _title(title)
, _content(this) {
_content->heightValue()
| rpl::on_next([this](int contentHeight) {
resize(width(), contentTop() + contentHeight + st::settingsBlockMarginBottom);
})
| rpl::start(lifetime());
}
void BlockWidget::setContentLeft(int contentLeft) {
@ -42,21 +49,25 @@ int BlockWidget::contentTop() const {
int BlockWidget::resizeGetHeight(int newWidth) {
int x = contentLeft(), result = contentTop();
int availw = newWidth - x;
for_const (auto &row, _rows) {
auto childMargins = row.child->getMargins();
row.child->moveToLeft(x + row.margin.left(), result + row.margin.top(), newWidth);
auto availRowWidth = availw - row.margin.left() - row.margin.right() - x;
auto natural = row.child->naturalWidth();
auto rowWidth = (natural < 0) ? availRowWidth : qMin(natural, availRowWidth);
if (row.child->widthNoMargins() != rowWidth) {
row.child->resizeToWidth(rowWidth);
}
result += row.margin.top() + row.child->heightNoMargins() + row.margin.bottom();
}
result += st::settingsBlockMarginBottom;
auto margins = getMargins();
_content->resizeToWidth(availw);
_content->moveToLeft(margins.left() + x, margins.top() + result, newWidth);
result += _content->heightNoMargins() + st::settingsBlockMarginBottom;
return result;
}
QMargins BlockWidget::getMargins() const {
auto result = _content->getMargins();
return QMargins(
result.left(),
qMax(result.top() - contentTop(), 0),
result.right(),
qMax(result.bottom() - st::settingsBlockMarginBottom, 0));
}
void BlockWidget::paintEvent(QPaintEvent *e) {
Painter p(this);
@ -69,28 +80,37 @@ void BlockWidget::paintTitle(Painter &p) {
p.setFont(st::settingsBlockTitleFont);
p.setPen(st::settingsBlockTitleFg);
int titleTop = st::settingsBlockMarginTop + st::settingsBlockTitleTop;
p.drawTextLeft(contentLeft(), titleTop, width(), _title);
auto margins = getMargins();
auto titleTop = st::settingsBlockMarginTop + st::settingsBlockTitleTop;
p.drawTextLeft(
margins.left() + contentLeft(),
margins.top() + titleTop,
width(),
_title);
}
void BlockWidget::addCreatedRow(TWidget *child, const style::margins &margin) {
_rows.push_back({ child, margin });
Ui::RpWidget *BlockWidget::addCreatedRow(
object_ptr<RpWidget> row,
const style::margins &margin) {
return _content->add(std::move(row), margin);
}
void BlockWidget::rowHeightUpdated() {
auto newHeight = resizeGetHeight(width());
if (newHeight != height()) {
resize(width(), newHeight);
emit heightUpdated();
}
}
void BlockWidget::createChildRow(object_ptr<Ui::Checkbox> &child, style::margins &margin, const QString &text, base::lambda<void(bool checked)> callback, bool checked) {
void BlockWidget::createChildWidget(
object_ptr<Ui::Checkbox> &child,
style::margins &margin,
const QString &text,
base::lambda<void(bool checked)> callback,
bool checked) {
child.create(this, text, checked, st::defaultBoxCheckbox);
subscribe(child->checkedChanged, std::move(callback));
}
void BlockWidget::createChildRow(object_ptr<Ui::LinkButton> &child, style::margins &margin, const QString &text, const char *slot, const style::LinkButton &st) {
void BlockWidget::createChildWidget(
object_ptr<Ui::LinkButton> &child,
style::margins &margin,
const QString &text,
const char *slot,
const style::LinkButton &st) {
child.create(this, text, st);
connect(child, SIGNAL(clicked()), this, slot);
}

View file

@ -21,6 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#pragma once
#include "base/observer.h"
#include "ui/rp_widget.h"
#include "styles/style_boxes.h"
namespace Ui {
@ -33,19 +34,20 @@ class RadioenumGroup;
template <typename Enum>
class Radioenum;
template <typename Widget>
class WidgetSlideWrap;
class SlideWrap;
class VerticalLayout;
} // namespace Ui
namespace Settings {
class BlockWidget : public TWidget, protected base::Subscriber {
Q_OBJECT
class BlockWidget : public Ui::RpWidget, protected base::Subscriber {
public:
BlockWidget(QWidget *parent, UserData *self, const QString &title);
void setContentLeft(int contentLeft);
QMargins getMargins() const override;
protected:
void paintEvent(QPaintEvent *e) override;
virtual void paintContents(Painter &p) {
@ -60,11 +62,6 @@ protected:
// Resizes content and counts natural widget height for the desired width.
int resizeGetHeight(int newWidth) override;
void contentSizeUpdated() {
resizeToWidth(width());
emit heightUpdated();
}
UserData *self() const {
return _self;
}
@ -74,39 +71,67 @@ protected:
}
template <typename Widget, typename ...Args>
Widget *addChildRow(object_ptr<Widget> &child, style::margins margin, Args&&... args) {
createChildRow(child, margin, std::forward<Args>(args)...);
addCreatedRow(child, margin);
return child;
void createChildRow(
Widget *&child,
style::margins margin,
Args&&... args) {
auto row = object_ptr<Widget>{ nullptr };
createChildWidget(row, margin, std::forward<Args>(args)...);
child = static_cast<Widget*>(addCreatedRow(
std::move(row),
margin));
}
private:
template <typename Widget, typename ...Args>
void createChildRow(object_ptr<Ui::WidgetSlideWrap<Widget>> &child, style::margins &margin, const style::margins &padding, Args&&... args) {
void createChildWidget(
object_ptr<Ui::SlideWrap<Widget>> &child,
style::margins &margin,
const style::margins &padding,
Args&&... args) {
object_ptr<Widget> entity = { nullptr };
createChildRow(entity, margin, std::forward<Args>(args)...);
child.create(this, std::move(entity), padding, [this] { rowHeightUpdated(); });
createChildWidget(entity, margin, std::forward<Args>(args)...);
child.create(this, std::move(entity), padding);
margin.setLeft(margin.left() - padding.left());
margin.setTop(margin.top() - padding.top());
margin.setRight(margin.right() - padding.right());
margin.setBottom(margin.bottom() - padding.bottom());
}
void createChildRow(object_ptr<Ui::Checkbox> &child, style::margins &margin, const QString &text, base::lambda<void(bool checked)> callback, bool checked);
void createChildRow(object_ptr<Ui::LinkButton> &child, style::margins &margin, const QString &text, const char *slot, const style::LinkButton &st = st::boxLinkButton);
void createChildWidget(
object_ptr<Ui::Checkbox> &child,
style::margins &margin,
const QString &text, base::lambda<void(bool checked)> callback, bool checked);
void createChildWidget(
object_ptr<Ui::LinkButton> &child,
style::margins &margin,
const QString &text,
const char *slot,
const style::LinkButton &st = st::boxLinkButton);
template <typename Enum>
void createChildRow(object_ptr<Ui::Radioenum<Enum>> &child, style::margins &margin, const std::shared_ptr<Ui::RadioenumGroup<Enum>> &group, Enum value, const QString &text) {
child.create(this, group, value, text, st::defaultBoxCheckbox);
void createChildWidget(
object_ptr<Ui::Radioenum<Enum>> &child,
style::margins &margin,
const std::shared_ptr<Ui::RadioenumGroup<Enum>> &group,
Enum value,
const QString &text) {
child.create(
this,
group,
value,
text,
st::defaultBoxCheckbox);
}
void addCreatedRow(TWidget *child, const style::margins &margin);
void rowHeightUpdated();
RpWidget *addCreatedRow(
object_ptr<RpWidget> row,
const style::margins &margin);
template <typename Widget>
struct IsWidgetSlideWrap : std::false_type {
struct IsSlideWrap : std::false_type {
};
template <typename Widget>
struct IsWidgetSlideWrap<Ui::WidgetSlideWrap<Widget>> : std::true_type {
struct IsSlideWrap<Ui::SlideWrap<Widget>> : std::true_type {
};
template <typename Widget>
struct IsRadioenum : std::false_type {
@ -117,23 +142,19 @@ private:
template <typename Widget>
using NotImplementedYet = std::enable_if_t<
!IsWidgetSlideWrap<Widget>::value &&
!IsSlideWrap<Widget>::value &&
!IsRadioenum<Widget>::value &&
!std::is_same<Ui::Checkbox, Widget>::value &&
!std::is_same<Ui::LinkButton, Widget>::value>;
template <typename Widget, typename... Args, typename = NotImplementedYet<Widget>>
void createChildRow(object_ptr<Widget> &child, style::margins &margin, Args&&... args) {
void createChildWidget(object_ptr<Widget> &child, style::margins &margin, Args&&... args) {
child.create(this, std::forward<Args>(args)...);
}
void paintTitle(Painter &p);
struct ChildRow {
TWidget *child;
style::margins margin;
};
QVector<ChildRow> _rows;
object_ptr<Ui::VerticalLayout> _content;
int _contentLeft = 0;
UserData *_self;

View file

@ -22,7 +22,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "styles/style_settings.h"
#include "lang/lang_keys.h"
#include "ui/effects/widget_slide_wrap.h"
#include "ui/wrap/slide_wrap.h"
#include "ui/widgets/checkbox.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/labels.h"
@ -36,7 +36,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
namespace Settings {
LabeledLink::LabeledLink(QWidget *parent, const QString &label, const QString &text, Type type, const char *slot) : TWidget(parent)
LabeledLink::LabeledLink(QWidget *parent, const QString &label, const QString &text, Type type, const char *slot) : RpWidget(parent)
, _label(this, label, Ui::FlatLabel::InitType::Simple, (type == Type::Primary) ? st::settingsPrimaryLabel : st::defaultFlatLabel)
, _link(this, text, (type == Type::Primary) ? st::boxLinkButton : st::defaultLinkButton) {
connect(_link, SIGNAL(clicked()), parent, slot);
@ -58,7 +58,7 @@ int LabeledLink::resizeGetHeight(int newWidth) {
}
#ifndef OS_WIN_STORE
DownloadPathState::DownloadPathState(QWidget *parent) : TWidget(parent)
DownloadPathState::DownloadPathState(QWidget *parent) : RpWidget(parent)
, _path(this, lang(lng_download_path_label), downloadPathText(), LabeledLink::Type::Secondary, SLOT(onDownloadPath()))
, _clear(this, lang(lng_download_path_clear)) {
connect(_clear, SIGNAL(clicked()), this, SLOT(onClear()));
@ -153,32 +153,32 @@ void ChatSettingsWidget::createControls() {
style::margins marginSub(0, 0, 0, st::settingsSubSkip);
style::margins slidedPadding(0, marginSub.bottom() / 2, 0, marginSub.bottom() - (marginSub.bottom() / 2));
addChildRow(_replaceEmoji, marginSkip, lang(lng_settings_replace_emojis), [this](bool) { onReplaceEmoji(); }, cReplaceEmojis());
createChildRow(_replaceEmoji, marginSkip, lang(lng_settings_replace_emojis), [this](bool) { onReplaceEmoji(); }, cReplaceEmojis());
#ifndef OS_WIN_STORE
auto pathMargin = marginSub;
#else // OS_WIN_STORE
auto pathMargin = marginSkip;
#endif // OS_WIN_STORE
addChildRow(_dontAskDownloadPath, pathMargin, lang(lng_download_path_dont_ask), [this](bool) { onDontAskDownloadPath(); }, !Global::AskDownloadPath());
createChildRow(_dontAskDownloadPath, pathMargin, lang(lng_download_path_dont_ask), [this](bool) { onDontAskDownloadPath(); }, !Global::AskDownloadPath());
#ifndef OS_WIN_STORE
style::margins marginPath(st::defaultCheck.diameter + st::defaultBoxCheckbox.textPosition.x(), 0, 0, st::settingsSkip);
addChildRow(_downloadPath, marginPath, slidedPadding);
createChildRow(_downloadPath, marginPath, slidedPadding);
if (Global::AskDownloadPath()) {
_downloadPath->hideFast();
}
#endif // OS_WIN_STORE
auto group = std::make_shared<Ui::RadioenumGroup<SendByType>>(cCtrlEnter() ? SendByType::CtrlEnter : SendByType::Enter);
addChildRow(_sendByEnter, marginSmall, group, SendByType::Enter, lang(lng_settings_send_enter));
addChildRow(_sendByCtrlEnter, marginSkip, group, SendByType::CtrlEnter, lang((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_settings_send_cmdenter : lng_settings_send_ctrlenter));
createChildRow(_sendByEnter, marginSmall, group, SendByType::Enter, lang(lng_settings_send_enter));
createChildRow(_sendByCtrlEnter, marginSkip, group, SendByType::CtrlEnter, lang((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_settings_send_cmdenter : lng_settings_send_ctrlenter));
group->setChangedCallback([this](SendByType value) {
sendByChanged(value);
});
addChildRow(_automaticMediaDownloadSettings, marginSmall, lang(lng_media_auto_settings), SLOT(onAutomaticMediaDownloadSettings()));
addChildRow(_manageStickerSets, marginSmall, lang(lng_stickers_you_have), SLOT(onManageStickerSets()));
createChildRow(_automaticMediaDownloadSettings, marginSmall, lang(lng_media_auto_settings), SLOT(onAutomaticMediaDownloadSettings()));
createChildRow(_manageStickerSets, marginSmall, lang(lng_stickers_you_have), SLOT(onManageStickerSets()));
}
void ChatSettingsWidget::onReplaceEmoji() {

View file

@ -21,6 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#pragma once
#include "settings/settings_block_widget.h"
#include "ui/rp_widget.h"
namespace Ui {
class FlatLabel;
@ -28,7 +29,7 @@ class FlatLabel;
namespace Settings {
class LabeledLink : public TWidget {
class LabeledLink : public Ui::RpWidget {
public:
enum class Type {
Primary,
@ -50,7 +51,7 @@ private:
};
#ifndef OS_WIN_STORE
class DownloadPathState : public TWidget, private base::Subscriber {
class DownloadPathState : public Ui::RpWidget, private base::Subscriber {
Q_OBJECT
public:
@ -106,17 +107,17 @@ private:
void sendByChanged(SendByType value);
void createControls();
object_ptr<Ui::Checkbox> _replaceEmoji = { nullptr };
object_ptr<Ui::Checkbox> _dontAskDownloadPath = { nullptr };
Ui::Checkbox *_replaceEmoji = nullptr;
Ui::Checkbox *_dontAskDownloadPath = nullptr;
#ifndef OS_WIN_STORE
object_ptr<Ui::WidgetSlideWrap<DownloadPathState>> _downloadPath = { nullptr };
Ui::SlideWrap<DownloadPathState> *_downloadPath = nullptr;
#endif // OS_WIN_STORE
object_ptr<Ui::Radioenum<SendByType>> _sendByEnter = { nullptr };
object_ptr<Ui::Radioenum<SendByType>> _sendByCtrlEnter = { nullptr };
object_ptr<Ui::LinkButton> _automaticMediaDownloadSettings = { nullptr };
object_ptr<Ui::LinkButton> _manageStickerSets = { nullptr };
Ui::Radioenum<SendByType> *_sendByEnter = nullptr;
Ui::Radioenum<SendByType> *_sendByCtrlEnter = nullptr;
Ui::LinkButton *_automaticMediaDownloadSettings = nullptr;
Ui::LinkButton *_manageStickerSets = nullptr;
};

View file

@ -101,12 +101,22 @@ int CoverWidget::resizeGetHeight(int newWidth) {
newHeight += st::settingsMarginTop;
_userpicButton->moveToLeft(contentLeft() + st::settingsPhotoLeft, newHeight, newWidth);
auto margins = getMargins();
_userpicButton->moveToLeft(
margins.left() + contentLeft() + st::settingsPhotoLeft,
margins.top() + newHeight,
newWidth);
int infoLeft = _userpicButton->x() + _userpicButton->width();
_statusPosition = QPoint(infoLeft + st::settingsStatusLeft, _userpicButton->y() + st::settingsStatusTop);
if (_cancelPhotoUpload) {
_cancelPhotoUpload->moveToLeft(_statusPosition.x() + st::settingsStatusFont->width(_statusText) + st::settingsStatusFont->spacew, _statusPosition.y(), newWidth);
_cancelPhotoUpload->moveToLeft(
margins.left()
+ _statusPosition.x()
+ st::settingsStatusFont->width(_statusText)
+ st::settingsStatusFont->spacew,
margins.top() + _statusPosition.y(),
newWidth);
}
refreshButtonsGeometry(newWidth);
@ -125,20 +135,27 @@ int CoverWidget::resizeGetHeight(int newWidth) {
}
void CoverWidget::refreshButtonsGeometry(int newWidth) {
int buttonLeft = _userpicButton->x() + _userpicButton->width() + st::settingsButtonLeft;
int buttonsRight = newWidth - st::settingsButtonSkip;
_setPhoto->moveToLeft(buttonLeft, _userpicButton->y() + st::settingsButtonTop, newWidth);
auto margins = getMargins();
auto buttonLeft = margins.left() + _userpicButton->x() + _userpicButton->width() + st::settingsButtonLeft;
_setPhoto->moveToLeft(
buttonLeft,
margins.top() + _userpicButton->y() + st::settingsButtonTop,
newWidth);
buttonLeft += _setPhoto->width() + st::settingsButtonSkip;
_editName->moveToLeft(buttonLeft, _setPhoto->y(), newWidth);
_editName->moveToLeft(
buttonLeft,
margins.top() + _setPhoto->y(),
newWidth);
_editNameVisible = (buttonLeft + _editName->width() + st::settingsButtonSkip <= newWidth);
_editName->setVisible(_editNameVisible);
}
void CoverWidget::refreshNameGeometry(int newWidth) {
int infoLeft = _userpicButton->x() + _userpicButton->width();
int nameLeft = infoLeft + st::settingsNameLeft - st::settingsNameLabel.margin.left();
int nameTop = _userpicButton->y() + st::settingsNameTop - st::settingsNameLabel.margin.top();
int nameWidth = newWidth - infoLeft - st::settingsNameLeft;
auto margins = getMargins();
auto infoLeft = _userpicButton->x() + _userpicButton->width();
auto nameLeft = infoLeft + st::settingsNameLeft - st::settingsNameLabel.margin.left();
auto nameTop = _userpicButton->y() + st::settingsNameTop - st::settingsNameLabel.margin.top();
auto nameWidth = newWidth - infoLeft - st::settingsNameLeft;
auto editNameInlineVisible = !_editNameVisible;
if (editNameInlineVisible) {
nameWidth -= _editNameInline->width();
@ -146,9 +163,15 @@ void CoverWidget::refreshNameGeometry(int newWidth) {
int marginsAdd = st::settingsNameLabel.margin.left() + st::settingsNameLabel.margin.right();
_name->resizeToWidth(qMin(nameWidth - marginsAdd, _name->naturalWidth()) + marginsAdd);
_name->moveToLeft(nameLeft, nameTop, newWidth);
_name->moveToLeft(
margins.left() + nameLeft,
margins.top() + nameTop,
newWidth);
_editNameInline->moveToLeft(nameLeft + _name->width(), nameTop, newWidth);
_editNameInline->moveToLeft(
margins.left() + nameLeft + _name->width(),
margins.top() + nameTop,
newWidth);
_editNameInline->setVisible(editNameInlineVisible);
}
@ -283,10 +306,16 @@ void CoverWidget::refreshStatusText() {
_statusText = lang(lng_settings_uploading_photo);
_statusTextIsOnline = false;
if (!_cancelPhotoUpload) {
auto margins = getMargins();
_cancelPhotoUpload.create(this, lang(lng_cancel), st::defaultLinkButton);
connect(_cancelPhotoUpload, SIGNAL(clicked()), this, SLOT(onCancelPhotoUpload()));
_cancelPhotoUpload->show();
_cancelPhotoUpload->moveToLeft(_statusPosition.x() + st::settingsStatusFont->width(_statusText) + st::settingsStatusFont->spacew, _statusPosition.y());
_cancelPhotoUpload->moveToLeft(
margins.left()
+ _statusPosition.x()
+ st::settingsStatusFont->width(_statusText)
+ st::settingsStatusFont->spacew,
margins.top() + _statusPosition.y());
}
update();
return;

View file

@ -22,7 +22,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "styles/style_settings.h"
#include "lang/lang_keys.h"
#include "ui/effects/widget_slide_wrap.h"
#include "ui/wrap/slide_wrap.h"
#include "ui/widgets/checkbox.h"
#include "ui/widgets/buttons.h"
#include "storage/localstorage.h"
@ -41,7 +41,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
namespace Settings {
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
UpdateStateRow::UpdateStateRow(QWidget *parent) : TWidget(parent)
UpdateStateRow::UpdateStateRow(QWidget *parent) : RpWidget(parent)
, _check(this, lang(lng_settings_check_now))
, _restart(this, lang(lng_settings_update_now)) {
connect(_check, SIGNAL(clicked()), this, SLOT(onCheck()));
@ -164,7 +164,7 @@ GeneralWidget::GeneralWidget(QWidget *parent, UserData *self) : BlockWidget(pare
}
int GeneralWidget::resizeGetHeight(int newWidth) {
_changeLanguage->moveToRight(contentLeft(), st::settingsBlockMarginTop + st::settingsBlockTitleTop + st::settingsBlockTitleFont->ascent - st::defaultLinkButton.font->ascent, newWidth);
_changeLanguage->moveToRight(0, st::settingsBlockMarginTop + st::settingsBlockTitleTop + st::settingsBlockTitleFont->ascent - st::defaultLinkButton.font->ascent, newWidth);
return BlockWidget::resizeGetHeight(newWidth);
}
@ -175,9 +175,9 @@ void GeneralWidget::refreshControls() {
style::margins slidedPadding(0, marginSmall.bottom() / 2, 0, marginSmall.bottom() - (marginSmall.bottom() / 2));
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
addChildRow(_updateAutomatically, marginSub, lang(lng_settings_update_automatically), [this](bool) { onUpdateAutomatically(); }, cAutoUpdate());
createChildRow(_updateAutomatically, marginSub, lang(lng_settings_update_automatically), [this](bool) { onUpdateAutomatically(); }, cAutoUpdate());
style::margins marginLink(st::defaultCheck.diameter + st::defaultBoxCheckbox.textPosition.x(), 0, 0, st::settingsSkip);
addChildRow(_updateRow, marginLink, slidedPadding);
createChildRow(_updateRow, marginLink, slidedPadding);
connect(_updateRow->entity(), SIGNAL(restart()), this, SLOT(onRestart()));
if (!cAutoUpdate()) {
_updateRow->hideFast();
@ -186,20 +186,20 @@ void GeneralWidget::refreshControls() {
if (cPlatform() == dbipWindows || cSupportTray()) {
auto workMode = Global::WorkMode().value();
addChildRow(_enableTrayIcon, marginSmall, lang(lng_settings_workmode_tray), [this](bool) { onEnableTrayIcon(); }, (workMode == dbiwmTrayOnly || workMode == dbiwmWindowAndTray));
createChildRow(_enableTrayIcon, marginSmall, lang(lng_settings_workmode_tray), [this](bool) { onEnableTrayIcon(); }, (workMode == dbiwmTrayOnly || workMode == dbiwmWindowAndTray));
if (cPlatform() == dbipWindows) {
addChildRow(_enableTaskbarIcon, marginLarge, lang(lng_settings_workmode_window), [this](bool) { onEnableTaskbarIcon(); }, (workMode == dbiwmWindowOnly || workMode == dbiwmWindowAndTray));
createChildRow(_enableTaskbarIcon, marginLarge, lang(lng_settings_workmode_window), [this](bool) { onEnableTaskbarIcon(); }, (workMode == dbiwmWindowOnly || workMode == dbiwmWindowAndTray));
#ifndef OS_WIN_STORE
addChildRow(_autoStart, marginSmall, lang(lng_settings_auto_start), [this](bool) { onAutoStart(); }, cAutoStart());
addChildRow(_startMinimized, marginLarge, slidedPadding, lang(lng_settings_start_min), [this](bool) { onStartMinimized(); }, (cStartMinimized() && !Global::LocalPasscode()));
createChildRow(_autoStart, marginSmall, lang(lng_settings_auto_start), [this](bool) { onAutoStart(); }, cAutoStart());
createChildRow(_startMinimized, marginLarge, slidedPadding, lang(lng_settings_start_min), [this](bool) { onStartMinimized(); }, (cStartMinimized() && !Global::LocalPasscode()));
subscribe(Global::RefLocalPasscodeChanged(), [this] {
_startMinimized->entity()->setChecked(cStartMinimized() && !Global::LocalPasscode());
});
if (!cAutoStart()) {
_startMinimized->hideFast();
}
addChildRow(_addInSendTo, marginSmall, lang(lng_settings_add_sendto), [this](bool) { onAddInSendTo(); }, cSendToMenu());
createChildRow(_addInSendTo, marginSmall, lang(lng_settings_add_sendto), [this](bool) { onAddInSendTo(); }, cSendToMenu());
#endif // OS_WIN_STORE
}
}

View file

@ -21,11 +21,12 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#pragma once
#include "settings/settings_block_widget.h"
#include "ui/rp_widget.h"
namespace Settings {
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
class UpdateStateRow : public TWidget {
class UpdateStateRow : public Ui::RpWidget {
Q_OBJECT
public:
@ -107,14 +108,14 @@ private:
object_ptr<Ui::LinkButton> _changeLanguage;
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
object_ptr<Ui::Checkbox> _updateAutomatically = { nullptr };
object_ptr<Ui::WidgetSlideWrap<UpdateStateRow>> _updateRow = { nullptr };
Ui::Checkbox *_updateAutomatically = nullptr;
Ui::SlideWrap<UpdateStateRow> *_updateRow = nullptr;
#endif // !TDESKTOP_DISABLE_AUTOUPDATE
object_ptr<Ui::Checkbox> _enableTrayIcon = { nullptr };
object_ptr<Ui::Checkbox> _enableTaskbarIcon = { nullptr };
object_ptr<Ui::Checkbox> _autoStart = { nullptr };
object_ptr<Ui::WidgetSlideWrap<Ui::Checkbox>> _startMinimized = { nullptr };
object_ptr<Ui::Checkbox> _addInSendTo = { nullptr };
Ui::Checkbox *_enableTrayIcon = nullptr;
Ui::Checkbox *_enableTaskbarIcon = nullptr;
Ui::Checkbox *_autoStart = nullptr;
Ui::SlideWrap<Ui::Checkbox> *_startMinimized = nullptr;
Ui::Checkbox *_addInSendTo = nullptr;
int _languagesLoadedSubscription = 0;

View file

@ -23,7 +23,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "styles/style_settings.h"
#include "lang/lang_keys.h"
#include "ui/widgets/labels.h"
#include "ui/effects/widget_slide_wrap.h"
#include "ui/wrap/slide_wrap.h"
#include "boxes/username_box.h"
#include "boxes/add_contact_box.h"
#include "boxes/change_phone_box.h"
@ -46,9 +46,9 @@ InfoWidget::InfoWidget(QWidget *parent, UserData *self) : BlockWidget(parent, se
void InfoWidget::createControls() {
style::margins margin(0, 0, 0, 0);
style::margins slidedPadding(0, 0, 0, 0);
addChildRow(_mobileNumber, margin, slidedPadding, st::settingsBlockOneLineTextPart);
addChildRow(_username, margin, slidedPadding, st::settingsBlockOneLineTextPart);
addChildRow(_bio, margin, slidedPadding, st::settingsBioValue);
createChildRow(_mobileNumber, margin, slidedPadding, st::settingsBlockOneLineTextPart);
createChildRow(_username, margin, slidedPadding, st::settingsBlockOneLineTextPart);
createChildRow(_bio, margin, slidedPadding, st::settingsBioValue);
refreshControls();
}
@ -67,7 +67,12 @@ void InfoWidget::refreshMobileNumber() {
phoneText.text = App::phoneFromSharedContact(peerToUser(user->id));
}
}
setLabeledText(_mobileNumber, lang(lng_profile_mobile_number), phoneText, TextWithEntities(), lang(lng_profile_copy_phone));
setLabeledText(
_mobileNumber,
lang(lng_profile_mobile_number),
phoneText,
TextWithEntities(),
lang(lng_profile_copy_phone));
if (auto text = _mobileNumber->entity()->textLabel()) {
text->setRichText(textcmdLink(1, phoneText.text));
text->setLink(1, MakeShared<LambdaClickHandler>([] {
@ -86,7 +91,12 @@ void InfoWidget::refreshUsername() {
copyText = lang(lng_context_copy_mention);
}
usernameText.entities.push_back(EntityInText(EntityInTextCustomUrl, 0, usernameText.text.size(), Messenger::Instance().createInternalLinkFull(self()->username)));
setLabeledText(_username, lang(lng_profile_username), usernameText, TextWithEntities(), copyText);
setLabeledText(
_username,
lang(lng_profile_username),
usernameText,
TextWithEntities(),
copyText);
if (auto text = _username->entity()->textLabel()) {
text->setClickHandlerHook([](const ClickHandlerPtr &handler, Qt::MouseButton button) {
Ui::show(Box<UsernameBox>());
@ -104,7 +114,12 @@ void InfoWidget::refreshBio() {
bioText.text = aboutText;
}
bioText.entities.push_back(EntityInText(EntityInTextCustomUrl, 0, bioText.text.size(), QString()));
setLabeledText(_bio, lang(lng_profile_bio), bioText, TextWithEntities(), QString());
setLabeledText(
_bio,
lang(lng_profile_bio),
bioText,
TextWithEntities(),
QString());
if (auto text = _bio->entity()->textLabel()) {
text->setClickHandlerHook([](const ClickHandlerPtr &handler, Qt::MouseButton button) {
Ui::show(Box<EditBioBox>(App::self()));
@ -113,19 +128,34 @@ void InfoWidget::refreshBio() {
}
}
void InfoWidget::setLabeledText(object_ptr<LabeledWrap> &row, const QString &label, const TextWithEntities &textWithEntities, const TextWithEntities &shortTextWithEntities, const QString &copyText) {
void InfoWidget::setLabeledText(
LabeledWrap *row,
const QString &label,
const TextWithEntities &textWithEntities,
const TextWithEntities &shortTextWithEntities,
const QString &copyText) {
auto nonEmptyText = !textWithEntities.text.isEmpty();
if (nonEmptyText) {
row->entity()->setLabeledText(label, textWithEntities, shortTextWithEntities, copyText);
row->entity()->setLabeledText(
label,
textWithEntities,
shortTextWithEntities,
copyText,
width());
}
row->toggleAnimated(nonEmptyText);
}
InfoWidget::LabeledWidget::LabeledWidget(QWidget *parent, const style::FlatLabel &valueSt) : TWidget(parent)
InfoWidget::LabeledWidget::LabeledWidget(QWidget *parent, const style::FlatLabel &valueSt) : RpWidget(parent)
, _valueSt(valueSt) {
}
void InfoWidget::LabeledWidget::setLabeledText(const QString &label, const TextWithEntities &textWithEntities, const TextWithEntities &shortTextWithEntities, const QString &copyText) {
void InfoWidget::LabeledWidget::setLabeledText(
const QString &label,
const TextWithEntities &textWithEntities,
const TextWithEntities &shortTextWithEntities,
const QString &copyText,
int availableWidth) {
_label.destroy();
_text.destroy();
_shortText.destroy();
@ -135,7 +165,7 @@ void InfoWidget::LabeledWidget::setLabeledText(const QString &label, const TextW
_label->show();
setLabelText(_text, textWithEntities, copyText);
setLabelText(_shortText, shortTextWithEntities, copyText);
resizeToWidth(width());
resizeToNaturalWidth(availableWidth);
}
Ui::FlatLabel *InfoWidget::LabeledWidget::textLabel() const {
@ -172,8 +202,6 @@ void InfoWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) {
if (update.flags & UpdateFlag::AboutChanged) {
refreshBio();
}
contentSizeUpdated();
}
int InfoWidget::LabeledWidget::naturalWidth() const {
@ -188,10 +216,7 @@ int InfoWidget::LabeledWidget::resizeGetHeight(int newWidth) {
if (!_label) return 0;
_label->moveToLeft(0, st::settingsBlockOneLineTextPart.margin.top(), newWidth);
auto labelNatural = _label->naturalWidth();
Assert(labelNatural >= 0);
_label->resize(qMin(newWidth, labelNatural), _label->height());
_label->resizeToNaturalWidth(newWidth);
int textLeft = _label->width() + st::normalFont->spacew;
int textWidth = _text->naturalWidth();

View file

@ -21,6 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#pragma once
#include "settings/settings_block_widget.h"
#include "ui/rp_widget.h"
namespace Ui {
class FlatLabel;
@ -46,11 +47,16 @@ private:
void refreshUsername();
void refreshBio();
class LabeledWidget : public TWidget {
class LabeledWidget : public Ui::RpWidget {
public:
LabeledWidget(QWidget *parent, const style::FlatLabel &valueSt);
void setLabeledText(const QString &label, const TextWithEntities &textWithEntities, const TextWithEntities &shortTextWithEntities, const QString &copyText);
void setLabeledText(
const QString &label,
const TextWithEntities &textWithEntities,
const TextWithEntities &shortTextWithEntities,
const QString &copyText,
int availableWidth);
Ui::FlatLabel *textLabel() const;
Ui::FlatLabel *shortTextLabel() const;
@ -61,7 +67,10 @@ private:
int resizeGetHeight(int newWidth) override;
private:
void setLabelText(object_ptr<Ui::FlatLabel> &text, const TextWithEntities &textWithEntities, const QString &copyText);
void setLabelText(
object_ptr<Ui::FlatLabel> &text,
const TextWithEntities &textWithEntities,
const QString &copyText);
const style::FlatLabel &_valueSt;
object_ptr<Ui::FlatLabel> _label = { nullptr };
@ -70,12 +79,17 @@ private:
};
using LabeledWrap = Ui::WidgetSlideWrap<LabeledWidget>;
void setLabeledText(object_ptr<LabeledWrap> &row, const QString &label, const TextWithEntities &textWithEntities, const TextWithEntities &shortTextWithEntities, const QString &copyText);
using LabeledWrap = Ui::SlideWrap<LabeledWidget>;
void setLabeledText(
LabeledWrap *row,
const QString &label,
const TextWithEntities &textWithEntities,
const TextWithEntities &shortTextWithEntities,
const QString &copyText);
object_ptr<LabeledWrap> _mobileNumber = { nullptr };
object_ptr<LabeledWrap> _username = { nullptr };
object_ptr<LabeledWrap> _bio = { nullptr };
LabeledWrap *_mobileNumber = nullptr;
LabeledWrap *_username = nullptr;
LabeledWrap *_bio = nullptr;
};

View file

@ -36,7 +36,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
namespace Settings {
InnerWidget::InnerWidget(QWidget *parent) : LayerInner(parent)
, _self(App::self()) {
, _self(App::self())
, _blocks(this) {
refreshBlocks();
subscribe(Global::RefSelfChanged(), [this] { fullRebuild(); });
subscribe(Lang::Current().updated(), [this] { fullRebuild(); });
@ -45,44 +46,34 @@ InnerWidget::InnerWidget(QWidget *parent) : LayerInner(parent)
void InnerWidget::fullRebuild() {
_self = App::self();
refreshBlocks();
if (_cover) {
_cover->setContentLeft(_contentLeft);
_cover->resizeToWidth(width());
}
for_const (auto block, _blocks) {
block->setContentLeft(_contentLeft);
block->resizeToWidth(width());
}
onBlockHeightUpdated();
}
void InnerWidget::refreshBlocks() {
_cover.destroyDelayed();
for_const (auto block, _blocks) {
block->hide();
block->deleteLater();
}
_blocks.clear();
if (App::quitting()) {
_cover.destroy();
_blocks.destroy();
return;
}
_cover = _self
? object_ptr<CoverWidget>(this, _self)
: nullptr;
_blocks = object_ptr<Ui::VerticalLayout>(this);
resizeToWidth(width(), _contentLeft);
if (_self) {
_cover.create(this, _self);
_blocks.push_back(new InfoWidget(this, _self));
_blocks.push_back(new NotificationsWidget(this, _self));
_blocks->add(object_ptr<InfoWidget>(this, _self));
_blocks->add(object_ptr<NotificationsWidget>(this, _self));
}
_blocks.push_back(new GeneralWidget(this, _self));
_blocks->add(object_ptr<GeneralWidget>(this, _self));
if (!cRetina()) {
_blocks.push_back(new ScaleWidget(this, _self));
_blocks->add(object_ptr<ScaleWidget>(this, _self));
}
if (_self) {
_blocks.push_back(new ChatSettingsWidget(this, _self));
_blocks.push_back(new BackgroundWidget(this, _self));
_blocks.push_back(new PrivacyWidget(this, _self));
_blocks->add(object_ptr<ChatSettingsWidget>(this, _self));
_blocks->add(object_ptr<BackgroundWidget>(this, _self));
_blocks->add(object_ptr<PrivacyWidget>(this, _self));
}
_blocks.push_back(new AdvancedWidget(this, _self));
_blocks->add(object_ptr<AdvancedWidget>(this, _self));
if (_cover) {
_cover->show();
@ -90,10 +81,12 @@ void InnerWidget::refreshBlocks() {
_cover->showFinished();
}
}
for_const (auto block, _blocks) {
block->show();
connect(block, SIGNAL(heightUpdated()), this, SLOT(onBlockHeightUpdated()));
}
_blocks->show();
_blocks->heightValue()
| rpl::on_next([this](int blocksHeight) {
resize(width(), _blocks->y() + blocksHeight);
})
| rpl::start(lifetime());
}
void InnerWidget::showFinished() {
@ -108,44 +101,25 @@ int InnerWidget::resizeGetHeight(int newWidth) {
_cover->setContentLeft(_contentLeft);
_cover->resizeToWidth(newWidth);
}
for_const (auto block, _blocks) {
block->setContentLeft(_contentLeft);
block->resizeToWidth(newWidth);
}
int result = refreshBlocksPositions(newWidth);
return result;
_blocks->resizeToWidth(newWidth - 2 * _contentLeft);
_blocks->moveToLeft(
_contentLeft,
(_cover ? (_cover->y() + _cover->height()) : 0)
+ st::settingsBlocksTop);
return height();
}
int InnerWidget::refreshBlocksPositions(int newWidth) {
int result = (_cover ? _cover->height() : 0) + st::settingsBlocksTop;
for_const (auto block, _blocks) {
if (block->isHidden()) {
continue;
}
block->moveToLeft(0, result, newWidth);
result += block->height();
}
return result;
}
void InnerWidget::onBlockHeightUpdated() {
int newHeight = refreshBlocksPositions(width());
if (newHeight != height()) {
resize(width(), newHeight);
emit heightUpdated();
}
}
void InnerWidget::setVisibleTopBottom(int visibleTop, int visibleBottom) {
_visibleTop = visibleTop;
_visibleBottom = visibleBottom;
for_const (auto block, _blocks) {
int blockY = block->y();
block->setVisibleTopBottom(visibleTop - blockY, visibleBottom - blockY);
}
void InnerWidget::visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) {
setChildVisibleTopBottom(
_cover,
visibleTop,
visibleBottom);
setChildVisibleTopBottom(
_blocks,
visibleTop,
visibleBottom);
}
} // namespace Settings

View file

@ -21,6 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#pragma once
#include "settings/settings_layer.h"
#include "ui/wrap/vertical_layout.h"
namespace Settings {
@ -28,8 +29,6 @@ class CoverWidget;
class BlockWidget;
class InnerWidget : public LayerInner, private base::Subscriber {
Q_OBJECT
public:
InnerWidget(QWidget *parent);
@ -39,36 +38,26 @@ public:
return TWidget::resizeToWidth(newWidth);
}
// Updates the area that is visible inside the scroll container.
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
void showFinished();
private slots:
void onBlockHeightUpdated();
protected:
// Resizes content and counts natural widget height for the desired width.
int resizeGetHeight(int newWidth) override;
void visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) override;
private:
void fullRebuild();
void refreshBlocks();
// Returns the new height value.
int refreshBlocksPositions(int newWidth);
object_ptr<CoverWidget> _cover = { nullptr };
QList<BlockWidget*> _blocks;
object_ptr<Ui::VerticalLayout> _blocks;
UserData *_self = nullptr;
int _contentLeft = 0;
bool _showFinished = false;
int _visibleTop = 0;
int _visibleBottom = 0;
};
} // namespace Settings

View file

@ -50,21 +50,19 @@ Layer::Layer()
_fixedBarShadow->hideFast();
_scroll->moveToLeft(0, st::settingsFixedBarHeight);
connect(_scroll, SIGNAL(scrolled()), this, SLOT(onScroll()));
_scroll->scrollTopValue()
| rpl::map([](int scrollTop) { return scrollTop > 0; })
| rpl::distinct_until_changed()
| rpl::on_next([this](bool scrolled) {
_fixedBarShadow->toggleAnimated(scrolled);
})
| rpl::start(lifetime());
}
void Layer::setCloseClickHandler(base::lambda<void()> callback) {
_fixedBarClose->setClickedCallback(std::move(callback));
}
void Layer::onScroll() {
if (_scroll->scrollTop() > 0) {
_fixedBarShadow->showAnimated();
} else {
_fixedBarShadow->hideAnimated();
}
}
void Layer::resizeToWidth(int newWidth, int newContentLeft) {
// Widget height depends on InnerWidget height, so we
// resize it here, not in the resizeEvent() handler.
@ -73,13 +71,13 @@ void Layer::resizeToWidth(int newWidth, int newContentLeft) {
resizeUsingInnerHeight(newWidth, _inner->height());
}
void Layer::onInnerHeightUpdated() {
resizeUsingInnerHeight(width(), _inner->height());
}
void Layer::doSetInnerWidget(object_ptr<LayerInner> widget) {
_inner = _scroll->setOwnedWidget(std::move(widget));
connect(_inner, SIGNAL(heightUpdated()), this, SLOT(onInnerHeightUpdated()));
_inner->heightValue()
| rpl::on_next([this](int innerHeight) {
resizeUsingInnerHeight(width(), innerHeight);
})
| rpl::start(lifetime());
}
void Layer::paintEvent(QPaintEvent *e) {

View file

@ -21,6 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#pragma once
#include "layerwidget.h"
#include "ui/rp_widget.h"
class BoxLayerTitleShadow;
@ -34,9 +35,9 @@ class WidgetFadeWrap;
namespace Settings {
class FixedBar;
class LayerInner : public TWidget {
class LayerInner : public Ui::RpWidget {
public:
LayerInner(QWidget *parent) : TWidget(parent) {
LayerInner(QWidget *parent) : RpWidget(parent) {
}
virtual void resizeToWidth(int newWidth, int contentLeft) {
@ -46,8 +47,6 @@ public:
};
class Layer : public LayerWidget {
Q_OBJECT
public:
Layer();
@ -70,10 +69,6 @@ protected:
_roundedCorners = roundedCorners;
}
private slots:
void onInnerHeightUpdated();
void onScroll();
private:
void doSetInnerWidget(object_ptr<LayerInner> widget);

View file

@ -23,7 +23,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "styles/style_settings.h"
#include "lang/lang_keys.h"
#include "storage/localstorage.h"
#include "ui/effects/widget_slide_wrap.h"
#include "ui/wrap/slide_wrap.h"
#include "ui/widgets/checkbox.h"
#include "ui/widgets/buttons.h"
#include "mainwindow.h"
@ -56,9 +56,9 @@ NotificationsWidget::NotificationsWidget(QWidget *parent, UserData *self) : Bloc
void NotificationsWidget::createControls() {
style::margins margin(0, 0, 0, st::settingsSkip);
style::margins slidedPadding(0, margin.bottom() / 2, 0, margin.bottom() - (margin.bottom() / 2));
addChildRow(_desktopNotifications, margin, lang(lng_settings_desktop_notify), [this](bool) { onDesktopNotifications(); }, Global::DesktopNotify());
addChildRow(_showSenderName, margin, slidedPadding, lang(lng_settings_show_name), [this](bool) { onShowSenderName(); }, Global::NotifyView() <= dbinvShowName);
addChildRow(_showMessagePreview, margin, slidedPadding, lang(lng_settings_show_preview), [this](bool) { onShowMessagePreview(); }, Global::NotifyView() <= dbinvShowPreview);
createChildRow(_desktopNotifications, margin, lang(lng_settings_desktop_notify), [this](bool) { onDesktopNotifications(); }, Global::DesktopNotify());
createChildRow(_showSenderName, margin, slidedPadding, lang(lng_settings_show_name), [this](bool) { onShowSenderName(); }, Global::NotifyView() <= dbinvShowName);
createChildRow(_showMessagePreview, margin, slidedPadding, lang(lng_settings_show_preview), [this](bool) { onShowMessagePreview(); }, Global::NotifyView() <= dbinvShowPreview);
if (!_showSenderName->entity()->checked()) {
_showMessagePreview->hideFast();
}
@ -66,8 +66,8 @@ void NotificationsWidget::createControls() {
_showSenderName->hideFast();
_showMessagePreview->hideFast();
}
addChildRow(_playSound, margin, lang(lng_settings_sound_notify), [this](bool) { onPlaySound(); }, Global::SoundNotify());
addChildRow(_includeMuted, margin, lang(lng_settings_include_muted), [this](bool) { onIncludeMuted(); }, Global::IncludeMuted());
createChildRow(_playSound, margin, lang(lng_settings_sound_notify), [this](bool) { onPlaySound(); }, Global::SoundNotify());
createChildRow(_includeMuted, margin, lang(lng_settings_include_muted), [this](bool) { onIncludeMuted(); }, Global::IncludeMuted());
if (cPlatform() != dbipMac) {
createNotificationsControls();
@ -87,9 +87,9 @@ void NotificationsWidget::createNotificationsControls() {
#endif // Q_OS_WIN || Q_OS_LINUX64 || Q_OS_LINUX32
}
if (!nativeNotificationsLabel.isEmpty()) {
addChildRow(_nativeNotifications, margin, nativeNotificationsLabel, [this](bool) { onNativeNotifications(); }, Global::NativeNotifications());
createChildRow(_nativeNotifications, margin, nativeNotificationsLabel, [this](bool) { onNativeNotifications(); }, Global::NativeNotifications());
}
addChildRow(_advanced, margin, slidedPadding, lang(lng_settings_advanced_notifications), SLOT(onAdvanced()));
createChildRow(_advanced, margin, slidedPadding, lang(lng_settings_advanced_notifications), SLOT(onAdvanced()));
if (!nativeNotificationsLabel.isEmpty() && Global::NativeNotifications()) {
_advanced->hideFast();
}

View file

@ -45,13 +45,13 @@ private:
void desktopEnabledUpdated();
void viewParamUpdated();
object_ptr<Ui::Checkbox> _desktopNotifications = { nullptr };
object_ptr<Ui::WidgetSlideWrap<Ui::Checkbox>> _showSenderName = { nullptr };
object_ptr<Ui::WidgetSlideWrap<Ui::Checkbox>> _showMessagePreview = { nullptr };
object_ptr<Ui::Checkbox> _nativeNotifications = { nullptr };
object_ptr<Ui::Checkbox> _playSound = { nullptr };
object_ptr<Ui::Checkbox> _includeMuted = { nullptr };
object_ptr<Ui::WidgetSlideWrap<Ui::LinkButton>> _advanced = { nullptr };
Ui::Checkbox *_desktopNotifications = nullptr;
Ui::SlideWrap<Ui::Checkbox> *_showSenderName = nullptr;
Ui::SlideWrap<Ui::Checkbox> *_showMessagePreview = nullptr;
Ui::Checkbox *_nativeNotifications = nullptr;
Ui::Checkbox *_playSound = nullptr;
Ui::Checkbox *_includeMuted = nullptr;
Ui::SlideWrap<Ui::LinkButton> *_advanced = nullptr;
};

View file

@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "settings/settings_privacy_widget.h"
#include "ui/effects/widget_slide_wrap.h"
#include "ui/wrap/slide_wrap.h"
#include "ui/widgets/buttons.h"
#include "styles/style_settings.h"
#include "lang/lang_keys.h"
@ -36,7 +36,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
namespace Settings {
LocalPasscodeState::LocalPasscodeState(QWidget *parent) : TWidget(parent)
LocalPasscodeState::LocalPasscodeState(QWidget *parent) : RpWidget(parent)
, _edit(this, GetEditPasscodeText(), st::boxLinkButton)
, _turnOff(this, lang(lng_passcode_turn_off), st::boxLinkButton) {
updateControls();
@ -69,7 +69,7 @@ QString LocalPasscodeState::GetEditPasscodeText() {
return lang(Global::LocalPasscode() ? lng_passcode_change : lng_passcode_turn_on);
}
CloudPasswordState::CloudPasswordState(QWidget *parent) : TWidget(parent)
CloudPasswordState::CloudPasswordState(QWidget *parent) : RpWidget(parent)
, _edit(this, lang(lng_cloud_password_set), st::boxLinkButton)
, _turnOff(this, lang(lng_passcode_turn_off), st::boxLinkButton) {
_turnOff->hide();
@ -182,20 +182,20 @@ void PrivacyWidget::createControls() {
style::margins marginSkip(0, 0, 0, st::settingsSkip);
style::margins slidedPadding(0, marginSmall.bottom() / 2, 0, marginSmall.bottom() - (marginSmall.bottom() / 2));
addChildRow(_blockedUsers, marginSmall, lang(lng_settings_blocked_users), SLOT(onBlockedUsers()));
addChildRow(_lastSeenPrivacy, marginSmall, lang(lng_settings_last_seen_privacy), SLOT(onLastSeenPrivacy()));
addChildRow(_callsPrivacy, marginSmall, lang(lng_settings_calls_privacy), SLOT(onCallsPrivacy()));
addChildRow(_groupsInvitePrivacy, marginSmall, lang(lng_settings_groups_invite_privacy), SLOT(onGroupsInvitePrivacy()));
addChildRow(_localPasscodeState, marginSmall);
createChildRow(_blockedUsers, marginSmall, lang(lng_settings_blocked_users), SLOT(onBlockedUsers()));
createChildRow(_lastSeenPrivacy, marginSmall, lang(lng_settings_last_seen_privacy), SLOT(onLastSeenPrivacy()));
createChildRow(_callsPrivacy, marginSmall, lang(lng_settings_calls_privacy), SLOT(onCallsPrivacy()));
createChildRow(_groupsInvitePrivacy, marginSmall, lang(lng_settings_groups_invite_privacy), SLOT(onGroupsInvitePrivacy()));
createChildRow(_localPasscodeState, marginSmall);
auto label = lang(psIdleSupported() ? lng_passcode_autolock_away : lng_passcode_autolock_inactive);
auto value = GetAutoLockText();
addChildRow(_autoLock, marginSmall, slidedPadding, label, value, LabeledLink::Type::Primary, SLOT(onAutoLock()));
createChildRow(_autoLock, marginSmall, slidedPadding, label, value, LabeledLink::Type::Primary, SLOT(onAutoLock()));
if (!Global::LocalPasscode()) {
_autoLock->hideFast();
}
addChildRow(_cloudPasswordState, marginSmall);
addChildRow(_showAllSessions, marginSmall, lang(lng_settings_show_sessions), SLOT(onShowSessions()));
addChildRow(_selfDestruction, marginSmall, lang(lng_settings_self_destruct), SLOT(onSelfDestruction()));
createChildRow(_cloudPasswordState, marginSmall);
createChildRow(_showAllSessions, marginSmall, lang(lng_settings_show_sessions), SLOT(onShowSessions()));
createChildRow(_selfDestruction, marginSmall, lang(lng_settings_self_destruct), SLOT(onSelfDestruction()));
}
void PrivacyWidget::autoLockUpdated() {

View file

@ -22,10 +22,11 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "settings/settings_block_widget.h"
#include "settings/settings_chat_settings_widget.h"
#include "ui/rp_widget.h"
namespace Settings {
class LocalPasscodeState : public TWidget, private base::Subscriber {
class LocalPasscodeState : public Ui::RpWidget, private base::Subscriber {
Q_OBJECT
public:
@ -48,7 +49,7 @@ private:
};
class CloudPasswordState : public TWidget, private base::Subscriber, public RPCSender {
class CloudPasswordState : public Ui::RpWidget, private base::Subscriber, public RPCSender {
Q_OBJECT
public:
@ -101,15 +102,15 @@ private:
void createControls();
void autoLockUpdated();
object_ptr<Ui::LinkButton> _blockedUsers = { nullptr };
object_ptr<Ui::LinkButton> _lastSeenPrivacy = { nullptr };
object_ptr<Ui::LinkButton> _callsPrivacy = { nullptr };
object_ptr<Ui::LinkButton> _groupsInvitePrivacy = { nullptr };
object_ptr<LocalPasscodeState> _localPasscodeState = { nullptr };
object_ptr<Ui::WidgetSlideWrap<LabeledLink>> _autoLock = { nullptr };
object_ptr<CloudPasswordState> _cloudPasswordState = { nullptr };
object_ptr<Ui::LinkButton> _showAllSessions = { nullptr };
object_ptr<Ui::LinkButton> _selfDestruction = { nullptr };
Ui::LinkButton *_blockedUsers = nullptr;
Ui::LinkButton *_lastSeenPrivacy = nullptr;
Ui::LinkButton *_callsPrivacy = nullptr;
Ui::LinkButton *_groupsInvitePrivacy = nullptr;
LocalPasscodeState *_localPasscodeState = nullptr;
Ui::SlideWrap<LabeledLink> *_autoLock = nullptr;
CloudPasswordState *_cloudPasswordState = nullptr;
Ui::LinkButton *_showAllSessions = nullptr;
Ui::LinkButton *_selfDestruction = nullptr;
};

View file

@ -52,15 +52,17 @@ ScaleWidget::ScaleWidget(QWidget *parent, UserData *self) : BlockWidget(parent,
void ScaleWidget::createControls() {
style::margins margin(0, 0, 0, st::settingsSmallSkip);
addChildRow(_auto, margin, lng_settings_scale_auto(lt_cur, scaleLabel(cScreenScale())), [this](bool) { onAutoChanged(); }, (cConfigScale() == dbisAuto));
addChildRow(_scale, style::margins(0, 0, 0, 0));
createChildRow(_auto, margin, lng_settings_scale_auto(lt_cur, scaleLabel(cScreenScale())), [this](bool) { onAutoChanged(); }, (cConfigScale() == dbisAuto));
createChildRow(_scale, style::margins(0, 0, 0, 0));
_scale->addSection(scaleLabel(dbisOne));
_scale->addSection(scaleLabel(dbisOneAndQuarter));
_scale->addSection(scaleLabel(dbisOneAndHalf));
_scale->addSection(scaleLabel(dbisTwo));
_scale->setActiveSectionFast(cEvalScale(cConfigScale()) - 1);
_scale->setSectionActivatedCallback([this] { scaleChanged(); });
_scale->sectionActivated()
| rpl::on_next([this](int) { scaleChanged(); })
| rpl::start(lifetime());
}
void ScaleWidget::onAutoChanged() {

View file

@ -43,8 +43,8 @@ private:
void createControls();
void setScale(DBIScale newScale);
object_ptr<Ui::Checkbox> _auto = { nullptr };
object_ptr<Ui::SettingsSlider> _scale = { nullptr };
Ui::Checkbox *_auto = nullptr;
Ui::SettingsSlider *_scale = nullptr;
DBIScale _newScale = dbisAuto;
bool _inSetScale = false;

View file

@ -245,7 +245,7 @@ void Widget::parentResized() {
}
void Widget::resizeUsingInnerHeight(int newWidth, int innerHeight) {
if (!App::wnd()) return;
if (!parentWidget()) return;
auto parentSize = parentWidget()->size();
auto windowWidth = parentSize.width();

View file

@ -27,8 +27,6 @@ namespace Settings {
class InnerWidget;
class Widget : public Layer, private base::Subscriber {
Q_OBJECT
public:
Widget(QWidget*);

View file

@ -20,8 +20,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include <rpl/producer.h>
#include "base/enum_mask.h"
#include "rpl/producer.h"
namespace Storage {

View file

@ -20,8 +20,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include <rpl/event_stream.h>
#include "storage/storage_facade.h"
#include "rpl/event_stream.h"
namespace Storage {

View file

@ -20,8 +20,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include <rpl/event_stream.h>
#include "storage/storage_facade.h"
#include "rpl/event_stream.h"
namespace Storage {

View file

@ -71,6 +71,7 @@ void AbstractButton::mouseReleaseEvent(QMouseEvent *e) {
onStateChanged(was, StateChangeSource::ByPress);
if (was & StateFlag::Over) {
_modifiers = e->modifiers();
_clicks.fire({});
if (_clickedCallback) {
_clickedCallback();
} else {

View file

@ -20,16 +20,17 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "ui/twidget.h"
#include <rpl/event_stream.h>
#include "ui/rp_widget.h"
#include "base/flags.h"
namespace Ui {
class AbstractButton : public TWidget {
class AbstractButton : public RpWidget {
Q_OBJECT
public:
AbstractButton(QWidget *parent) : TWidget(parent) {
AbstractButton(QWidget *parent) : RpWidget(parent) {
setMouseTracking(true);
}
@ -64,6 +65,10 @@ public:
}
}
rpl::producer<> clicks() const {
return _clicks.events();
}
protected:
void enterEventHook(QEvent *e) override;
void leaveEventHook(QEvent *e) override;
@ -109,6 +114,8 @@ private:
base::lambda<void()> _clickedCallback;
rpl::event_stream<> _clicks;
};
} // namespace Ui

View file

@ -22,115 +22,159 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
namespace Ui {
WidgetSlideWrap<TWidget>::WidgetSlideWrap(QWidget *parent
, object_ptr<TWidget> entity
, style::margins entityPadding
, base::lambda<void()> updateCallback
, int duration) : TWidget(parent)
, _entity(std::move(entity))
, _padding(entityPadding)
, _duration(duration)
, _updateCallback(std::move(updateCallback)) {
_entity->setParent(this);
auto margins = getMargins();
_entity->moveToLeft(margins.left() + _padding.left(), margins.top() + _padding.top());
_realSize = _entity->rectNoMargins().marginsAdded(_padding).size();
_entity->installEventFilter(this);
resizeToWidth(_realSize.width());
}
void WidgetSlideWrap<TWidget>::hideAnimated() {
if (isHidden()) {
_forceHeight = 0;
resizeToWidth(_realSize.width());
if (_updateCallback) _updateCallback();
return;
}
if (_a_height.animating()) {
if (_hiding) return;
}
_hiding = true;
_a_height.start([this] { animationCallback(); }, _realSize.height(), 0., _duration);
}
void WidgetSlideWrap<TWidget>::showAnimated() {
if (isHidden()) {
show();
}
if (_forceHeight < 0) {
return;
}
if (_a_height.animating()) {
if (!_hiding) return;
}
_hiding = false;
_forceHeight = qRound(_a_height.current(0.));
_a_height.start([this] { animationCallback(); }, 0., _realSize.height(), _duration);
}
void WidgetSlideWrap<TWidget>::toggleFast(bool visible) {
_hiding = !visible;
if (!_hiding) show();
_a_height.finish();
_forceHeight = _hiding ? 0 : -1;
resizeToWidth(_realSize.width());
if (_hiding) hide();
if (_updateCallback) {
_updateCallback();
PaddingWrap<RpWidget>::PaddingWrap(
QWidget *parent,
object_ptr<RpWidget> child,
const style::margins &padding)
: Parent(parent, std::move(child))
, _padding(padding) {
if (auto weak = wrapped()) {
auto margins = weak->getMargins();
weak->sizeValue()
| rpl::on_next([this](QSize&&) { updateSize(); })
| rpl::start(lifetime());
weak->moveToLeft(_padding.left() + margins.left(), _padding.top() + margins.top());
}
}
QMargins WidgetSlideWrap<TWidget>::getMargins() const {
auto entityMargins = _entity->getMargins();
if (_forceHeight < 0) {
return entityMargins;
}
return QMargins(entityMargins.left(), 0, entityMargins.right(), 0);
}
int WidgetSlideWrap<TWidget>::naturalWidth() const {
auto inner = _entity->naturalWidth();
return (inner < 0) ? inner : (_padding.left() + inner + _padding.right());
}
bool WidgetSlideWrap<TWidget>::eventFilter(QObject *object, QEvent *event) {
if (object == _entity && event->type() == QEvent::Resize) {
_realSize = _entity->rectNoMargins().marginsAdded(_padding).size();
if (!_inResizeToWidth) {
resizeToWidth(_realSize.width());
if (_updateCallback) {
_updateCallback();
}
void PaddingWrap<RpWidget>::updateSize() {
auto inner = [this] {
if (auto weak = wrapped()) {
return weak->rect();
}
}
return TWidget::eventFilter(object, event);
return QRect(0, 0, _innerWidth, 0);
}();
resize(inner.marginsAdded(_padding).size());
}
int WidgetSlideWrap<TWidget>::resizeGetHeight(int newWidth) {
_inResizeToWidth = true;
auto resized = (_forceHeight >= 0);
_entity->resizeToWidth(newWidth - _padding.left() - _padding.right());
auto margins = getMargins();
_entity->moveToLeft(margins.left() + _padding.left(), margins.top() + _padding.top());
_inResizeToWidth = false;
if (resized) {
return _forceHeight;
}
_realSize = _entity->rectNoMargins().marginsAdded(_padding).size();
return _realSize.height();
int PaddingWrap<RpWidget>::naturalWidth() const {
auto inner = [this] {
if (auto weak = wrapped()) {
return weak->naturalWidth();
}
return RpWidget::naturalWidth();
}();
return (inner < 0)
? inner
: (_padding.left() + inner + _padding.right());
}
void WidgetSlideWrap<TWidget>::animationCallback() {
_forceHeight = qRound(_a_height.current(_hiding ? 0 : -1));
resizeToWidth(_realSize.width());
if (!_a_height.animating()) {
_forceHeight = _hiding ? 0 : -1;
if (_hiding) hide();
int PaddingWrap<RpWidget>::resizeGetHeight(int newWidth) {
_innerWidth = newWidth;
if (auto weak = wrapped()) {
weak->resizeToWidth(newWidth
- _padding.left()
- _padding.right());
} else {
updateSize();
}
if (_updateCallback) {
_updateCallback();
return height();
}
SlideWrap<RpWidget>::SlideWrap(
QWidget *parent,
object_ptr<RpWidget> child)
: SlideWrap(
parent,
std::move(child),
style::margins(),
st::slideWrapDuration) {
}
SlideWrap<RpWidget>::SlideWrap(
QWidget *parent,
object_ptr<RpWidget> child,
const style::margins &padding)
: SlideWrap(
parent,
std::move(child),
padding,
st::slideWrapDuration) {
}
SlideWrap<RpWidget>::SlideWrap(
QWidget *parent,
object_ptr<RpWidget> child,
int duration)
: SlideWrap(parent, std::move(child), style::margins(), duration) {
}
SlideWrap<RpWidget>::SlideWrap(
QWidget *parent,
object_ptr<RpWidget> child,
const style::margins &padding,
int duration)
: Parent(parent, object_ptr<PaddingWrap<RpWidget>>(parent, std::move(child), padding))
, _duration(duration * 10) {
if (auto weak = wrapped()) {
weak->heightValue()
| rpl::on_next([this](int newHeight) {
if (_slideAnimation.animating()) {
animationStep();
} else if (_visible) {
resize(width(), newHeight);
}
}) | rpl::start(lifetime());
}
}
void SlideWrap<RpWidget>::animationStep() {
if (wrapped()) {
auto margins = getMargins();
wrapped()->moveToLeft(margins.left(), margins.top());
}
auto current = _slideAnimation.current(_visible ? 1. : 0.);
auto newHeight = wrapped()
? (_slideAnimation.animating()
? anim::interpolate(0, wrapped()->heightNoMargins(), current)
: (_visible ? wrapped()->height() : 0))
: 0;
if (newHeight != height()) {
resize(width(), newHeight);
}
auto shouldBeHidden = !_visible && !_slideAnimation.animating();
if (shouldBeHidden != isHidden()) {
setVisible(!shouldBeHidden);
}
}
void SlideWrap<RpWidget>::toggleAnimated(bool visible) {
if (_visible == visible) {
animationStep();
return;
}
_visible = visible;
_slideAnimation.start(
[this] { animationStep(); },
_visible ? 0. : 1.,
_visible ? 1. : 0.,
_duration,
anim::linear);
animationStep();
}
void SlideWrap<RpWidget>::toggleFast(bool visible) {
_visible = visible;
finishAnimations();
}
void SlideWrap<RpWidget>::finishAnimations() {
_slideAnimation.finish();
animationStep();
}
QMargins SlideWrap<RpWidget>::getMargins() const {
auto result = wrapped()->getMargins();
return (animating() || !_visible)
? QMargins(result.left(), 0, result.right(), 0)
: result;
}
int SlideWrap<RpWidget>::resizeGetHeight(int newWidth) {
if (wrapped()) {
wrapped()->resizeToWidth(newWidth);
}
return height();
}
} // namespace Ui

View file

@ -21,100 +21,263 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#pragma once
#include "styles/style_widgets.h"
#include "ui/rp_widget.h"
namespace Ui {
template <typename Widget, typename ParentType = RpWidget>
class Wrap;
namespace details {
struct UnwrapHelper {
struct Large {
char data[2];
};
static char Check(...);
template <typename Widget, typename Parent>
static Large Check(Wrap<Widget, Parent>*);
template <typename Widget, typename Parent>
static Large Check(const Wrap<Widget, Parent>*);
template <typename Entity>
static constexpr bool Is() {
return sizeof(Check(std::declval<Entity>()))
== sizeof(Large);
}
template <typename Entity>
static auto Unwrap(Entity *entity, std::true_type) {
return entity
? entity->entity()
: nullptr;
}
template <typename Entity>
static Entity *Unwrap(Entity *entity, std::false_type) {
return entity;
}
template <typename Entity>
static auto Unwrap(Entity *entity) {
return Unwrap(
entity,
std::integral_constant<bool, Is<Entity*>()>());
}
};
} // namespace details
template <typename Widget>
class WidgetSlideWrap;
class Wrap<Widget, RpWidget> : public RpWidget {
public:
Wrap(QWidget *parent, object_ptr<Widget> child);
Widget *wrapped() {
return _wrapped;
}
const Widget *wrapped() const {
return _wrapped;
}
auto entity() {
return details::UnwrapHelper::Unwrap(wrapped());
}
auto entity() const {
return details::UnwrapHelper::Unwrap(wrapped());
}
QMargins getMargins() const override {
if (auto weak = wrapped()) {
return weak->getMargins();
}
return RpWidget::getMargins();
}
int naturalWidth() const override {
if (auto weak = wrapped()) {
return weak->naturalWidth();
}
return RpWidget::naturalWidth();
}
private:
object_ptr<Widget> _wrapped;
};
template <typename Widget>
Wrap<Widget, RpWidget>::Wrap(QWidget *parent, object_ptr<Widget> child)
: RpWidget(parent)
, _wrapped(std::move(child)) {
if (_wrapped) {
resize(_wrapped->size());
AttachParentChild(this, _wrapped);
_wrapped->move(0, 0);
_wrapped->alive()
| rpl::on_done([this] {
_wrapped->setParent(nullptr);
_wrapped = nullptr;
delete this;
})
| rpl::start(lifetime());
}
}
template <typename Widget, typename ParentType>
class Wrap : public ParentType {
public:
using ParentType::ParentType;
Widget *wrapped() {
return static_cast<Widget*>(ParentType::wrapped());
}
const Widget *wrapped() const {
return static_cast<const Widget*>(ParentType::wrapped());
}
auto entity() {
return details::UnwrapHelper::Unwrap(wrapped());
}
auto entity() const {
return details::UnwrapHelper::Unwrap(wrapped());
}
};
template <typename Widget>
class PaddingWrap;
template <>
class WidgetSlideWrap<TWidget> : public TWidget {
public:
WidgetSlideWrap(QWidget *parent
, object_ptr<TWidget> entity
, style::margins entityPadding
, base::lambda<void()> updateCallback
, int duration = st::widgetSlideDuration);
class PaddingWrap<RpWidget> : public Wrap<RpWidget> {
using Parent = Wrap<RpWidget>;
void showAnimated();
void hideAnimated();
void toggleAnimated(bool visible) {
if (visible) {
showAnimated();
} else {
hideAnimated();
}
public:
PaddingWrap(
QWidget *parent,
object_ptr<RpWidget> child,
const style::margins &padding);
PaddingWrap(
QWidget *parent,
const style::margins &padding)
: PaddingWrap(parent, nullptr, padding) {
}
int naturalWidth() const override;
protected:
int resizeGetHeight(int newWidth) override;
private:
void updateSize();
int _innerWidth = 0;
style::margins _padding;
};
template <typename Widget>
class PaddingWrap : public Wrap<Widget, PaddingWrap<RpWidget>> {
using Parent = Wrap<Widget, PaddingWrap<RpWidget>>;
public:
PaddingWrap(
QWidget *parent,
object_ptr<Widget> child,
const style::margins &padding)
: Parent(parent, std::move(child), padding) {
}
PaddingWrap(QWidget *parent, const style::margins &padding)
: Parent(parent, padding) {
}
};
template <typename Widget>
class SlideWrap;
template <>
class SlideWrap<RpWidget> : public Wrap<PaddingWrap<RpWidget>> {
using Parent = Wrap<PaddingWrap<RpWidget>>;
public:
SlideWrap(QWidget *parent, object_ptr<RpWidget> child);
SlideWrap(
QWidget *parent,
object_ptr<RpWidget> child,
const style::margins &padding);
SlideWrap(
QWidget *parent,
object_ptr<RpWidget> child,
int duration);
SlideWrap(
QWidget *parent,
object_ptr<RpWidget> child,
const style::margins &padding,
int duration);
void toggleAnimated(bool visible);
void toggleFast(bool visible);
void showAnimated() {
toggleAnimated(true);
}
void hideAnimated() {
toggleAnimated(false);
}
void showFast() {
toggleFast(true);
}
void hideFast() {
toggleFast(false);
}
void toggleFast(bool visible);
bool isHiddenOrHiding() const {
return isHidden() || (_a_height.animating() && _hiding);
}
void finishAnimation() {
_a_height.finish();
myEnsureResized(_entity);
animationCallback();
}
bool animating() const {
return _a_height.animating();
}
TWidget *entity() {
return _entity;
}
const TWidget *entity() const {
return _entity;
return _slideAnimation.animating();
}
void finishAnimations();
QMargins getMargins() const override;
int naturalWidth() const override;
bool isHiddenOrHiding() const {
return !_visible;
}
protected:
bool eventFilter(QObject *object, QEvent *event) override;
int resizeGetHeight(int newWidth) override;
private:
void animationCallback();
void animationStep();
object_ptr<TWidget> _entity;
bool _inResizeToWidth = false;
style::margins _padding;
int _duration;
base::lambda<void()> _updateCallback;
style::size _realSize;
int _forceHeight = -1;
Animation _a_height;
bool _hiding = false;
bool _visible = true;
Animation _slideAnimation;
int _duration = 0;
};
template <typename Widget>
class WidgetSlideWrap : public WidgetSlideWrap<TWidget> {
class SlideWrap : public Wrap<PaddingWrap<Widget>, SlideWrap<RpWidget>> {
using Parent = Wrap<PaddingWrap<Widget>, SlideWrap<RpWidget>>;
public:
WidgetSlideWrap(QWidget *parent
, object_ptr<Widget> entity
, style::margins entityPadding
, base::lambda<void()> updateCallback
, int duration = st::widgetSlideDuration) : WidgetSlideWrap<TWidget>(parent
, std::move(entity)
, entityPadding
, std::move(updateCallback)
, duration) {
SlideWrap(QWidget *parent, object_ptr<Widget> child)
: Parent(parent, std::move(child)) {
}
Widget *entity() {
return static_cast<Widget*>(WidgetSlideWrap<TWidget>::entity());
SlideWrap(
QWidget *parent,
object_ptr<Widget> child,
const style::margins &padding)
: Parent(parent, std::move(child), padding) {
}
const Widget *entity() const {
return static_cast<const Widget*>(WidgetSlideWrap<TWidget>::entity());
SlideWrap(
QWidget *parent,
object_ptr<Widget> child,
int duration)
: Parent(parent, std::move(child), duration) {
}
SlideWrap(
QWidget *parent,
object_ptr<Widget> child,
const style::margins &padding,
int duration)
: Parent(parent, std::move(child), padding, duration) {
}
};

View file

@ -0,0 +1,130 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include <rpl/event_stream.h>
#include <rpl/map.h>
#include <rpl/distinct_until_changed.h>
namespace Ui {
class RpWidget : public TWidget {
public:
RpWidget::RpWidget(QWidget *parent = nullptr) : TWidget(parent) {
setGeometry(0, 0, 0, 0);
}
rpl::producer<QRect> geometryValue() const {
auto &stream = eventFilter().geometry;
return stream.events_starting_with_copy(geometry());
}
rpl::producer<QSize> sizeValue() const {
return geometryValue()
| rpl::map([](QRect &&value) { return value.size(); })
| rpl::distinct_until_changed();
}
rpl::producer<int> heightValue() const {
return geometryValue()
| rpl::map([](QRect &&value) { return value.height(); })
| rpl::distinct_until_changed();
}
rpl::producer<int> widthValue() const {
return geometryValue()
| rpl::map([](QRect &&value) { return value.width(); })
| rpl::distinct_until_changed();
}
rpl::producer<QPoint> positionValue() const {
return geometryValue()
| rpl::map([](QRect &&value) { return value.topLeft(); })
| rpl::distinct_until_changed();
}
rpl::producer<int> leftValue() const {
return geometryValue()
| rpl::map([](QRect &&value) { return value.left(); })
| rpl::distinct_until_changed();
}
rpl::producer<int> topValue() const {
return geometryValue()
| rpl::map([](QRect &&value) { return value.top(); })
| rpl::distinct_until_changed();
}
virtual rpl::producer<int> desiredHeightValue() const {
return heightValue();
}
rpl::producer<QRect> paintRequest() const {
return eventFilter().paint.events();
}
rpl::producer<> alive() const {
return eventFilter().alive.events();
}
rpl::lifetime &lifetime() {
return _lifetime;
}
private:
class EventFilter : public QObject {
public:
EventFilter(RpWidget *parent) : QObject(parent) {
parent->installEventFilter(this);
}
rpl::event_stream<QRect> geometry;
rpl::event_stream<QRect> paint;
rpl::event_stream<> alive;
protected:
bool eventFilter(QObject *object, QEvent *event) {
auto widget = static_cast<RpWidget*>(parent());
switch (event->type()) {
case QEvent::Move:
case QEvent::Resize:
geometry.fire_copy(widget->geometry());
break;
case QEvent::Paint:
paint.fire_copy(
static_cast<QPaintEvent*>(event)->rect());
break;
}
return QObject::eventFilter(object, event);
}
};
EventFilter &eventFilter() const {
if (!_eventFilter) {
auto that = const_cast<RpWidget*>(this);
that->_eventFilter = std::make_unique<EventFilter>(that);
}
return *_eventFilter;
}
std::unique_ptr<EventFilter> _eventFilter;
rpl::lifetime _lifetime;
};
} // namespace Ui

View file

@ -57,18 +57,6 @@ inline ChildWidget *AttachParentChild(
return nullptr;
}
template <typename ChildWidget>
inline ChildWidget *AttachParentChildToBottom(
not_null<QWidget*> parent,
const object_ptr<ChildWidget> &child) {
if (auto raw = AttachParentChild(parent, child)) {
raw->resizeToWidth(parent->width());
raw->move(0, parent->height());
return raw;
}
return nullptr;
}
} // namespace Ui
enum class RectPart {
@ -288,7 +276,7 @@ public:
QRect mapFromGlobal(const QRect &rect) const {
return QRect(mapFromGlobal(rect.topLeft()), rect.size());
}
QRect mapToGlobal(const QRect &rect) {
QRect mapToGlobal(const QRect &rect) const {
return QRect(mapToGlobal(rect.topLeft()), rect.size());
}
@ -410,7 +398,11 @@ public:
}
// Updates the area that is visible inside the scroll container.
virtual void setVisibleTopBottom(int visibleTop, int visibleBottom) {
void setVisibleTopBottom(int visibleTop, int visibleBottom) {
auto max = height();
visibleTopBottomUpdated(
snap(visibleTop, 0, max),
snap(visibleBottom, 0, max));
}
signals:
@ -418,11 +410,28 @@ signals:
void heightUpdated();
protected:
void setChildVisibleTopBottom(
TWidget *child,
int visibleTop,
int visibleBottom) {
if (child) {
auto top = child->y();
child->setVisibleTopBottom(
visibleTop - top,
visibleBottom - top);
}
}
// Resizes content and counts natural widget height for the desired width.
virtual int resizeGetHeight(int newWidth) {
return height();
}
virtual void visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) {
}
};
template <typename Widget>

View file

@ -25,14 +25,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
namespace Ui {
DiscreteSlider::DiscreteSlider(QWidget *parent) : TWidget(parent) {
DiscreteSlider::DiscreteSlider(QWidget *parent) : RpWidget(parent) {
setCursor(style::cur_pointer);
}
void DiscreteSlider::setSectionActivatedCallback(SectionActivatedCallback &&callback) {
_callback = std::move(callback);
}
void DiscreteSlider::setActiveSection(int index) {
if (_activeIndex != index) {
_activeIndex = index;
@ -48,9 +44,7 @@ void DiscreteSlider::activateCallback() {
}
auto ms = getms();
if (ms >= _callbackAfterMs) {
if (_callback) {
_callback();
}
_sectionActivated.fire_copy(_activeIndex);
} else {
_timerId = startTimer(_callbackAfterMs - ms, Qt::PreciseTimer);
}
@ -62,6 +56,10 @@ void DiscreteSlider::timerEvent(QTimerEvent *e) {
void DiscreteSlider::setActiveSectionFast(int index) {
setActiveSection(index);
finishAnimations();
}
void DiscreteSlider::finishAnimations() {
_a_left.finish();
update();
}

View file

@ -20,13 +20,15 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include <rpl/event_stream.h>
#include "ui/rp_widget.h"
#include "styles/style_widgets.h"
namespace Ui {
class RippleAnimation;
class DiscreteSlider : public TWidget {
class DiscreteSlider : public RpWidget {
public:
DiscreteSlider(QWidget *parent);
@ -37,9 +39,11 @@ public:
}
void setActiveSection(int index);
void setActiveSectionFast(int index);
void finishAnimations();
using SectionActivatedCallback = base::lambda<void()>;
void setSectionActivatedCallback(SectionActivatedCallback &&callback);
rpl::producer<int> sectionActivated() const {
return _sectionActivated.events();
}
protected:
void timerEvent(QTimerEvent *e) override;
@ -88,7 +92,7 @@ private:
int _activeIndex = 0;
bool _selectOnPress = true;
SectionActivatedCallback _callback;
rpl::event_stream<int> _sectionActivated;
int _pressed = -1;
int _selected = 0;

Some files were not shown because too many files have changed in this diff Show more