Boxes redesigned. Common groups moved to Shared Media.

Also transparent images sending fixed.
This commit is contained in:
John Preston 2016-12-13 20:07:56 +03:00
parent 85b434bee4
commit 2436ad74bd
231 changed files with 4233 additions and 4235 deletions

View File

@ -36,11 +36,6 @@ emojiPadding: 1px;
lineWidth: 1px;
defaultDropdownDuration: 150;
defaultDropdownPadding: margins(10px, 10px, 10px, 10px);
defaultDropdownShadow: icon {{ "dropdown_shadow", windowShadowFg }};
defaultDropdownShadowShift: 1px;
defaultTooltip: Tooltip {
textBg: #eef2f5;
textFg: #5d6c80;
@ -309,8 +304,6 @@ simpleCloseIcon: icon {{ "simple_close", #c7c7c7 }};
simpleCloseIconOver: icon {{ "simple_close", #a3a3a3 }};
dialogsForwardCancelIcon: icon {{ "simple_close", dialogsForwardFg }};
membersPadding: margins(0px, 10px, 0px, 10px);
forwardMargins: margins(30px, 10px, 30px, 10px);
forwardFont: font(16px);
forwardBg: #0000004c;
@ -450,8 +443,8 @@ historyReplyCancelIcon: icon {{ "box_button_close", historyReplyCancelFg }};
historyReplyCancelIconOver: icon {{ "box_button_close", historyReplyCancelFgOver }};
boxSearchCancelIcon: icon {{ "box_button_close", boxSearchCancelIconFg }};
boxSearchCancelIconOver: icon {{ "box_button_close", boxSearchCancelIconFgOver }};
boxBlockTitleCloseIcon: icon {{ "box_button_close", boxBlockTitleCloseFg }};
boxBlockTitleCloseIconOver: icon {{ "box_button_close", boxBlockTitleCloseFgOver }};
boxTitleCloseIcon: icon {{ "box_button_close", boxTitleCloseFg }};
boxTitleCloseIconOver: icon {{ "box_button_close", boxTitleCloseFgOver }};
notifyFadeRight: icon {{ "fade_horizontal", notificationBg }};

View File

@ -86,8 +86,8 @@ trayCounterFgMacInvert: #ffffff01;
// layers
layerBg: #0000007f;
cancelIconFg: #a2a2a2;
cancelIconFgOver: #808080;
cancelIconFg: menuIconFg;
cancelIconFgOver: menuIconFgOver;
// boxes
boxBg: windowBg;
@ -99,11 +99,9 @@ boxSearchBg: boxBg;
boxSearchCancelIconFg: cancelIconFg;
boxSearchCancelIconFgOver: cancelIconFgOver;
boxBlockTitleBg: boxBg;
boxBlockTitleFg: boxTitleFg;
boxBlockTitleAdditionalFg: #808080;
boxBlockTitleCloseFg: cancelIconFg;
boxBlockTitleCloseFgOver: cancelIconFgOver;
boxTitleAdditionalFg: #808080;
boxTitleCloseFg: cancelIconFg;
boxTitleCloseFgOver: cancelIconFgOver;
membersAboutLimitFg: windowSubTextFgOver;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 190 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 294 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 168 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 240 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 539 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 423 B

View File

@ -296,7 +296,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
"lng_backgrounds_header" = "Choose your new chat background";
"lng_theme_sure_keep" = "Keep this color theme?";
"lng_theme_reverting" = "Reverting to previous color theme in {count:_not_used_|# second|# seconds}.";
"lng_theme_reverting" = "Reverting to the old color theme in {count:_not_used_|# second|# seconds}.";
"lng_theme_keep_changes" = "Keep changes";
"lng_theme_revert" = "Revert";

View File

@ -74,8 +74,8 @@ trayCounterFg: #ffffff;
trayCounterBgMacInvert: #ffffff;
trayCounterFgMacInvert: #ffffff01;
layerBg: #0000007f;
cancelIconFg: #a2a2a2;
cancelIconFgOver: #808080;
cancelIconFg: menuIconFg;
cancelIconFgOver: menuIconFgOver;
boxBg: windowBg;
boxTextFg: windowFg;
boxTextFgGood: #4ab44a;
@ -84,11 +84,9 @@ boxTitleFg: #404040;
boxSearchBg: boxBg;
boxSearchCancelIconFg: cancelIconFg;
boxSearchCancelIconFgOver: cancelIconFgOver;
boxBlockTitleBg: boxBg;
boxBlockTitleFg: boxTitleFg;
boxBlockTitleAdditionalFg: #808080;
boxBlockTitleCloseFg: cancelIconFg;
boxBlockTitleCloseFgOver: cancelIconFgOver;
boxTitleAdditionalFg: #808080;
boxTitleCloseFg: cancelIconFg;
boxTitleCloseFgOver: cancelIconFgOver;
membersAboutLimitFg: windowSubTextFgOver;
contactsBg: windowBg;
contactsBgOver: windowBgOver;

View File

@ -34,8 +34,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,10,19,14
PRODUCTVERSION 0,10,19,14
FILEVERSION 0,10,20,1
PRODUCTVERSION 0,10,20,1
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -51,10 +51,10 @@ BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Telegram Messenger LLP"
VALUE "FileVersion", "0.10.19.14"
VALUE "FileVersion", "0.10.20.1"
VALUE "LegalCopyright", "Copyright (C) 2014-2016"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "0.10.19.14"
VALUE "ProductVersion", "0.10.20.1"
END
END
BLOCK "VarFileInfo"

View File

@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,10,19,14
PRODUCTVERSION 0,10,19,14
FILEVERSION 0,10,20,1
PRODUCTVERSION 0,10,20,1
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -43,10 +43,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Telegram Messenger LLP"
VALUE "FileDescription", "Telegram Updater"
VALUE "FileVersion", "0.10.19.14"
VALUE "FileVersion", "0.10.20.1"
VALUE "LegalCopyright", "Copyright (C) 2014-2016"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "0.10.19.14"
VALUE "ProductVersion", "0.10.20.1"
END
END
BLOCK "VarFileInfo"

View File

@ -830,7 +830,7 @@ bool ApiWrap::channelAmInFail(ChannelData *channel, const RPCError &error) {
if (MTP::isDefaultHandledError(error)) return false;
if (error.type() == qstr("CHANNELS_TOO_MUCH")) {
Ui::showLayer(new InformBox(lang(lng_join_channel_error)));
Ui::show(Box<InformBox>(lang(lng_join_channel_error)));
}
_channelAmInRequests.remove(channel);
return true;

View File

@ -29,6 +29,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "styles/style_mediaview.h"
#include "styles/style_stickers.h"
#include "styles/style_history.h"
#include "styles/style_boxes.h"
#include "lang.h"
#include "data/data_abstract_structure.h"
#include "history/history_service_layout.h"
@ -2243,6 +2244,7 @@ namespace {
::cornersMaskSmall[i]->setDevicePixelRatio(cRetinaFactor());
}
prepareCorners(MenuCorners, st::buttonRadius, st::menuBg);
prepareCorners(BoxCorners, st::boxRadius, st::boxBg);
prepareCorners(BotKbOverCorners, st::dateRadius, st::msgBotKbOverBg);
prepareCorners(StickerCorners, st::dateRadius, st::msgServiceBg);
prepareCorners(StickerSelectedCorners, st::dateRadius, st::msgServiceSelectBg);

View File

@ -32,32 +32,35 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "styles/style_boxes.h"
#include "platform/platform_file_dialog.h"
AboutBox::AboutBox() : AbstractBox(st::aboutWidth, qsl("Telegram Desktop"))
, _version(this, lng_about_version(lt_version, QString::fromLatin1(AppVersionStr.c_str()) + (cAlphaVersion() ? " alpha" : "") + (cBetaVersion() ? qsl(" beta %1").arg(cBetaVersion()) : QString())), st::aboutVersionLink)
AboutBox::AboutBox(QWidget *parent)
: _version(this, lng_about_version(lt_version, QString::fromLatin1(AppVersionStr.c_str()) + (cAlphaVersion() ? " alpha" : "") + (cBetaVersion() ? qsl(" beta %1").arg(cBetaVersion()) : QString())), st::aboutVersionLink)
, _text1(this, lang(lng_about_text_1), Ui::FlatLabel::InitType::Rich, st::aboutLabel, st::aboutTextStyle)
, _text2(this, lang(lng_about_text_2), Ui::FlatLabel::InitType::Rich, st::aboutLabel, st::aboutTextStyle)
, _text3(this,st::aboutLabel, st::aboutTextStyle)
, _done(this, lang(lng_close), st::defaultBoxButton) {
, _text3(this, st::aboutLabel, st::aboutTextStyle) {
}
void AboutBox::prepare() {
setTitle(qsl("Telegram Desktop"));
addButton(lang(lng_close), [this] { closeBox(); });
_text3->setRichText(lng_about_text_3(lt_faq_open, qsl("[a href=\"%1\"]").arg(telegramFaqLink()), lt_faq_close, qsl("[/a]")));
setMaxHeight(titleHeight() + st::aboutTextTop + _text1->height() + st::aboutSkip + _text2->height() + st::aboutSkip + _text3->height() + st::boxButtonPadding.top() + _done->height() + st::boxButtonPadding.bottom());
_version->setClickedCallback([this] { showVersionHistory(); });
connect(_version, SIGNAL(clicked()), this, SLOT(onVersion()));
connect(_done, SIGNAL(clicked()), this, SLOT(onClose()));
setAcceptDrops(true);
setDimensions(st::aboutWidth, st::aboutTextTop + _text1->height() + st::aboutSkip + _text2->height() + st::aboutSkip + _text3->height());
}
void AboutBox::resizeEvent(QResizeEvent *e) {
_version->moveToLeft(st::boxPadding.left(), titleHeight() + st::aboutVersionTop);
_text1->moveToLeft(st::boxPadding.left(), titleHeight() + st::aboutTextTop);
BoxContent::resizeEvent(e);
_version->moveToLeft(st::boxPadding.left(), st::aboutVersionTop);
_text1->moveToLeft(st::boxPadding.left(), st::aboutTextTop);
_text2->moveToLeft(st::boxPadding.left(), _text1->y() + _text1->height() + st::aboutSkip);
_text3->moveToLeft(st::boxPadding.left(), _text2->y() + _text2->height() + st::aboutSkip);
_done->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _done->height());
AbstractBox::resizeEvent(e);
}
void AboutBox::onVersion() {
void AboutBox::showVersionHistory() {
if (cRealBetaVersion()) {
auto url = qsl("https://tdesktop.com/");
switch (cPlatform()) {
@ -71,7 +74,7 @@ void AboutBox::onVersion() {
Application::clipboard()->setText(url);
Ui::showLayer(new InformBox("The link to the current private beta version of Telegram Desktop was copied to the clipboard."));
Ui::show(Box<InformBox>("The link to the current private beta version of Telegram Desktop was copied to the clipboard."));
} else {
QDesktopServices::openUrl(qsl("https://desktop.telegram.org/?_hash=changelog"));
}
@ -79,9 +82,9 @@ void AboutBox::onVersion() {
void AboutBox::keyPressEvent(QKeyEvent *e) {
if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
onClose();
closeBox();
} else {
AbstractBox::keyPressEvent(e);
BoxContent::keyPressEvent(e);
}
}

View File

@ -23,32 +23,29 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "boxes/abstractbox.h"
namespace Ui {
class RoundButton;
class LinkButton;
class FlatLabel;
} // namespace Ui
class AboutBox : public AbstractBox {
Q_OBJECT
class AboutBox : public BoxContent {
public:
AboutBox();
public slots:
void onVersion();
AboutBox(QWidget*);
protected:
void prepare() override;
void resizeEvent(QResizeEvent *e) override;
void keyPressEvent(QKeyEvent *e) override;
void dragEnterEvent(QDragEnterEvent *e) override;
void dropEvent(QDropEvent *e) override;
private:
ChildWidget<Ui::LinkButton> _version;
ChildWidget<Ui::FlatLabel> _text1;
ChildWidget<Ui::FlatLabel> _text2;
ChildWidget<Ui::FlatLabel> _text3;
ChildWidget<Ui::RoundButton> _done;
void showVersionHistory();
object_ptr<Ui::LinkButton> _version;
object_ptr<Ui::FlatLabel> _text1;
object_ptr<Ui::FlatLabel> _text2;
object_ptr<Ui::FlatLabel> _text3;
};

View File

@ -24,187 +24,341 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "styles/style_boxes.h"
#include "localstorage.h"
#include "lang.h"
#include "ui/effects/widget_fade_wrap.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/scroll_area.h"
#include "mainwidget.h"
#include "mainwindow.h"
AbstractBox::AbstractBox(int w, const QString &title) : LayerWidget(App::wnd()->bodyWidget())
, _title(title) {
setAttribute(Qt::WA_OpaquePaintEvent);
resize((w > 0) ? w : st::boxWideWidth, 0);
BoxLayerTitleShadow::BoxLayerTitleShadow(QWidget *parent) : Ui::PlainShadow(parent, st::boxLayerTitleShadow) {
}
void AbstractBox::setTitleText(const QString &title) {
_title = title;
update();
QPointer<Ui::RoundButton> BoxContent::addButton(const QString &text, base::lambda<void()> &&clickCallback) {
return addButton(text, std_::move(clickCallback), st::defaultBoxButton);
}
void AbstractBox::setAdditionalTitle(const QString &additionalTitle) {
_additionalTitle = additionalTitle;
update();
QPointer<Ui::RoundButton> BoxContent::addLeftButton(const QString &text, base::lambda<void()> &&clickCallback) {
return getDelegate()->addLeftButton(text, std_::move(clickCallback), st::defaultBoxButton);
}
void AbstractBox::keyPressEvent(QKeyEvent *e) {
if (e->key() == Qt::Key_Escape) {
onClose();
void BoxContent::setInner(object_ptr<TWidget> inner) {
setInner(std_::move(inner), st::boxLayerScroll);
}
void BoxContent::setInner(object_ptr<TWidget> inner, const style::ScrollArea &st) {
if (inner) {
getDelegate()->setLayerType(true);
if (!_scroll) {
_scroll.create(this, st);
connect(_scroll, SIGNAL(scrolled()), this, SLOT(onScroll()));
_topShadow.create(this, object_ptr<BoxLayerTitleShadow>(this));
if (_innerTopSkip > 0) {
_topShadow->showFast();
} else {
_topShadow->hideFast();
}
_bottomShadow.create(this);
_bottomShadow->show();
} else {
_scroll->setGeometryToLeft(0, _innerTopSkip, width(), 0);
}
_scroll->setOwnedWidget(std_::move(inner));
updateScrollAreaGeometry();
} else {
LayerWidget::keyPressEvent(e);
getDelegate()->setLayerType(false);
_scroll.destroyDelayed();
_topShadow.destroyDelayed();
_bottomShadow.destroyDelayed();
}
}
void AbstractBox::resizeEvent(QResizeEvent *e) {
updateBlockTitleGeometry();
LayerWidget::resizeEvent(e);
void BoxContent::onScrollToY(int top, int bottom) {
if (_scroll) {
_scroll->scrollToY(top, bottom);
}
}
void AbstractBox::updateBlockTitleGeometry() {
if (_blockClose) {
_blockClose->moveToRight(0, 0);
void BoxContent::onDraggingScrollDelta(int delta) {
_draggingScrollDelta = _scroll ? delta : 0;
if (_draggingScrollDelta) {
if (!_draggingScrollTimer) {
_draggingScrollTimer.create(this);
_draggingScrollTimer->setSingleShot(false);
connect(_draggingScrollTimer, SIGNAL(timeout()), this, SLOT(onDraggingScrollTimer()));
}
_draggingScrollTimer->start(15);
} else {
_draggingScrollTimer.destroy();
}
if (_blockShadow) {
_blockShadow->setGeometry(0, st::boxBlockTitleHeight, width(), st::boxBlockTitleShadow.height());
}
void BoxContent::onDraggingScrollTimer() {
auto delta = (_draggingScrollDelta > 0) ? qMin(_draggingScrollDelta * 3 / 20 + 1, int32(MaxScrollSpeed)) : qMax(_draggingScrollDelta * 3 / 20 - 1, -int32(MaxScrollSpeed));
_scroll->scrollToY(_scroll->scrollTop() + delta);
}
void BoxContent::onScroll() {
if (_scroll) {
auto top = _scroll->scrollTop();
if (auto widget = static_cast<TWidget*>(_scroll->widget())) {
widget->setVisibleTopBottom(top, top + _scroll->height());
}
if (top > 0 || _innerTopSkip > 0) {
_topShadow->showAnimated();
} else {
_topShadow->hideAnimated();
}
}
}
void BoxContent::setInnerTopSkip(int innerTopSkip, bool scrollBottomFixed) {
if (_innerTopSkip != innerTopSkip) {
auto delta = innerTopSkip - _innerTopSkip;
_innerTopSkip = innerTopSkip;
if (_scroll) {
auto scrollTopWas = _scroll->scrollTop();
updateScrollAreaGeometry();
if (scrollBottomFixed) {
_scroll->scrollToY(scrollTopWas + delta);
}
if (_innerTopSkip > 0) {
_topShadow->showFast();
} else {
_topShadow->hideFast();
}
}
}
}
void BoxContent::setInnerVisible(bool scrollAreaVisible) {
if (_scroll) {
_scroll->setVisible(scrollAreaVisible);
}
}
QPixmap BoxContent::grabInnerCache() {
auto isTopShadowVisible = !_topShadow->isHidden();
auto isBottomShadowVisible = !_bottomShadow->isHidden();
if (isTopShadowVisible) _topShadow->hide();
if (isBottomShadowVisible) _bottomShadow->hide();
auto result = myGrab(this, _scroll->geometry());
if (isTopShadowVisible) _topShadow->show();
if (isBottomShadowVisible) _bottomShadow->show();
return std_::move(result);
}
void BoxContent::resizeEvent(QResizeEvent *e) {
if (_scroll) {
updateScrollAreaGeometry();
}
}
void BoxContent::updateScrollAreaGeometry() {
auto newScrollHeight = height() - _innerTopSkip;
auto changed = (_scroll->height() != newScrollHeight);
_scroll->setGeometryToLeft(0, _innerTopSkip, width(), newScrollHeight);
_topShadow->entity()->resize(width(), st::lineWidth);
_topShadow->moveToLeft(0, _innerTopSkip);
_bottomShadow->resize(width(), st::lineWidth);
_bottomShadow->moveToLeft(0, height() - st::lineWidth);
if (changed) {
onScroll();
}
}
object_ptr<TWidget> BoxContent::doTakeInnerWidget() {
return _scroll->takeWidget<TWidget>();
}
void BoxContent::paintEvent(QPaintEvent *e) {
Painter p(this);
if (testAttribute(Qt::WA_OpaquePaintEvent)) {
for_const (auto rect, e->region().rects()) {
p.fillRect(rect, st::boxBg);
}
}
}
AbstractBox::AbstractBox(object_ptr<BoxContent> content)
: _content(std_::move(content)) {
_content->setParent(this);
_content->setDelegate(this);
}
void AbstractBox::setLayerType(bool layerType) {
_layerType = layerType;
}
int AbstractBox::titleHeight() const {
return _layerType ? st::boxLayerTitleHeight : st::boxTitleHeight;
}
int AbstractBox::buttonsHeight() const {
auto padding = _layerType ? st::boxLayerButtonPadding : st::boxButtonPadding;
return padding.top() + st::defaultBoxButton.height + padding.bottom();
}
int AbstractBox::buttonsTop() const {
auto padding = _layerType ? st::boxLayerButtonPadding : st::boxButtonPadding;
return height() - padding.bottom() - st::defaultBoxButton.height;
}
void AbstractBox::paintEvent(QPaintEvent *e) {
Painter p(this);
auto clip = e->rect();
auto paintTopRounded = clip.intersects(QRect(0, 0, width(), st::boxRadius));
auto paintBottomRounded = clip.intersects(QRect(0, height() - st::boxRadius, width(), st::boxRadius));
if (paintTopRounded || paintBottomRounded) {
auto parts = qFlags(App::RectPart::None);
if (paintTopRounded) parts |= App::RectPart::TopFull;
if (paintBottomRounded) parts |= App::RectPart::BottomFull;
App::roundRect(p, rect(), st::boxBg, BoxCorners, nullptr, parts);
}
auto other = e->region().intersected(QRect(0, st::boxRadius, width(), height() - 2 * st::boxRadius));
if (!other.isEmpty()) {
for_const (auto rect, other.rects()) {
p.fillRect(rect, st::boxBg);
}
}
if (!_title.isEmpty() && clip.intersects(QRect(0, 0, width(), titleHeight()))) {
paintTitle(p, _title, _additionalTitle);
}
}
void AbstractBox::paintTitle(Painter &p, const QString &title, const QString &additional) {
p.setFont(st::boxTitleFont);
p.setPen(st::boxTitleFg);
if (_layerType) {
auto titleWidth = st::boxTitleFont->width(title);
p.drawTextLeft(st::boxLayerTitlePosition.x(), st::boxLayerTitlePosition.y(), width(), title, titleWidth);
if (!additional.isEmpty()) {
p.setFont(st::boxLayerTitleAdditionalFont);
p.setPen(st::boxTitleAdditionalFg);
p.drawTextLeft(st::boxLayerTitlePosition.x() + titleWidth + st::boxLayerTitleAdditionalSkip, st::boxLayerTitlePosition.y() + st::boxTitleFont->ascent - st::boxLayerTitleAdditionalFont->ascent, width(), additional);
}
} else {
p.drawTextLeft(st::boxTitlePosition.x(), st::boxTitlePosition.y(), width(), title);
}
}
void AbstractBox::parentResized() {
auto newHeight = countHeight();
auto newHeight = countRealHeight();
auto parentSize = parentWidget()->size();
setGeometry((parentSize.width() - width()) / 2, (parentSize.height() - newHeight) / 2, width(), newHeight);
update();
}
int AbstractBox::titleHeight() const {
return _blockTitle ? st::boxBlockTitleHeight : st::boxTitleHeight;
void AbstractBox::setTitle(const QString &title, const QString &additional) {
auto wasTitle = hasTitle();
_title = title;
_additionalTitle = additional;
update();
if (wasTitle != hasTitle()) {
updateSize();
}
}
void AbstractBox::paintTitle(Painter &p, const QString &title, const QString &additional) {
if (_blockTitle) {
p.fillRect(0, 0, width(), titleHeight(), st::boxBlockTitleBg);
bool AbstractBox::hasTitle() const {
return !_title.isEmpty() || !_additionalTitle.isEmpty();
}
p.setFont(st::boxBlockTitleFont);
p.setPen(st::boxBlockTitleFg);
void AbstractBox::updateSize() {
setDimensions(width(), _maxContentHeight);
}
auto titleWidth = st::boxBlockTitleFont->width(title);
p.drawTextLeft(st::boxBlockTitlePosition.x(), st::boxBlockTitlePosition.y(), width(), title, titleWidth);
if (!additional.isEmpty()) {
p.setFont(st::boxBlockTitleAdditionalFont);
p.setPen(st::boxBlockTitleAdditionalFg);
p.drawTextLeft(st::boxBlockTitlePosition.x() + titleWidth + st::boxBlockTitleAdditionalSkip, st::boxBlockTitlePosition.y(), width(), additional);
void AbstractBox::updateButtonsPositions() {
if (!_buttons.isEmpty() || _leftButton) {
auto padding = _layerType ? st::boxLayerButtonPadding : st::boxButtonPadding;
auto right = padding.right();
auto top = buttonsTop();
if (_leftButton) {
_leftButton->moveToLeft(right, top);
}
for_const (auto &button, _buttons) {
button->moveToRight(right, top);
right += button->width() + padding.left();
}
} else {
p.setFont(st::boxTitleFont);
p.setPen(st::boxTitleFg);
p.drawTextLeft(st::boxTitlePosition.x(), st::boxTitlePosition.y(), width(), title);
}
}
void AbstractBox::paintEvent(QPaintEvent *e) {
Painter p(this);
p.fillRect(e->rect(), st::boxBg);
if (!_title.isEmpty()) {
paintTitle(p, _title, _additionalTitle);
void AbstractBox::clearButtons() {
for (auto &button : base::take(_buttons)) {
button.destroy();
}
_leftButton.destroy();
}
void AbstractBox::setMaxHeight(int32 maxHeight) {
resizeMaxHeight(width(), maxHeight);
QPointer<Ui::RoundButton> AbstractBox::addButton(const QString &text, base::lambda<void()> &&clickCallback, const style::RoundButton &st) {
_buttons.push_back(object_ptr<Ui::RoundButton>(this, text, st));
auto result = QPointer<Ui::RoundButton>(_buttons.back());
result->setClickedCallback(std_::move(clickCallback));
result->show();
updateButtonsPositions();
return result;
}
void AbstractBox::resizeMaxHeight(int32 newWidth, int32 maxHeight) {
if (width() != newWidth || _maxHeight != maxHeight) {
QRect g(geometry());
_maxHeight = maxHeight;
resize(newWidth, countHeight());
QPointer<Ui::RoundButton> AbstractBox::addLeftButton(const QString &text, base::lambda<void()> &&clickCallback, const style::RoundButton &st) {
_leftButton = object_ptr<Ui::RoundButton>(this, text, st);
auto result = QPointer<Ui::RoundButton>(_leftButton);
result->setClickedCallback(std_::move(clickCallback));
result->show();
updateButtonsPositions();
return result;
}
void AbstractBox::setDimensions(int newWidth, int maxHeight) {
_maxContentHeight = maxHeight;
auto fullHeight = countFullHeight();
if (width() != newWidth || _fullHeight != fullHeight) {
_fullHeight = fullHeight;
if (parentWidget()) {
QRect r = geometry();
int32 parenth = parentWidget()->height();
if (r.top() + r.height() + st::boxVerticalMargin > parenth) {
int32 newTop = qMax(parenth - int(st::boxVerticalMargin) - r.height(), (parenth - r.height()) / 2);
if (newTop != r.top()) {
move(r.left(), newTop);
auto oldGeometry = geometry();
resize(newWidth, countRealHeight());
auto newGeometry = geometry();
auto parentHeight = parentWidget()->height();
if (newGeometry.top() + newGeometry.height() + st::boxVerticalMargin > parentHeight) {
auto newTop = qMax(parentHeight - int(st::boxVerticalMargin) - newGeometry.height(), (parentHeight - newGeometry.height()) / 2);
if (newTop != newGeometry.top()) {
move(newGeometry.left(), newTop);
}
}
parentWidget()->update(geometry().united(g).marginsAdded(QMargins(st::boxShadow.width(), st::boxShadow.height(), st::boxShadow.width(), st::boxShadow.height())));
parentWidget()->update(oldGeometry.united(geometry()).marginsAdded(st::boxRoundShadow.extend));
} else {
resize(newWidth, 0);
}
}
}
int AbstractBox::countHeight() const {
return qMin(_maxHeight, parentWidget()->height() - 2 * st::boxVerticalMargin);
int AbstractBox::countRealHeight() const {
return qMin(_fullHeight, parentWidget()->height() - 2 * st::boxVerticalMargin);
}
void AbstractBox::onClose() {
if (!_closed) {
_closed = true;
closePressed();
}
emit closed(this);
int AbstractBox::countFullHeight() const {
return contentTop() + _maxContentHeight + buttonsHeight();
}
void AbstractBox::setBlockTitle(bool block, bool withClose, bool withShadow) {
_blockTitle = block;
if (withClose) {
_blockClose.create(this, st::boxBlockTitleClose);
_blockClose->setClickedCallback([this] { onClose(); });
_blockClose->show();
int AbstractBox::contentTop() const {
return hasTitle() ? titleHeight() : (_noContentMargin ? 0 : st::boxTopMargin);
}
void AbstractBox::resizeEvent(QResizeEvent *e) {
updateButtonsPositions();
auto top = contentTop();
_content->resize(width(), height() - top - buttonsHeight());
_content->moveToLeft(0, top);
LayerWidget::resizeEvent(e);
}
void AbstractBox::keyPressEvent(QKeyEvent *e) {
if (e->key() == Qt::Key_Escape) {
closeBox();
} else {
_blockClose.destroy();
}
if (withShadow) {
_blockShadow.create(this, st::boxBlockTitleShadow);
_blockShadow->show();
} else {
_blockShadow.destroy();
}
updateBlockTitleGeometry();
}
void AbstractBox::raiseShadow() {
if (_blockShadow) {
_blockShadow->raise();
LayerWidget::keyPressEvent(e);
}
}
ScrollableBoxShadow::ScrollableBoxShadow(QWidget *parent) : Ui::PlainShadow(parent, st::boxScrollShadowBg) {
}
ScrollableBox::ScrollableBox(const style::FlatScroll &scroll, int32 w) : AbstractBox(w)
, _scroll(this, scroll)
, _topSkip(st::boxBlockTitleHeight)
, _bottomSkip(st::boxScrollSkip) {
setBlockTitle(true);
}
void ScrollableBox::resizeEvent(QResizeEvent *e) {
updateScrollGeometry();
AbstractBox::resizeEvent(e);
}
void ScrollableBox::init(TWidget *inner, int bottomSkip, int topSkip) {
if (bottomSkip < 0) bottomSkip = st::boxScrollSkip;
if (topSkip < 0) topSkip = st::boxBlockTitleHeight;
_bottomSkip = bottomSkip;
_topSkip = topSkip;
_scroll->setOwnedWidget(inner);
updateScrollGeometry();
}
void ScrollableBox::setScrollSkips(int bottomSkip, int topSkip) {
if (bottomSkip < 0) bottomSkip = st::boxScrollSkip;
if (topSkip < 0) topSkip = st::boxBlockTitleHeight;
if (_topSkip != topSkip || _bottomSkip != bottomSkip) {
_topSkip = topSkip;
_bottomSkip = bottomSkip;
updateScrollGeometry();
}
}
void ScrollableBox::updateScrollGeometry() {
_scroll->setGeometry(0, _topSkip, width(), height() - _topSkip - _bottomSkip);
}
ItemListBox::ItemListBox(const style::FlatScroll &scroll, int32 w) : ScrollableBox(scroll, w) {
setMaxHeight(st::boxMaxListHeight);
}

View File

@ -24,88 +24,229 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "ui/widgets/shadow.h"
namespace Ui {
class RoundButton;
class IconButton;
class GradientShadow;
class ScrollArea;
template <typename Widget>
class WidgetFadeWrap;
} // namespace Ui
class AbstractBox : public LayerWidget, protected base::Subscriber {
class BoxLayerTitleShadow : public Ui::PlainShadow {
public:
BoxLayerTitleShadow(QWidget *parent);
};
class BoxContentDelegate {
public:
virtual void setLayerType(bool layerType) = 0;
virtual void setTitle(const QString &title, const QString &additional) = 0;
virtual void clearButtons() = 0;
virtual QPointer<Ui::RoundButton> addButton(const QString &text, base::lambda<void()> &&clickCallback, const style::RoundButton &st) = 0;
virtual QPointer<Ui::RoundButton> addLeftButton(const QString &text, base::lambda<void()> &&clickCallback, const style::RoundButton &st) = 0;
virtual void updateButtonsPositions() = 0;
virtual void setDimensions(int newWidth, int maxHeight) = 0;
virtual void setNoContentMargin(bool noContentMargin) = 0;
virtual bool isBoxShown() const = 0;
virtual void closeBox() = 0;
};
class BoxContent : public TWidget, protected base::Subscriber {
Q_OBJECT
public:
AbstractBox(int w = 0, const QString &title = QString());
void parentResized() override;
BoxContent() {
setAttribute(Qt::WA_OpaquePaintEvent);
}
void setTitleText(const QString &title);
void setAdditionalTitle(const QString &additionalTitle);
void setBlockTitle(bool block, bool withClose = true, bool withShadow = true);
void setDelegate(BoxContentDelegate *newDelegate) {
_delegate = newDelegate;
prepare();
}
virtual void setInnerFocus() {
setFocus();
}
virtual void closeHook() {
}
bool isBoxShown() const {
return getDelegate()->isBoxShown();
}
void closeBox() {
getDelegate()->closeBox();
}
public slots:
void onClose();
void onScrollToY(int top, int bottom = -1);
void onDraggingScrollDelta(int delta);
protected:
virtual void prepare() = 0;
void setLayerType(bool layerType) {
getDelegate()->setLayerType(layerType);
}
void setTitle(const QString &title, const QString &additional = QString()) {
getDelegate()->setTitle(title, additional);
}
void clearButtons() {
getDelegate()->clearButtons();
}
QPointer<Ui::RoundButton> addButton(const QString &text, base::lambda<void()> &&clickCallback);
QPointer<Ui::RoundButton> addLeftButton(const QString &text, base::lambda<void()> &&clickCallback);
QPointer<Ui::RoundButton> addButton(const QString &text, base::lambda<void()> &&clickCallback, const style::RoundButton &st) {
return getDelegate()->addButton(text, std_::move(clickCallback), st);
}
void updateButtonsGeometry() {
getDelegate()->updateButtonsPositions();
}
void setNoContentMargin(bool noContentMargin) {
if (_noContentMargin != noContentMargin) {
_noContentMargin = noContentMargin;
setAttribute(Qt::WA_OpaquePaintEvent, !_noContentMargin);
}
getDelegate()->setNoContentMargin(noContentMargin);
}
void setDimensions(int newWidth, int maxHeight) {
getDelegate()->setDimensions(newWidth, maxHeight);
}
void setInnerTopSkip(int topSkip, bool scrollBottomFixed = false);
template <typename Widget>
QPointer<Widget> setInnerWidget(object_ptr<Widget> inner, const style::ScrollArea &st, int topSkip = 0) {
auto result = QPointer<Widget>(inner.data());
setInner(std_::move(inner), st);
setInnerTopSkip(topSkip);
return result;
}
template <typename Widget>
QPointer<Widget> setInnerWidget(object_ptr<Widget> inner, int topSkip = 0) {
auto result = QPointer<Widget>(inner.data());
setInner(std_::move(inner));
setInnerTopSkip(topSkip);
return result;
}
template <typename Widget>
object_ptr<Widget> takeInnerWidget() {
return static_object_cast<Widget>(doTakeInnerWidget());
}
void setInnerVisible(bool scrollAreaVisible);
QPixmap grabInnerCache();
void resizeEvent(QResizeEvent *e) override;
void paintEvent(QPaintEvent *e) override;
private slots:
void onScroll();
void onDraggingScrollTimer();
private:
void setInner(object_ptr<TWidget> inner);
void setInner(object_ptr<TWidget> inner, const style::ScrollArea &st);
void updateScrollAreaGeometry();
object_ptr<TWidget> doTakeInnerWidget();
BoxContentDelegate *getDelegate() const {
t_assert(_delegate != nullptr);
return _delegate;
}
BoxContentDelegate *_delegate = nullptr;
bool _noContentMargin = false;
int _innerTopSkip = 0;
object_ptr<Ui::ScrollArea> _scroll = { nullptr };
object_ptr<Ui::WidgetFadeWrap<BoxLayerTitleShadow>> _topShadow = { nullptr };
object_ptr<BoxLayerTitleShadow> _bottomShadow = { nullptr };
object_ptr<QTimer> _draggingScrollTimer = { nullptr };
int _draggingScrollDelta = 0;
};
class AbstractBox : public LayerWidget, public BoxContentDelegate, protected base::Subscriber {
public:
AbstractBox(object_ptr<BoxContent> content);
void parentResized() override;
void setLayerType(bool layerType) override;
void setTitle(const QString &title, const QString &additional) override;
void clearButtons() override;
QPointer<Ui::RoundButton> addButton(const QString &text, base::lambda<void()> &&clickCallback, const style::RoundButton &st) override;
QPointer<Ui::RoundButton> addLeftButton(const QString &text, base::lambda<void()> &&clickCallback, const style::RoundButton &st) override;
void updateButtonsPositions() override;
void setDimensions(int newWidth, int maxHeight) override;
void setNoContentMargin(bool noContentMargin) override {
if (_noContentMargin != noContentMargin) {
_noContentMargin = noContentMargin;
updateSize();
}
}
bool isBoxShown() const override {
return !isHidden();
}
void closeBox() override {
closeLayer();
}
protected:
void keyPressEvent(QKeyEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void paintEvent(QPaintEvent *e) override;
void raiseShadow();
int titleHeight() const;
void paintTitle(Painter &p, const QString &title, const QString &additional = QString());
void setMaxHeight(int32 maxHeight);
void resizeMaxHeight(int32 newWidth, int32 maxHeight);
virtual void closePressed() {
void doSetInnerFocus() override {
_content->setInnerFocus();
}
void closeHook() override {
_content->closeHook();
}
private:
void updateBlockTitleGeometry();
int countHeight() const;
void paintTitle(Painter &p, const QString &title, const QString &additional = QString());
int _maxHeight = 0;
bool hasTitle() const;
int titleHeight() const;
int buttonsHeight() const;
int buttonsTop() const;
int contentTop() const;
int countFullHeight() const;
int countRealHeight() const;
void updateSize();
bool _closed = false;
int _fullHeight = 0;
bool _noContentMargin = false;
int _maxContentHeight = 0;
object_ptr<BoxContent> _content;
QString _title;
QString _additionalTitle;
bool _blockTitle = false;
ChildWidget<Ui::IconButton> _blockClose = { nullptr };
ChildWidget<Ui::GradientShadow> _blockShadow = { nullptr };
bool _layerType = false;
std_::vector_of_moveable<object_ptr<Ui::RoundButton>> _buttons;
object_ptr<Ui::RoundButton> _leftButton = { nullptr };
};
class ScrollableBoxShadow : public Ui::PlainShadow {
public:
ScrollableBoxShadow(QWidget *parent);
};
class ScrollableBox : public AbstractBox {
public:
ScrollableBox(const style::FlatScroll &scroll, int w = 0);
protected:
void init(TWidget *inner, int bottomSkip = -1, int topSkip = -1);
void setScrollSkips(int bottomSkip = -1, int topSkip = -1);
void resizeEvent(QResizeEvent *e) override;
Ui::ScrollArea *scrollArea() {
return _scroll;
}
private:
void updateScrollGeometry();
ChildWidget<Ui::ScrollArea> _scroll;
int _topSkip, _bottomSkip;
};
class ItemListBox : public ScrollableBox {
public:
ItemListBox(const style::FlatScroll &scroll, int32 w = 0);
};
template <typename BoxType, typename ...Args>
inline object_ptr<BoxType> Box(Args&&... args) {
auto parent = static_cast<QWidget*>(nullptr);
return object_ptr<BoxType>(parent, std_::forward<Args>(args)...);
}
enum CreatingGroupType {
CreatingGroupNone,

View File

@ -39,57 +39,52 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "apiwrap.h"
#include "observer_peer.h"
AddContactBox::AddContactBox(QString fname, QString lname, QString phone) : AbstractBox(st::boxWidth)
, _first(this, st::defaultInputField, lang(lng_signup_firstname), fname)
AddContactBox::AddContactBox(QWidget*, QString fname, QString lname, QString phone)
: _first(this, st::defaultInputField, lang(lng_signup_firstname), fname)
, _last(this, st::defaultInputField, lang(lng_signup_lastname), lname)
, _phone(this, st::defaultInputField, lang(lng_contact_phone), phone)
, _save(this, lang(lng_add_contact), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _retry(this, lang(lng_try_other_contact), st::defaultBoxButton)
, _invertOrder(langFirstNameGoesSecond()) {
if (!phone.isEmpty()) {
_phone->setDisabled(true);
}
initBox();
}
AddContactBox::AddContactBox(UserData *user) : AbstractBox(st::boxWidth)
, _user(user)
AddContactBox::AddContactBox(QWidget*, UserData *user)
: _user(user)
, _first(this, st::defaultInputField, lang(lng_signup_firstname), user->firstName)
, _last(this, st::defaultInputField, lang(lng_signup_lastname), user->lastName)
, _phone(this, st::defaultInputField, lang(lng_contact_phone), user->phone())
, _save(this, lang(lng_settings_save), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _retry(this, lang(lng_try_other_contact), st::defaultBoxButton)
, _invertOrder(langFirstNameGoesSecond()) {
_phone->setDisabled(true);
initBox();
}
void AddContactBox::initBox() {
void AddContactBox::prepare() {
if (_invertOrder) {
setTabOrder(_last, _first);
}
if (_user) {
setTitleText(lang(lng_edit_contact_title));
setTitle(lang(lng_edit_contact_title));
} else {
bool readyToAdd = !_phone->getLastText().isEmpty() && (!_first->getLastText().isEmpty() || !_last->getLastText().isEmpty());
setTitleText(lang(readyToAdd ? lng_confirm_contact_data : lng_enter_contact_data));
setTitle(lang(readyToAdd ? lng_confirm_contact_data : lng_enter_contact_data));
}
setMaxHeight(titleHeight() + st::contactPadding.top() + _first->height() + st::contactSkip + _last->height() + st::contactPhoneSkip + _phone->height() + st::contactPadding.bottom() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom());
_retry->hide();
connect(_save, SIGNAL(clicked()), this, SLOT(onSave()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
connect(_retry, SIGNAL(clicked()), this, SLOT(onRetry()));
updateButtons();
connect(_first, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
connect(_last, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
connect(_phone, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
if ((_first->getLastText().isEmpty() && _last->getLastText().isEmpty()) || !_phone->isEnabled()) {
(_invertOrder ? _last : _first)->setDisplayFocused(true);
_phone->finishAnimations();
} else {
_phone->setDisplayFocused(true);
}
setDimensions(st::boxWideWidth, st::contactPadding.top() + _first->height() + st::contactSkip + _last->height() + st::contactPhoneSkip + _phone->height() + st::contactPadding.bottom() + st::boxPadding.bottom());
}
void AddContactBox::doSetInnerFocus() {
void AddContactBox::setInnerFocus() {
if ((_first->getLastText().isEmpty() && _last->getLastText().isEmpty()) || !_phone->isEnabled()) {
(_invertOrder ? _last : _first)->setFocus();
} else {
@ -98,38 +93,35 @@ void AddContactBox::doSetInnerFocus() {
}
void AddContactBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e);
BoxContent::paintEvent(e);
Painter p(this);
if (_retry->isHidden()) {
st::contactUserIcon.paint(p, st::boxPadding.left(), _first->y() + st::contactIconTop, width());
st::contactPhoneIcon.paint(p, st::boxPadding.left(), _phone->y() + st::contactIconTop, width());
} else {
if (_retrying) {
p.setPen(st::boxTextFg);
p.setFont(st::boxTextFont);
int32 h = height() - titleHeight() - st::contactPadding.top() - st::contactPadding.bottom() - st::boxPadding.bottom() - st::boxButtonPadding.top() - _retry->height() - st::boxButtonPadding.bottom();
p.drawText(QRect(st::boxPadding.left(), titleHeight() + st::contactPadding.top(), width() - st::boxPadding.left() - st::boxPadding.right(), h), lng_contact_not_joined(lt_name, _sentName), style::al_topleft);
auto textHeight = height() - st::contactPadding.top() - st::contactPadding.bottom() - st::boxPadding.bottom();
p.drawText(QRect(st::boxPadding.left(), st::contactPadding.top(), width() - st::boxPadding.left() - st::boxPadding.right(), textHeight), lng_contact_not_joined(lt_name, _sentName), style::al_topleft);
} else {
st::contactUserIcon.paint(p, st::boxPadding.left(), _first->y() + st::contactIconTop, width());
st::contactPhoneIcon.paint(p, st::boxPadding.left(), _phone->y() + st::contactIconTop, width());
}
}
void AddContactBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e);
_first->resize(width() - st::boxPadding.left() - st::contactPadding.left() - st::boxPadding.right(), _first->height());
_last->resize(_first->width(), _last->height());
_phone->resize(_first->width(), _last->height());
if (_invertOrder) {
_last->moveToLeft(st::boxPadding.left() + st::contactPadding.left(), titleHeight() + st::contactPadding.top());
_last->moveToLeft(st::boxPadding.left() + st::contactPadding.left(), st::contactPadding.top());
_first->moveToLeft(st::boxPadding.left() + st::contactPadding.left(), _last->y() + _last->height() + st::contactSkip);
_phone->moveToLeft(st::boxPadding.left() + st::contactPadding.left(), _first->y() + _first->height() + st::contactPhoneSkip);
} else {
_first->moveToLeft(st::boxPadding.left() + st::contactPadding.left(), titleHeight() + st::contactPadding.top());
_first->moveToLeft(st::boxPadding.left() + st::contactPadding.left(), st::contactPadding.top());
_last->moveToLeft(st::boxPadding.left() + st::contactPadding.left(), _first->y() + _first->height() + st::contactSkip);
_phone->moveToLeft(st::boxPadding.left() + st::contactPadding.left(), _last->y() + _last->height() + st::contactPhoneSkip);
}
_save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height());
_retry->moveToRight(st::boxButtonPadding.right(), _save->y());
_cancel->moveToRight(st::boxButtonPadding.right() + (_retry->isHidden() ? _save->width() : _retry->width()) + st::boxButtonPadding.left(), _save->y());
AbstractBox::resizeEvent(e);
}
void AddContactBox::onSubmit() {
@ -190,7 +182,7 @@ bool AddContactBox::onSaveUserFail(const RPCError &error) {
QString firstName = _first->getLastText().trimmed(), lastName = _last->getLastText().trimmed();
if (err == "CHAT_TITLE_NOT_MODIFIED") {
_user->setName(firstName, lastName, _user->nameOrPhone, _user->username);
onClose();
closeBox();
return true;
} else if (err == "NO_CHAT_TITLE") {
_first->setFocus();
@ -202,12 +194,12 @@ bool AddContactBox::onSaveUserFail(const RPCError &error) {
}
void AddContactBox::onImportDone(const MTPcontacts_ImportedContacts &res) {
if (isHidden() || !App::main()) return;
if (!isBoxShown() || !App::main()) return;
const auto &d(res.c_contacts_importedContacts());
auto &d = res.c_contacts_importedContacts();
App::feedUsers(d.vusers);
const auto &v(d.vimported.c_vector().v);
auto &v = d.vimported.c_vector().v;
UserData *user = nullptr;
if (!v.isEmpty()) {
const auto &c(v.front().c_importedContact());
@ -220,8 +212,8 @@ void AddContactBox::onImportDone(const MTPcontacts_ImportedContacts &res) {
Ui::hideLayer();
} else {
hideChildren();
_retry->show();
resizeEvent(0);
_retrying = true;
updateButtons();
update();
}
}
@ -229,15 +221,15 @@ void AddContactBox::onImportDone(const MTPcontacts_ImportedContacts &res) {
void AddContactBox::onSaveUserDone(const MTPcontacts_ImportedContacts &res) {
auto &d = res.c_contacts_importedContacts();
App::feedUsers(d.vusers);
onClose();
closeBox();
}
void AddContactBox::onRetry() {
_addRequest = 0;
_contactId = 0;
showChildren();
_retry->hide();
resizeEvent(0);
_retrying = false;
updateButtons();
_first->setText(QString());
_last->setText(QString());
_phone->clearText();
@ -246,31 +238,42 @@ void AddContactBox::onRetry() {
update();
}
GroupInfoBox::GroupInfoBox(CreatingGroupType creating, bool fromTypeChoose) : AbstractBox()
, _creating(creating)
, _photo(this, st::newGroupPhotoSize, st::newGroupPhotoIconPosition)
, _title(this, st::defaultInputField, lang(_creating == CreatingGroupChannel ? lng_dlg_new_channel_name : lng_dlg_new_group_name))
, _description(this, st::newGroupDescription, lang(lng_create_group_description))
, _next(this, lang(_creating == CreatingGroupChannel ? lng_create_group_create : lng_create_group_next), st::defaultBoxButton)
, _cancel(this, lang(fromTypeChoose ? lng_create_group_back : lng_cancel), st::cancelBoxButton) {
void AddContactBox::updateButtons() {
clearButtons();
if (_retrying) {
addButton(lang(lng_try_other_contact), [this] { onRetry(); });
} else {
addButton(lang(_user ? lng_settings_save : lng_add_contact), [this] { onSave(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
}
}
GroupInfoBox::GroupInfoBox(QWidget*, CreatingGroupType creating, bool fromTypeChoose)
: _creating(creating)
, _fromTypeChoose(fromTypeChoose)
, _photo(this, st::newGroupPhotoSize, st::newGroupPhotoIconPosition)
, _title(this, st::defaultInputField, lang(_creating == CreatingGroupChannel ? lng_dlg_new_channel_name : lng_dlg_new_group_name)) {
}
void GroupInfoBox::prepare() {
setMouseTracking(true);
_title->setMaxLength(MaxGroupChannelTitle);
_description->setMaxLength(MaxChannelDescription);
_description->resize(width() - st::boxPadding.left() - st::newGroupInfoPadding.left() - st::boxPadding.right(), _description->height());
_description->setVisible(_creating == CreatingGroupChannel);
if (_creating == CreatingGroupChannel) {
_description.create(this, st::newGroupDescription, lang(lng_create_group_description));
_description->show();
_description->setMaxLength(MaxChannelDescription);
updateMaxHeight();
connect(_description, SIGNAL(resized()), this, SLOT(onDescriptionResized()));
connect(_description, SIGNAL(submitted(bool)), this, SLOT(onNext()));
connect(_description, SIGNAL(cancelled()), this, SLOT(onClose()));
connect(_description, SIGNAL(resized()), this, SLOT(onDescriptionResized()));
connect(_description, SIGNAL(submitted(bool)), this, SLOT(onNext()));
connect(_description, SIGNAL(cancelled()), this, SLOT(onClose()));
}
connect(_title, SIGNAL(submitted(bool)), this, SLOT(onNameSubmit()));
connect(_next, SIGNAL(clicked()), this, SLOT(onNext()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
addButton(lang(_creating == CreatingGroupChannel ? lng_create_group_create : lng_create_group_next), [this] { onNext(); });
addButton(lang(_fromTypeChoose ? lng_create_group_back : lng_cancel), [this] { closeBox(); });
_photo->setClickedCallback(App::LambdaDelayed(st::defaultActiveButton.ripple.hideDuration, this, [this] {
auto imgExtensions = cImgExtensions();
@ -280,48 +283,53 @@ GroupInfoBox::GroupInfoBox(CreatingGroupType creating, bool fromTypeChoose) : Ab
subscribe(FileDialog::QueryDone(), [this](const FileDialog::QueryUpdate &update) {
notifyFileQueryUpdated(update);
});
_title->setDisplayFocused(true);
updateMaxHeight();
}
void GroupInfoBox::doSetInnerFocus() {
void GroupInfoBox::setInnerFocus() {
_title->setFocus();
}
void GroupInfoBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e);
_photo->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), st::boxPadding.top() + st::newGroupInfoPadding.top());
int32 nameLeft = st::newGroupPhotoSize + st::newGroupNamePosition.x();
auto nameLeft = st::newGroupPhotoSize + st::newGroupNamePosition.x();
_title->resize(width() - st::boxPadding.left() - st::newGroupInfoPadding.left() - st::boxPadding.right() - nameLeft, _title->height());
_title->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left() + nameLeft, st::boxPadding.top() + st::newGroupInfoPadding.top() + st::newGroupNamePosition.y());
_description->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), st::boxPadding.top() + st::newGroupInfoPadding.top() + st::newGroupPhotoSize + st::newGroupDescriptionPadding.top());
_next->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _next->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _next->width() + st::boxButtonPadding.left(), _next->y());
AbstractBox::resizeEvent(e);
if (_description) {
_description->resize(width() - st::boxPadding.left() - st::newGroupInfoPadding.left() - st::boxPadding.right(), _description->height());
_description->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), st::boxPadding.top() + st::newGroupInfoPadding.top() + st::newGroupPhotoSize + st::newGroupDescriptionPadding.top());
}
}
void GroupInfoBox::onNameSubmit() {
if (_title->getLastText().trimmed().isEmpty()) {
_title->setFocus();
_title->showError();
} else if (_description->isHidden()) {
onNext();
} else {
} else if (_description) {
_description->setFocus();
} else {
onNext();
}
}
void GroupInfoBox::onNext() {
if (_creationRequestId) return;
QString title = prepareText(_title->getLastText()), description = prepareText(_description->getLastText(), true);
auto title = prepareText(_title->getLastText());
auto description = _description ? prepareText(_description->getLastText(), true) : QString();
if (title.isEmpty()) {
_title->setFocus();
_title->showError();
return;
}
if (_creating == CreatingGroupGroup) {
Ui::showLayer(new ContactsBox(title, _photoImage), KeepOtherLayers);
Ui::show(Box<ContactsBox>(title, _photoImage), KeepOtherLayers);
} else {
bool mega = false;
MTPchannels_CreateChannel::Flags flags = mega ? MTPchannels_CreateChannel::Flag::f_megagroup : MTPchannels_CreateChannel::Flag::f_broadcast;
@ -354,7 +362,7 @@ void GroupInfoBox::creationDone(const MTPUpdates &updates) {
LOG(("API Error: channel not found in updates (GroupInfoBox::creationDone)"));
}
onClose();
closeBox();
}
bool GroupInfoBox::creationFail(const RPCError &error) {
@ -366,7 +374,7 @@ bool GroupInfoBox::creationFail(const RPCError &error) {
_title->showError();
return true;
} else if (error.type() == qstr("USER_RESTRICTED")) {
Ui::showLayer(new InformBox(lang(lng_cant_do_this)));
Ui::show(Box<InformBox>(lang(lng_cant_do_this)));
return true;
}
return false;
@ -377,7 +385,7 @@ void GroupInfoBox::exportDone(const MTPExportedChatInvite &result) {
if (result.type() == mtpc_chatInviteExported) {
_createdChannel->setInviteLink(qs(result.c_chatInviteExported().vlink));
}
Ui::showLayer(new SetupChannelBox(_createdChannel));
Ui::show(Box<SetupChannelBox>(_createdChannel));
}
void GroupInfoBox::onDescriptionResized() {
@ -386,11 +394,11 @@ void GroupInfoBox::onDescriptionResized() {
}
void GroupInfoBox::updateMaxHeight() {
int32 h = st::boxPadding.top() + st::newGroupInfoPadding.top() + st::newGroupPhotoSize + st::boxPadding.bottom() + st::newGroupInfoPadding.bottom() + st::boxButtonPadding.top() + _next->height() + st::boxButtonPadding.bottom();
if (_creating == CreatingGroupChannel) {
h += st::newGroupDescriptionPadding.top() + _description->height() + st::newGroupDescriptionPadding.bottom();
auto newHeight = st::boxPadding.top() + st::newGroupInfoPadding.top() + st::newGroupPhotoSize + st::boxPadding.bottom() + st::newGroupInfoPadding.bottom();
if (_description) {
newHeight += st::newGroupDescriptionPadding.top() + _description->height() + st::newGroupDescriptionPadding.bottom();
}
setMaxHeight(h);
setDimensions(st::boxWideWidth, newHeight);
}
void GroupInfoBox::notifyFileQueryUpdated(const FileDialog::QueryUpdate &update) {
@ -411,9 +419,8 @@ void GroupInfoBox::notifyFileQueryUpdated(const FileDialog::QueryUpdate &update)
if (img.isNull() || img.width() > 10 * img.height() || img.height() > 10 * img.width()) {
return;
}
auto box = new PhotoCropBox(img, (_creating == CreatingGroupChannel) ? peerFromChannel(0) : peerFromChat(0));
auto box = Ui::show(Box<PhotoCropBox>(img, (_creating == CreatingGroupChannel) ? peerFromChannel(0) : peerFromChat(0)), KeepOtherLayers);
connect(box, SIGNAL(ready(const QImage&)), this, SLOT(onPhotoReady(const QImage&)));
Ui::showLayer(box, KeepOtherLayers);
}
void GroupInfoBox::onPhotoReady(const QImage &img) {
@ -421,27 +428,26 @@ void GroupInfoBox::onPhotoReady(const QImage &img) {
_photo->setImage(_photoImage);
}
SetupChannelBox::SetupChannelBox(ChannelData *channel, bool existing) : AbstractBox()
, _channel(channel)
SetupChannelBox::SetupChannelBox(QWidget*, ChannelData *channel, bool existing)
: _channel(channel)
, _existing(existing)
, _public(this, qsl("channel_privacy"), 0, lang(channel->isMegagroup() ? lng_create_public_group_title : lng_create_public_channel_title), true, st::defaultBoxCheckbox)
, _private(this, qsl("channel_privacy"), 1, lang(channel->isMegagroup() ? lng_create_private_group_title : lng_create_private_channel_title), false, st::defaultBoxCheckbox)
, _aboutPublicWidth(width() - st::boxPadding.left() - st::boxButtonPadding.right() - st::newGroupPadding.left() - st::defaultBoxCheckbox.textPosition.x())
, _aboutPublic(st::normalFont, lang(channel->isMegagroup() ? lng_create_public_group_about : lng_create_public_channel_about), _defaultOptions, _aboutPublicWidth)
, _aboutPrivate(st::normalFont, lang(channel->isMegagroup() ? lng_create_private_group_about : lng_create_private_channel_about), _defaultOptions, _aboutPublicWidth)
, _link(this, st::setupChannelLink, QString(), channel->username, true)
, _linkOver(false)
, _save(this, lang(lng_settings_save), st::defaultBoxButton)
, _skip(this, lang(existing ? lng_cancel : lng_create_group_skip), st::cancelBoxButton) {
, _link(this, st::setupChannelLink, QString(), channel->username, true) {
}
void SetupChannelBox::prepare() {
_aboutPublicHeight = _aboutPublic.countHeight(_aboutPublicWidth);
setMouseTracking(true);
_checkRequestId = MTP::send(MTPchannels_CheckUsername(_channel->inputChannel, MTP_string("preston")), RPCDoneHandlerPtr(), rpcFail(&SetupChannelBox::onFirstCheckFail));
_aboutPublicHeight = _aboutPublic.countHeight(_aboutPublicWidth);
updateMaxHeight();
connect(_save, SIGNAL(clicked()), this, SLOT(onSave()));
connect(_skip, SIGNAL(clicked()), this, SLOT(onClose()));
addButton(lang(lng_settings_save), [this] { onSave(); });
addButton(lang(_existing ? lng_cancel : lng_create_group_skip), [this] { closeBox(); });
connect(_link, SIGNAL(changed()), this, SLOT(onChange()));
_link->setVisible(_public->checked());
@ -451,9 +457,11 @@ SetupChannelBox::SetupChannelBox(ChannelData *channel, bool existing) : Abstract
connect(_public, SIGNAL(changed()), this, SLOT(onPrivacyChange()));
connect(_private, SIGNAL(changed()), this, SLOT(onPrivacyChange()));
updateMaxHeight();
}
void SetupChannelBox::doSetInnerFocus() {
void SetupChannelBox::setInnerFocus() {
if (_link->isHidden()) {
setFocus();
} else {
@ -462,11 +470,11 @@ void SetupChannelBox::doSetInnerFocus() {
}
void SetupChannelBox::updateMaxHeight() {
auto newHeight = st::boxPadding.top() + st::newGroupPadding.top() + _public->heightNoMargins() + _aboutPublicHeight + st::newGroupSkip + _private->heightNoMargins() + _aboutPrivate.countHeight(_aboutPublicWidth) + st::newGroupSkip + st::newGroupPadding.bottom();
if (!_channel->isMegagroup() || _public->checked()) {
setMaxHeight(st::boxPadding.top() + st::newGroupPadding.top() + _public->heightNoMargins() + _aboutPublicHeight + st::newGroupSkip + _private->heightNoMargins() + _aboutPrivate.countHeight(_aboutPublicWidth) + st::newGroupSkip + st::newGroupPadding.bottom() + st::newGroupLinkPadding.top() + _link->height() + st::newGroupLinkPadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom());
} else {
setMaxHeight(st::boxPadding.top() + st::newGroupPadding.top() + _public->heightNoMargins() + _aboutPublicHeight + st::newGroupSkip + _private->heightNoMargins() + _aboutPrivate.countHeight(_aboutPublicWidth) + st::newGroupSkip + st::newGroupPadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom());
newHeight += st::newGroupLinkPadding.top() + _link->height() + st::newGroupLinkPadding.bottom();
}
setDimensions(st::boxWideWidth, newHeight);
}
void SetupChannelBox::keyPressEvent(QKeyEvent *e) {
@ -480,7 +488,7 @@ void SetupChannelBox::keyPressEvent(QKeyEvent *e) {
}
}
} else {
AbstractBox::keyPressEvent(e);
BoxContent::keyPressEvent(e);
}
}
@ -534,16 +542,14 @@ void SetupChannelBox::paintEvent(QPaintEvent *e) {
}
void SetupChannelBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e);
_public->moveToLeft(st::boxPadding.left() + st::newGroupPadding.left(), st::boxPadding.top() + st::newGroupPadding.top());
_private->moveToLeft(st::boxPadding.left() + st::newGroupPadding.left(), _public->bottomNoMargins() + _aboutPublicHeight + st::newGroupSkip);
_link->resize(width() - st::boxPadding.left() - st::newGroupLinkPadding.left() - st::boxPadding.right(), _link->height());
_link->moveToLeft(st::boxPadding.left() + st::newGroupLinkPadding.left(), _private->bottomNoMargins() + _aboutPrivate.countHeight(_aboutPublicWidth) + st::newGroupSkip + st::newGroupPadding.bottom() + st::newGroupLinkPadding.top());
_invitationLink = QRect(_link->x(), _link->y() + (_link->height() / 2) - st::boxTextFont->height, _link->width(), 2 * st::boxTextFont->height);
_save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height());
_skip->moveToRight(st::boxButtonPadding.right() + _save->width() + st::boxButtonPadding.left(), _save->y());
AbstractBox::resizeEvent(e);
}
void SetupChannelBox::mouseMoveEvent(QMouseEvent *e) {
@ -574,9 +580,9 @@ void SetupChannelBox::updateSelected(const QPoint &cursorGlobalPosition) {
}
}
void SetupChannelBox::closePressed() {
void SetupChannelBox::closeHook() {
if (!_existing) {
Ui::showLayer(new ContactsBox(_channel));
Ui::show(Box<ContactsBox>(_channel));
}
}
@ -586,7 +592,7 @@ void SetupChannelBox::onSave() {
_sentUsername = QString();
_saveRequestId = MTP::send(MTPchannels_UpdateUsername(_channel->inputChannel, MTP_string(_sentUsername)), rpcDone(&SetupChannelBox::onUpdateDone), rpcFail(&SetupChannelBox::onUpdateFail));
} else {
onClose();
closeBox();
}
}
@ -655,7 +661,7 @@ void SetupChannelBox::onPrivacyChange() {
if (_public->checked()) {
if (_tooMuchUsernames) {
_private->setChecked(true);
Ui::showLayer(new RevokePublicLinkBox(base::lambda_guarded(this, [this] {
Ui::show(Box<RevokePublicLinkBox>(base::lambda_guarded(this, [this] {
_tooMuchUsernames = false;
_public->setChecked(true);
onCheck();
@ -676,7 +682,7 @@ void SetupChannelBox::onPrivacyChange() {
void SetupChannelBox::onUpdateDone(const MTPBool &result) {
_channel->setName(textOneLine(_channel->name), _sentUsername);
onClose();
closeBox();
}
bool SetupChannelBox::onUpdateFail(const RPCError &error) {
@ -686,7 +692,7 @@ bool SetupChannelBox::onUpdateFail(const RPCError &error) {
QString err(error.type());
if (err == "USERNAME_NOT_MODIFIED" || _sentUsername == _channel->username) {
_channel->setName(textOneLine(_channel->name), textOneLine(_sentUsername));
onClose();
closeBox();
return true;
} else if (err == "USERNAME_INVALID") {
_link->setFocus();
@ -748,9 +754,9 @@ bool SetupChannelBox::onCheckFail(const RPCError &error) {
}
void SetupChannelBox::showRevokePublicLinkBoxForEdit() {
onClose();
Ui::showLayer(new RevokePublicLinkBox([channel = _channel, existing = _existing]() {
Ui::showLayer(new SetupChannelBox(channel, existing), KeepOtherLayers);
closeBox();
Ui::show(Box<RevokePublicLinkBox>([channel = _channel, existing = _existing]() {
Ui::show(Box<SetupChannelBox>(channel, existing), KeepOtherLayers);
}), KeepOtherLayers);
}
@ -777,38 +783,40 @@ bool SetupChannelBox::onFirstCheckFail(const RPCError &error) {
return true;
}
EditNameTitleBox::EditNameTitleBox(PeerData *peer) :
_peer(peer),
_first(this, st::defaultInputField, lang(peer->isUser() ? lng_signup_firstname : lng_dlg_new_group_name), peer->isUser() ? peer->asUser()->firstName : peer->name),
_last(this, st::defaultInputField, lang(lng_signup_lastname), peer->isUser() ? peer->asUser()->lastName : QString()),
_save(this, lang(lng_settings_save), st::defaultBoxButton),
_cancel(this, lang(lng_cancel), st::cancelBoxButton),
_invertOrder(!peer->isChat() && langFirstNameGoesSecond()) {
EditNameTitleBox::EditNameTitleBox(QWidget*, PeerData *peer)
: _peer(peer)
, _first(this, st::defaultInputField, lang(peer->isUser() ? lng_signup_firstname : lng_dlg_new_group_name), peer->isUser() ? peer->asUser()->firstName : peer->name)
, _last(this, st::defaultInputField, lang(lng_signup_lastname), peer->isUser() ? peer->asUser()->lastName : QString())
, _invertOrder(!peer->isChat() && langFirstNameGoesSecond()) {
}
void EditNameTitleBox::prepare() {
auto newHeight = st::contactPadding.top() + _first->height();
if (_peer->isUser()) {
setTitle(lang(_peer == App::self() ? lng_edit_self_title : lng_edit_contact_title));
newHeight += st::contactSkip + _last->height();
} else if (_peer->isChat()) {
setTitle(lang(lng_edit_group_title));
}
newHeight += st::boxPadding.bottom() + st::contactPadding.bottom();
setDimensions(st::boxWideWidth, newHeight);
addButton(lang(lng_settings_save), [this] { onSave(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
if (_invertOrder) {
setTabOrder(_last, _first);
}
_first->setMaxLength(MaxGroupChannelTitle);
_last->setMaxLength(MaxGroupChannelTitle);
int32 h = titleHeight() + st::contactPadding.top() + _first->height();
if (_peer->isUser()) {
setTitleText(lang(_peer == App::self() ? lng_edit_self_title : lng_edit_contact_title));
h += st::contactSkip + _last->height();
} else if (_peer->isChat()) {
setTitleText(lang(lng_edit_group_title));
}
h += st::boxPadding.bottom() + st::contactPadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom();
setMaxHeight(h);
connect(_save, SIGNAL(clicked()), this, SLOT(onSave()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
connect(_first, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
connect(_last, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
_last->setVisible(!_peer->isChat());
(_invertOrder ? _last : _first)->setDisplayFocused(true);
}
void EditNameTitleBox::doSetInnerFocus() {
void EditNameTitleBox::setInnerFocus() {
(_invertOrder ? _last : _first)->setFocus();
}
@ -838,19 +846,17 @@ void EditNameTitleBox::onSubmit() {
}
void EditNameTitleBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e);
_first->resize(width() - st::boxPadding.left() - st::newGroupInfoPadding.left() - st::boxPadding.right(), _first->height());
_last->resize(_first->size());
if (_invertOrder) {
_last->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), titleHeight() + st::contactPadding.top());
_last->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), st::contactPadding.top());
_first->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _last->y() + _last->height() + st::contactSkip);
} else {
_first->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), titleHeight() + st::contactPadding.top());
_first->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), st::contactPadding.top());
_last->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _first->y() + _first->height() + st::contactSkip);
}
_save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _save->width() + st::boxButtonPadding.left(), _save->y());
AbstractBox::resizeEvent(e);
}
void EditNameTitleBox::onSave() {
@ -882,7 +888,7 @@ void EditNameTitleBox::onSave() {
void EditNameTitleBox::onSaveSelfDone(const MTPUser &user) {
App::feedUsers(MTP_vector<MTPUser>(1, user));
onClose();
closeBox();
}
bool EditNameTitleBox::onSaveSelfFail(const RPCError &error) {
@ -892,7 +898,7 @@ bool EditNameTitleBox::onSaveSelfFail(const RPCError &error) {
QString first = textOneLine(_first->getLastText().trimmed()), last = textOneLine(_last->getLastText().trimmed());
if (err == "NAME_NOT_MODIFIED") {
App::self()->setName(first, last, QString(), textOneLine(App::self()->username));
onClose();
closeBox();
return true;
} else if (err == "FIRSTNAME_INVALID") {
_first->setFocus();
@ -916,7 +922,7 @@ bool EditNameTitleBox::onSaveChatFail(const RPCError &error) {
if (auto chatData = _peer->asChat()) {
chatData->setName(_sentName);
}
onClose();
closeBox();
return true;
} else if (err == qstr("NO_CHAT_TITLE")) {
_first->setFocus();
@ -929,42 +935,44 @@ bool EditNameTitleBox::onSaveChatFail(const RPCError &error) {
void EditNameTitleBox::onSaveChatDone(const MTPUpdates &updates) {
App::main()->sentUpdatesReceived(updates);
onClose();
closeBox();
}
EditChannelBox::EditChannelBox(ChannelData *channel) : AbstractBox()
, _channel(channel)
EditChannelBox::EditChannelBox(QWidget*, ChannelData *channel)
: _channel(channel)
, _title(this, st::defaultInputField, lang(lng_dlg_new_channel_name), _channel->name)
, _description(this, st::newGroupDescription, lang(lng_create_group_description), _channel->about())
, _sign(this, lang(lng_edit_sign_messages), channel->addsSignature(), st::defaultBoxCheckbox)
, _publicLink(this, lang(channel->isPublic() ? lng_profile_edit_public_link : lng_profile_create_public_link), st::boxLinkButton)
, _save(this, lang(lng_settings_save), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
connect(App::main(), SIGNAL(peerNameChanged(PeerData*,const PeerData::Names&,const PeerData::NameFirstChars&)), this, SLOT(peerUpdated(PeerData*)));
, _publicLink(this, lang(channel->isPublic() ? lng_profile_edit_public_link : lng_profile_create_public_link), st::boxLinkButton) {
}
setTitleText(lang(_channel->isMegagroup() ? lng_edit_group : lng_edit_channel_title));
void EditChannelBox::prepare() {
setTitle(lang(_channel->isMegagroup() ? lng_edit_group : lng_edit_channel_title));
addButton(lang(lng_settings_save), [this] { onSave(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
connect(App::main(), SIGNAL(peerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)), this, SLOT(peerUpdated(PeerData*)));
setMouseTracking(true);
_title->setMaxLength(MaxGroupChannelTitle);
_description->setMaxLength(MaxChannelDescription);
_description->resize(width() - st::boxPadding.left() - st::newGroupInfoPadding.left() - st::boxPadding.right(), _description->height());
myEnsureResized(_description);
updateMaxHeight();
connect(_description, SIGNAL(resized()), this, SLOT(onDescriptionResized()));
connect(_description, SIGNAL(submitted(bool)), this, SLOT(onSave()));
connect(_description, SIGNAL(cancelled()), this, SLOT(onClose()));
connect(_save, SIGNAL(clicked()), this, SLOT(onSave()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
connect(_publicLink, SIGNAL(clicked()), this, SLOT(onPublicLink()));
_publicLink->setVisible(_channel->canEditUsername());
_sign->setVisible(!_channel->isMegagroup());
_title->setDisplayFocused(true);
updateMaxHeight();
}
void EditChannelBox::doSetInnerFocus() {
void EditChannelBox::setInnerFocus() {
_title->setFocus();
}
@ -974,7 +982,7 @@ void EditChannelBox::keyPressEvent(QKeyEvent *e) {
onSave();
}
} else {
AbstractBox::keyPressEvent(e);
BoxContent::keyPressEvent(e);
}
}
@ -991,22 +999,25 @@ void EditChannelBox::onDescriptionResized() {
}
void EditChannelBox::updateMaxHeight() {
int32 h = titleHeight() + st::newGroupInfoPadding.top() + _title->height();
h += st::newGroupDescriptionPadding.top() + _description->height() + st::newGroupDescriptionPadding.bottom();
auto newHeight = st::newGroupInfoPadding.top() + _title->height();
newHeight += st::newGroupDescriptionPadding.top() + _description->height() + st::newGroupDescriptionPadding.bottom();
if (!_channel->isMegagroup()) {
h += st::newGroupPublicLinkPadding.top() + _sign->heightNoMargins() + st::newGroupPublicLinkPadding.bottom();
newHeight += st::newGroupPublicLinkPadding.top() + _sign->heightNoMargins() + st::newGroupPublicLinkPadding.bottom();
}
if (_channel->canEditUsername()) {
h += st::newGroupPublicLinkPadding.top() + _publicLink->height() + st::newGroupPublicLinkPadding.bottom();
newHeight += st::newGroupPublicLinkPadding.top() + _publicLink->height() + st::newGroupPublicLinkPadding.bottom();
}
h += st::boxPadding.bottom() + st::newGroupInfoPadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom();
setMaxHeight(h);
newHeight += st::boxPadding.bottom() + st::newGroupInfoPadding.bottom();
setDimensions(st::boxWideWidth, newHeight);
}
void EditChannelBox::resizeEvent(QResizeEvent *e) {
_title->resize(width() - st::boxPadding.left() - st::newGroupInfoPadding.left() - st::boxPadding.right(), _title->height());
_title->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), titleHeight() + st::newGroupInfoPadding.top() + st::newGroupNamePosition.y());
BoxContent::resizeEvent(e);
_title->resize(width() - st::boxPadding.left() - st::newGroupInfoPadding.left() - st::boxPadding.right(), _title->height());
_title->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), st::newGroupInfoPadding.top() + st::newGroupNamePosition.y());
_description->resize(width() - st::boxPadding.left() - st::newGroupInfoPadding.left() - st::boxPadding.right(), _description->height());
_description->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _title->y() + _title->height() + st::newGroupDescriptionPadding.top());
_sign->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _description->y() + _description->height() + st::newGroupDescriptionPadding.bottom() + st::newGroupPublicLinkPadding.top());
@ -1016,10 +1027,6 @@ void EditChannelBox::resizeEvent(QResizeEvent *e) {
} else {
_publicLink->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _sign->bottomNoMargins() + st::newGroupDescriptionPadding.bottom() + st::newGroupPublicLinkPadding.top());
}
_save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _save->width() + st::boxButtonPadding.left(), _save->y());
AbstractBox::resizeEvent(e);
}
void EditChannelBox::onSave() {
@ -1041,7 +1048,7 @@ void EditChannelBox::onSave() {
}
void EditChannelBox::onPublicLink() {
Ui::showLayer(new SetupChannelBox(_channel, true), KeepOtherLayers);
Ui::show(Box<SetupChannelBox>(_channel, true), KeepOtherLayers);
}
void EditChannelBox::saveDescription() {
@ -1054,7 +1061,7 @@ void EditChannelBox::saveDescription() {
void EditChannelBox::saveSign() {
if (_channel->isMegagroup() || _channel->addsSignature() == _sign->checked()) {
onClose();
closeBox();
} else {
_saveSignRequestId = MTP::send(MTPchannels_ToggleSignatures(_channel->inputChannel, MTP_bool(_sign->checked())), rpcDone(&EditChannelBox::onSaveSignDone), rpcFail(&EditChannelBox::onSaveFail));
}
@ -1093,7 +1100,7 @@ bool EditChannelBox::onSaveFail(const RPCError &error, mtpRequestId req) {
} else if (req == _saveSignRequestId) {
_saveSignRequestId = 0;
if (err == qstr("CHAT_NOT_MODIFIED")) {
onClose();
closeBox();
return true;
}
}
@ -1123,28 +1130,31 @@ void EditChannelBox::onSaveSignDone(const MTPUpdates &updates) {
if (App::main()) {
App::main()->sentUpdatesReceived(updates);
}
onClose();
closeBox();
}
RevokePublicLinkBox::RevokePublicLinkBox(base::lambda<void()> &&revokeCallback) : AbstractBox()
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
RevokePublicLinkBox::RevokePublicLinkBox(QWidget*, base::lambda<void()> &&revokeCallback)
: _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
, _revokeWidth(st::normalFont->width(lang(lng_channels_too_much_public_revoke)))
, _aboutRevoke(this, lang(lng_channels_too_much_public_about), Ui::FlatLabel::InitType::Simple, st::aboutRevokePublicLabel)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _revokeCallback(std_::move(revokeCallback)) {
}
void RevokePublicLinkBox::prepare() {
setMouseTracking(true);
MTP::send(MTPchannels_GetAdminedPublicChannels(), rpcDone(&RevokePublicLinkBox::getPublicDone), rpcFail(&RevokePublicLinkBox::getPublicFail));
updateMaxHeight();
addButton(lang(lng_cancel), [this] { closeBox(); });
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
subscribe(FileDownload::ImageLoaded(), [this] { update(); });
updateMaxHeight();
}
void RevokePublicLinkBox::updateMaxHeight() {
_rowsTop = st::boxPadding.top() + _aboutRevoke->height() + st::boxPadding.top();
setMaxHeight(_rowsTop + (5 * _rowHeight) + st::boxButtonPadding.top() + _cancel->height() + st::boxButtonPadding.bottom());
setDimensions(st::boxWideWidth, _rowsTop + (5 * _rowHeight));
}
void RevokePublicLinkBox::mouseMoveEvent(QMouseEvent *e) {
@ -1183,23 +1193,16 @@ void RevokePublicLinkBox::mouseReleaseEvent(QMouseEvent *e) {
if (pressed && pressed == _selected) {
auto text_method = pressed->isMegagroup() ? lng_channels_too_much_public_revoke_confirm_group : lng_channels_too_much_public_revoke_confirm_channel;
auto text = text_method(lt_link, qsl("telegram.me/") + pressed->userName(), lt_group, pressed->name);
weakRevokeConfirmBox = new ConfirmBox(text, lang(lng_channels_too_much_public_revoke));
struct Data {
Data(QPointer<TWidget> &&weakThis, PeerData *pressed) : weakThis(std_::move(weakThis)), pressed(pressed) {
}
QPointer<TWidget> weakThis;
PeerData *pressed;
};
weakRevokeConfirmBox->setConfirmedCallback(base::lambda_guarded(this, [this, pressed]() {
auto confirmText = lang(lng_channels_too_much_public_revoke);
_weakRevokeConfirmBox = Ui::show(Box<ConfirmBox>(text, confirmText, base::lambda_guarded(this, [this, pressed]() {
if (_revokeRequestId) return;
_revokeRequestId = MTP::send(MTPchannels_UpdateUsername(pressed->asChannel()->inputChannel, MTP_string("")), rpcDone(&RevokePublicLinkBox::revokeLinkDone), rpcFail(&RevokePublicLinkBox::revokeLinkFail));
}));
Ui::showLayer(weakRevokeConfirmBox, KeepOtherLayers);
})), KeepOtherLayers);
}
}
void RevokePublicLinkBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e);
BoxContent::paintEvent(e);
Painter p(this);
p.translate(0, _rowsTop);
@ -1210,9 +1213,9 @@ void RevokePublicLinkBox::paintEvent(QPaintEvent *e) {
}
void RevokePublicLinkBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e);
_aboutRevoke->moveToLeft(st::boxPadding.left(), st::boxPadding.top());
_cancel->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _cancel->height());
AbstractBox::resizeEvent(e);
}
void RevokePublicLinkBox::paintChat(Painter &p, const ChatRow &row, bool selected, bool pressed) const {
@ -1268,10 +1271,10 @@ bool RevokePublicLinkBox::getPublicFail(const RPCError &error) {
}
void RevokePublicLinkBox::revokeLinkDone(const MTPBool &result) {
if (weakRevokeConfirmBox) {
weakRevokeConfirmBox->onClose();
if (_weakRevokeConfirmBox) {
_weakRevokeConfirmBox->closeBox();
}
onClose();
closeBox();
if (_revokeCallback) {
_revokeCallback();
}

View File

@ -34,114 +34,110 @@ class UsernameInput;
class Checkbox;
class Radiobutton;
class LinkButton;
class RoundButton;
class NewAvatarButton;
} // namespace Ui
class AddContactBox : public AbstractBox, public RPCSender {
class AddContactBox : public BoxContent, public RPCSender {
Q_OBJECT
public:
AddContactBox(QString fname = QString(), QString lname = QString(), QString phone = QString());
AddContactBox(UserData *user);
AddContactBox(QWidget*, QString fname = QString(), QString lname = QString(), QString phone = QString());
AddContactBox(QWidget*, UserData *user);
public slots:
protected:
void prepare() override;
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void setInnerFocus() override;
private slots:
void onSubmit();
void onSave();
void onRetry();
protected:
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void doSetInnerFocus() override;
private:
void updateButtons();
void onImportDone(const MTPcontacts_ImportedContacts &res);
void onSaveUserDone(const MTPcontacts_ImportedContacts &res);
bool onSaveUserFail(const RPCError &e);
void initBox();
UserData *_user = nullptr;
ChildWidget<Ui::InputField> _first;
ChildWidget<Ui::InputField> _last;
ChildWidget<Ui::PhoneInput> _phone;
object_ptr<Ui::InputField> _first;
object_ptr<Ui::InputField> _last;
object_ptr<Ui::PhoneInput> _phone;
ChildWidget<Ui::RoundButton> _save;
ChildWidget<Ui::RoundButton> _cancel;
ChildWidget<Ui::RoundButton> _retry;
bool _invertOrder;
bool _retrying = false;
bool _invertOrder = false;
uint64 _contactId = 0;
mtpRequestId _addRequest = 0;
QString _sentName;
};
class GroupInfoBox : public AbstractBox, public RPCSender {
class GroupInfoBox : public BoxContent, public RPCSender {
Q_OBJECT
public:
GroupInfoBox(CreatingGroupType creating, bool fromTypeChoose);
GroupInfoBox(QWidget*, CreatingGroupType creating, bool fromTypeChoose);
public slots:
protected:
void prepare() override;
void setInnerFocus() override;
void resizeEvent(QResizeEvent *e) override;
private slots:
void onPhotoReady(const QImage &img);
void onNext();
void onNameSubmit();
void onDescriptionResized();
protected:
void resizeEvent(QResizeEvent *e) override;
void doSetInnerFocus() override;
private:
void notifyFileQueryUpdated(const FileDialog::QueryUpdate &update);
void creationDone(const MTPUpdates &updates);
bool creationFail(const RPCError &e);
void exportDone(const MTPExportedChatInvite &result);
void updateMaxHeight();
void updateSelected(const QPoint &cursorGlobalPosition);
CreatingGroupType _creating;
ChildWidget<Ui::NewAvatarButton> _photo;
ChildWidget<Ui::InputField> _title;
ChildWidget<Ui::InputArea> _description;
CreatingGroupType _creating;
bool _fromTypeChoose = false;
object_ptr<Ui::NewAvatarButton> _photo;
object_ptr<Ui::InputField> _title;
object_ptr<Ui::InputArea> _description = { nullptr };
QImage _photoImage;
ChildWidget<Ui::RoundButton> _next;
ChildWidget<Ui::RoundButton> _cancel;
// channel creation
mtpRequestId _creationRequestId = 0;
ChannelData *_createdChannel = nullptr;
FileDialog::QueryId _setPhotoFileQueryId = 0;
void creationDone(const MTPUpdates &updates);
bool creationFail(const RPCError &e);
void exportDone(const MTPExportedChatInvite &result);
};
class SetupChannelBox : public AbstractBox, public RPCSender {
class SetupChannelBox : public BoxContent, public RPCSender {
Q_OBJECT
public:
SetupChannelBox(ChannelData *channel, bool existing = false);
SetupChannelBox(QWidget*, ChannelData *channel, bool existing = false);
public slots:
void onSave();
void onChange();
void onCheck();
void onPrivacyChange();
void setInnerFocus() override;
void closeHook() override;
protected:
void prepare() override;
void keyPressEvent(QKeyEvent *e) override;
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
@ -149,8 +145,12 @@ protected:
void mousePressEvent(QMouseEvent *e) override;
void leaveEvent(QEvent *e) override;
void closePressed() override;
void doSetInnerFocus() override;
private slots:
void onSave();
void onChange();
void onCheck();
void onPrivacyChange();
private:
void updateSelected(const QPoint &cursorGlobalPosition);
@ -166,22 +166,18 @@ private:
void showRevokePublicLinkBoxForEdit();
ChannelData *_channel;
bool _existing;
ChannelData *_channel = nullptr;
bool _existing = false;
ChildWidget<Ui::Radiobutton> _public;
ChildWidget<Ui::Radiobutton> _private;
object_ptr<Ui::Radiobutton> _public;
object_ptr<Ui::Radiobutton> _private;
int32 _aboutPublicWidth, _aboutPublicHeight;
Text _aboutPublic, _aboutPrivate;
ChildWidget<Ui::UsernameInput> _link;
object_ptr<Ui::UsernameInput> _link;
QRect _invitationLink;
bool _linkOver;
ChildWidget<Ui::RoundButton> _save;
ChildWidget<Ui::RoundButton> _skip;
bool _linkOver = false;
bool _tooMuchUsernames = false;
mtpRequestId _saveRequestId = 0;
@ -195,20 +191,21 @@ private:
};
class EditNameTitleBox : public AbstractBox, public RPCSender {
class EditNameTitleBox : public BoxContent, public RPCSender {
Q_OBJECT
public:
EditNameTitleBox(PeerData *peer);
public slots:
void onSave();
void onSubmit();
EditNameTitleBox(QWidget*, PeerData *peer);
protected:
void setInnerFocus() override;
void prepare() override;
void resizeEvent(QResizeEvent *e) override;
void doSetInnerFocus() override;
private slots:
void onSave();
void onSubmit();
private:
void onSaveSelfDone(const MTPUser &user);
@ -219,11 +216,8 @@ private:
PeerData *_peer;
ChildWidget<Ui::InputField> _first;
ChildWidget<Ui::InputField> _last;
ChildWidget<Ui::RoundButton> _save;
ChildWidget<Ui::RoundButton> _cancel;
object_ptr<Ui::InputField> _first;
object_ptr<Ui::InputField> _last;
bool _invertOrder = false;
@ -232,25 +226,26 @@ private:
};
class EditChannelBox : public AbstractBox, public RPCSender {
class EditChannelBox : public BoxContent, public RPCSender {
Q_OBJECT
public:
EditChannelBox(ChannelData *channel);
EditChannelBox(QWidget*, ChannelData *channel);
public slots:
protected:
void prepare() override;
void setInnerFocus() override;
void keyPressEvent(QKeyEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
private slots:
void peerUpdated(PeerData *peer);
void onSave();
void onDescriptionResized();
void onPublicLink();
protected:
void keyPressEvent(QKeyEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void doSetInnerFocus() override;
private:
void updateMaxHeight();
@ -264,14 +259,11 @@ private:
ChannelData *_channel;
ChildWidget<Ui::InputField> _title;
ChildWidget<Ui::InputArea> _description;
ChildWidget<Ui::Checkbox> _sign;
object_ptr<Ui::InputField> _title;
object_ptr<Ui::InputArea> _description;
object_ptr<Ui::Checkbox> _sign;
ChildWidget<Ui::LinkButton> _publicLink;
ChildWidget<Ui::RoundButton> _save;
ChildWidget<Ui::RoundButton> _cancel;
object_ptr<Ui::LinkButton> _publicLink;
mtpRequestId _saveTitleRequestId = 0;
mtpRequestId _saveDescriptionRequestId = 0;
@ -281,13 +273,13 @@ private:
};
class RevokePublicLinkBox : public AbstractBox, public RPCSender {
Q_OBJECT
class RevokePublicLinkBox : public BoxContent, public RPCSender {
public:
RevokePublicLinkBox(base::lambda<void()> &&revokeCallback);
RevokePublicLinkBox(QWidget*, base::lambda<void()> &&revokeCallback);
protected:
void prepare() override;
void mouseMoveEvent(QMouseEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
@ -319,11 +311,10 @@ private:
int _rowHeight = 0;
int _revokeWidth = 0;
ChildWidget<Ui::FlatLabel> _aboutRevoke;
ChildWidget<Ui::RoundButton> _cancel;
object_ptr<Ui::FlatLabel> _aboutRevoke;
base::lambda<void()> _revokeCallback;
mtpRequestId _revokeRequestId = 0;
QPointer<ConfirmBox> weakRevokeConfirmBox;
QPointer<ConfirmBox> _weakRevokeConfirmBox;
};

View File

@ -30,32 +30,27 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "ui/widgets/buttons.h"
#include "styles/style_boxes.h"
AutoLockBox::AutoLockBox() : _close(this, lang(lng_box_ok), st::defaultBoxButton) {
setTitleText(lang(lng_passcode_autolock));
void AutoLockBox::prepare() {
setTitle(lang(lng_passcode_autolock));
bool haveTestLang = (cLang() == languageTest);
addButton(lang(lng_box_ok), [this] { closeBox(); });
int32 opts[] = { 60, 300, 3600, 18000 }, cnt = sizeof(opts) / sizeof(opts[0]);
resizeMaxHeight(st::langsWidth, titleHeight() + cnt * (st::boxOptionListPadding.top() + st::langsButton.height) + st::boxOptionListPadding.bottom() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _close->height() + st::boxButtonPadding.bottom());
int32 y = titleHeight() + st::boxOptionListPadding.top();
int opts[] = { 60, 300, 3600, 18000 }, cnt = sizeof(opts) / sizeof(opts[0]);
auto y = st::boxOptionListPadding.top();
_options.reserve(cnt);
for (int32 i = 0; i < cnt; ++i) {
int32 v = opts[i];
for (auto i = 0; i != cnt; ++i) {
auto v = opts[i];
_options.push_back(new Ui::Radiobutton(this, qsl("autolock"), v, (v % 3600) ? lng_passcode_autolock_minutes(lt_count, v / 60) : lng_passcode_autolock_hours(lt_count, v / 3600), (Global::AutoLock() == v), st::langsButton));
_options.back()->move(st::boxPadding.left() + st::boxOptionListPadding.left(), y);
y += _options.back()->heightNoMargins() + st::boxOptionListPadding.top();
y += _options.back()->heightNoMargins() + st::boxOptionListSkip;
connect(_options.back(), SIGNAL(changed()), this, SLOT(onChange()));
}
connect(_close, SIGNAL(clicked()), this, SLOT(onClose()));
_close->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _close->height());
setDimensions(st::langsWidth, st::boxOptionListPadding.top() + cnt * st::langsButton.height + (cnt - 1) * st::boxOptionListSkip + st::boxOptionListPadding.bottom() + st::boxPadding.bottom());
}
void AutoLockBox::onChange() {
if (isHidden()) return;
if (!isBoxShown()) return;
for (int32 i = 0, l = _options.size(); i < l; ++i) {
int32 v = _options[i]->val();
@ -66,5 +61,5 @@ void AutoLockBox::onChange() {
}
}
App::wnd()->checkAutoLock();
onClose();
closeBox();
}

View File

@ -24,20 +24,22 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Ui {
class Radiobutton;
class RoundButton;
} // namespace Ui
class AutoLockBox : public AbstractBox {
class AutoLockBox : public BoxContent {
Q_OBJECT
public:
AutoLockBox();
AutoLockBox(QWidget*) {
}
public slots:
protected:
void prepare() override;
private slots:
void onChange();
private:
QVector<Ui::Radiobutton*> _options;
ChildWidget<Ui::RoundButton> _close;
};

View File

@ -29,25 +29,29 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "styles/style_boxes.h"
#include "ui/effects/round_checkbox.h"
BackgroundBox::BackgroundBox() : ItemListBox(st::backgroundScroll)
, _inner(this) {
init(_inner);
setTitleText(lang(lng_backgrounds_header));
connect(_inner, SIGNAL(backgroundChosen(int)), this, SLOT(onBackgroundChosen(int)));
raiseShadow();
BackgroundBox::BackgroundBox(QWidget*) {
}
void BackgroundBox::onBackgroundChosen(int index) {
void BackgroundBox::prepare() {
setTitle(lang(lng_backgrounds_header));
addButton(lang(lng_close), [this] { closeBox(); });
setDimensions(st::boxWideWidth, st::boxMaxListHeight);
_inner = setInnerWidget(object_ptr<Inner>(this), st::backgroundScroll);
_inner->setBackgroundChosenCallback([this](int index) { backgroundChosen(index); });
}
void BackgroundBox::backgroundChosen(int index) {
if (index >= 0 && index < App::cServerBackgrounds().size()) {
const App::WallPaper &paper(App::cServerBackgrounds().at(index));
auto &paper = App::cServerBackgrounds()[index];
if (App::main()) App::main()->setChatBackground(paper);
using Update = Window::Theme::BackgroundUpdate;
Window::Theme::Background()->notify(Update(Update::Type::Start, !paper.id));
}
onClose();
closeBox();
}
BackgroundBox::Inner::Inner(QWidget *parent) : TWidget(parent)
@ -163,8 +167,8 @@ void BackgroundBox::Inner::paintEvent(QPaintEvent *e) {
}
}
} else {
p.setFont(st::noContactsFont->f);
p.setPen(st::noContactsColor->p);
p.setFont(st::noContactsFont);
p.setPen(st::noContactsColor);
p.drawText(QRect(0, 0, width(), st::noContactsHeight), lang(lng_contacts_loading), style::al_center);
}
}
@ -191,7 +195,9 @@ void BackgroundBox::Inner::mousePressEvent(QMouseEvent *e) {
void BackgroundBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
if (_overDown == _over && _over >= 0) {
emit backgroundChosen(_over);
if (_backgroundChosenCallback) {
_backgroundChosenCallback(_over);
}
} else if (_over < 0) {
setCursor(style::cur_default);
}

View File

@ -26,31 +26,31 @@ namespace Ui {
class RoundCheckbox;
} // namespace Ui
class BackgroundBox : public ItemListBox {
Q_OBJECT
class BackgroundBox : public BoxContent {
public:
BackgroundBox();
BackgroundBox(QWidget*);
public slots:
void onBackgroundChosen(int index);
protected:
void prepare() override;
private:
void backgroundChosen(int index);
class Inner;
ChildWidget<Inner> _inner;
QPointer<Inner> _inner;
};
// This class is hold in header because it requires Qt preprocessing.
class BackgroundBox::Inner : public TWidget, public RPCSender, private base::Subscriber {
Q_OBJECT
public:
Inner(QWidget *parent);
~Inner();
signals:
void backgroundChosen(int index);
void setBackgroundChosenCallback(base::lambda<void(int index)> &&callback) {
_backgroundChosenCallback = std_::move(callback);
}
~Inner();
protected:
void paintEvent(QPaintEvent *e) override;
@ -62,10 +62,12 @@ private:
void gotWallpapers(const MTPVector<MTPWallPaper> &result);
void updateWallpapers();
base::lambda<void(int index)> _backgroundChosenCallback;
int _bgCount = 0;
int _rows = 0;
int _over = -1;
int _overDown = -1;
std_::unique_ptr<Ui::RoundCheckbox> _check;
std_::unique_ptr<Ui::RoundCheckbox> _check; // this not a widget
};

View File

@ -24,16 +24,10 @@ using "ui/widgets/widgets.style";
using "intro/intro.style";
boxDuration: 200;
boxRadius: 3px;
boxButtonFont: font(boxFontSize semibold);
defaultBoxButton: RoundButton {
textFg: #2f9fea;
textFgOver: #2f9fea;
secondaryTextFg: #2f9fea;
secondaryTextFgOver: #2f9fea;
textBg: boxBg;
textBgOver: lightButtonBgOver;
defaultBoxButton: RoundButton(defaultLightButton) {
width: -24px;
height: 36px;
padding: margins(0px, 0px, 0px, 0px);
@ -47,9 +41,7 @@ defaultBoxButton: RoundButton {
}
}
cancelBoxButton: RoundButton(defaultBoxButton) {
textFg: #aeaeae;
}
cancelBoxButton: defaultBoxButton;
attentionBoxButton: RoundButton(defaultBoxButton) {
textFg: attentionButtonFg;
@ -67,22 +59,40 @@ defaultBoxCheckbox: Checkbox(defaultCheckbox) {
font: boxTextFont;
}
boxBlockTitleHeight: 48px;
boxBlockTitlePosition: point(18px, 14px);
boxBlockTitleFont: font(boxFontSize semibold);
boxBlockTitleAdditionalSkip: 6px;
boxBlockTitleAdditionalFont: normalFont;
boxBlockTitleShadow: icon {{ "box_title_shadow", windowShadowFg }};
boxRoundShadow: Shadow {
left: icon {{ "round_shadow_box_left", windowShadowFg }};
topLeft: icon {{ "round_shadow_box_top_left", windowShadowFg }};
top: icon {{ "round_shadow_box_top", windowShadowFg }};
topRight: icon {{ "round_shadow_box_top_left-flip_horizontal", windowShadowFg }};
right: icon {{ "round_shadow_box_left-flip_horizontal", windowShadowFg }};
bottomRight: icon {{ "round_shadow_box_bottom_left-flip_horizontal", windowShadowFg }};
bottom: icon {{ "round_shadow_box_bottom", windowShadowFg }};
bottomLeft: icon {{ "round_shadow_box_bottom_left", windowShadowFg }};
extend: margins(10px, 10px, 10px, 10px);
fallback: windowShadowFgFallback;
}
boxBlockTitleClose: IconButton(defaultIconButton) {
width: boxBlockTitleHeight;
height: boxBlockTitleHeight;
boxTitleFont: font(17px semibold);
boxTitlePosition: point(23px, 20px);
boxTitleHeight: 56px;
boxLayerTitlePosition: point(23px, 16px);
boxLayerTitleHeight: 56px;
boxLayerTitleAdditionalSkip: 9px;
boxLayerTitleAdditionalFont: normalFont;
boxLayerTitleShadow: #0000001a;
boxLayerScroll: defaultSolidScroll;
icon: boxBlockTitleCloseIcon;
iconOver: boxBlockTitleCloseIconOver;
boxTopMargin: 6px;
boxTitleClose: IconButton(defaultIconButton) {
width: boxTitleHeight;
height: boxTitleHeight;
icon: boxTitleCloseIcon;
iconOver: boxTitleCloseIconOver;
rippleAreaPosition: point(4px, 4px);
rippleAreaSize: 40px;
rippleAreaSize: 48px;
ripple: RippleAnimation(defaultRippleAnimation) {
color: windowBgOver;
}
@ -96,34 +106,25 @@ boxLinkButton: LinkButton {
overFont: font(boxFontSize underline);
}
boxOptionListPadding: margins(2px, 20px, 2px, 2px);
boxOptionListPadding: margins(0px, 0px, 0px, 0px);
boxOptionListSkip: 20px;
boxOptionInputSkip: 6px;
boxVerticalMargin: 10px;
boxWidth: 320px;
boxWideWidth: 364px;
boxPadding: margins(26px, 30px, 34px, 8px);
boxPadding: margins(23px, 30px, 23px, 8px);
boxMaxListHeight: 600px;
boxLittleSkip: 10px;
boxMediumSkip: 20px;
boxTitleFont: font(boxFontSize bold);
boxTitlePosition: point(26px, 28px);
boxTitleHeight: 54px;
boxButtonPadding: margins(12px, 16px, 22px, 16px);
boxButtonPadding: margins(8px, 12px, 13px, 12px);
boxLayerButtonPadding: margins(8px, 8px, 8px, 8px);
boxLabel: FlatLabel(defaultFlatLabel) {
font: font(boxFontSize);
align: align(topleft);
}
boxScroll: defaultSolidScroll;
boxScrollSkip: 6px;
boxScrollShadowBg: #00000012;
boxShadow: icon {{ "box_shadow", windowShadowFg }};
boxShadowShift: 2px;
countryRowHeight: 36px;
countryRowNameFont: semiboldFont;
countryRowNameFg: boxTextFg;
@ -134,7 +135,7 @@ countryRowBgOver: windowBgOver;
countryRowCodeFg: windowSubTextFg;
countryRowCodeFgOver: windowSubTextFgOver;
countriesSkip: 12px;
countriesScroll: FlatScroll(boxScroll) {
countriesScroll: ScrollArea(boxLayerScroll) {
deltat: 9px;
deltab: 3px;
}
@ -145,7 +146,7 @@ boxTextStyle: TextStyle(defaultTextStyle) {
boxPhotoTitleFont: font(16px semibold);
boxPhotoTitlePosition: point(28px, 26px);
boxPhotoPadding: margins(28px, 28px, 28px, 0px);
boxPhotoPadding: margins(28px, 28px, 28px, 18px);
boxPhotoCompressedSkip: 20px;
boxPhotoCaptionSkip: 8px;
boxPhotoTextFg: #808080;
@ -223,7 +224,7 @@ contactsAdd: TwoIconButton {
}
contactsAddPosition: point(14px, 8px);
contactPadding: margins(49px, 2px, 0px, 6px);
contactPadding: margins(49px, 2px, 0px, 12px);
contactSkip: 6px;
contactPhoneSkip: 30px;
@ -240,15 +241,12 @@ contactsAboutFg: windowSubTextFgOver;
contactsAboutShadow: #0000001F;
contactsAboutTop: 60px;
contactsAboutBottom: 19px;
contactsScroll: FlatScroll(boxScroll) {
deltab: 0px;
}
contactsMultiSelect: MultiSelect {
bg: boxSearchBg;
padding: margins(8px, 8px, 8px, 8px);
padding: margins(8px, 6px, 8px, 6px);
maxHeight: 104px;
scroll: FlatScroll(defaultSolidScroll) {
scroll: ScrollArea(defaultSolidScroll) {
deltat: 3px;
deltab: 3px;
round: 1px;
@ -302,17 +300,17 @@ contactsMultiSelect: MultiSelect {
fieldIconSkip: 36px;
fieldCancel: CrossButton {
width: boxBlockTitleHeight;
height: boxBlockTitleHeight;
width: 44px;
height: 44px;
cross: CrossAnimation {
size: 40px;
skip: 14px;
size: 36px;
skip: 12px;
stroke: 2px;
minScale: 0.3;
}
crossFg: boxBlockTitleCloseFg;
crossFgOver: boxBlockTitleCloseFgOver;
crossFg: boxTitleCloseFg;
crossFgOver: boxTitleCloseFgOver;
crossPosition: point(4px, 4px);
duration: 150;
@ -338,6 +336,11 @@ contactsPhotoDisabledCheckFg: #bbbbbb;
contactsNameCheckedFg: #2b88b8;
contactsRipple: defaultRippleAnimation;
contactsMarginTop: 4px;
contactsMarginBottom: 4px;
membersMarginTop: 10px;
membersMarginBottom: 10px;
localStorageBoxSkip: 10px;
shareRowsTop: 12px;
@ -355,7 +358,7 @@ shareColumnSkip: 6px;
shareActivateDuration: 150;
shareScrollDuration: 300;
notificationsBoxHeight: 450px;
notificationsBoxHeight: 420px;
notificationsBoxMonitorTop: 63px;
notificationsBoxMonitor: icon {{ "monitor", notificationsBoxMonitorFg }};
notificationsBoxScreenTop: 10px;
@ -374,8 +377,8 @@ notificationSampleSize: size(64px, 16px);
membersAboutLimitPadding: margins(0px, 12px, 0px, 12px);
sessionsScroll: boxScroll;
sessionsHeight: 440px;
sessionsScroll: boxLayerScroll;
sessionsHeight: 350px;
sessionHeight: 70px;
sessionCurrentPadding: margins(0px, 7px, 0px, 4px);
sessionCurrentHeight: 118px;
@ -417,9 +420,10 @@ passcodeSubmit: RoundButton(introNextButton) {
width: 225px;
}
passcodeSubmitSkip: 40px;
passcodePadding: margins(0px, 6px, 0px, 13px);
passcodePadding: margins(0px, 0px, 0px, 12px);
passcodeTextLine: 28px;
passcodeSkip: 21px;
passcodeLittleSkip: 5px;
passcodeSkip: 20px;
newGroupAboutFg: #808080;
newGroupPadding: margins(4px, 6px, 4px, 3px);
@ -453,8 +457,6 @@ newGroupLinkFadeDuration: 5000;
themeWarningWidth: boxWideWidth;
themeWarningHeight: 150px;
themeWarningShadow: boxShadow;
themeWarningShadowShift: boxShadowShift;
themeWarningTextTop: 60px;
aboutWidth: 390px;
@ -475,6 +477,9 @@ aboutTextStyle: TextStyle(defaultTextStyle) {
lineHeight: 22px;
}
autoDownloadTitlePosition: point(23px, 28px);
autoDownloadTitleFont: font(15px semibold);
editTextArea: InputField(defaultInputField) {
textMargins: margins(1px, 26px, 1px, 4px);
heightMax: 276px;
@ -509,9 +514,11 @@ langsButton: Checkbox(defaultBoxCheckbox) {
backgroundPadding: 10px;
backgroundSize: size(108px, 193px);
backgroundScroll: FlatScroll(boxScroll) {
backgroundScroll: ScrollArea(boxLayerScroll) {
deltax: 3px;
width: 10px;
deltat: 10px;
deltab: 0px;
deltab: 10px;
}
usernamePadding: margins(23px, 6px, 21px, 12px);

View File

@ -30,6 +30,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "ui/widgets/checkbox.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/labels.h"
#include "ui/toast/toast.h"
#include "core/click_handler_types.h"
#include "localstorage.h"
@ -40,54 +41,103 @@ TextParseOptions _confirmBoxTextOptions = {
Qt::LayoutDirectionAuto, // dir
};
ConfirmBox::ConfirmBox(const QString &text, const QString &doneText, const style::RoundButton &doneStyle, const QString &cancelText, const style::RoundButton &cancelStyle) : AbstractBox(st::boxWidth)
, _informative(false)
, _text(100)
, _confirm(this, doneText.isEmpty() ? lang(lng_box_ok) : doneText, doneStyle)
, _cancel(this, cancelText.isEmpty() ? lang(lng_cancel) : cancelText, cancelStyle) {
ConfirmBox::ConfirmBox(QWidget*, const QString &text, base::lambda<void()> &&confirmedCallback, base::lambda<void()> &&cancelledCallback)
: _confirmText(lang(lng_box_ok))
, _cancelText(lang(lng_cancel))
, _confirmStyle(st::defaultBoxButton)
, _text(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right())
, _confirmedCallback(std_::move(confirmedCallback))
, _cancelledCallback(std_::move(cancelledCallback)) {
init(text);
}
ConfirmBox::ConfirmBox(const QString &text, const QString &doneText, const style::RoundButton &doneStyle, bool informative) : AbstractBox(st::boxWidth)
ConfirmBox::ConfirmBox(QWidget*, const QString &text, const QString &confirmText, base::lambda<void()> &&confirmedCallback, base::lambda<void()> &&cancelledCallback)
: _confirmText(confirmText)
, _cancelText(lang(lng_cancel))
, _confirmStyle(st::defaultBoxButton)
, _text(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right())
, _confirmedCallback(std_::move(confirmedCallback))
, _cancelledCallback(std_::move(cancelledCallback)) {
init(text);
}
ConfirmBox::ConfirmBox(QWidget*, const QString &text, const QString &confirmText, const style::RoundButton &confirmStyle, base::lambda<void()> &&confirmedCallback, base::lambda<void()> &&cancelledCallback)
: _confirmText(confirmText)
, _cancelText(lang(lng_cancel))
, _confirmStyle(confirmStyle)
, _text(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right())
, _confirmedCallback(std_::move(confirmedCallback))
, _cancelledCallback(std_::move(cancelledCallback)) {
init(text);
}
ConfirmBox::ConfirmBox(QWidget*, const QString &text, const QString &confirmText, const QString &cancelText, base::lambda<void()> &&confirmedCallback, base::lambda<void()> &&cancelledCallback)
: _confirmText(confirmText)
, _cancelText(cancelText)
, _confirmStyle(st::defaultBoxButton)
, _text(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right())
, _confirmedCallback(std_::move(confirmedCallback))
, _cancelledCallback(std_::move(cancelledCallback)) {
init(text);
}
ConfirmBox::ConfirmBox(QWidget*, const QString &text, const QString &confirmText, const style::RoundButton &confirmStyle, const QString &cancelText, base::lambda<void()> &&confirmedCallback, base::lambda<void()> &&cancelledCallback)
: _confirmText(confirmText)
, _cancelText(cancelText)
, _confirmStyle(st::defaultBoxButton)
, _text(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right())
, _confirmedCallback(std_::move(confirmedCallback))
, _cancelledCallback(std_::move(cancelledCallback)) {
init(text);
}
ConfirmBox::ConfirmBox(const InformBoxTag &, const QString &text, const QString &doneText, base::lambda_copy<void()> &&closedCallback)
: _confirmText(doneText)
, _confirmStyle(st::defaultBoxButton)
, _informative(true)
, _text(100)
, _confirm(this, doneText.isEmpty() ? lang(lng_box_ok) : doneText, doneStyle)
, _cancel(this, QString(), st::cancelBoxButton) {
, _text(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right())
, _confirmedCallback(base::lambda_copy<void()>(closedCallback))
, _cancelledCallback(base::lambda_copy<void()>(closedCallback)) {
init(text);
}
void ConfirmBox::init(const QString &text) {
textstyleSet(&st::boxTextStyle);
_text.setText(st::boxTextFont, text, _informative ? _confirmBoxTextOptions : _textPlainOptions);
connect(_confirm, SIGNAL(clicked()), this, SLOT(onConfirmPressed()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onCancel()));
if (_informative) {
_cancel->hide();
connect(this, SIGNAL(confirmed()), this, SLOT(onCancel()));
}
onTextUpdated();
textstyleRestore();
}
void ConfirmBox::onConfirmPressed() {
if (_confirmedCallback) {
_confirmedCallback();
void ConfirmBox::prepare() {
addButton(_confirmText, [this] { confirmed(); }, _confirmStyle);
if (!_informative) {
addButton(_cancelText, [this] { _cancelled = true; closeBox(); });
}
emit confirmed();
textUpdated();
}
void ConfirmBox::onTextUpdated() {
void ConfirmBox::textUpdated() {
textstyleSet(&st::boxTextStyle);
_textWidth = st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right();
_textHeight = qMin(_text.countHeight(_textWidth), 16 * int(st::boxTextStyle.lineHeight));
setMaxHeight(st::boxPadding.top() + _textHeight + st::boxPadding.bottom() + st::boxButtonPadding.top() + _confirm->height() + st::boxButtonPadding.bottom());
setDimensions(st::boxWidth, st::boxPadding.top() + _textHeight + st::boxPadding.bottom());
textstyleRestore();
setMouseTracking(_text.hasLinks());
}
void ConfirmBox::onCancel() {
emit cancelPressed();
onClose();
void ConfirmBox::closeHook() {
if (!_confirmed && (!_strictCancel || _cancelled) && _cancelledCallback) {
_cancelledCallback();
}
}
void ConfirmBox::confirmed() {
if (!_confirmed) {
_confirmed = true;
if (_confirmedCallback) {
_confirmedCallback();
}
}
}
void ConfirmBox::mouseMoveEvent(QMouseEvent *e) {
@ -99,7 +149,7 @@ void ConfirmBox::mousePressEvent(QMouseEvent *e) {
_lastMousePos = e->globalPos();
updateHover();
ClickHandler::pressed();
return LayerWidget::mousePressEvent(e);
return BoxContent::mousePressEvent(e);
}
void ConfirmBox::mouseReleaseEvent(QMouseEvent *e) {
@ -109,6 +159,7 @@ void ConfirmBox::mouseReleaseEvent(QMouseEvent *e) {
Ui::hideLayer();
App::activateClickHandler(activated, e->button());
}
return BoxContent::mouseReleaseEvent(e);
}
void ConfirmBox::leaveEvent(QEvent *e) {
@ -139,20 +190,16 @@ void ConfirmBox::updateHover() {
ClickHandler::setActive(state.link, this);
}
void ConfirmBox::closePressed() {
emit cancelled();
}
void ConfirmBox::keyPressEvent(QKeyEvent *e) {
if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
onConfirmPressed();
confirmed();
} else {
AbstractBox::keyPressEvent(e);
BoxContent::keyPressEvent(e);
}
}
void ConfirmBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e);
BoxContent::paintEvent(e);
Painter p(this);
@ -163,55 +210,19 @@ void ConfirmBox::paintEvent(QPaintEvent *e) {
textstyleRestore();
}
void ConfirmBox::resizeEvent(QResizeEvent *e) {
_confirm->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _confirm->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _confirm->width() + st::boxButtonPadding.left(), _confirm->y());
AbstractBox::resizeEvent(e);
}
SharePhoneConfirmBox::SharePhoneConfirmBox(PeerData *recipient)
: ConfirmBox(lang(lng_bot_share_phone), lang(lng_bot_share_phone_confirm))
, _recipient(recipient) {
connect(this, SIGNAL(confirmed()), this, SLOT(onConfirm()));
}
void SharePhoneConfirmBox::onConfirm() {
emit confirmed(_recipient);
}
ConfirmLinkBox::ConfirmLinkBox(const QString &url) : ConfirmBox(lang(lng_open_this_link) + qsl("\n\n") + url, lang(lng_open_link))
, _url(url) {
connect(this, SIGNAL(confirmed()), this, SLOT(onOpenLink()));
}
void ConfirmLinkBox::onOpenLink() {
Ui::hideLayer();
UrlClickHandler::doOpen(_url);
}
ConfirmBotGameBox::ConfirmBotGameBox(UserData *bot, const QString &url) : ConfirmBox(lng_allow_bot_pass(lt_bot_name, bot->name), lang(lng_allow_bot))
, _bot(bot)
, _url(url) {
connect(this, SIGNAL(confirmed()), this, SLOT(onOpenLink()));
}
void ConfirmBotGameBox::onOpenLink() {
Ui::hideLayer();
Local::makeBotTrusted(_bot);
UrlClickHandler::doOpen(_url);
}
MaxInviteBox::MaxInviteBox(const QString &link) : AbstractBox(st::boxWidth)
, _close(this, lang(lng_box_ok), st::defaultBoxButton)
, _text(st::boxTextFont, lng_participant_invite_sorry(lt_count, Global::ChatSizeMax()), _confirmBoxTextOptions, st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right())
MaxInviteBox::MaxInviteBox(QWidget*, const QString &link)
: _text(st::boxTextFont, lng_participant_invite_sorry(lt_count, Global::ChatSizeMax()), _confirmBoxTextOptions, st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right())
, _link(link) {
}
void MaxInviteBox::prepare() {
setMouseTracking(true);
addButton(lang(lng_box_ok), [this] { closeBox(); });
_textWidth = st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right();
_textHeight = qMin(_text.countHeight(_textWidth), 16 * int(st::boxTextStyle.lineHeight));
setMaxHeight(st::boxPadding.top() + _textHeight + st::boxTextFont->height + st::boxTextFont->height * 2 + st::newGroupLinkPadding.bottom() + st::boxButtonPadding.top() + _close->height() + st::boxButtonPadding.bottom());
connect(_close, SIGNAL(clicked()), this, SLOT(onClose()));
setDimensions(st::boxWidth, st::boxPadding.top() + _textHeight + st::boxTextFont->height + st::boxTextFont->height * 2 + st::newGroupLinkPadding.bottom());
}
void MaxInviteBox::mouseMoveEvent(QMouseEvent *e) {
@ -222,9 +233,10 @@ void MaxInviteBox::mousePressEvent(QMouseEvent *e) {
mouseMoveEvent(e);
if (_linkOver) {
Application::clipboard()->setText(_link);
_goodTextLink = lang(lng_create_channel_link_copied);
_a_goodOpacity.finish();
_a_goodOpacity.start([this] { update(); }, 1., 0., st::newGroupLinkFadeDuration);
Ui::Toast::Config toast;
toast.text = lang(lng_create_channel_link_copied);
Ui::Toast::Show(App::wnd(), toast);
}
}
@ -244,7 +256,7 @@ void MaxInviteBox::updateSelected(const QPoint &cursorGlobalPosition) {
}
void MaxInviteBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e);
BoxContent::paintEvent(e);
Painter p(this);
@ -257,49 +269,41 @@ void MaxInviteBox::paintEvent(QPaintEvent *e) {
p.setFont(_linkOver ? st::defaultInputField.font->underline() : st::defaultInputField.font);
p.setPen(st::defaultLinkButton.color);
p.drawText(_invitationLink, _link, option);
if (!_goodTextLink.isEmpty()) {
auto opacity = _a_goodOpacity.current(getms(), 0.);
if (opacity > 0.) {
p.setOpacity(opacity);
p.setPen(st::boxTextFgGood);
p.setFont(st::boxTextFont);
p.drawTextLeft(st::boxPadding.left(), height() - st::boxButtonPadding.bottom() - _close->height() + st::defaultBoxButton.textTop + st::defaultBoxButton.font->ascent - st::boxTextFont->ascent, width(), _goodTextLink);
p.setOpacity(1);
}
}
}
void MaxInviteBox::resizeEvent(QResizeEvent *e) {
_close->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _close->height());
BoxContent::resizeEvent(e);
_invitationLink = myrtlrect(st::boxPadding.left(), st::boxPadding.top() + _textHeight + st::boxTextFont->height, width() - st::boxPadding.left() - st::boxPadding.right(), 2 * st::boxTextFont->height);
AbstractBox::resizeEvent(e);
}
ConvertToSupergroupBox::ConvertToSupergroupBox(ChatData *chat) : AbstractBox(st::boxWideWidth, lang(lng_profile_convert_title))
, _chat(chat)
ConvertToSupergroupBox::ConvertToSupergroupBox(QWidget*, ChatData *chat)
: _chat(chat)
, _text(100)
, _note(100)
, _convert(this, lang(lng_profile_convert_confirm), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
, _note(100) {
}
void ConvertToSupergroupBox::prepare() {
QStringList text;
text.push_back(lang(lng_profile_convert_feature1));
text.push_back(lang(lng_profile_convert_feature2));
text.push_back(lang(lng_profile_convert_feature3));
text.push_back(lang(lng_profile_convert_feature4));
setTitle(lang(lng_profile_convert_title));
addButton(lang(lng_profile_convert_confirm), [this] { convertToSupergroup(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
textstyleSet(&st::boxTextStyle);
_text.setText(st::boxTextFont, text.join('\n'), _confirmBoxTextOptions);
_note.setText(st::boxTextFont, lng_profile_convert_warning(lt_bold_start, textcmdStartSemibold(), lt_bold_end, textcmdStopSemibold()), _confirmBoxTextOptions);
_textWidth = st::boxWideWidth - st::boxPadding.left() - st::boxButtonPadding.right();
_textHeight = _text.countHeight(_textWidth);
setMaxHeight(titleHeight() + _textHeight + st::boxPadding.bottom() + _note.countHeight(_textWidth) + st::boxButtonPadding.top() + _convert->height() + st::boxButtonPadding.bottom());
setDimensions(st::boxWideWidth, _textHeight + st::boxPadding.bottom() + _note.countHeight(_textWidth));
textstyleRestore();
connect(_convert, SIGNAL(clicked()), this, SLOT(onConvert()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
}
void ConvertToSupergroupBox::onConvert() {
void ConvertToSupergroupBox::convertToSupergroup() {
MTP::send(MTPmessages_MigrateChat(_chat->inputChat), rpcDone(&ConvertToSupergroupBox::convertDone), rpcFail(&ConvertToSupergroupBox::convertFail));
}
@ -336,54 +340,48 @@ bool ConvertToSupergroupBox::convertFail(const RPCError &error) {
void ConvertToSupergroupBox::keyPressEvent(QKeyEvent *e) {
if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
onConvert();
convertToSupergroup();
} else {
AbstractBox::keyPressEvent(e);
BoxContent::keyPressEvent(e);
}
}
void ConvertToSupergroupBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e);
BoxContent::paintEvent(e);
Painter p(this);
// draw box title / text
p.setPen(st::boxTextFg);
textstyleSet(&st::boxTextStyle);
_text.drawLeft(p, st::boxPadding.left(), titleHeight(), _textWidth, width());
_note.drawLeft(p, st::boxPadding.left(), titleHeight() + _textHeight + st::boxPadding.bottom(), _textWidth, width());
_text.drawLeft(p, st::boxPadding.left(), 0, _textWidth, width());
_note.drawLeft(p, st::boxPadding.left(), _textHeight + st::boxPadding.bottom(), _textWidth, width());
textstyleRestore();
}
void ConvertToSupergroupBox::resizeEvent(QResizeEvent *e) {
_convert->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _convert->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _convert->width() + st::boxButtonPadding.left(), _convert->y());
AbstractBox::resizeEvent(e);
}
PinMessageBox::PinMessageBox(ChannelData *channel, MsgId msgId) : AbstractBox(st::boxWidth)
, _channel(channel)
PinMessageBox::PinMessageBox(QWidget*, ChannelData *channel, MsgId msgId)
: _channel(channel)
, _msgId(msgId)
, _text(this, lang(lng_pinned_pin_sure), Ui::FlatLabel::InitType::Simple, st::boxLabel)
, _notify(this, lang(lng_pinned_notify), true, st::defaultBoxCheckbox)
, _pin(this, lang(lng_pinned_pin), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
_text->resizeToWidth(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right());
setMaxHeight(st::boxPadding.top() + _text->height() + st::boxMediumSkip + _notify->heightNoMargins() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _pin->height() + st::boxButtonPadding.bottom());
, _notify(this, lang(lng_pinned_notify), true, st::defaultBoxCheckbox) {
}
connect(_pin, SIGNAL(clicked()), this, SLOT(onPin()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
void PinMessageBox::prepare() {
_text->resizeToWidth(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right());
addButton(lang(lng_pinned_pin), [this] { pinMessage(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
setDimensions(st::boxWidth, st::boxPadding.top() + _text->height() + st::boxMediumSkip + _notify->heightNoMargins() + st::boxPadding.bottom());
}
void PinMessageBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e);
_text->moveToLeft(st::boxPadding.left(), st::boxPadding.top());
_notify->moveToLeft(st::boxPadding.left(), _text->y() + _text->height() + st::boxMediumSkip);
_pin->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _pin->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _pin->width() + st::boxButtonPadding.left(), _pin->y());
AbstractBox::resizeEvent(e);
}
void PinMessageBox::onPin() {
void PinMessageBox::pinMessage() {
if (_requestId) return;
MTPchannels_UpdatePinnedMessage::Flags flags = 0;
@ -406,36 +404,35 @@ bool PinMessageBox::pinFail(const RPCError &error) {
return true;
}
RichDeleteMessageBox::RichDeleteMessageBox(ChannelData *channel, UserData *from, MsgId msgId) : AbstractBox(st::boxWidth)
, _channel(channel)
RichDeleteMessageBox::RichDeleteMessageBox(QWidget*, ChannelData *channel, UserData *from, MsgId msgId)
: _channel(channel)
, _from(from)
, _msgId(msgId)
, _text(this, lang(lng_selected_delete_sure_this), Ui::FlatLabel::InitType::Simple, st::boxLabel)
, _banUser(this, lang(lng_ban_user), false, st::defaultBoxCheckbox)
, _reportSpam(this, lang(lng_report_spam), false, st::defaultBoxCheckbox)
, _deleteAll(this, lang(lng_delete_all_from), false, st::defaultBoxCheckbox)
, _delete(this, lang(lng_box_delete), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
, _deleteAll(this, lang(lng_delete_all_from), false, st::defaultBoxCheckbox) {
}
void RichDeleteMessageBox::prepare() {
t_assert(_channel != nullptr);
_text->resizeToWidth(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right());
setMaxHeight(st::boxPadding.top() + _text->height() + st::boxMediumSkip + _banUser->heightNoMargins() + st::boxLittleSkip + _reportSpam->heightNoMargins() + st::boxLittleSkip + _deleteAll->heightNoMargins() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _delete->height() + st::boxButtonPadding.bottom());
addButton(lang(lng_box_delete), [this] { deleteAndClear(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
connect(_delete, SIGNAL(clicked()), this, SLOT(onDelete()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
_text->resizeToWidth(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right());
setDimensions(st::boxWidth, st::boxPadding.top() + _text->height() + st::boxMediumSkip + _banUser->heightNoMargins() + st::boxLittleSkip + _reportSpam->heightNoMargins() + st::boxLittleSkip + _deleteAll->heightNoMargins() + st::boxPadding.bottom());
}
void RichDeleteMessageBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e);
_text->moveToLeft(st::boxPadding.left(), st::boxPadding.top());
_banUser->moveToLeft(st::boxPadding.left(), _text->bottomNoMargins() + st::boxMediumSkip);
_reportSpam->moveToLeft(st::boxPadding.left(), _banUser->bottomNoMargins() + st::boxLittleSkip);
_deleteAll->moveToLeft(st::boxPadding.left(), _reportSpam->bottomNoMargins() + st::boxLittleSkip);
_delete->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _delete->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _delete->width() + st::boxButtonPadding.left(), _delete->y());
AbstractBox::resizeEvent(e);
}
void RichDeleteMessageBox::onDelete() {
void RichDeleteMessageBox::deleteAndClear() {
if (_banUser->checked()) {
MTP::send(MTPchannels_KickFromChannel(_channel->inputChannel, _from->inputUser, MTP_boolTrue()), App::main()->rpcDone(&MainWidget::sentUpdatesReceived));
}
@ -445,7 +442,7 @@ void RichDeleteMessageBox::onDelete() {
if (_deleteAll->checked()) {
App::main()->deleteAllFromUser(_channel, _from);
}
if (HistoryItem *item = App::histItemById(_channel ? peerToChannel(_channel->id) : 0, _msgId)) {
if (auto item = App::histItemById(_channel ? peerToChannel(_channel->id) : 0, _msgId)) {
bool wasLast = (item->history()->lastMsg == item);
item->destroy();
@ -458,33 +455,11 @@ void RichDeleteMessageBox::onDelete() {
Ui::hideLayer();
}
KickMemberBox::KickMemberBox(PeerData *chat, UserData *member)
: ConfirmBox(lng_profile_sure_kick(lt_user, member->firstName), lang(lng_box_remove))
, _chat(chat)
, _member(member) {
connect(this, SIGNAL(confirmed()), this, SLOT(onConfirm()));
}
void KickMemberBox::onConfirm() {
Ui::hideLayer();
if (auto chat = _chat->asChat()) {
App::main()->kickParticipant(chat, _member);
} else if (auto channel = _chat->asChannel()) {
App::api()->kickParticipant(channel, _member);
}
}
ConfirmInviteBox::ConfirmInviteBox(const QString &title, const MTPChatPhoto &photo, int count, const QVector<UserData*> &participants) : AbstractBox()
, _title(this, st::confirmInviteTitle)
ConfirmInviteBox::ConfirmInviteBox(QWidget*, const QString &title, const MTPChatPhoto &photo, int count, const QVector<UserData*> &participants)
: _title(this, st::confirmInviteTitle)
, _status(this, st::confirmInviteStatus)
, _photo(chatDefPhoto(0))
, _participants(participants)
, _join(this, lang(lng_group_invite_join), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
if (_participants.size() > 4) {
_participants.resize(4);
}
, _participants(participants) {
_title->setText(title);
QString status;
if (_participants.isEmpty() || _participants.size() >= count) {
@ -504,8 +479,21 @@ ConfirmInviteBox::ConfirmInviteBox(const QString &title, const MTPChatPhoto &pho
}
}
}
}
int h = st::confirmInviteStatusTop + _status->height() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _join->height() + st::boxButtonPadding.bottom();
void ConfirmInviteBox::prepare() {
addButton(lang(lng_group_invite_join), [this] {
if (auto main = App::main()) {
main->onInviteImport();
}
});
addButton(lang(lng_cancel), [this] { closeBox(); });
if (_participants.size() > 4) {
_participants.resize(4);
}
auto newHeight = st::confirmInviteStatusTop + _status->height() + st::boxPadding.bottom();
if (!_participants.isEmpty()) {
int skip = (width() - 4 * st::confirmInviteUserPhotoSize) / 5;
int padding = skip / 2;
@ -520,24 +508,19 @@ ConfirmInviteBox::ConfirmInviteBox(const QString &title, const MTPChatPhoto &pho
left += _userWidth;
}
h += st::confirmInviteUserHeight;
newHeight += st::confirmInviteUserHeight;
}
setMaxHeight(h);
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
connect(_join, SIGNAL(clicked()), App::main(), SLOT(onInviteImport()));
setDimensions(st::boxWideWidth, newHeight);
}
void ConfirmInviteBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e);
_title->move((width() - _title->width()) / 2, st::confirmInviteTitleTop);
_status->move((width() - _status->width()) / 2, st::confirmInviteStatusTop);
_join->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _join->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _join->width() + st::boxButtonPadding.left(), _join->y());
AbstractBox::resizeEvent(e);
}
void ConfirmInviteBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e);
BoxContent::paintEvent(e);
Painter p(this);

View File

@ -24,138 +24,88 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Ui {
class Checkbox;
class RoundButton;
class FlatLabel;
} // namespace Ui
namespace st {
extern const style::RoundButton &defaultBoxButton;
extern const style::RoundButton &cancelBoxButton;
} // namespace style
class InformBox;
class ConfirmBox : public AbstractBox, public ClickHandlerHost {
Q_OBJECT
class ConfirmBox : public BoxContent, public ClickHandlerHost {
public:
ConfirmBox(const QString &text, const QString &doneText = QString(), const style::RoundButton &doneStyle = st::defaultBoxButton, const QString &cancelText = QString(), const style::RoundButton &cancelStyle = st::cancelBoxButton);
ConfirmBox(QWidget*, const QString &text, base::lambda<void()> &&confirmedCallback = base::lambda<void()>(), base::lambda<void()> &&cancelledCallback = base::lambda<void()>());
ConfirmBox(QWidget*, const QString &text, const QString &confirmText, base::lambda<void()> &&confirmedCallback = base::lambda<void()>(), base::lambda<void()> &&cancelledCallback = base::lambda<void()>());
ConfirmBox(QWidget*, const QString &text, const QString &confirmText, const style::RoundButton &confirmStyle, base::lambda<void()> &&confirmedCallback = base::lambda<void()>(), base::lambda<void()> &&cancelledCallback = base::lambda<void()>());
ConfirmBox(QWidget*, const QString &text, const QString &confirmText, const QString &cancelText, base::lambda<void()> &&confirmedCallback = base::lambda<void()>(), base::lambda<void()> &&cancelledCallback = base::lambda<void()>());
ConfirmBox(QWidget*, const QString &text, const QString &confirmText, const style::RoundButton &confirmStyle, const QString &cancelText, base::lambda<void()> &&confirmedCallback = base::lambda<void()>(), base::lambda<void()> &&cancelledCallback = base::lambda<void()>());
void updateLink();
// You can use this instead of connecting to "confirmed()" signal.
void setConfirmedCallback(base::lambda<void()> &&callback) {
_confirmedCallback = std_::move(callback);
// If strict cancel is set the cancelledCallback is only called if the cancel button was pressed.
void setStrictCancel(bool strictCancel) {
_strictCancel = strictCancel;
}
// ClickHandlerHost interface
void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override;
void clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) override;
public slots:
void onCancel();
signals:
void confirmed();
void cancelled();
void cancelPressed();
void closeHook() override;
protected:
void prepare() override;
void keyPressEvent(QKeyEvent *e) override;
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
void leaveEvent(QEvent *e) override;
void closePressed() override;
private slots:
void onConfirmPressed();
private:
ConfirmBox(const QString &text, const QString &doneText, const style::RoundButton &doneStyle, bool informative);
struct InformBoxTag {
};
ConfirmBox(const InformBoxTag &, const QString &text, const QString &doneText, base::lambda_copy<void()> &&closedCallback);
friend class InformBox;
void confirmed();
void init(const QString &text);
void onTextUpdated();
void textUpdated();
bool _informative;
QString _confirmText;
QString _cancelText;
const style::RoundButton &_confirmStyle;
bool _informative = false;
Text _text;
int32 _textWidth, _textHeight;
int _textWidth = 0;
int _textHeight = 0;
void updateHover();
QPoint _lastMousePos;
ChildWidget<Ui::RoundButton> _confirm;
ChildWidget<Ui::RoundButton> _cancel;
bool _confirmed = false;
bool _cancelled = false;
bool _strictCancel = false;
base::lambda<void()> _confirmedCallback;
base::lambda<void()> _cancelledCallback;
};
class InformBox : public ConfirmBox {
public:
InformBox(const QString &text, const QString &doneText = QString(), const style::RoundButton &doneStyle = st::defaultBoxButton) : ConfirmBox(text, doneText, doneStyle, true) {
InformBox(QWidget*, const QString &text, base::lambda_copy<void()> &&closedCallback = base::lambda_copy<void()>()) : ConfirmBox(ConfirmBox::InformBoxTag(), text, QString(), std_::move(closedCallback)) {
}
InformBox(QWidget*, const QString &text, const QString &doneText, base::lambda_copy<void()> &&closedCallback = base::lambda_copy<void()>()) : ConfirmBox(ConfirmBox::InformBoxTag(), text, doneText, std_::move(closedCallback)) {
}
};
class SharePhoneConfirmBox : public ConfirmBox {
Q_OBJECT
class MaxInviteBox : public BoxContent {
public:
SharePhoneConfirmBox(PeerData *recipient);
signals:
void confirmed(PeerData *recipient);
private slots:
void onConfirm();
private:
PeerData *_recipient;
};
class ConfirmLinkBox : public ConfirmBox {
Q_OBJECT
public:
ConfirmLinkBox(const QString &url);
public slots:
void onOpenLink();
private:
QString _url;
};
class ConfirmBotGameBox : public ConfirmBox {
Q_OBJECT
public:
ConfirmBotGameBox(UserData *bot, const QString &url);
public slots:
void onOpenLink();
private:
UserData *_bot;
QString _url;
};
class MaxInviteBox : public AbstractBox {
Q_OBJECT
public:
MaxInviteBox(const QString &link);
MaxInviteBox(QWidget*, const QString &link);
protected:
void prepare() override;
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override;
@ -165,8 +115,6 @@ protected:
private:
void updateSelected(const QPoint &cursorGlobalPosition);
ChildWidget<Ui::RoundButton> _close;
Text _text;
int32 _textWidth, _textHeight;
@ -176,26 +124,20 @@ private:
QPoint _lastMousePos;
QString _goodTextLink;
Animation _a_goodOpacity;
};
class ConvertToSupergroupBox : public AbstractBox, public RPCSender {
Q_OBJECT
class ConvertToSupergroupBox : public BoxContent, public RPCSender {
public:
ConvertToSupergroupBox(ChatData *chat);
public slots:
void onConvert();
ConvertToSupergroupBox(QWidget*, ChatData *chat);
protected:
void prepare() override;
void keyPressEvent(QKeyEvent *e) override;
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
private:
void convertToSupergroup();
void convertDone(const MTPUpdates &updates);
bool convertFail(const RPCError &error);
@ -203,100 +145,71 @@ private:
Text _text, _note;
int32 _textWidth, _textHeight;
ChildWidget<Ui::RoundButton> _convert;
ChildWidget<Ui::RoundButton> _cancel;
};
class PinMessageBox : public AbstractBox, public RPCSender {
Q_OBJECT
class PinMessageBox : public BoxContent, public RPCSender {
public:
PinMessageBox(ChannelData *channel, MsgId msgId);
public slots:
void onPin();
PinMessageBox(QWidget*, ChannelData *channel, MsgId msgId);
protected:
void prepare() override;
void resizeEvent(QResizeEvent *e) override;
private:
void pinMessage();
void pinDone(const MTPUpdates &updates);
bool pinFail(const RPCError &error);
ChannelData *_channel;
MsgId _msgId;
ChildWidget<Ui::FlatLabel> _text;
ChildWidget<Ui::Checkbox> _notify;
ChildWidget<Ui::RoundButton> _pin;
ChildWidget<Ui::RoundButton> _cancel;
object_ptr<Ui::FlatLabel> _text;
object_ptr<Ui::Checkbox> _notify;
mtpRequestId _requestId = 0;
};
class RichDeleteMessageBox : public AbstractBox, public RPCSender {
Q_OBJECT
class RichDeleteMessageBox : public BoxContent, public RPCSender {
public:
RichDeleteMessageBox(ChannelData *channel, UserData *from, MsgId msgId);
public slots:
void onDelete();
RichDeleteMessageBox(QWidget*, ChannelData *channel, UserData *from, MsgId msgId);
protected:
void prepare() override;
void resizeEvent(QResizeEvent *e) override;
private:
void deleteAndClear();
ChannelData *_channel;
UserData *_from;
MsgId _msgId;
ChildWidget<Ui::FlatLabel> _text;
ChildWidget<Ui::Checkbox> _banUser;
ChildWidget<Ui::Checkbox> _reportSpam;
ChildWidget<Ui::Checkbox> _deleteAll;
ChildWidget<Ui::RoundButton> _delete;
ChildWidget<Ui::RoundButton> _cancel;
object_ptr<Ui::FlatLabel> _text;
object_ptr<Ui::Checkbox> _banUser;
object_ptr<Ui::Checkbox> _reportSpam;
object_ptr<Ui::Checkbox> _deleteAll;
};
class KickMemberBox : public ConfirmBox {
Q_OBJECT
class ConfirmInviteBox : public BoxContent, public RPCSender {
public:
KickMemberBox(PeerData *chat, UserData *member);
private slots:
void onConfirm();
private:
PeerData *_chat;
UserData *_member;
};
class ConfirmInviteBox : public AbstractBox, public RPCSender {
Q_OBJECT
public:
ConfirmInviteBox(const QString &title, const MTPChatPhoto &photo, int count, const QVector<UserData*> &participants);
ConfirmInviteBox(QWidget*, const QString &title, const MTPChatPhoto &photo, int count, const QVector<UserData*> &participants);
protected:
void prepare() override;
void resizeEvent(QResizeEvent *e) override;
void paintEvent(QPaintEvent *e) override;
private:
ChildWidget<Ui::FlatLabel> _title;
ChildWidget<Ui::FlatLabel> _status;
object_ptr<Ui::FlatLabel> _title;
object_ptr<Ui::FlatLabel> _status;
ImagePtr _photo;
QVector<UserData*> _participants;
ChildWidget<Ui::RoundButton> _join;
ChildWidget<Ui::RoundButton> _cancel;
int _userWidth = 0;
};

View File

@ -31,24 +31,30 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace {
QPointer<ConfirmPhoneBox> CurrentConfirmPhoneBox = nullptr;
object_ptr<ConfirmPhoneBox> CurrentConfirmPhoneBox = { nullptr };
} // namespace
void ConfirmPhoneBox::start(const QString &phone, const QString &hash) {
if (CurrentConfirmPhoneBox) {
if (CurrentConfirmPhoneBox->getPhone() == phone) return;
delete CurrentConfirmPhoneBox;
if (CurrentConfirmPhoneBox && CurrentConfirmPhoneBox->getPhone() != phone) {
CurrentConfirmPhoneBox.destroyDelayed();
}
if (auto main = App::main()) {
CurrentConfirmPhoneBox = new ConfirmPhoneBox(main, phone, hash);
if (!CurrentConfirmPhoneBox) {
CurrentConfirmPhoneBox = Box<ConfirmPhoneBox>(phone, hash);
}
CurrentConfirmPhoneBox->checkPhoneAndHash();
}
ConfirmPhoneBox::ConfirmPhoneBox(QWidget *parent, const QString &phone, const QString &hash) : AbstractBox(st::boxWidth, lang(lng_confirm_phone_title))
, _phone(phone)
, _hash(hash) {
setParent(parent);
ConfirmPhoneBox::ConfirmPhoneBox(QWidget*, const QString &phone, const QString &hash)
: _phone(phone)
, _hash(hash)
, _callTimer(this) {
}
void ConfirmPhoneBox::checkPhoneAndHash() {
if (_sendCodeRequestId) {
return;
}
MTPaccount_SendConfirmPhoneCode::Flags flags = 0;
_sendCodeRequestId = MTP::send(MTPaccount_SendConfirmPhoneCode(MTP_flags(flags), MTP_string(_hash), MTPBool()), rpcDone(&ConfirmPhoneBox::sendCodeDone), rpcFail(&ConfirmPhoneBox::sendCodeFail));
@ -83,20 +89,28 @@ bool ConfirmPhoneBox::sendCodeFail(const RPCError &error) {
errorText = lang(lng_confirm_phone_link_invalid);
}
_sendCodeRequestId = 0;
Ui::showLayer(new InformBox(errorText));
deleteLater();
Ui::show(Box<InformBox>(errorText));
if (this == CurrentConfirmPhoneBox) {
CurrentConfirmPhoneBox.destroyDelayed();
} else {
deleteLater();
}
return true;
}
void ConfirmPhoneBox::setCallStatus(const CallStatus &status) {
_callStatus = status;
if (_callStatus.state == CallState::Waiting) {
_callTimer.start(1000);
_callTimer->start(1000);
}
}
void ConfirmPhoneBox::launch() {
setBlockTitle(true);
if (!CurrentConfirmPhoneBox) return;
Ui::show(std_::move(CurrentConfirmPhoneBox));
}
void ConfirmPhoneBox::prepare() {
_about.create(this, st::confirmPhoneAboutLabel);
TextWithEntities aboutText;
@ -110,30 +124,26 @@ void ConfirmPhoneBox::launch() {
_code.create(this, st::confirmPhoneCodeField, lang(lng_code_ph));
_send.create(this, lang(lng_confirm_phone_send), st::defaultBoxButton);
_cancel.create(this, lang(lng_cancel), st::cancelBoxButton);
setTitle(lang(lng_confirm_phone_title));
setMaxHeight(titleHeight() + st::usernamePadding.top() + _code->height() + st::usernameSkip + _about->height() + st::usernameSkip + _send->height() + st::boxButtonPadding.bottom());
addButton(lang(lng_confirm_phone_send), [this] { onSendCode(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
connect(_send, SIGNAL(clicked()), this, SLOT(onSendCode()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
setDimensions(st::boxWidth, st::usernamePadding.top() + _code->height() + st::usernameSkip + _about->height() + st::usernameSkip);
connect(_code, SIGNAL(changed()), this, SLOT(onCodeChanged()));
connect(_code, SIGNAL(submitted(bool)), this, SLOT(onSendCode()));
connect(&_callTimer, SIGNAL(timeout()), this, SLOT(onCallStatusTimer()));
connect(_callTimer, SIGNAL(timeout()), this, SLOT(onCallStatusTimer()));
showChildren();
raiseShadow();
Ui::showLayer(this);
}
void ConfirmPhoneBox::onCallStatusTimer() {
if (_callStatus.state == CallState::Waiting) {
if (--_callStatus.timeout <= 0) {
_callStatus.state = CallState::Calling;
_callTimer.stop();
_callTimer->stop();
MTP::send(MTPauth_ResendCode(MTP_string(_phone), MTP_string(_phoneHash)), rpcDone(&ConfirmPhoneBox::callDone));
}
}
@ -167,7 +177,7 @@ void ConfirmPhoneBox::onSendCode() {
void ConfirmPhoneBox::confirmDone(const MTPBool &result) {
_sendCodeRequestId = 0;
Ui::showLayer(new InformBox(lng_confirm_phone_success(lt_phone, App::formatPhone(_phone))));
Ui::show(Box<InformBox>(lng_confirm_phone_success(lt_phone, App::formatPhone(_phone))));
}
bool ConfirmPhoneBox::confirmFail(const RPCError &error) {
@ -248,7 +258,7 @@ void ConfirmPhoneBox::showError(const QString &error) {
}
void ConfirmPhoneBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e);
BoxContent::paintEvent(e);
Painter p(this);
@ -291,18 +301,15 @@ QString ConfirmPhoneBox::getCallText() const {
}
void ConfirmPhoneBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e);
_code->resize(width() - st::usernamePadding.left() - st::usernamePadding.right(), _code->height());
_code->moveToLeft(st::usernamePadding.left(), titleHeight() + st::usernamePadding.top());
_code->moveToLeft(st::usernamePadding.left(), st::usernamePadding.top());
_about->moveToLeft(st::usernamePadding.left(), _code->y() + _code->height() + st::usernameSkip);
_send->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _send->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _send->width() + st::boxButtonPadding.left(), _send->y());
AbstractBox::resizeEvent(e);
}
void ConfirmPhoneBox::doSetInnerFocus() {
void ConfirmPhoneBox::setInnerFocus() {
_code->setFocus();
}

View File

@ -24,11 +24,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Ui {
class InputField;
class RoundButton;
class FlatLabel;
} // namespace Ui
class ConfirmPhoneBox : public AbstractBox, public RPCSender {
class ConfirmPhoneBox : public BoxContent, public RPCSender {
Q_OBJECT
public:
@ -42,12 +41,18 @@ private slots:
void onCodeChanged();
protected:
void prepare() override;
void setInnerFocus() override;
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void doSetInnerFocus() override;
private:
ConfirmPhoneBox(QWidget *parent, const QString &phone, const QString &hash);
ConfirmPhoneBox(QWidget*, const QString &phone, const QString &hash);
friend class object_ptr<ConfirmPhoneBox>;
void checkPhoneAndHash();
void sendCodeDone(const MTPauth_SentCode &result);
bool sendCodeFail(const RPCError &error);
@ -88,16 +93,14 @@ private:
mtpRequestId _checkCodeRequestId = 0;
ChildWidget<Ui::FlatLabel> _about = { nullptr };
ChildWidget<Ui::RoundButton> _send = { nullptr };
ChildWidget<Ui::RoundButton> _cancel = { nullptr };
ChildWidget<Ui::InputField> _code = { nullptr };
object_ptr<Ui::FlatLabel> _about = { nullptr };
object_ptr<Ui::InputField> _code = { nullptr };
// Flag for not calling onTextChanged() recursively.
bool _fixing = false;
QString _error;
CallStatus _callStatus;
QTimer _callTimer;
object_ptr<QTimer> _callTimer;
};

View File

@ -31,20 +31,22 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "history/history_location_manager.h"
#include "styles/style_boxes.h"
ConnectionBox::ConnectionBox() : AbstractBox(st::boxWidth, lang(lng_connection_header))
, _hostInput(this, st::connectionHostInputField, lang(lng_connection_host_ph), Global::ConnectionProxy().host)
ConnectionBox::ConnectionBox(QWidget *parent)
: _hostInput(this, st::connectionHostInputField, lang(lng_connection_host_ph), Global::ConnectionProxy().host)
, _portInput(this, st::connectionPortInputField, lang(lng_connection_port_ph), QString::number(Global::ConnectionProxy().port))
, _userInput(this, st::connectionUserInputField, lang(lng_connection_user_ph), Global::ConnectionProxy().user)
, _passwordInput(this, st::connectionPasswordInputField, lang(lng_connection_password_ph), Global::ConnectionProxy().password)
, _autoRadio(this, qsl("conn_type"), dbictAuto, lang(lng_connection_auto_rb), (Global::ConnectionType() == dbictAuto), st::defaultBoxCheckbox)
, _httpProxyRadio(this, qsl("conn_type"), dbictHttpProxy, lang(lng_connection_http_proxy_rb), (Global::ConnectionType() == dbictHttpProxy), st::defaultBoxCheckbox)
, _tcpProxyRadio(this, qsl("conn_type"), dbictTcpProxy, lang(lng_connection_tcp_proxy_rb), (Global::ConnectionType() == dbictTcpProxy), st::defaultBoxCheckbox)
, _tryIPv6(this, lang(lng_connection_try_ipv6), Global::TryIPv6(), st::defaultBoxCheckbox)
, _save(this, lang(lng_connection_save), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
, _tryIPv6(this, lang(lng_connection_try_ipv6), Global::TryIPv6(), st::defaultBoxCheckbox) {
}
connect(_save, SIGNAL(clicked()), this, SLOT(onSave()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
void ConnectionBox::prepare() {
setTitle(lang(lng_connection_header));
addButton(lang(lng_connection_save), [this] { onSave(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
connect(_autoRadio, SIGNAL(changed()), this, SLOT(onChange()));
connect(_httpProxyRadio, SIGNAL(changed()), this, SLOT(onChange()));
@ -59,9 +61,9 @@ ConnectionBox::ConnectionBox() : AbstractBox(st::boxWidth, lang(lng_connection_h
}
void ConnectionBox::updateControlsVisibility() {
int32 h = titleHeight() + st::boxOptionListPadding.top() + _autoRadio->heightNoMargins() + st::boxOptionListPadding.top() + _httpProxyRadio->heightNoMargins() + st::boxOptionListPadding.top() + _tcpProxyRadio->heightNoMargins() + st::boxOptionListPadding.top() + st::connectionIPv6Skip + _tryIPv6->heightNoMargins() + st::boxOptionListPadding.bottom() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom();
auto newHeight = st::boxOptionListPadding.top() + _autoRadio->heightNoMargins() + st::boxOptionListSkip + _httpProxyRadio->heightNoMargins() + st::boxOptionListSkip + _tcpProxyRadio->heightNoMargins() + st::boxOptionListSkip + st::connectionIPv6Skip + _tryIPv6->heightNoMargins() + st::boxOptionListPadding.bottom() + st::boxPadding.bottom();
if (_httpProxyRadio->checked() || _tcpProxyRadio->checked()) {
h += 2 * st::boxOptionInputSkip + 2 * _hostInput->height();
newHeight += 2 * st::boxOptionInputSkip + 2 * _hostInput->height();
_hostInput->show();
_portInput->show();
_userInput->show();
@ -73,26 +75,32 @@ void ConnectionBox::updateControlsVisibility() {
_passwordInput->hide();
}
setMaxHeight(h);
resizeEvent(0);
setDimensions(st::boxWidth, newHeight);
updateControlsPosition();
}
void ConnectionBox::doSetInnerFocus() {
void ConnectionBox::setInnerFocus() {
if (!_hostInput->isHidden()) {
_hostInput->setFocus();
}
}
void ConnectionBox::resizeEvent(QResizeEvent *e) {
_autoRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), titleHeight() + st::boxOptionListPadding.top());
_httpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _autoRadio->bottomNoMargins() + st::boxOptionListPadding.top());
BoxContent::resizeEvent(e);
updateControlsPosition();
}
void ConnectionBox::updateControlsPosition() {
_autoRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), st::boxOptionListPadding.top());
_httpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _autoRadio->bottomNoMargins() + st::boxOptionListSkip);
int32 inputy = 0;
if (_httpProxyRadio->checked()) {
inputy = _httpProxyRadio->bottomNoMargins() + st::boxOptionInputSkip;
_tcpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), inputy + st::boxOptionInputSkip + 2 * _hostInput->height() + st::boxOptionListPadding.top());
_tcpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), inputy + st::boxOptionInputSkip + 2 * _hostInput->height() + st::boxOptionListSkip);
} else {
_tcpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _httpProxyRadio->bottomNoMargins() + st::boxOptionListPadding.top());
_tcpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _httpProxyRadio->bottomNoMargins() + st::boxOptionListSkip);
if (_tcpProxyRadio->checked()) {
inputy = _tcpProxyRadio->bottomNoMargins() + st::boxOptionInputSkip;
}
@ -105,13 +113,8 @@ void ConnectionBox::resizeEvent(QResizeEvent *e) {
_passwordInput->moveToRight(st::boxPadding.right(), _userInput->y());
}
int32 tryipv6y = (_tcpProxyRadio->checked() ? _userInput->bottomNoMargins() : _tcpProxyRadio->bottomNoMargins()) + st::boxOptionListPadding.top() + st::connectionIPv6Skip;
auto tryipv6y = (_tcpProxyRadio->checked() ? _userInput->bottomNoMargins() : _tcpProxyRadio->bottomNoMargins()) + st::boxOptionListSkip + st::connectionIPv6Skip;
_tryIPv6->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), tryipv6y);
_save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _save->width() + st::boxButtonPadding.left(), _save->y());
AbstractBox::resizeEvent(e);
}
void ConnectionBox::onChange() {
@ -195,55 +198,52 @@ void ConnectionBox::onSave() {
MTP::restart();
reinitLocationManager();
reinitWebLoadManager();
onClose();
closeBox();
}
}
AutoDownloadBox::AutoDownloadBox() : AbstractBox(st::boxWidth)
, _photoPrivate(this, lang(lng_media_auto_private_chats), !(cAutoDownloadPhoto() & dbiadNoPrivate), st::defaultBoxCheckbox)
AutoDownloadBox::AutoDownloadBox(QWidget *parent)
: _photoPrivate(this, lang(lng_media_auto_private_chats), !(cAutoDownloadPhoto() & dbiadNoPrivate), st::defaultBoxCheckbox)
, _photoGroups(this, lang(lng_media_auto_groups), !(cAutoDownloadPhoto() & dbiadNoGroups), st::defaultBoxCheckbox)
, _audioPrivate(this, lang(lng_media_auto_private_chats), !(cAutoDownloadAudio() & dbiadNoPrivate), st::defaultBoxCheckbox)
, _audioGroups(this, lang(lng_media_auto_groups), !(cAutoDownloadAudio() & dbiadNoGroups), st::defaultBoxCheckbox)
, _gifPrivate(this, lang(lng_media_auto_private_chats), !(cAutoDownloadGif() & dbiadNoPrivate), st::defaultBoxCheckbox)
, _gifGroups(this, lang(lng_media_auto_groups), !(cAutoDownloadGif() & dbiadNoGroups), st::defaultBoxCheckbox)
, _gifPlay(this, lang(lng_media_auto_play), cAutoPlayGif(), st::defaultBoxCheckbox)
, _sectionHeight(titleHeight() + 2 * (st::defaultBoxCheckbox.height + st::setLittleSkip))
, _save(this, lang(lng_connection_save), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
, _sectionHeight(st::boxTitleHeight + 2 * (st::defaultBoxCheckbox.height + st::setLittleSkip)) {
}
setMaxHeight(3 * _sectionHeight + st::setLittleSkip + _gifPlay->heightNoMargins() + st::setLittleSkip + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom());
void AutoDownloadBox::prepare() {
addButton(lang(lng_connection_save), [this] { onSave(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
connect(_save, SIGNAL(clicked()), this, SLOT(onSave()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
setDimensions(st::boxWidth, 3 * _sectionHeight + st::setLittleSkip + _gifPlay->heightNoMargins() + st::setLittleSkip);
}
void AutoDownloadBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e);
BoxContent::paintEvent(e);
Painter p(this);
p.setPen(st::boxTextFg);
p.setFont(st::semiboldFont);
p.drawTextLeft(st::boxTitlePosition.x(), st::boxTitlePosition.y(), width(), lang(lng_media_auto_photo));
p.drawTextLeft(st::boxTitlePosition.x(), _sectionHeight + st::boxTitlePosition.y(), width(), lang(lng_media_auto_audio));
p.drawTextLeft(st::boxTitlePosition.x(), 2 * _sectionHeight + st::boxTitlePosition.y(), width(), lang(lng_media_auto_gif));
p.setPen(st::boxTitleFg);
p.setFont(st::autoDownloadTitleFont);
p.drawTextLeft(st::autoDownloadTitlePosition.x(), st::autoDownloadTitlePosition.y(), width(), lang(lng_media_auto_photo));
p.drawTextLeft(st::autoDownloadTitlePosition.x(), _sectionHeight + st::autoDownloadTitlePosition.y(), width(), lang(lng_media_auto_audio));
p.drawTextLeft(st::autoDownloadTitlePosition.x(), 2 * _sectionHeight + st::autoDownloadTitlePosition.y(), width(), lang(lng_media_auto_gif));
}
void AutoDownloadBox::resizeEvent(QResizeEvent *e) {
_photoPrivate->moveToLeft(st::boxTitlePosition.x(), titleHeight() + st::setLittleSkip);
BoxContent::resizeEvent(e);
_photoPrivate->moveToLeft(st::boxTitlePosition.x(), st::boxTitleHeight + st::setLittleSkip);
_photoGroups->moveToLeft(st::boxTitlePosition.x(), _photoPrivate->bottomNoMargins() + st::setLittleSkip);
_audioPrivate->moveToLeft(st::boxTitlePosition.x(), _sectionHeight + titleHeight() + st::setLittleSkip);
_audioPrivate->moveToLeft(st::boxTitlePosition.x(), _sectionHeight + st::boxTitleHeight + st::setLittleSkip);
_audioGroups->moveToLeft(st::boxTitlePosition.x(), _audioPrivate->bottomNoMargins() + st::setLittleSkip);
_gifPrivate->moveToLeft(st::boxTitlePosition.x(), 2 * _sectionHeight + titleHeight() + st::setLittleSkip);
_gifPrivate->moveToLeft(st::boxTitlePosition.x(), 2 * _sectionHeight + st::boxTitleHeight + st::setLittleSkip);
_gifGroups->moveToLeft(st::boxTitlePosition.x(), _gifPrivate->bottomNoMargins() + st::setLittleSkip);
_gifPlay->moveToLeft(st::boxTitlePosition.x(), _gifGroups->bottomNoMargins() + st::setLittleSkip);
_save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _save->width() + st::boxButtonPadding.left(), _save->y());
AbstractBox::resizeEvent(e);
}
void AutoDownloadBox::onSave() {
@ -299,5 +299,5 @@ void AutoDownloadBox::onSave() {
changed = true;
}
if (changed) Local::writeUserSettings();
onClose();
closeBox();
}

View File

@ -28,67 +28,64 @@ class PortInput;
class PasswordInput;
class Checkbox;
class Radiobutton;
class RoundButton;
} // namespace Ui
class ConnectionBox : public AbstractBox {
class ConnectionBox : public BoxContent {
Q_OBJECT
public:
ConnectionBox();
ConnectionBox(QWidget *parent);
public slots:
protected:
void prepare() override;
void setInnerFocus() override;
void resizeEvent(QResizeEvent *e) override;
private slots:
void onChange();
void onSubmit();
void onSave();
protected:
void resizeEvent(QResizeEvent *e) override;
void doSetInnerFocus() override;
private:
void updateControlsVisibility();
void updateControlsPosition();
ChildWidget<Ui::InputField> _hostInput;
ChildWidget<Ui::PortInput> _portInput;
ChildWidget<Ui::InputField> _userInput;
ChildWidget<Ui::PasswordInput> _passwordInput;
ChildWidget<Ui::Radiobutton> _autoRadio;
ChildWidget<Ui::Radiobutton> _httpProxyRadio;
ChildWidget<Ui::Radiobutton> _tcpProxyRadio;
ChildWidget<Ui::Checkbox> _tryIPv6;
ChildWidget<Ui::RoundButton> _save;
ChildWidget<Ui::RoundButton> _cancel;
object_ptr<Ui::InputField> _hostInput;
object_ptr<Ui::PortInput> _portInput;
object_ptr<Ui::InputField> _userInput;
object_ptr<Ui::PasswordInput> _passwordInput;
object_ptr<Ui::Radiobutton> _autoRadio;
object_ptr<Ui::Radiobutton> _httpProxyRadio;
object_ptr<Ui::Radiobutton> _tcpProxyRadio;
object_ptr<Ui::Checkbox> _tryIPv6;
};
class AutoDownloadBox : public AbstractBox {
class AutoDownloadBox : public BoxContent {
Q_OBJECT
public:
AutoDownloadBox();
public slots:
void onSave();
AutoDownloadBox(QWidget *parent);
protected:
void prepare() override;
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
private slots:
void onSave();
private:
ChildWidget<Ui::Checkbox> _photoPrivate;
ChildWidget<Ui::Checkbox> _photoGroups;
ChildWidget<Ui::Checkbox> _audioPrivate;
ChildWidget<Ui::Checkbox> _audioGroups;
ChildWidget<Ui::Checkbox> _gifPrivate;
ChildWidget<Ui::Checkbox> _gifGroups;
ChildWidget<Ui::Checkbox> _gifPlay;
object_ptr<Ui::Checkbox> _photoPrivate;
object_ptr<Ui::Checkbox> _photoGroups;
object_ptr<Ui::Checkbox> _audioPrivate;
object_ptr<Ui::Checkbox> _audioGroups;
object_ptr<Ui::Checkbox> _gifPrivate;
object_ptr<Ui::Checkbox> _gifGroups;
object_ptr<Ui::Checkbox> _gifPlay;
int _sectionHeight;
ChildWidget<Ui::RoundButton> _save;
ChildWidget<Ui::RoundButton> _cancel;
int _sectionHeight = 0;
};

View File

@ -47,76 +47,84 @@ QString cantInviteError() {
return lng_cant_invite_not_contact(lt_more_info, textcmdLink(qsl("https://telegram.me/spambot"), lang(lng_cant_more_info)));
}
ContactsBox::ContactsBox() : ItemListBox(st::contactsScroll)
, _inner(this, CreatingGroupNone)
, _select(this, new Ui::MultiSelect(this, st::contactsMultiSelect, lang(lng_participant_filter)), QMargins(0, 0, 0, 0), [this] { updateScrollSkips(); })
, _next(this, lang(lng_create_group_next), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _topShadow(this) {
init();
ContactsBox::ContactsBox(QWidget*, ChatData *chat, MembersFilter filter)
: _chat(chat)
, _membersFilter(filter)
, _select(createMultiSelect())
, _searchTimer(this) {
}
ContactsBox::ContactsBox(const QString &name, const QImage &photo) : ItemListBox(st::boxScroll)
, _inner(this, CreatingGroupGroup)
, _select(this, new Ui::MultiSelect(this, st::contactsMultiSelect, lang(lng_participant_filter)), QMargins(0, 0, 0, 0), [this] { updateScrollSkips(); })
, _next(this, lang(lng_create_group_create), st::defaultBoxButton)
, _cancel(this, lang(lng_create_group_back), st::cancelBoxButton)
, _topShadow(this)
ContactsBox::ContactsBox(QWidget*, ChannelData *channel)
: _creating(CreatingGroupChannel)
, _channel(channel)
, _select(createMultiSelect())
, _searchTimer(this) {
}
ContactsBox::ContactsBox(QWidget*, ChannelData *channel, MembersFilter filter, const MembersAlreadyIn &already)
: _channel(channel)
, _membersFilter(filter)
, _alreadyIn(already)
, _select(createMultiSelect())
, _searchTimer(this) {
}
ContactsBox::ContactsBox(QWidget*, UserData *bot)
: _bot(bot)
, _select(createMultiSelect())
, _searchTimer(this) {
}
ContactsBox::ContactsBox(QWidget*, const QString &name, const QImage &photo)
: _creating(CreatingGroupGroup)
, _select(createMultiSelect())
, _searchTimer(this)
, _creationName(name)
, _creationPhoto(photo) {
init();
}
ContactsBox::ContactsBox(ChannelData *channel) : ItemListBox(st::boxScroll)
, _inner(this, channel, MembersFilter::Recent, MembersAlreadyIn())
, _select(this, new Ui::MultiSelect(this, st::contactsMultiSelect, lang(lng_participant_filter)), QMargins(0, 0, 0, 0), [this] { updateScrollSkips(); })
, _next(this, lang(lng_participant_invite), st::defaultBoxButton)
, _cancel(this, lang(lng_create_group_skip), st::cancelBoxButton)
, _topShadow(this) {
init();
ContactsBox::ContactsBox(QWidget*)
: _select(createMultiSelect())
, _searchTimer(this) {
}
ContactsBox::ContactsBox(ChannelData *channel, MembersFilter filter, const MembersAlreadyIn &already) : ItemListBox((filter == MembersFilter::Admins) ? st::contactsScroll : st::boxScroll)
, _inner(this, channel, filter, already)
, _select(this, new Ui::MultiSelect(this, st::contactsMultiSelect, lang(lng_participant_filter)), QMargins(0, 0, 0, 0), [this] { updateScrollSkips(); })
, _next(this, lang(lng_participant_invite), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _topShadow(this) {
init();
}
ContactsBox::ContactsBox(ChatData *chat, MembersFilter filter) : ItemListBox(st::boxScroll)
, _inner(this, chat, filter)
, _select(this, new Ui::MultiSelect(this, st::contactsMultiSelect, lang(lng_participant_filter)), QMargins(0, 0, 0, 0), [this] { updateScrollSkips(); })
, _next(this, lang((filter == MembersFilter::Admins) ? lng_settings_save : lng_participant_invite), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _topShadow(this) {
init();
}
ContactsBox::ContactsBox(UserData *bot) : ItemListBox(st::contactsScroll)
, _inner(this, bot)
, _select(this, new Ui::MultiSelect(this, st::contactsMultiSelect, lang(lng_participant_filter)), QMargins(0, 0, 0, 0), [this] { updateScrollSkips(); })
, _next(this, lang(lng_create_group_next), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _topShadow(this) {
init();
}
void ContactsBox::init() {
void ContactsBox::prepare() {
_select->resizeToWidth(st::boxWideWidth);
myEnsureResized(_select);
auto inviting = (_inner->creating() == CreatingGroupGroup) || (_inner->channel() && _inner->membersFilter() == MembersFilter::Recent) || _inner->chat();
auto topSkip = getTopScrollSkip();
auto bottomSkip = inviting ? (st::boxButtonPadding.top() + _next->height() + st::boxButtonPadding.bottom()) : st::boxScrollSkip;
ItemListBox::init(_inner, bottomSkip, topSkip);
auto createInner = [this] {
if (_chat) {
return object_ptr<Inner>(this, _chat, _membersFilter);
} else if (_channel) {
return object_ptr<Inner>(this, _channel, _membersFilter, _alreadyIn);
} else if (_bot) {
return object_ptr<Inner>(this, _bot);
}
return object_ptr<Inner>(this, _creating);
};
_inner = setInnerWidget(createInner(), getTopScrollSkip());
if (_inner->creating() == CreatingGroupNone && !_inner->chat() && !_inner->channel() && !_inner->bot()) {
_add.create(this, st::contactsAdd);
_add->setClickedCallback([] {
App::wnd()->onShowAddContact();
});
updateTitle();
if (_chat) {
if (_membersFilter == MembersFilter::Admins) {
addButton(lang(lng_settings_save), [this] { saveChatAdmins(); });
} else {
addButton(lang(lng_participant_invite), [this] { inviteParticipants(); });
}
addButton(lang(lng_cancel), [this] { closeBox(); });
} else if (_channel) {
if (_membersFilter != MembersFilter::Admins) {
addButton(lang(lng_participant_invite), [this] { inviteParticipants(); });
}
addButton(lang((_creating == CreatingGroupChannel) ? lng_create_group_skip : lng_cancel), [this] { closeBox(); });
} else if (_bot) {
addButton(lang(lng_close), [this] { closeBox(); });
} else if (_creating == CreatingGroupGroup) {
addButton(lang(lng_create_group_create), [this] { createGroup(); });
addButton(lang(lng_create_group_back), [this] { closeBox(); });
} else {
addButton(lang(lng_close), [this] { closeBox(); });
addLeftButton(lang(lng_profile_add_contact), [] { App::wnd()->onShowAddContact(); });
}
_inner->setPeerSelectedChangedCallback([this](PeerData *peer, bool checked) {
@ -141,24 +149,6 @@ void ContactsBox::init() {
} else {
_select->showFast();
}
if (_inner->channel() && _inner->membersFilter() == MembersFilter::Admins) {
_next->hide();
_cancel->hide();
} else if (_inner->chat() && _inner->membersFilter() == MembersFilter::Admins) {
connect(_next, SIGNAL(clicked()), this, SLOT(onSaveAdmins()));
_bottomShadow.create(this);
} else if (_inner->chat() || _inner->channel()) {
connect(_next, SIGNAL(clicked()), this, SLOT(onInvite()));
_bottomShadow.create(this);
} else if (_inner->creating() != CreatingGroupNone) {
connect(_next, SIGNAL(clicked()), this, SLOT(onCreate()));
_bottomShadow.create(this);
} else {
_next->hide();
_cancel->hide();
}
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
connect(scrollArea(), SIGNAL(scrolled()), this, SLOT(onScroll()));
_select->entity()->setQueryChangedCallback([this](const QString &query) { onFilterUpdate(query); });
_select->entity()->setItemRemovedCallback([this](uint64 itemId) {
if (auto peer = App::peerLoaded(itemId)) {
@ -167,14 +157,16 @@ void ContactsBox::init() {
}
});
_select->entity()->setSubmittedCallback([this](bool) { onSubmit(); });
connect(_inner, SIGNAL(mustScrollTo(int, int)), scrollArea(), SLOT(scrollToY(int, int)));
connect(_inner, SIGNAL(mustScrollTo(int, int)), this, SLOT(onScrollToY(int, int)));
connect(_inner, SIGNAL(searchByUsername()), this, SLOT(onNeedSearchByUsername()));
connect(_inner, SIGNAL(adminAdded()), this, SIGNAL(adminAdded()));
_searchTimer.setSingleShot(true);
connect(&_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchByUsername()));
_searchTimer->setSingleShot(true);
connect(_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchByUsername()));
raiseShadow();
setDimensions(st::boxWideWidth, st::boxMaxListHeight);
_select->raise();
}
bool ContactsBox::onSearchByUsername(bool searchCache) {
@ -204,9 +196,26 @@ bool ContactsBox::onSearchByUsername(bool searchCache) {
return false;
}
void ContactsBox::updateTitle() {
if (_chat && _membersFilter == MembersFilter::Admins) {
setTitle(lang(lng_channel_admins));
} else if (_chat || _creating != CreatingGroupNone) {
auto addingAdmin = _channel && (_membersFilter == MembersFilter::Admins);
auto title = lang(addingAdmin ? lng_channel_add_admin : lng_profile_add_participant);
auto additional = (addingAdmin || (_inner->channel() && !_inner->channel()->isMegagroup())) ? QString() : QString("%1 / %2").arg(_inner->selectedCount()).arg(Global::MegagroupSizeMax());
setTitle(title, additional);
} else if (_inner->sharingBotGame()) {
setTitle(lang(lng_bot_choose_chat));
} else if (_inner->bot()) {
setTitle(lang(lng_bot_choose_group));
} else {
setTitle(lang(lng_contacts_header));
}
}
void ContactsBox::onNeedSearchByUsername() {
if (!onSearchByUsername(true)) {
_searchTimer.start(AutoSearchTimeout);
_searchTimer->start(AutoSearchTimeout);
}
}
@ -231,7 +240,6 @@ void ContactsBox::peopleReceived(const MTPcontacts_Found &result, mtpRequestId r
_peopleRequest = 0;
_inner->updateSelection();
onScroll();
}
}
@ -245,7 +253,7 @@ bool ContactsBox::peopleFailed(const RPCError &error, mtpRequestId req) {
return true;
}
void ContactsBox::doSetInnerFocus() {
void ContactsBox::setInnerFocus() {
if (_select->isHidden()) {
_inner->setFocus();
} else {
@ -265,40 +273,26 @@ void ContactsBox::keyPressEvent(QKeyEvent *e) {
} else if (e->key() == Qt::Key_Up) {
_inner->selectSkip(-1);
} else if (e->key() == Qt::Key_PageDown) {
_inner->selectSkipPage(scrollArea()->height(), 1);
_inner->selectSkipPage(height() - getTopScrollSkip(), 1);
} else if (e->key() == Qt::Key_PageUp) {
_inner->selectSkipPage(scrollArea()->height(), -1);
_inner->selectSkipPage(height() - getTopScrollSkip(), -1);
} else {
ItemListBox::keyPressEvent(e);
BoxContent::keyPressEvent(e);
}
} else {
ItemListBox::keyPressEvent(e);
BoxContent::keyPressEvent(e);
}
}
void ContactsBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e);
Painter p(this);
bool addingAdmin = _inner->channel() && _inner->membersFilter() == MembersFilter::Admins;
if (_inner->chat() && _inner->membersFilter() == MembersFilter::Admins) {
paintTitle(p, lang(lng_channel_admins));
} else if (_inner->chat() || _inner->creating() != CreatingGroupNone) {
QString title(lang(addingAdmin ? lng_channel_add_admin : lng_profile_add_participant));
QString additional((addingAdmin || (_inner->channel() && !_inner->channel()->isMegagroup())) ? QString() : QString("%1 / %2").arg(_inner->selectedCount()).arg(Global::MegagroupSizeMax()));
paintTitle(p, title, additional);
} else if (_inner->sharingBotGame()) {
paintTitle(p, lang(lng_bot_choose_chat));
} else if (_inner->bot()) {
paintTitle(p, lang(lng_bot_choose_group));
} else {
paintTitle(p, lang(lng_contacts_header));
}
object_ptr<Ui::WidgetSlideWrap<Ui::MultiSelect>> ContactsBox::createMultiSelect() {
auto entity = object_ptr<Ui::MultiSelect>(this, st::contactsMultiSelect, lang(lng_participant_filter));
auto margins = style::margins(0, 0, 0, 0);
auto callback = [this] { updateScrollSkips(); };
return object_ptr<Ui::WidgetSlideWrap<Ui::MultiSelect>>(this, std_::move(entity), margins, std_::move(callback));
}
int ContactsBox::getTopScrollSkip() const {
auto result = titleHeight();
auto result = 0;
if (!_select->isHidden()) {
result += _select->height();
}
@ -306,45 +300,28 @@ int ContactsBox::getTopScrollSkip() const {
}
void ContactsBox::updateScrollSkips() {
auto oldScrollHeight = scrollArea()->height();
auto inviting = (_inner->creating() == CreatingGroupGroup) || (_inner->channel() && _inner->membersFilter() == MembersFilter::Recent) || _inner->chat();
auto topSkip = getTopScrollSkip();
auto bottomSkip = inviting ? (st::boxButtonPadding.top() + _next->height() + st::boxButtonPadding.bottom()) : st::boxScrollSkip;
setScrollSkips(bottomSkip, topSkip);
auto scrollHeightDelta = scrollArea()->height() - oldScrollHeight;
if (scrollHeightDelta) {
scrollArea()->scrollToY(scrollArea()->scrollTop() - scrollHeightDelta);
}
_topShadow->setGeometry(0, topSkip, width(), st::lineWidth);
setInnerTopSkip(getTopScrollSkip(), true);
}
void ContactsBox::resizeEvent(QResizeEvent *e) {
ItemListBox::resizeEvent(e);
BoxContent::resizeEvent(e);
_select->resizeToWidth(width());
_select->moveToLeft(0, titleHeight());
_select->moveToLeft(0, 0);
updateScrollSkips();
if (_add) {
_add->moveToRight(st::contactsAddPosition.x(), height() - st::contactsAddPosition.y() - _add->height());
}
_inner->resize(width(), _inner->height());
_next->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _next->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _next->width() + st::boxButtonPadding.left(), _next->y());
if (_bottomShadow) _bottomShadow->setGeometry(0, height() - st::boxButtonPadding.bottom() - _next->height() - st::boxButtonPadding.top() - st::lineWidth, width(), st::lineWidth);
}
void ContactsBox::closePressed() {
if (_inner->channel() && !_inner->hasAlreadyMembersInChannel()) {
Ui::showPeerHistory(_inner->channel(), ShowAtTheEndMsgId);
void ContactsBox::closeHook() {
if (_channel && _creating == CreatingGroupChannel) {
Ui::showPeerHistory(_channel, ShowAtTheEndMsgId);
}
}
void ContactsBox::onFilterUpdate(const QString &filter) {
scrollArea()->scrollToY(0);
onScrollToY(0);
_inner->updateFilter(filter);
}
@ -361,10 +338,10 @@ void ContactsBox::onPeerSelectedChanged(PeerData *peer, bool checked) {
} else {
_select->entity()->removeItem(peer->id);
}
update();
updateTitle();
}
void ContactsBox::onInvite() {
void ContactsBox::inviteParticipants() {
QVector<UserData*> users(_inner->selected());
if (users.isEmpty()) {
_select->entity()->setInnerFocus();
@ -376,11 +353,11 @@ void ContactsBox::onInvite() {
Ui::hideLayer();
Ui::showPeerHistory(_inner->chat(), ShowAtTheEndMsgId);
} else {
onClose();
closeBox();
}
}
void ContactsBox::onCreate() {
void ContactsBox::createGroup() {
if (_saveRequestId) return;
auto users = _inner->selectedInputs();
@ -391,7 +368,7 @@ void ContactsBox::onCreate() {
_saveRequestId = MTP::send(MTPmessages_CreateChat(MTP_vector<MTPInputUser>(users), MTP_string(_creationName)), rpcDone(&ContactsBox::creationDone), rpcFail(&ContactsBox::creationFail));
}
void ContactsBox::onSaveAdmins() {
void ContactsBox::saveChatAdmins() {
if (_saveRequestId) return;
_inner->saving(true);
@ -405,7 +382,7 @@ void ContactsBox::saveAdminsDone(const MTPUpdates &result) {
void ContactsBox::saveSelectedAdmins() {
if (_inner->allAdmins() && !_inner->chat()->participants.isEmpty()) {
onClose();
closeBox();
} else {
_saveRequestId = MTP::send(MTPmessages_GetFullChat(_inner->chat()->inputChat), rpcDone(&ContactsBox::getAdminsDone), rpcFail(&ContactsBox::saveAdminsFail));
}
@ -414,7 +391,7 @@ void ContactsBox::saveSelectedAdmins() {
void ContactsBox::getAdminsDone(const MTPmessages_ChatFull &result) {
App::api()->processFullPeer(_inner->chat(), result);
if (_inner->allAdmins()) {
onClose();
closeBox();
return;
}
ChatData::Admins curadmins = _inner->chat()->admins;
@ -444,7 +421,7 @@ void ContactsBox::getAdminsDone(const MTPmessages_ChatFull &result) {
_saveRequestId = curadmins.size() + appoint.size();
if (!_saveRequestId) {
onClose();
closeBox();
}
}
@ -459,7 +436,7 @@ void ContactsBox::setAdminDone(UserData *user, const MTPBool &result) {
--_saveRequestId;
if (!_saveRequestId) {
emit App::main()->peerUpdated(_inner->chat());
onClose();
closeBox();
}
}
@ -470,7 +447,7 @@ void ContactsBox::removeAdminDone(UserData *user, const MTPBool &result) {
--_saveRequestId;
if (!_saveRequestId) {
emit App::main()->peerUpdated(_inner->chat());
onClose();
closeBox();
}
}
@ -490,18 +467,14 @@ bool ContactsBox::editAdminFail(const RPCError &error) {
_inner->chat()->invalidateParticipants();
if (!_saveRequestId) {
if (error.type() == qstr("USER_RESTRICTED")) {
Ui::showLayer(new InformBox(lang(lng_cant_do_this)));
Ui::show(Box<InformBox>(lang(lng_cant_do_this)));
return true;
}
onClose();
closeBox();
}
return false;
}
void ContactsBox::onScroll() {
_inner->loadProfilePhotos(scrollArea()->scrollTop());
}
void ContactsBox::creationDone(const MTPUpdates &updates) {
Ui::hideLayer();
@ -532,16 +505,16 @@ bool ContactsBox::creationFail(const RPCError &error) {
_saveRequestId = 0;
if (error.type() == "NO_CHAT_TITLE") {
onClose();
closeBox();
return true;
} else if (error.type() == "USERS_TOO_FEW") {
_select->entity()->setInnerFocus();
return true;
} else if (error.type() == "PEER_FLOOD") {
Ui::showLayer(new InformBox(cantInviteError()), KeepOtherLayers);
Ui::show(Box<InformBox>(cantInviteError()), KeepOtherLayers);
return true;
} else if (error.type() == qstr("USER_RESTRICTED")) {
Ui::showLayer(new InformBox(lang(lng_cant_do_this)));
Ui::show(Box<InformBox>(lang(lng_cant_do_this)));
return true;
}
return false;
@ -649,6 +622,7 @@ void ContactsBox::Inner::init() {
connect(_addContactLnk, SIGNAL(clicked()), App::wnd(), SLOT(onShowAddContact()));
connect(_allAdmins, SIGNAL(changed()), this, SLOT(onAllAdminsChanged()));
_rowsTop = st::contactsMarginTop;
setAttribute(Qt::WA_OpaquePaintEvent);
for_const (auto row, _contacts->all()) {
@ -706,7 +680,7 @@ void ContactsBox::Inner::onPeerNameChanged(PeerData *peer, const PeerData::Names
peerUpdated(peer);
}
void ContactsBox::Inner::onAddBot() {
void ContactsBox::Inner::addBot() {
if (auto &info = _bot->botInfo) {
if (!info->shareGameShortName.isEmpty()) {
MTPmessages_SendMedia::Flags sendFlags = 0;
@ -730,17 +704,6 @@ void ContactsBox::Inner::onAddBot() {
Ui::showPeerHistory(_addToPeer, ShowAtUnreadMsgId);
}
void ContactsBox::Inner::onAddAdmin() {
if (_addAdminRequestId) return;
_addAdminRequestId = MTP::send(MTPchannels_EditAdmin(_channel->inputChannel, _addAdmin->inputUser, MTP_channelRoleEditor()), rpcDone(&Inner::addAdminDone), rpcFail(&Inner::addAdminFail));
}
void ContactsBox::Inner::onNoAddAdminBox(QObject *obj) {
if (obj == _addAdminBox) {
_addAdminBox = 0;
}
}
void ContactsBox::Inner::onAllAdminsChanged() {
if (_saving && _allAdmins->checked() != _allAdminsChecked) {
_allAdmins->setChecked(_allAdminsChecked);
@ -771,7 +734,7 @@ void ContactsBox::Inner::addAdminDone(const MTPUpdates &result, mtpRequestId req
}
Notify::peerUpdatedDelayed(update);
}
if (_addAdminBox) _addAdminBox->onClose();
if (_addAdminBox) _addAdminBox->closeBox();
emit adminAdded();
}
@ -781,13 +744,13 @@ bool ContactsBox::Inner::addAdminFail(const RPCError &error, mtpRequestId req) {
if (req != _addAdminRequestId) return true;
_addAdminRequestId = 0;
if (_addAdminBox) _addAdminBox->onClose();
if (_addAdminBox) _addAdminBox->closeBox();
if (error.type() == "USERS_TOO_MUCH") {
Ui::showLayer(new MaxInviteBox(_channel->inviteLink()), KeepOtherLayers);
Ui::show(Box<MaxInviteBox>(_channel->inviteLink()), KeepOtherLayers);
} else if (error.type() == "ADMINS_TOO_MUCH") {
Ui::showLayer(new InformBox(lang(lng_channel_admins_too_much)), KeepOtherLayers);
Ui::show(Box<InformBox>(lang(lng_channel_admins_too_much)), KeepOtherLayers);
} else if (error.type() == qstr("USER_RESTRICTED")) {
Ui::showLayer(new InformBox(lang(lng_cant_do_this)), KeepOtherLayers);
Ui::show(Box<InformBox>(lang(lng_cant_do_this)), KeepOtherLayers);
} else {
emit adminAdded();
}
@ -834,14 +797,14 @@ void ContactsBox::Inner::peerUpdated(PeerData *peer) {
for_const (auto row, _contacts->all()) {
if (row->attached == i.value()) {
row->attached = nullptr;
update(0, _aboutHeight + _rowHeight * row->pos(), width(), _rowHeight);
update(0, _rowsTop + _aboutHeight + _rowHeight * row->pos(), width(), _rowHeight);
}
}
if (!_filter.isEmpty()) {
for (int32 j = 0, s = _filtered.size(); j < s; ++j) {
if (_filtered[j]->attached == i.value()) {
_filtered[j]->attached = 0;
update(0, _rowHeight * j, width(), _rowHeight);
update(0, _rowsTop + _rowHeight * j, width(), _rowHeight);
}
}
}
@ -851,9 +814,11 @@ void ContactsBox::Inner::peerUpdated(PeerData *peer) {
}
}
void ContactsBox::Inner::loadProfilePhotos(int32 yFrom) {
if (!parentWidget()) return;
int32 yTo = yFrom + parentWidget()->height() * 5;
void ContactsBox::Inner::loadProfilePhotos() {
if (_visibleTop >= _visibleBottom) return;
auto yFrom = _visibleTop - _rowsTop;
auto yTo = yFrom + (_visibleBottom - _visibleTop) * 5;
MTP::clearLoaderPriorities();
if (yTo < 0) return;
@ -870,10 +835,10 @@ void ContactsBox::Inner::loadProfilePhotos(int32 yFrom) {
}
}
} else if (!_filtered.isEmpty()) {
int32 from = yFrom / _rowHeight;
auto from = yFrom / _rowHeight;
if (from < 0) from = 0;
if (from < _filtered.size()) {
int32 to = (yTo / _rowHeight) + 1;
auto to = (yTo / _rowHeight) + 1;
if (to > _filtered.size()) to = _filtered.size();
for (; from < to; ++from) {
@ -1047,8 +1012,10 @@ void ContactsBox::Inner::paintEvent(QPaintEvent *e) {
p.fillRect(r, st::contactsBg);
auto ms = getms();
int32 yFrom = r.y(), yTo = r.y() + r.height();
auto yFrom = r.y(), yTo = r.y() + r.height();
auto skip = _rowsTop;
if (_filter.isEmpty()) {
skip += _aboutHeight;
if (!_contacts->isEmpty() || !_byUsername.isEmpty()) {
if (_aboutHeight) {
auto infoTop = _allAdmins->bottomNoMargins() + st::contactsAllAdminsTop - st::lineWidth;
@ -1063,11 +1030,10 @@ void ContactsBox::Inner::paintEvent(QPaintEvent *e) {
int aboutw = width() - st::contactsPadding.left() - st::contactsPadding.right();
p.setPen(st::contactsAboutFg);
(_allAdmins->checked() ? _aboutAllAdmins : _aboutAdmins).draw(p, st::contactsPadding.left(), st::contactsAboutTop, aboutw);
yFrom -= _aboutHeight;
yTo -= _aboutHeight;
p.translate(0, _aboutHeight);
}
yFrom -= skip;
yTo -= skip;
p.translate(0, skip);
if (!_contacts->isEmpty()) {
auto i = _contacts->cfind(yFrom, _rowHeight);
p.translate(0, (*i)->pos() * _rowHeight);
@ -1103,7 +1069,7 @@ void ContactsBox::Inner::paintEvent(QPaintEvent *e) {
}
} else {
QString text;
int32 skip = 0;
skip = 0;
if (bot()) {
text = lang((cDialogsReceived() && !_searching) ? (sharingBotGame() ? lng_bot_no_chats : lng_bot_no_groups) : lng_contacts_loading);
} else if (_chat && _membersFilter == MembersFilter::Admins) {
@ -1126,8 +1092,8 @@ void ContactsBox::Inner::paintEvent(QPaintEvent *e) {
}
} else {
if (_filtered.isEmpty() && _byUsernameFiltered.isEmpty()) {
p.setFont(st::noContactsFont->f);
p.setPen(st::noContactsColor->p);
p.setFont(st::noContactsFont);
p.setPen(st::noContactsColor);
QString text;
if (bot()) {
text = lang((cDialogsReceived() && !_searching) ? (sharingBotGame() ? lng_bot_chats_not_found : lng_bot_groups_not_found) : lng_contacts_loading);
@ -1138,6 +1104,9 @@ void ContactsBox::Inner::paintEvent(QPaintEvent *e) {
}
p.drawText(QRect(0, 0, width(), st::noContactsHeight), text, style::al_center);
} else {
yFrom -= skip;
yTo -= skip;
p.translate(0, skip);
if (!_filtered.isEmpty()) {
int32 from = floorclamp(yFrom, _rowHeight, 0, _filtered.size());
int32 to = ceilclamp(yTo, _rowHeight, 0, _filtered.size());
@ -1177,15 +1146,15 @@ void ContactsBox::Inner::enterEvent(QEvent *e) {
int ContactsBox::Inner::getSelectedRowTop() const {
if (_filter.isEmpty()) {
if (_selected) {
return _aboutHeight + (_selected->pos() * _rowHeight);
return _rowsTop + _aboutHeight + (_selected->pos() * _rowHeight);
} else if (_searchedSelected >= 0) {
return _aboutHeight + (_contacts->size() * _rowHeight) + st::searchedBarHeight + (_searchedSelected * _rowHeight);
return _rowsTop + _aboutHeight + (_contacts->size() * _rowHeight) + st::searchedBarHeight + (_searchedSelected * _rowHeight);
}
} else {
if (_filteredSelected >= 0) {
return (_filteredSelected * _rowHeight);
return _rowsTop + (_filteredSelected * _rowHeight);
} else if (_searchedSelected >= 0) {
return (_filtered.size() * _rowHeight + st::searchedBarHeight + _searchedSelected * _rowHeight);
return _rowsTop + (_filtered.size() * _rowHeight + st::searchedBarHeight + _searchedSelected * _rowHeight);
}
}
return -1;
@ -1206,23 +1175,23 @@ int ContactsBox::Inner::getRowTopWithPeer(PeerData *peer) const {
if (_filter.isEmpty()) {
for (auto i = _contacts->cbegin(), end = _contacts->cend(); i != end; ++i) {
if ((*i)->history()->peer == peer) {
return _aboutHeight + ((*i)->pos() * _rowHeight);
return _rowsTop + _aboutHeight + ((*i)->pos() * _rowHeight);
}
}
for (auto i = 0, count = _byUsername.size(); i != count; ++i) {
if (_byUsername[i] == peer) {
return _aboutHeight + (_contacts->size() * _rowHeight) + st::searchedBarHeight + (i * _rowHeight);
return _rowsTop + _aboutHeight + (_contacts->size() * _rowHeight) + st::searchedBarHeight + (i * _rowHeight);
}
}
} else {
for (auto i = 0, count = _filtered.size(); i != count; ++i) {
if (_filtered[i]->history()->peer == peer) {
return (i * _rowHeight);
return _rowsTop + (i * _rowHeight);
}
}
for (auto i = 0, count = _byUsernameFiltered.size(); i != count; ++i) {
if (_byUsernameFiltered[i] == peer) {
return (_contacts->size() * _rowHeight) + st::searchedBarHeight + (i * _rowHeight);
return _rowsTop + (_contacts->size() * _rowHeight) + st::searchedBarHeight + (i * _rowHeight);
}
}
}
@ -1415,10 +1384,10 @@ void ContactsBox::Inner::chooseParticipant() {
_addAdminRequestId = 0;
}
if (_addAdminBox) _addAdminBox->deleteLater();
_addAdminBox = new ConfirmBox(lng_channel_admin_sure(lt_user, _addAdmin->firstName));
connect(_addAdminBox, SIGNAL(confirmed()), this, SLOT(onAddAdmin()));
connect(_addAdminBox, SIGNAL(destroyed(QObject*)), this, SLOT(onNoAddAdminBox(QObject*)));
Ui::showLayer(_addAdminBox, KeepOtherLayers);
_addAdminBox = Ui::show(Box<ConfirmBox>(lng_channel_admin_sure(lt_user, _addAdmin->firstName), base::lambda_guarded(this, [this] {
if (_addAdminRequestId) return;
_addAdminRequestId = MTP::send(MTPchannels_EditAdmin(_channel->inputChannel, _addAdmin->inputUser, MTP_channelRoleEditor()), rpcDone(&Inner::addAdminDone), rpcFail(&Inner::addAdminFail));
})), KeepOtherLayers);
} else if (sharingBotGame()) {
_addToPeer = peer;
auto confirmText = [peer] {
@ -1427,14 +1396,14 @@ void ContactsBox::Inner::chooseParticipant() {
}
return lng_bot_sure_share_game_group(lt_group, peer->name);
};
auto box = std_::make_unique<ConfirmBox>(confirmText());
connect(box.get(), SIGNAL(confirmed()), this, SLOT(onAddBot()));
Ui::showLayer(box.release(), KeepOtherLayers);
Ui::show(Box<ConfirmBox>(confirmText(), base::lambda_guarded(this, [this] {
addBot();
})), KeepOtherLayers);
} else if (bot() && (peer->isChat() || peer->isMegagroup())) {
_addToPeer = peer;
auto box = std_::make_unique<ConfirmBox>(lng_bot_sure_invite(lt_group, peer->name));
connect(box.get(), SIGNAL(confirmed()), this, SLOT(onAddBot()));
Ui::showLayer(box.release(), KeepOtherLayers);
Ui::show(Box<ConfirmBox>(lng_bot_sure_invite(lt_group, peer->name), base::lambda_guarded(this, [this] {
addBot();
})), KeepOtherLayers);
} else {
Ui::hideSettingsAndLayer(true);
App::main()->choosePeer(peer->id, ShowAtUnreadMsgId);
@ -1457,9 +1426,9 @@ void ContactsBox::Inner::changeCheckState(ContactData *data, PeerData *peer) {
} else if (selectedCount() < ((_channel && _channel->isMegagroup()) ? Global::MegagroupSizeMax() : Global::ChatSizeMax())) {
changePeerCheckState(data, peer, true);
} else if (_channel && !_channel->isMegagroup()) {
Ui::showLayer(new MaxInviteBox(_channel->inviteLink()), KeepOtherLayers);
Ui::show(Box<MaxInviteBox>(_channel->inviteLink()), KeepOtherLayers);
} else if (!_channel && selectedCount() >= Global::ChatSizeMax() && selectedCount() < Global::MegagroupSizeMax()) {
Ui::showLayer(new InformBox(lng_profile_add_more_after_upgrade(lt_count, Global::MegagroupSizeMax())), KeepOtherLayers);
Ui::show(Box<InformBox>(lng_profile_add_more_after_upgrade(lt_count, Global::MegagroupSizeMax())), KeepOtherLayers);
}
}
@ -1487,7 +1456,7 @@ void ContactsBox::Inner::changePeerCheckState(ContactData *data, PeerData *peer,
}
}
int32 ContactsBox::Inner::selectedCount() const {
int ContactsBox::Inner::selectedCount() const {
auto result = _checkedContacts.size();
if (_chat) {
result += qMax(_chat->count, 1);
@ -1499,11 +1468,18 @@ int32 ContactsBox::Inner::selectedCount() const {
return result;
}
void ContactsBox::Inner::setVisibleTopBottom(int visibleTop, int visibleBottom) {
_visibleTop = visibleTop;
_visibleBottom = visibleBottom;
loadProfilePhotos();
}
void ContactsBox::Inner::updateSelection() {
if (!_mouseSelection) return;
auto p = mapFromGlobal(_lastMousePos);
bool in = parentWidget()->rect().contains(parentWidget()->mapFromGlobal(_lastMousePos));
auto in = parentWidget()->rect().contains(parentWidget()->mapFromGlobal(_lastMousePos));
p.setY(p.y() - _rowsTop);
if (_filter.isEmpty()) {
_filteredSelected = -1;
setFilteredPressed(-1);
@ -1511,7 +1487,7 @@ void ContactsBox::Inner::updateSelection() {
p.setY(p.y() - _aboutHeight);
}
auto selected = (in && (p.y() >= 0) && (p.y() < _contacts->size() * _rowHeight)) ? _contacts->rowAtY(p.y(), _rowHeight) : nullptr;
auto searchedSelected = (in && p.y() >= _contacts->size() * _rowHeight + st::searchedBarHeight) ? ((p.y() - _contacts->size() * _rowHeight - st::searchedBarHeight) / _rowHeight) : -1;
auto searchedSelected = (in && (p.y() >= _contacts->size() * _rowHeight + st::searchedBarHeight)) ? ((p.y() - _contacts->size() * _rowHeight - st::searchedBarHeight) / _rowHeight) : -1;
if (searchedSelected >= _byUsername.size()) searchedSelected = -1;
if (_selected != selected || _searchedSelected != searchedSelected) {
updateSelectedRow();
@ -1522,8 +1498,8 @@ void ContactsBox::Inner::updateSelection() {
} else {
_selected = nullptr;
setPressed(nullptr);
auto filteredSelected = (in && p.y() >= 0 && p.y() < _filtered.size() * _rowHeight) ? (p.y() / _rowHeight) : -1;
auto searchedSelected = (in && p.y() >= _filtered.size() * _rowHeight + st::searchedBarHeight) ? ((p.y() - _filtered.size() * _rowHeight - st::searchedBarHeight) / _rowHeight) : -1;
auto filteredSelected = (in && (p.y() >= 0) && (p.y() < _filtered.size() * _rowHeight)) ? (p.y() / _rowHeight) : -1;
auto searchedSelected = (in && (p.y() >= _filtered.size() * _rowHeight + st::searchedBarHeight)) ? ((p.y() - _filtered.size() * _rowHeight - st::searchedBarHeight) / _rowHeight) : -1;
if (searchedSelected >= _byUsernameFiltered.size()) searchedSelected = -1;
if (_filteredSelected != filteredSelected || _searchedSelected != searchedSelected) {
updateSelectedRow();
@ -1653,7 +1629,7 @@ void ContactsBox::Inner::updateFilter(QString filter) {
}
}
update();
loadProfilePhotos(0);
loadProfilePhotos();
}
}
@ -1760,10 +1736,10 @@ void ContactsBox::Inner::refresh() {
}
if (!_contacts->isEmpty() || !_byUsername.isEmpty()) {
if (!_addContactLnk->isHidden()) _addContactLnk->hide();
resize(width(), _aboutHeight + (_contacts->size() * _rowHeight) + (_byUsername.isEmpty() ? 0 : (st::searchedBarHeight + _byUsername.size() * _rowHeight)));
resize(width(), _rowsTop + _aboutHeight + (_contacts->size() * _rowHeight) + (_byUsername.isEmpty() ? 0 : (st::searchedBarHeight + _byUsername.size() * _rowHeight)) + st::contactsMarginBottom);
} else if (_chat && _membersFilter == MembersFilter::Admins) {
if (!_addContactLnk->isHidden()) _addContactLnk->hide();
resize(width(), _aboutHeight + st::noContactsHeight);
resize(width(), _rowsTop + _aboutHeight + st::noContactsHeight + st::contactsMarginBottom);
} else {
if (cContactsReceived() && !bot()) {
if (_addContactLnk->isHidden()) _addContactLnk->show();
@ -1778,9 +1754,10 @@ void ContactsBox::Inner::refresh() {
if (!_addContactLnk->isHidden()) _addContactLnk->hide();
resize(width(), st::noContactsHeight);
} else {
resize(width(), (_filtered.size() * _rowHeight) + (_byUsernameFiltered.isEmpty() ? 0 : (st::searchedBarHeight + _byUsernameFiltered.size() * _rowHeight)));
resize(width(), _rowsTop + (_filtered.size() * _rowHeight) + (_byUsernameFiltered.isEmpty() ? 0 : (st::searchedBarHeight + _byUsernameFiltered.size() * _rowHeight)) + st::contactsMarginBottom);
}
}
loadProfilePhotos();
update();
}
@ -1902,9 +1879,9 @@ void ContactsBox::Inner::selectSkip(int32 dir) {
}
}
if (_selected) {
emit mustScrollTo(_aboutHeight + _selected->pos() * _rowHeight, _aboutHeight + (_selected->pos() + 1) * _rowHeight);
emit mustScrollTo(_rowsTop + _aboutHeight + _selected->pos() * _rowHeight, _rowsTop + _aboutHeight + (_selected->pos() + 1) * _rowHeight);
} else if (_searchedSelected >= 0) {
emit mustScrollTo(_aboutHeight + (_contacts->size() + _searchedSelected) * _rowHeight + st::searchedBarHeight, _aboutHeight + (_contacts->size() + _searchedSelected + 1) * _rowHeight + st::searchedBarHeight);
emit mustScrollTo(_rowsTop + _aboutHeight + (_contacts->size() + _searchedSelected) * _rowHeight + st::searchedBarHeight, _rowsTop + _aboutHeight + (_contacts->size() + _searchedSelected + 1) * _rowHeight + st::searchedBarHeight);
}
} else {
int cur = (_filteredSelected >= 0) ? _filteredSelected : ((_searchedSelected >= 0) ? (_filtered.size() + _searchedSelected) : -1);
@ -1948,10 +1925,10 @@ void ContactsBox::Inner::selectSkip(int32 dir) {
}
}
if (_filteredSelected >= 0) {
emit mustScrollTo(_filteredSelected * _rowHeight, (_filteredSelected + 1) * _rowHeight);
emit mustScrollTo(_rowsTop + _filteredSelected * _rowHeight, _rowsTop + (_filteredSelected + 1) * _rowHeight);
} else if (_searchedSelected >= 0) {
int skip = _filtered.size() * _rowHeight + st::searchedBarHeight;
emit mustScrollTo(skip + _searchedSelected * _rowHeight, skip + (_searchedSelected + 1) * _rowHeight);
emit mustScrollTo(_rowsTop + skip + _searchedSelected * _rowHeight, _rowsTop + skip + (_searchedSelected + 1) * _rowHeight);
}
}
update();

View File

@ -32,7 +32,6 @@ class IndexedList;
namespace Ui {
class RippleAnimation;
class RoundButton;
class LinkButton;
class Checkbox;
class MultiSelect;
@ -48,64 +47,79 @@ inline Ui::RoundImageCheckbox::PaintRoundImage PaintUserpicCallback(PeerData *pe
};
}
class ContactsBox : public ItemListBox, public RPCSender {
class ContactsBox : public BoxContent, public RPCSender {
Q_OBJECT
public:
ContactsBox();
ContactsBox(const QString &name, const QImage &photo); // group creation
ContactsBox(ChannelData *channel); // channel setup
ContactsBox(ChannelData *channel, MembersFilter filter, const MembersAlreadyIn &already);
ContactsBox(ChatData *chat, MembersFilter filter);
ContactsBox(UserData *bot);
ContactsBox(QWidget*);
ContactsBox(QWidget*, const QString &name, const QImage &photo); // group creation
ContactsBox(QWidget*, ChannelData *channel); // channel setup
ContactsBox(QWidget*, ChannelData *channel, MembersFilter filter, const MembersAlreadyIn &already);
ContactsBox(QWidget*, ChatData *chat, MembersFilter filter);
ContactsBox(QWidget*, UserData *bot);
void closeHook() override;
signals:
void adminAdded();
private slots:
void onScroll();
void onInvite();
void onCreate();
void onSaveAdmins();
void onSubmit();
bool onSearchByUsername(bool searchCache = false);
void onNeedSearchByUsername();
protected:
void prepare() override;
void setInnerFocus() override;
void keyPressEvent(QKeyEvent *e) override;
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void closePressed() override;
void doSetInnerFocus() override;
private:
void init();
object_ptr<Ui::WidgetSlideWrap<Ui::MultiSelect>> createMultiSelect();
void updateTitle();
int getTopScrollSkip() const;
void updateScrollSkips();
void onFilterUpdate(const QString &filter);
void onPeerSelectedChanged(PeerData *peer, bool checked);
void addPeerToMultiSelect(PeerData *peer, bool skipAnimation = false);
class Inner;
ChildWidget<Inner> _inner;
ChildWidget<Ui::WidgetSlideWrap<Ui::MultiSelect>> _select;
ChildWidget<MembersAddButton> _add = { nullptr };
ChildWidget<Ui::RoundButton> _next;
ChildWidget<Ui::RoundButton> _cancel;
MembersFilter _membersFilter;
ChildWidget<ScrollableBoxShadow> _topShadow;
ChildWidget<ScrollableBoxShadow> _bottomShadow = { nullptr };
void saveChatAdmins();
void inviteParticipants();
void createGroup();
// global search
void peopleReceived(const MTPcontacts_Found &result, mtpRequestId req);
bool peopleFailed(const RPCError &error, mtpRequestId req);
QTimer _searchTimer;
// saving admins
void saveAdminsDone(const MTPUpdates &result);
void saveSelectedAdmins();
void getAdminsDone(const MTPmessages_ChatFull &result);
void setAdminDone(UserData *user, const MTPBool &result);
void removeAdminDone(UserData *user, const MTPBool &result);
bool saveAdminsFail(const RPCError &error);
bool editAdminFail(const RPCError &error);
// group creation
void creationDone(const MTPUpdates &updates);
bool creationFail(const RPCError &e);
ChatData *_chat = nullptr;
ChannelData *_channel = nullptr;
MembersFilter _membersFilter = MembersFilter::Recent;
UserData *_bot = nullptr;
CreatingGroupType _creating = CreatingGroupNone;
MembersAlreadyIn _alreadyIn;
object_ptr<Ui::WidgetSlideWrap<Ui::MultiSelect>> _select;
class Inner;
QPointer<Inner> _inner;
object_ptr<QTimer> _searchTimer;
QString _peopleQuery;
bool _peopleFull;
mtpRequestId _peopleRequest;
@ -118,22 +132,9 @@ private:
mtpRequestId _saveRequestId = 0;
// saving admins
void saveAdminsDone(const MTPUpdates &result);
void saveSelectedAdmins();
void getAdminsDone(const MTPmessages_ChatFull &result);
void setAdminDone(UserData *user, const MTPBool &result);
void removeAdminDone(UserData *user, const MTPBool &result);
bool saveAdminsFail(const RPCError &error);
bool editAdminFail(const RPCError &error);
// group creation
QString _creationName;
QImage _creationPhoto;
void creationDone(const MTPUpdates &updates);
bool creationFail(const RPCError &e);
};
// This class is hold in header because it requires Qt preprocessing.
@ -162,7 +163,6 @@ public:
_allAdminsChangedCallback = std_::move(allAdminsChangedCallback);
}
void loadProfilePhotos(int32 yFrom);
void chooseParticipant();
void peopleReceived(const QString &query, const QVector<MTPPeer> &people);
@ -177,13 +177,15 @@ public:
bool sharingBotGame() const;
int32 selectedCount() const;
int selectedCount() const;
bool hasAlreadyMembersInChannel() const {
return !_already.isEmpty();
}
void saving(bool flag);
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
~Inner();
signals:
@ -197,10 +199,6 @@ private slots:
void peerUpdated(PeerData *peer);
void onPeerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars);
void onAddBot();
void onAddAdmin();
void onNoAddAdminBox(QObject *obj);
void onAllAdminsChanged();
protected:
@ -233,6 +231,9 @@ private:
void setSearchedPressed(int pressed);
void clearSearchedContactDatas();
void loadProfilePhotos();
void addBot();
void init();
void initList();
@ -264,7 +265,10 @@ private:
base::lambda<void(PeerData *peer, bool selected)> _peerSelectedChangedCallback;
int _rowHeight;
int _visibleTop = 0;
int _visibleBottom = 0;
int _rowHeight = 0;
int _rowsTop = 0;
int _aboutHeight = 0;
ChatData *_chat = nullptr;
@ -274,7 +278,7 @@ private:
CreatingGroupType _creating = CreatingGroupNone;
MembersAlreadyIn _already;
ChildWidget<Ui::Checkbox> _allAdmins;
object_ptr<Ui::Checkbox> _allAdmins;
int32 _aboutWidth;
Text _aboutAllAdmins, _aboutAdmins;
base::lambda<void()> _allAdminsChangedCallback;
@ -282,7 +286,7 @@ private:
PeerData *_addToPeer = nullptr;
UserData *_addAdmin = nullptr;
mtpRequestId _addAdminRequestId = 0;
ConfirmBox *_addAdminBox = nullptr;
QPointer<ConfirmBox> _addAdminBox;
int32 _time;
@ -315,7 +319,7 @@ private:
int _searchedPressed = -1;
QPoint _lastMousePos;
ChildWidget<Ui::LinkButton> _addContactLnk;
object_ptr<Ui::LinkButton> _addContactLnk;
bool _saving = false;
bool _allAdminsChecked = false;

View File

@ -29,19 +29,20 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "pspecific.h"
#include "styles/style_boxes.h"
DownloadPathBox::DownloadPathBox() : AbstractBox()
, _path(Global::DownloadPath())
DownloadPathBox::DownloadPathBox(QWidget *parent)
: _path(Global::DownloadPath())
, _pathBookmark(Global::DownloadPathBookmark())
, _default(this, qsl("dir_type"), 0, lang(lng_download_path_default_radio), _path.isEmpty(), st::defaultBoxCheckbox)
, _temp(this, qsl("dir_type"), 1, lang(lng_download_path_temp_radio), (_path == qsl("tmp")), st::defaultBoxCheckbox)
, _dir(this, qsl("dir_type"), 2, lang(lng_download_path_dir_radio), (!_path.isEmpty() && _path != qsl("tmp")), st::defaultBoxCheckbox)
, _pathLink(this, QString(), st::boxLinkButton)
, _save(this, lang(lng_connection_save), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
setTitleText(lang(lng_download_path_header));
, _pathLink(this, QString(), st::boxLinkButton) {
}
connect(_save, SIGNAL(clicked()), this, SLOT(onSave()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
void DownloadPathBox::prepare() {
addButton(lang(lng_connection_save), [this] { save(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
setTitle(lang(lng_download_path_header));
connect(_default, SIGNAL(changed()), this, SLOT(onChange()));
connect(_temp, SIGNAL(changed()), this, SLOT(onChange()));
@ -57,25 +58,25 @@ DownloadPathBox::DownloadPathBox() : AbstractBox()
void DownloadPathBox::updateControlsVisibility() {
_pathLink->setVisible(_dir->checked());
int32 h = titleHeight() + st::boxOptionListPadding.top() + _default->heightNoMargins() + st::boxOptionListPadding.top() + _temp->heightNoMargins() + st::boxOptionListPadding.top() + _dir->heightNoMargins();
if (_dir->checked()) h += st::downloadPathSkip + _pathLink->height();
h += st::boxOptionListPadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom();
auto newHeight = st::boxOptionListPadding.top() + _default->heightNoMargins() + st::boxOptionListSkip + _temp->heightNoMargins() + st::boxOptionListSkip + _dir->heightNoMargins();
if (_dir->checked()) {
newHeight += st::downloadPathSkip + _pathLink->height();
}
newHeight += st::boxOptionListPadding.bottom();
setMaxHeight(h);
setDimensions(st::boxWideWidth, newHeight);
}
void DownloadPathBox::resizeEvent(QResizeEvent *e) {
_default->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), titleHeight() + st::boxOptionListPadding.top());
_temp->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _default->bottomNoMargins() + st::boxOptionListPadding.top());
_dir->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _temp->bottomNoMargins() + st::boxOptionListPadding.top());
int32 inputx = st::boxPadding.left() + st::boxOptionListPadding.left() + st::defaultBoxCheckbox.textPosition.x();
int32 inputy = _dir->bottomNoMargins() + st::downloadPathSkip;
BoxContent::resizeEvent(e);
_default->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), st::boxOptionListPadding.top());
_temp->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _default->bottomNoMargins() + st::boxOptionListSkip);
_dir->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _temp->bottomNoMargins() + st::boxOptionListSkip);
auto inputx = st::boxPadding.left() + st::boxOptionListPadding.left() + st::defaultBoxCheckbox.textPosition.x();
auto inputy = _dir->bottomNoMargins() + st::downloadPathSkip;
_pathLink->moveToLeft(inputx, inputy);
_save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _save->width() + st::boxButtonPadding.left(), _save->y());
AbstractBox::resizeEvent(e);
}
void DownloadPathBox::onChange() {
@ -114,15 +115,15 @@ void DownloadPathBox::onEditPath() {
cSetDialogLastPath(lastPath);
}
void DownloadPathBox::onSave() {
void DownloadPathBox::save() {
Global::SetDownloadPath(_default->checked() ? QString() : (_temp->checked() ? qsl("tmp") : _path));
Global::SetDownloadPathBookmark((_default->checked() || _temp->checked()) ? QByteArray() : _pathBookmark);
Local::writeUserSettings();
Global::RefDownloadPathChanged().notify();
onClose();
closeBox();
}
void DownloadPathBox::setPathText(const QString &text) {
int32 availw = st::boxWideWidth - st::boxPadding.left() - st::defaultBoxCheckbox.textPosition.x() - st::boxPadding.right();
auto availw = st::boxWideWidth - st::boxPadding.left() - st::defaultBoxCheckbox.textPosition.x() - st::boxPadding.right();
_pathLink->setText(st::boxTextFont->elided(text, availw));
}

View File

@ -26,36 +26,34 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Ui {
class Radiobutton;
class LinkButton;
class RoundButton;
} // namespace Ui
class DownloadPathBox : public AbstractBox {
class DownloadPathBox : public BoxContent {
Q_OBJECT
public:
DownloadPathBox();
public slots:
void onChange();
void onEditPath();
void onSave();
DownloadPathBox(QWidget *parent);
protected:
void prepare() override;
void resizeEvent(QResizeEvent *e) override;
private slots:
void onChange();
void onEditPath();
private:
void save();
void updateControlsVisibility();
void setPathText(const QString &text);
QString _path;
QByteArray _pathBookmark;
ChildWidget<Ui::Radiobutton> _default;
ChildWidget<Ui::Radiobutton> _temp;
ChildWidget<Ui::Radiobutton> _dir;
ChildWidget<Ui::LinkButton> _pathLink;
ChildWidget<Ui::RoundButton> _save;
ChildWidget<Ui::RoundButton> _cancel;
object_ptr<Ui::Radiobutton> _default;
object_ptr<Ui::Radiobutton> _temp;
object_ptr<Ui::Radiobutton> _dir;
object_ptr<Ui::LinkButton> _pathLink;
};

View File

@ -71,17 +71,18 @@ namespace {
const uint32 replacesCount = sizeof(replaces) / sizeof(EmojiReplace), replacesInRow = 7;
}
EmojiBox::EmojiBox() : _esize(EmojiSizes[EIndex + 1]) {
setTitleText(lang(lng_settings_emoji_list));
setBlockTitle(true);
EmojiBox::EmojiBox(QWidget*) : _esize(EmojiSizes[EIndex + 1]) {
}
void EmojiBox::prepare() {
setTitle(lang(lng_settings_emoji_list));
fillBlocks();
addButton(lang(lng_close), [this] { closeBox(); });
_blockHeight = st::emojiReplaceInnerHeight;
resizeMaxHeight(_blocks[0].size() * st::emojiReplaceWidth + 2 * st::emojiReplacePadding, titleHeight() + st::emojiReplacePadding + _blocks.size() * st::emojiReplaceHeight + (st::emojiReplaceHeight - _blockHeight) + st::emojiReplacePadding);
raiseShadow();
setDimensions(_blocks[0].size() * st::emojiReplaceWidth + 2 * st::emojiReplacePadding, st::emojiReplacePadding + _blocks.size() * st::emojiReplaceHeight + (st::emojiReplaceHeight - _blockHeight) + st::emojiReplacePadding);
}
void EmojiBox::fillBlocks() {
@ -116,20 +117,20 @@ void EmojiBox::fillBlocks() {
void EmojiBox::keyPressEvent(QKeyEvent *e) {
if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
onClose();
closeBox();
} else {
AbstractBox::keyPressEvent(e);
BoxContent::keyPressEvent(e);
}
}
void EmojiBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e);
BoxContent::paintEvent(e);
Painter p(this);
p.setFont(st::emojiTextFont);
p.setPen(st::boxTextFg);
int32 top = titleHeight() + st::emojiReplacePadding + (st::emojiReplaceHeight - _blockHeight) / 2;
auto top = st::emojiReplacePadding + (st::emojiReplaceHeight - _blockHeight) / 2;
for (Blocks::const_iterator i = _blocks.cbegin(), e = _blocks.cend(); i != e; ++i) {
int32 rowSize = i->size(), left = (width() - rowSize * st::emojiReplaceWidth) / 2;
for (BlockRow::const_iterator j = i->cbegin(), en = i->cend(); j != en; ++j) {

View File

@ -22,13 +22,13 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "boxes/abstractbox.h"
class EmojiBox : public AbstractBox {
Q_OBJECT
class EmojiBox : public BoxContent {
public:
EmojiBox();
EmojiBox(QWidget*);
protected:
void prepare() override;
void keyPressEvent(QKeyEvent *e) override;
void paintEvent(QPaintEvent *e) override;

View File

@ -31,21 +31,22 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "langloaderplain.h"
#include "styles/style_boxes.h"
LanguageBox::LanguageBox() :
_close(this, lang(lng_box_ok), st::defaultBoxButton) {
setTitleText(lang(lng_languages));
void LanguageBox::prepare() {
addButton(lang(lng_box_ok), [this] { closeBox(); });
bool haveTestLang = (cLang() == languageTest);
setTitle(lang(lng_languages));
int32 y = titleHeight() + st::boxOptionListPadding.top();
auto haveTestLang = (cLang() == languageTest);
auto y = st::boxOptionListPadding.top();
_langs.reserve(languageCount + (haveTestLang ? 1 : 0));
if (haveTestLang) {
_langs.push_back(new Ui::Radiobutton(this, qsl("lang"), languageTest, qsl("Custom Lang"), (cLang() == languageTest), st::langsButton));
_langs.back()->move(st::boxPadding.left() + st::boxOptionListPadding.left(), y);
y += _langs.back()->heightNoMargins() + st::boxOptionListPadding.top();
y += _langs.back()->heightNoMargins() + st::boxOptionListSkip;
connect(_langs.back(), SIGNAL(changed()), this, SLOT(onChange()));
}
for (int32 i = 0; i < languageCount; ++i) {
for (auto i = 0; i != languageCount; ++i) {
LangLoaderResult result;
if (i) {
LangLoaderPlain loader(qsl(":/langs/lang_") + LanguageCodes[i].c_str() + qsl(".strings"), langLoaderRequest(lng_language_name));
@ -55,15 +56,12 @@ _close(this, lang(lng_box_ok), st::defaultBoxButton) {
}
_langs.push_back(new Ui::Radiobutton(this, qsl("lang"), i, result.value(lng_language_name, LanguageCodes[i].c_str() + qsl(" language")), (cLang() == i), st::langsButton));
_langs.back()->move(st::boxPadding.left() + st::boxOptionListPadding.left(), y);
y += _langs.back()->heightNoMargins() + st::boxOptionListPadding.top();
y += _langs.back()->heightNoMargins() + st::boxOptionListSkip;
connect(_langs.back(), SIGNAL(changed()), this, SLOT(onChange()));
}
resizeMaxHeight(st::langsWidth, titleHeight() + (languageCount + (haveTestLang ? 1 : 0)) * (st::boxOptionListPadding.top() + st::langsButton.height) + st::boxOptionListPadding.bottom() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _close->height() + st::boxButtonPadding.bottom());
connect(_close, SIGNAL(clicked()), this, SLOT(onClose()));
_close->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _close->height());
auto optionsCount = languageCount + (haveTestLang ? 1 : 0);
setDimensions(st::langsWidth, st::boxOptionListPadding.top() + optionsCount * st::langsButton.height + (optionsCount - 1) * st::boxOptionListSkip + st::boxOptionListPadding.bottom() + st::boxPadding.bottom());
}
void LanguageBox::mousePressEvent(QMouseEvent *e) {
@ -71,21 +69,21 @@ void LanguageBox::mousePressEvent(QMouseEvent *e) {
for (int32 i = 1; i < languageCount; ++i) {
LangLoaderPlain loader(qsl(":/langs/lang_") + LanguageCodes[i].c_str() + qsl(".strings"), langLoaderRequest(lngkeys_cnt));
if (!loader.errors().isEmpty()) {
Ui::showLayer(new InformBox(qsl("Lang \"") + LanguageCodes[i].c_str() + qsl("\" error :(\n\nError: ") + loader.errors()));
Ui::show(Box<InformBox>(qsl("Lang \"") + LanguageCodes[i].c_str() + qsl("\" error :(\n\nError: ") + loader.errors()));
return;
} else if (!loader.warnings().isEmpty()) {
QString warn = loader.warnings();
if (warn.size() > 256) warn = warn.mid(0, 253) + qsl("...");
Ui::showLayer(new InformBox(qsl("Lang \"") + LanguageCodes[i].c_str() + qsl("\" warnings :(\n\nWarnings: ") + warn));
Ui::show(Box<InformBox>(qsl("Lang \"") + LanguageCodes[i].c_str() + qsl("\" warnings :(\n\nWarnings: ") + warn));
return;
}
}
Ui::showLayer(new InformBox(qsl("Everything seems great in all %1 languages!").arg(languageCount - 1)));
Ui::show(Box<InformBox>(qsl("Everything seems great in all %1 languages!").arg(languageCount - 1)));
}
}
void LanguageBox::onChange() {
if (isHidden()) return;
if (!isBoxShown()) return;
for (int32 i = 0, l = _langs.size(); i < l; ++i) {
int32 langId = _langs[i]->val();
@ -98,27 +96,28 @@ void LanguageBox::onChange() {
LangLoaderPlain loader(cLangFile(), langLoaderRequest(lng_sure_save_language, lng_cancel, lng_box_ok));
result = loader.found();
}
QString text = result.value(lng_sure_save_language, langOriginal(lng_sure_save_language)),
save = result.value(lng_box_ok, langOriginal(lng_box_ok)),
cancel = result.value(lng_cancel, langOriginal(lng_cancel));
ConfirmBox *box = new ConfirmBox(text, save, st::defaultBoxButton, cancel);
connect(box, SIGNAL(confirmed()), this, SLOT(onSave()));
connect(box, SIGNAL(cancelled()), this, SLOT(onRestore()));
Ui::showLayer(box, KeepOtherLayers);
auto text = result.value(lng_sure_save_language, langOriginal(lng_sure_save_language)),
save = result.value(lng_box_ok, langOriginal(lng_box_ok)),
cancel = result.value(lng_cancel, langOriginal(lng_cancel));
Ui::show(Box<ConfirmBox>(text, save, cancel, base::lambda_guarded(this, [this] {
saveLanguage();
}), base::lambda_guarded(this, [this] {
restoreLanguage();
})), KeepOtherLayers);
}
}
}
void LanguageBox::onRestore() {
for (int32 i = 0, l = _langs.size(); i < l; ++i) {
void LanguageBox::restoreLanguage() {
for (auto i = 0, l = _langs.size(); i != l; ++i) {
if (_langs[i]->val() == cLang()) {
_langs[i]->setChecked(true);
}
}
}
void LanguageBox::onSave() {
for (int32 i = 0, l = _langs.size(); i < l; ++i) {
void LanguageBox::saveLanguage() {
for (auto i = 0, l = _langs.size(); i != l; ++i) {
if (_langs[i]->checked()) {
cSetLang(_langs[i]->val());
Local::writeSettings();

View File

@ -24,25 +24,27 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Ui {
class Radiobutton;
class RoundButton;
} // namespace Ui
class LanguageBox : public AbstractBox {
class LanguageBox : public BoxContent {
Q_OBJECT
public:
LanguageBox();
public slots:
void onChange();
void onRestore();
void onSave();
LanguageBox(QWidget*) {
}
protected:
void prepare() override;
void mousePressEvent(QMouseEvent *e) override;
private slots:
void onChange();
private:
void saveLanguage();
void restoreLanguage();
QVector<Ui::Radiobutton*> _langs;
ChildWidget<Ui::RoundButton> _close;
};

View File

@ -27,13 +27,16 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "lang.h"
#include "mainwindow.h"
LocalStorageBox::LocalStorageBox() : AbstractBox()
, _clear(this, lang(lng_local_storage_clear), st::boxLinkButton)
, _close(this, lang(lng_box_ok), st::defaultBoxButton) {
setTitleText(lang(lng_local_storage_title));
LocalStorageBox::LocalStorageBox(QWidget *parent)
: _clear(this, lang(lng_local_storage_clear), st::boxLinkButton) {
}
connect(_clear, SIGNAL(clicked()), this, SLOT(onClear()));
connect(_close, SIGNAL(clicked()), this, SLOT(onClose()));
void LocalStorageBox::prepare() {
setTitle(lang(lng_local_storage_title));
addButton(lang(lng_box_ok), [this] { closeBox(); });
_clear->setClickedCallback([this] { clearStorage(); });
connect(App::wnd(), SIGNAL(tempDirCleared(int)), this, SLOT(onTempDirCleared(int)));
connect(App::wnd(), SIGNAL(tempDirClearFailed(int)), this, SLOT(onTempDirClearFailed(int)));
@ -46,16 +49,15 @@ LocalStorageBox::LocalStorageBox() : AbstractBox()
}
void LocalStorageBox::updateControls() {
int rowsHeight = 0;
auto rowsHeight = 0;
if (_imagesCount > 0 && _audiosCount > 0) {
rowsHeight = 2 * (st::linkFont->height + st::localStorageBoxSkip);
} else {
rowsHeight = st::linkFont->height + st::localStorageBoxSkip;
}
_clear->setVisible(_imagesCount > 0 || _audiosCount > 0);
setMaxHeight(titleHeight() + st::localStorageBoxSkip + rowsHeight + _clear->height() + st::boxButtonPadding.top() + _close->height() + st::boxButtonPadding.bottom());
_clear->moveToLeft(st::boxPadding.left(), titleHeight() + st::localStorageBoxSkip + rowsHeight);
_close->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _close->height());
setDimensions(st::boxWidth, st::localStorageBoxSkip + rowsHeight + _clear->height());
_clear->moveToLeft(st::boxPadding.left(), st::localStorageBoxSkip + rowsHeight);
update();
}
@ -73,14 +75,14 @@ void LocalStorageBox::checkLocalStoredCounts() {
}
void LocalStorageBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e);
BoxContent::paintEvent(e);
Painter p(this);
p.setFont(st::boxTextFont);
p.setPen(st::windowFg);
checkLocalStoredCounts();
int top = titleHeight() + st::localStorageBoxSkip;
auto top = st::localStorageBoxSkip;
if (_imagesCount > 0) {
auto text = lng_settings_images_cached(lt_count, _imagesCount, lt_size, formatSizeText(Local::storageImagesSize() + Local::storageStickersSize() + Local::storageWebFilesSize()));
p.drawTextLeft(st::boxPadding.left(), top, width(), text);
@ -108,7 +110,7 @@ void LocalStorageBox::paintEvent(QPaintEvent *e) {
}
}
void LocalStorageBox::onClear() {
void LocalStorageBox::clearStorage() {
App::wnd()->tempDirDelete(Local::ClearManagerStorage);
_state = State::Clearing;
updateControls();

View File

@ -23,25 +23,26 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "boxes/abstractbox.h"
namespace Ui {
class RoundButton;
class LinkButton;
} // namespace Ui
class LocalStorageBox : public AbstractBox {
class LocalStorageBox : public BoxContent {
Q_OBJECT
public:
LocalStorageBox();
LocalStorageBox(QWidget*);
private slots:
void onClear();
void onTempDirCleared(int task);
void onTempDirClearFailed(int task);
protected:
void prepare() override;
void paintEvent(QPaintEvent *e) override;
private:
void clearStorage();
void updateControls();
void checkLocalStoredCounts();
@ -53,8 +54,7 @@ private:
};
State _state = State::Normal;
ChildWidget<Ui::LinkButton> _clear;
ChildWidget<Ui::RoundButton> _close;
object_ptr<Ui::LinkButton> _clear;
int _imagesCount = -1;
int _audiosCount = -1;

View File

@ -60,22 +60,26 @@ QPoint MembersAddButton::prepareRippleStartPosition() const {
return mapFromGlobal(QCursor::pos()) - _st.rippleAreaPosition;
}
MembersBox::MembersBox(ChannelData *channel, MembersFilter filter) : ItemListBox(st::boxScroll)
, _inner(this, channel, filter) {
ItemListBox::init(_inner);
MembersBox::MembersBox(QWidget*, ChannelData *channel, MembersFilter filter)
: _channel(channel)
, _filter(filter) {
}
setTitleText(lang(_inner->filter() == MembersFilter::Recent ? lng_channel_members : lng_channel_admins));
if (channel->amCreator() && (channel->membersCount() < (channel->isMegagroup() ? Global::MegagroupSizeMax() : Global::ChatSizeMax()) || (!channel->isMegagroup() && !channel->isPublic()) || filter == MembersFilter::Admins)) {
_add.create(this, st::contactsAdd);
_add->setClickedCallback([this] { onAdd(); });
void MembersBox::prepare() {
setTitle(lang(_filter == MembersFilter::Recent ? lng_channel_members : lng_channel_admins));
_inner = setInnerWidget(object_ptr<Inner>(this, _channel, _filter), st::boxLayerScroll);
setDimensions(st::boxWideWidth, st::boxMaxListHeight);
addButton(lang(lng_close), [this] { closeBox(); });
if (_channel->amCreator() && (_channel->membersCount() < (_channel->isMegagroup() ? Global::MegagroupSizeMax() : Global::ChatSizeMax()) || (!_channel->isMegagroup() && !_channel->isPublic()) || _filter == MembersFilter::Admins)) {
addLeftButton(lang((_filter == MembersFilter::Admins) ? lng_channel_add_admin : lng_channel_add_members), [this] { onAdd(); });
}
connect(scrollArea(), SIGNAL(scrolled()), this, SLOT(onScroll()));
connect(_inner, SIGNAL(mustScrollTo(int, int)), scrollArea(), SLOT(scrollToY(int, int)));
connect(_inner, SIGNAL(mustScrollTo(int, int)), this, SLOT(onScrollToY(int, int)));
connect(&_loadTimer, SIGNAL(timeout()), _inner, SLOT(load()));
raiseShadow();
_loadTimer.create(this);
connect(_loadTimer, SIGNAL(timeout()), _inner, SLOT(load()));
}
void MembersBox::keyPressEvent(QKeyEvent *e) {
@ -84,47 +88,41 @@ void MembersBox::keyPressEvent(QKeyEvent *e) {
} else if (e->key() == Qt::Key_Up) {
_inner->selectSkip(-1);
} else if (e->key() == Qt::Key_PageDown) {
_inner->selectSkipPage(scrollArea()->height(), 1);
_inner->selectSkipPage(height(), 1);
} else if (e->key() == Qt::Key_PageUp) {
_inner->selectSkipPage(scrollArea()->height(), -1);
_inner->selectSkipPage(height(), -1);
} else {
ItemListBox::keyPressEvent(e);
BoxContent::keyPressEvent(e);
}
}
void MembersBox::resizeEvent(QResizeEvent *e) {
ItemListBox::resizeEvent(e);
BoxContent::resizeEvent(e);
_inner->resize(width(), _inner->height());
if (_add) {
_add->moveToRight(st::contactsAddPosition.x(), height() - st::contactsAddPosition.y() - _add->height());
}
}
void MembersBox::onScroll() {
_inner->loadProfilePhotos(scrollArea()->scrollTop());
}
void MembersBox::onAdd() {
if (_inner->filter() == MembersFilter::Recent && _inner->channel()->membersCount() >= (_inner->channel()->isMegagroup() ? Global::MegagroupSizeMax() : Global::ChatSizeMax())) {
Ui::showLayer(new MaxInviteBox(_inner->channel()->inviteLink()), KeepOtherLayers);
Ui::show(Box<MaxInviteBox>(_inner->channel()->inviteLink()), KeepOtherLayers);
return;
}
ContactsBox *box = new ContactsBox(_inner->channel(), _inner->filter(), _inner->already());
auto box = Box<ContactsBox>(_inner->channel(), _inner->filter(), _inner->already());
if (_inner->filter() == MembersFilter::Recent) {
Ui::showLayer(box);
Ui::show(std_::move(box));
} else {
_addBox = box;
connect(_addBox, SIGNAL(adminAdded()), this, SLOT(onAdminAdded()));
Ui::showLayer(_addBox, KeepOtherLayers);
_addBox = Ui::show(std_::move(box), KeepOtherLayers);
if (_addBox) {
connect(_addBox, SIGNAL(adminAdded()), this, SLOT(onAdminAdded()));
}
}
}
void MembersBox::onAdminAdded() {
if (!_addBox) return;
_addBox->onClose();
_addBox = 0;
_loadTimer.start(ReloadChannelMembersTimeout);
_addBox->closeBox();
_addBox = nullptr;
_loadTimer->start(ReloadChannelMembersTimeout);
}
MembersBox::Inner::Inner(QWidget *parent, ChannelData *channel, MembersFilter filter) : TWidget(parent)
@ -169,8 +167,9 @@ void MembersBox::Inner::paintEvent(QPaintEvent *e) {
_time = unixtime();
p.fillRect(r, st::contactsBg);
int32 yFrom = r.y() - st::membersPadding.top(), yTo = r.y() + r.height() - st::membersPadding.top();
p.translate(0, st::membersPadding.top());
auto yFrom = r.y() - st::membersMarginTop;
auto yTo = r.y() + r.height() - st::membersMarginTop;
p.translate(0, st::membersMarginTop);
if (_rows.isEmpty()) {
p.setFont(st::noContactsFont);
p.setPen(st::noContactsColor);
@ -229,28 +228,18 @@ void MembersBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
if (_kickDown >= 0 && _kickDown == _kickSel && !_kickRequestId) {
_kickConfirm = _rows.at(_kickSel);
if (_kickBox) _kickBox->deleteLater();
_kickBox = new ConfirmBox((_filter == MembersFilter::Recent ? (_channel->isMegagroup() ? lng_profile_sure_kick : lng_profile_sure_kick_channel) : lng_profile_sure_kick_admin)(lt_user, _kickConfirm->firstName));
connect(_kickBox, SIGNAL(confirmed()), this, SLOT(onKickConfirm()));
connect(_kickBox, SIGNAL(destroyed(QObject*)), this, SLOT(onKickBoxDestroyed(QObject*)));
Ui::showLayer(_kickBox, KeepOtherLayers);
auto text = (_filter == MembersFilter::Recent ? (_channel->isMegagroup() ? lng_profile_sure_kick : lng_profile_sure_kick_channel) : lng_profile_sure_kick_admin)(lt_user, _kickConfirm->firstName);
_kickBox = Ui::show(Box<ConfirmBox>(text, base::lambda_guarded(this, [this] {
if (_filter == MembersFilter::Recent) {
_kickRequestId = MTP::send(MTPchannels_KickFromChannel(_channel->inputChannel, _kickConfirm->inputUser, MTP_bool(true)), rpcDone(&Inner::kickDone), rpcFail(&Inner::kickFail));
} else {
_kickRequestId = MTP::send(MTPchannels_EditAdmin(_channel->inputChannel, _kickConfirm->inputUser, MTP_channelRoleEmpty()), rpcDone(&Inner::kickAdminDone), rpcFail(&Inner::kickFail));
}
})), KeepOtherLayers);
}
_kickDown = -1;
}
void MembersBox::Inner::onKickBoxDestroyed(QObject *obj) {
if (_kickBox == obj) {
_kickBox = 0;
}
}
void MembersBox::Inner::onKickConfirm() {
if (_filter == MembersFilter::Recent) {
_kickRequestId = MTP::send(MTPchannels_KickFromChannel(_channel->inputChannel, _kickConfirm->inputUser, MTP_bool(true)), rpcDone(&Inner::kickDone), rpcFail(&Inner::kickFail));
} else {
_kickRequestId = MTP::send(MTPchannels_EditAdmin(_channel->inputChannel, _kickConfirm->inputUser, MTP_channelRoleEmpty()), rpcDone(&Inner::kickAdminDone), rpcFail(&Inner::kickFail));
}
}
void MembersBox::Inner::paintDialog(Painter &p, PeerData *peer, MemberData *data, bool sel, bool kickSel, bool kickDown) {
UserData *user = peer->asUser();
@ -317,9 +306,11 @@ void MembersBox::Inner::selectSkipPage(int32 h, int32 dir) {
selectSkip(points * dir);
}
void MembersBox::Inner::loadProfilePhotos(int32 yFrom) {
if (!parentWidget()) return;
int32 yTo = yFrom + parentWidget()->height() * 5;
void MembersBox::Inner::loadProfilePhotos() {
if (_visibleTop >= _visibleBottom) return;
auto yFrom = _visibleTop;
auto yTo = yFrom + (_visibleBottom - _visibleTop) * 5;
MTP::clearLoaderPriorities();
if (yTo < 0) return;
@ -349,7 +340,7 @@ void MembersBox::Inner::chooseParticipant() {
void MembersBox::Inner::refresh() {
if (_rows.isEmpty()) {
resize(width(), st::membersPadding.top() + st::noContactsHeight + st::membersPadding.bottom());
resize(width(), st::membersMarginTop + st::noContactsHeight + st::membersMarginBottom);
_aboutHeight = 0;
} else {
_about.setText(st::boxTextFont, lng_channel_only_last_shown(lt_count, _rows.size()));
@ -357,7 +348,7 @@ void MembersBox::Inner::refresh() {
if (_filter != MembersFilter::Recent || (_rows.size() >= _channel->membersCount() && _rows.size() < Global::ChatSizeMax())) {
_aboutHeight = 0;
}
resize(width(), st::membersPadding.top() + _rows.size() * _rowHeight + st::membersPadding.bottom() + _aboutHeight);
resize(width(), st::membersMarginTop + _aboutHeight + _rows.size() * _rowHeight + st::membersMarginBottom);
}
update();
}
@ -380,6 +371,12 @@ MembersAlreadyIn MembersBox::Inner::already() const {
return result;
}
void MembersBox::Inner::setVisibleTopBottom(int visibleTop, int visibleBottom) {
_visibleTop = visibleTop;
_visibleBottom = visibleBottom;
loadProfilePhotos();
}
void MembersBox::Inner::clearSel() {
updateSelectedRow();
_sel = _kickSel = _kickDown = -1;
@ -426,7 +423,7 @@ void MembersBox::Inner::updateSel() {
if (!_mouseSel) return;
QPoint p(mapFromGlobal(_lastMousePos));
p.setY(p.y() - st::membersPadding.top());
p.setY(p.y() - st::membersMarginTop);
bool in = parentWidget()->rect().contains(parentWidget()->mapFromGlobal(_lastMousePos));
int32 newSel = (in && p.y() >= 0 && p.y() < _rows.size() * _rowHeight) ? (p.y() / _rowHeight) : -1;
int32 newKickSel = newSel;
@ -448,7 +445,7 @@ void MembersBox::Inner::peerUpdated(PeerData *peer) {
void MembersBox::Inner::updateSelectedRow() {
if (_sel >= 0) {
update(0, st::membersPadding.top() + _sel * _rowHeight, width(), _rowHeight);
update(0, st::membersMarginTop + _sel * _rowHeight, width(), _rowHeight);
}
}
@ -457,7 +454,7 @@ void MembersBox::Inner::onPeerNameChanged(PeerData *peer, const PeerData::Names
if (_rows.at(i) == peer) {
if (_datas.at(i)) {
_datas.at(i)->name.setText(st::contactsNameFont, peer->name, _textNameOptions);
update(0, st::membersPadding.top() + i * _rowHeight, width(), _rowHeight);
update(0, st::membersMarginTop + i * _rowHeight, width(), _rowHeight);
} else {
break;
}
@ -566,20 +563,20 @@ void MembersBox::Inner::kickDone(const MTPUpdates &result, mtpRequestId req) {
if (_kickRequestId != req) return;
removeKicked();
if (_kickBox) _kickBox->onClose();
if (_kickBox) _kickBox->closeBox();
}
void MembersBox::Inner::kickAdminDone(const MTPUpdates &result, mtpRequestId req) {
if (_kickRequestId != req) return;
if (App::main()) App::main()->sentUpdatesReceived(result);
removeKicked();
if (_kickBox) _kickBox->onClose();
if (_kickBox) _kickBox->closeBox();
}
bool MembersBox::Inner::kickFail(const RPCError &error, mtpRequestId req) {
if (MTP::isDefaultHandledError(error)) return false;
if (_kickBox) _kickBox->onClose();
if (_kickBox) _kickBox->closeBox();
load();
return true;
}

View File

@ -49,31 +49,33 @@ private:
};
class MembersBox : public ItemListBox {
class MembersBox : public BoxContent {
Q_OBJECT
public:
MembersBox(ChannelData *channel, MembersFilter filter);
MembersBox(QWidget*, ChannelData *channel, MembersFilter filter);
public slots:
void onScroll();
void onAdminAdded();
protected:
void prepare() override;
void keyPressEvent(QKeyEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
private:
void onAdd();
ChannelData *_channel = nullptr;
MembersFilter _filter = MembersFilter::Recent;
class Inner;
ChildWidget<Inner> _inner;
ChildWidget<MembersAddButton> _add = { nullptr };
QPointer<Inner> _inner;
ContactsBox *_addBox = nullptr;
QPointer<ContactsBox> _addBox;
SingleTimer _loadTimer;
object_ptr<SingleTimer> _loadTimer = { nullptr };
};
@ -87,7 +89,6 @@ public:
void selectSkip(int32 dir);
void selectSkipPage(int32 h, int32 dir);
void loadProfilePhotos(int32 yFrom);
void chooseParticipant();
void refresh();
@ -101,6 +102,7 @@ public:
void clearSel();
MembersAlreadyIn already() const;
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
~Inner();
@ -114,8 +116,6 @@ public slots:
void updateSel();
void peerUpdated(PeerData *peer);
void onPeerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars);
void onKickConfirm();
void onKickBoxDestroyed(QObject *obj);
protected:
void paintEvent(QPaintEvent *e) override;
@ -133,6 +133,8 @@ private:
bool canKick;
};
void loadProfilePhotos();
void updateSelectedRow();
MemberData *data(int32 index);
@ -149,6 +151,8 @@ private:
void clear();
int _rowHeight;
int _visibleTop = 0;
int _visibleBottom = 0;
ChannelData *_channel;
MembersFilter _filter;
@ -162,7 +166,7 @@ private:
UserData *_kickConfirm;
mtpRequestId _kickRequestId;
ConfirmBox *_kickBox;
QPointer<ConfirmBox> _kickBox;
enum class MemberRole {
None,

View File

@ -108,11 +108,15 @@ private:
};
NotificationsBox::NotificationsBox() : AbstractBox()
, _chosenCorner(Global::NotificationsCorner())
NotificationsBox::NotificationsBox(QWidget *parent)
: _chosenCorner(Global::NotificationsCorner())
, _oldCount(snap(Global::NotificationsCount(), 1, kMaxNotificationsCount))
, _countSlider(this)
, _done(this, lang(lng_about_done), st::defaultBoxButton) {
, _countSlider(this) {
}
void NotificationsBox::prepare() {
addButton(lang(lng_close), [this] { closeBox(); });
_sampleOpacities.reserve(kMaxNotificationsCount);
for (int i = 0; i != kMaxNotificationsCount; ++i) {
_countSlider->addSection(QString::number(i + 1));
@ -122,15 +126,15 @@ NotificationsBox::NotificationsBox() : AbstractBox()
_countSlider->setSectionActivatedCallback([this] { countChanged(); });
setMouseTracking(true);
_done->setClickedCallback([this] { onClose(); });
prepareNotificationSampleSmall();
prepareNotificationSampleLarge();
setMaxHeight(st::notificationsBoxHeight);
setDimensions(st::boxWideWidth, st::notificationsBoxHeight);
}
void NotificationsBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e);
BoxContent::paintEvent(e);
Painter p(this);
@ -203,14 +207,13 @@ QRect NotificationsBox::getScreenRect() const {
}
void NotificationsBox::resizeEvent(QResizeEvent *e) {
_done->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _done->height());
BoxContent::resizeEvent(e);
auto screenRect = getScreenRect();
auto sliderTop = screenRect.y() + screenRect.height() + st::notificationsBoxCountLabelTop + st::notificationsBoxCountTop;
auto contentLeft = getContentLeft();
_countSlider->resizeToWidth(width() - 2 * contentLeft);
_countSlider->move(contentLeft, sliderTop);
AbstractBox::resizeEvent(e);
}
void NotificationsBox::prepareNotificationSampleSmall() {

View File

@ -23,17 +23,18 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "boxes/abstractbox.h"
namespace Ui {
class RoundButton;
class LinkButton;
class SettingsSlider;
} // namespace Ui
class NotificationsBox : public AbstractBox {
class NotificationsBox : public BoxContent {
public:
NotificationsBox();
NotificationsBox(QWidget*);
~NotificationsBox();
protected:
void prepare() override;
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
@ -70,8 +71,7 @@ private:
ScreenCorner _downCorner = ScreenCorner::TopLeft;
int _oldCount;
ChildWidget<Ui::SettingsSlider> _countSlider;
ChildWidget<Ui::RoundButton> _done;
object_ptr<Ui::SettingsSlider> _countSlider;
QVector<SampleWidget*> _cornerSamples[4];

View File

@ -29,29 +29,24 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h"
PasscodeBox::PasscodeBox(bool turningOff) : AbstractBox(st::boxWidth)
, _turningOff(turningOff)
PasscodeBox::PasscodeBox(QWidget*, bool turningOff)
: _turningOff(turningOff)
, _about(st::boxWidth - st::boxPadding.left() * 1.5)
, _saveButton(this, lang(_turningOff ? lng_passcode_remove_button : lng_settings_save), st::defaultBoxButton)
, _cancelButton(this, lang(lng_cancel), st::cancelBoxButton)
, _oldPasscode(this, st::defaultInputField, lang(lng_passcode_enter_old))
, _newPasscode(this, st::defaultInputField, lang(Global::LocalPasscode() ? lng_passcode_enter_new : lng_passcode_enter_first))
, _reenterPasscode(this, st::defaultInputField, lang(lng_passcode_confirm_new))
, _passwordHint(this, st::defaultInputField, lang(lng_cloud_password_hint))
, _recoverEmail(this, st::defaultInputField, lang(lng_cloud_password_email))
, _recover(this, lang(lng_signin_recover)) {
init();
}
PasscodeBox::PasscodeBox(const QByteArray &newSalt, const QByteArray &curSalt, bool hasRecovery, const QString &hint, bool turningOff) : AbstractBox(st::boxWidth)
, _turningOff(turningOff)
PasscodeBox::PasscodeBox(QWidget*, const QByteArray &newSalt, const QByteArray &curSalt, bool hasRecovery, const QString &hint, bool turningOff)
: _turningOff(turningOff)
, _cloudPwd(true)
, _newSalt(newSalt)
, _curSalt(curSalt)
, _hasRecovery(hasRecovery)
, _about(st::boxWidth - st::boxPadding.left() * 1.5)
, _saveButton(this, lang(_turningOff ? lng_passcode_remove_button : lng_settings_save), st::defaultBoxButton)
, _cancelButton(this, lang(lng_cancel), st::cancelBoxButton)
, _oldPasscode(this, st::defaultInputField, lang(lng_cloud_password_enter_old))
, _newPasscode(this, st::defaultInputField, lang(curSalt.isEmpty() ? lng_cloud_password_enter_first : lng_cloud_password_enter_new))
, _reenterPasscode(this, st::defaultInputField, lang(lng_cloud_password_confirm_new))
@ -61,12 +56,11 @@ PasscodeBox::PasscodeBox(const QByteArray &newSalt, const QByteArray &curSalt, b
textstyleSet(&st::usernameTextStyle);
if (!hint.isEmpty()) _hintText.setText(st::normalFont, lng_signin_hint(lt_password_hint, hint));
textstyleRestore();
init();
}
void PasscodeBox::init() {
setBlockTitle(true);
void PasscodeBox::prepare() {
addButton(lang(_turningOff ? lng_passcode_remove_button : lng_settings_save), [this] { onSave(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
textstyleSet(&st::usernameTextStyle);
_about.setRichText(st::normalFont, lang(_cloudPwd ? lng_cloud_password_about : lng_passcode_about));
@ -74,24 +68,21 @@ void PasscodeBox::init() {
textstyleRestore();
if (_turningOff) {
_oldPasscode->show();
setTitleText(lang(_cloudPwd ? lng_cloud_password_remove : lng_passcode_remove));
setMaxHeight(titleHeight() + st::passcodePadding.top() + _oldPasscode->height() + st::passcodeTextLine + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeTextLine : 0) + _aboutHeight + st::passcodePadding.bottom() + st::boxButtonPadding.top() + _saveButton->height() + st::boxButtonPadding.bottom());
setTitle(lang(_cloudPwd ? lng_cloud_password_remove : lng_passcode_remove));
setDimensions(st::boxWidth, st::passcodePadding.top() + _oldPasscode->height() + st::passcodeTextLine + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeTextLine : 0) + _aboutHeight + st::passcodePadding.bottom());
} else {
bool has = _cloudPwd ? (!_curSalt.isEmpty()) : Global::LocalPasscode();
auto has = _cloudPwd ? (!_curSalt.isEmpty()) : Global::LocalPasscode();
if (has) {
_oldPasscode->show();
setTitleText(lang(_cloudPwd ? lng_cloud_password_change : lng_passcode_change));
setMaxHeight(titleHeight() + st::passcodePadding.top() + _oldPasscode->height() + st::passcodeTextLine + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeTextLine : 0) + _newPasscode->height() + st::contactSkip + _reenterPasscode->height() + st::passcodeSkip + (_cloudPwd ? _passwordHint->height() + st::contactSkip : 0) + _aboutHeight + st::passcodePadding.bottom() + st::boxButtonPadding.top() + _saveButton->height() + st::boxButtonPadding.bottom());
setTitle(lang(_cloudPwd ? lng_cloud_password_change : lng_passcode_change));
setDimensions(st::boxWidth, st::passcodePadding.top() + _oldPasscode->height() + st::passcodeTextLine + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeTextLine : 0) + _newPasscode->height() + st::passcodeLittleSkip + _reenterPasscode->height() + st::passcodeSkip + (_cloudPwd ? _passwordHint->height() + st::passcodeLittleSkip : 0) + _aboutHeight + st::passcodePadding.bottom());
} else {
_oldPasscode->hide();
setTitleText(lang(_cloudPwd ? lng_cloud_password_create : lng_passcode_create));
setMaxHeight(titleHeight() + st::passcodePadding.top() + _newPasscode->height() + st::contactSkip + _reenterPasscode->height() + st::passcodeSkip + (_cloudPwd ? _passwordHint->height() + st::contactSkip : 0) + _aboutHeight + (_cloudPwd ? st::contactSkip + _recoverEmail->height() + st::passcodeSkip : st::passcodePadding.bottom()) + st::boxButtonPadding.top() + _saveButton->height() + st::boxButtonPadding.bottom());
setTitle(lang(_cloudPwd ? lng_cloud_password_create : lng_passcode_create));
setDimensions(st::boxWidth, st::passcodePadding.top() + _newPasscode->height() + st::passcodeLittleSkip + _reenterPasscode->height() + st::passcodeSkip + (_cloudPwd ? _passwordHint->height() + st::passcodeLittleSkip : 0) + _aboutHeight + (_cloudPwd ? st::passcodeLittleSkip + _recoverEmail->height() + st::passcodeSkip : st::passcodePadding.bottom()));
}
}
connect(_saveButton, SIGNAL(clicked()), this, SLOT(onSave()));
connect(_cancelButton, SIGNAL(clicked()), this, SLOT(onClose()));
connect(_oldPasscode, SIGNAL(changed()), this, SLOT(onOldChanged()));
connect(_newPasscode, SIGNAL(changed()), this, SLOT(onNewChanged()));
connect(_reenterPasscode, SIGNAL(changed()), this, SLOT(onNewChanged()));
@ -113,8 +104,6 @@ void PasscodeBox::init() {
_reenterPasscode->setVisible(!_turningOff);
_passwordHint->setVisible(!_turningOff && _cloudPwd);
_recoverEmail->setVisible(!_turningOff && _cloudPwd && _curSalt.isEmpty());
raiseShadow();
}
void PasscodeBox::onSubmit() {
@ -153,14 +142,14 @@ void PasscodeBox::onSubmit() {
}
void PasscodeBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e);
BoxContent::paintEvent(e);
Painter p(this);
textstyleSet(&st::usernameTextStyle);
int32 w = st::boxWidth - st::boxPadding.left() * 1.5;
int32 abouty = (_passwordHint->isHidden() ? (_reenterPasscode->isHidden() ? (_oldPasscode->y() + (_hasRecovery && !_hintText.isEmpty() ? st::passcodeTextLine : 0)) : _reenterPasscode->y()) + st::passcodeSkip : _passwordHint->y() + st::contactSkip) + _oldPasscode->height() + st::passcodePadding.bottom();
int32 abouty = (_passwordHint->isHidden() ? (_reenterPasscode->isHidden() ? (_oldPasscode->y() + (_hasRecovery && !_hintText.isEmpty() ? st::passcodeTextLine : 0)) : _reenterPasscode->y()) + st::passcodeSkip : _passwordHint->y() + st::passcodeLittleSkip) + _oldPasscode->height() + st::passcodePadding.bottom();
p.setPen(st::boxTextFg);
_about.drawLeft(p, st::boxPadding.left(), abouty, w, width());
@ -187,30 +176,27 @@ void PasscodeBox::paintEvent(QPaintEvent *e) {
}
void PasscodeBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e);
bool has = _cloudPwd ? (!_curSalt.isEmpty()) : Global::LocalPasscode();
int32 w = st::boxWidth - st::boxPadding.left() - st::boxPadding.right();
_oldPasscode->resize(w, _oldPasscode->height());
_oldPasscode->moveToLeft(st::boxPadding.left(), titleHeight() + st::passcodePadding.top());
_oldPasscode->moveToLeft(st::boxPadding.left(), st::passcodePadding.top());
_newPasscode->resize(w, _newPasscode->height());
_newPasscode->moveToLeft(st::boxPadding.left(), _oldPasscode->y() + ((_turningOff || has) ? (_oldPasscode->height() + st::passcodeTextLine + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeTextLine : 0)) : 0));
_reenterPasscode->resize(w, _reenterPasscode->height());
_reenterPasscode->moveToLeft(st::boxPadding.left(), _newPasscode->y() + _newPasscode->height() + st::contactSkip);
_reenterPasscode->moveToLeft(st::boxPadding.left(), _newPasscode->y() + _newPasscode->height() + st::passcodeLittleSkip);
_passwordHint->resize(w, _passwordHint->height());
_passwordHint->moveToLeft(st::boxPadding.left(), _reenterPasscode->y() + _reenterPasscode->height() + st::passcodeSkip);
_recoverEmail->resize(w, _passwordHint->height());
_recoverEmail->moveToLeft(st::boxPadding.left(), _passwordHint->y() + _passwordHint->height() + st::contactSkip + _aboutHeight + st::contactSkip);
_recoverEmail->moveToLeft(st::boxPadding.left(), _passwordHint->y() + _passwordHint->height() + st::passcodeLittleSkip + _aboutHeight + st::passcodeLittleSkip);
if (!_recover->isHidden()) {
_recover->moveToLeft(st::boxPadding.left(), _oldPasscode->y() + _oldPasscode->height() + (_hintText.isEmpty() ? ((st::passcodeTextLine - _recover->height()) / 2) : st::passcodeTextLine));
}
_saveButton->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _saveButton->height());
_cancelButton->moveToRight(st::boxButtonPadding.right() + _saveButton->width() + st::boxButtonPadding.left(), _saveButton->y());
AbstractBox::resizeEvent(e);
}
void PasscodeBox::doSetInnerFocus() {
void PasscodeBox::setInnerFocus() {
if (_skipEmailWarning && !_recoverEmail->isHidden()) {
_recoverEmail->setFocus();
} else if (_oldPasscode->isHidden()) {
@ -223,15 +209,23 @@ void PasscodeBox::doSetInnerFocus() {
void PasscodeBox::setPasswordDone(const MTPBool &result) {
_setRequest = 0;
emit reloadPassword();
ConfirmBox *box = new InformBox(lang(_reenterPasscode->isHidden() ? lng_cloud_password_removed : (_oldPasscode->isHidden() ? lng_cloud_password_was_set : lng_cloud_password_updated)));
Ui::showLayer(box);
auto text = lang(_reenterPasscode->isHidden() ? lng_cloud_password_removed : (_oldPasscode->isHidden() ? lng_cloud_password_was_set : lng_cloud_password_updated));
Ui::show(Box<InformBox>(text));
}
void PasscodeBox::closeReplacedBy() {
if (isHidden()) {
if (_replacedBy && !_replacedBy->isHidden()) {
_replacedBy->closeBox();
}
}
}
bool PasscodeBox::setPasswordFail(const RPCError &error) {
if (MTP::isFloodError(error)) {
if (_oldPasscode->isHidden()) return false;
if (isHidden() && _replacedBy && !_replacedBy->isHidden()) _replacedBy->onClose();
closeReplacedBy();
_setRequest = 0;
_oldPasscode->selectAll();
@ -246,13 +240,13 @@ bool PasscodeBox::setPasswordFail(const RPCError &error) {
}
if (MTP::isDefaultHandledError(error)) return false;
if (isHidden() && _replacedBy && !_replacedBy->isHidden()) _replacedBy->onClose();
closeReplacedBy();
_setRequest = 0;
QString err = error.type();
if (err == qstr("PASSWORD_HASH_INVALID")) {
if (_oldPasscode->isHidden()) {
emit reloadPassword();
onClose();
closeBox();
} else {
onBadOldPasscode();
}
@ -263,14 +257,14 @@ bool PasscodeBox::setPasswordFail(const RPCError &error) {
update();
} else if (err == qstr("NEW_SALT_INVALID")) {
emit reloadPassword();
onClose();
closeBox();
} else if (err == qstr("EMAIL_INVALID")) {
_emailError = lang(lng_cloud_password_bad_email);
_recoverEmail->setFocus();
_recoverEmail->showError();
update();
} else if (err == qstr("EMAIL_UNCONFIRMED")) {
Ui::showLayer(new InformBox(lang(lng_cloud_password_almost)));
Ui::show(Box<InformBox>(lang(lng_cloud_password_almost)));
emit reloadPassword();
}
return true;
@ -303,7 +297,7 @@ void PasscodeBox::onSave(bool force) {
if (!_turningOff && pwd.isEmpty()) {
_newPasscode->setFocus();
_newPasscode->showError();
if (isHidden() && _replacedBy && !_replacedBy->isHidden()) _replacedBy->onClose();
closeReplacedBy();
return;
}
if (pwd != conf) {
@ -314,13 +308,13 @@ void PasscodeBox::onSave(bool force) {
_newError = lang(_cloudPwd ? lng_cloud_password_differ : lng_passcode_differ);
update();
}
if (isHidden() && _replacedBy && !_replacedBy->isHidden()) _replacedBy->onClose();
closeReplacedBy();
} else if (!_turningOff && has && old == pwd) {
_newPasscode->setFocus();
_newPasscode->showError();
_newError = lang(_cloudPwd ? lng_cloud_password_is_same : lng_passcode_is_same);
update();
if (isHidden() && _replacedBy && !_replacedBy->isHidden()) _replacedBy->onClose();
closeReplacedBy();
} else if (_cloudPwd) {
QString hint = _passwordHint->getLastText(), email = _recoverEmail->getLastText().trimmed();
if (_cloudPwd && pwd == hint && !_passwordHint->isHidden() && !_newPasscode->isHidden()) {
@ -328,15 +322,14 @@ void PasscodeBox::onSave(bool force) {
_newPasscode->showError();
_newError = lang(lng_cloud_password_bad);
update();
if (isHidden() && _replacedBy && !_replacedBy->isHidden()) _replacedBy->onClose();
closeReplacedBy();
return;
}
if (!_recoverEmail->isHidden() && email.isEmpty() && !force) {
_skipEmailWarning = true;
_replacedBy = new ConfirmBox(lang(lng_cloud_password_about_recover), lang(lng_cloud_password_skip_email), st::attentionBoxButton);
connect(_replacedBy, SIGNAL(confirmed()), this, SLOT(onForceNoMail()));
connect(_replacedBy, SIGNAL(destroyed(QObject*)), this, SLOT(onBoxDestroyed(QObject*)));
Ui::showLayer(_replacedBy, KeepOtherLayers);
_replacedBy = Ui::show(Box<ConfirmBox>(lang(lng_cloud_password_about_recover), lang(lng_cloud_password_skip_email), st::attentionBoxButton, base::lambda_guarded(this, [this] {
onSave(true);
})), KeepOtherLayers);
} else {
QByteArray newPasswordData = pwd.isEmpty() ? QByteArray() : (_newSalt + pwd.toUtf8() + _newSalt);
QByteArray newPasswordHash = pwd.isEmpty() ? QByteArray() : QByteArray(32, Qt::Uninitialized);
@ -362,7 +355,7 @@ void PasscodeBox::onSave(bool force) {
cSetPasscodeBadTries(0);
Local::setPasscode(pwd.toUtf8());
App::wnd()->checkAutoLock();
onClose();
closeBox();
}
}
@ -401,16 +394,6 @@ void PasscodeBox::onEmailChanged() {
}
}
void PasscodeBox::onForceNoMail() {
onSave(true);
}
void PasscodeBox::onBoxDestroyed(QObject *obj) {
if (obj == _replacedBy) {
_replacedBy = 0;
}
}
void PasscodeBox::onRecoverByEmail() {
if (_pattern.isEmpty()) {
_pattern = "-";
@ -427,11 +410,9 @@ void PasscodeBox::onRecoverExpired() {
void PasscodeBox::recover() {
if (_pattern == "-") return;
_replacedBy = new RecoverBox(_pattern);
_replacedBy = Ui::show(Box<RecoverBox>(_pattern), KeepOtherLayers);
connect(_replacedBy, SIGNAL(reloadPassword()), this, SIGNAL(reloadPassword()));
connect(_replacedBy, SIGNAL(recoveryExpired()), this, SLOT(onRecoverExpired()));
connect(_replacedBy, SIGNAL(destroyed(QObject*)), this, SLOT(onBoxDestroyed(QObject*)));
Ui::showLayer(_replacedBy, KeepOtherLayers);
}
void PasscodeBox::recoverStarted(const MTPauth_PasswordRecovery &result) {
@ -443,31 +424,29 @@ bool PasscodeBox::recoverStartFail(const RPCError &error) {
if (MTP::isDefaultHandledError(error)) return false;
_pattern = QString();
onClose();
closeBox();
return true;
}
RecoverBox::RecoverBox(const QString &pattern) : AbstractBox(st::boxWidth, lang(lng_signin_recover_title))
, _submitRequest(0)
, _pattern(st::normalFont->elided(lng_signin_recover_hint(lt_recover_email, pattern), st::boxWidth - st::boxPadding.left() * 1.5))
, _saveButton(this, lang(lng_passcode_submit), st::defaultBoxButton)
, _cancelButton(this, lang(lng_cancel), st::cancelBoxButton)
RecoverBox::RecoverBox(QWidget*, const QString &pattern)
: _pattern(st::normalFont->elided(lng_signin_recover_hint(lt_recover_email, pattern), st::boxWidth - st::boxPadding.left() * 1.5))
, _recoverCode(this, st::defaultInputField, lang(lng_signin_code)) {
setBlockTitle(true);
}
setMaxHeight(titleHeight() + st::passcodePadding.top() + st::passcodePadding.bottom() + st::passcodeTextLine + _recoverCode->height() + st::passcodeTextLine + st::boxButtonPadding.top() + _saveButton->height() + st::boxButtonPadding.bottom());
void RecoverBox::prepare() {
setTitle(lang(lng_signin_recover_title));
connect(_saveButton, SIGNAL(clicked()), this, SLOT(onSubmit()));
connect(_cancelButton, SIGNAL(clicked()), this, SLOT(onClose()));
addButton(lang(lng_passcode_submit), [this] { onSubmit(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
setDimensions(st::boxWidth, st::passcodePadding.top() + st::passcodePadding.bottom() + st::passcodeTextLine + _recoverCode->height() + st::passcodeTextLine);
connect(_recoverCode, SIGNAL(changed()), this, SLOT(onCodeChanged()));
connect(_recoverCode, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
raiseShadow();
}
void RecoverBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e);
BoxContent::paintEvent(e);
Painter p(this);
@ -483,16 +462,13 @@ void RecoverBox::paintEvent(QPaintEvent *e) {
}
void RecoverBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e);
_recoverCode->resize(st::boxWidth - st::boxPadding.left() - st::boxPadding.right(), _recoverCode->height());
_recoverCode->moveToLeft(st::boxPadding.left(), titleHeight() + st::passcodePadding.top() + st::passcodePadding.bottom() + st::passcodeTextLine);
_saveButton->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _saveButton->height());
_cancelButton->moveToRight(st::boxButtonPadding.right() + _saveButton->width() + st::boxButtonPadding.left(), _saveButton->y());
AbstractBox::resizeEvent(e);
_recoverCode->moveToLeft(st::boxPadding.left(), st::passcodePadding.top() + st::passcodePadding.bottom() + st::passcodeTextLine);
}
void RecoverBox::doSetInnerFocus() {
void RecoverBox::setInnerFocus() {
_recoverCode->setFocus();
}
@ -518,7 +494,7 @@ void RecoverBox::codeSubmitDone(bool recover, const MTPauth_Authorization &resul
_submitRequest = 0;
emit reloadPassword();
Ui::showLayer(new InformBox(lang(lng_cloud_password_removed)));
Ui::show(Box<InformBox>(lang(lng_cloud_password_removed)));
}
bool RecoverBox::codeSubmitFail(const RPCError &error) {
@ -536,14 +512,14 @@ bool RecoverBox::codeSubmitFail(const RPCError &error) {
const QString &err = error.type();
if (err == qstr("PASSWORD_EMPTY")) {
emit reloadPassword();
Ui::showLayer(new InformBox(lang(lng_cloud_password_removed)));
Ui::show(Box<InformBox>(lang(lng_cloud_password_removed)));
return true;
} else if (err == qstr("PASSWORD_RECOVERY_NA")) {
onClose();
closeBox();
return true;
} else if (err == qstr("PASSWORD_RECOVERY_EXPIRED")) {
emit recoveryExpired();
onClose();
closeBox();
return true;
} else if (err == qstr("CODE_INVALID")) {
_error = lang(lng_signin_wrong_code);

View File

@ -26,15 +26,14 @@ namespace Ui {
class InputField;
class PasswordInput;
class LinkButton;
class RoundButton;
} // namespace Ui
class PasscodeBox : public AbstractBox, public RPCSender {
class PasscodeBox : public BoxContent, public RPCSender {
Q_OBJECT
public:
PasscodeBox(bool turningOff = false);
PasscodeBox(const QByteArray &newSalt, const QByteArray &curSalt, bool hasRecovery, const QString &hint, bool turningOff = false);
PasscodeBox(QWidget*, bool turningOff);
PasscodeBox(QWidget*, const QByteArray &newSalt, const QByteArray &curSalt, bool hasRecovery, const QString &hint, bool turningOff = false);
private slots:
void onSave(bool force = false);
@ -42,8 +41,6 @@ private slots:
void onOldChanged();
void onNewChanged();
void onEmailChanged();
void onForceNoMail();
void onBoxDestroyed(QObject *obj);
void onRecoverByEmail();
void onRecoverExpired();
void onSubmit();
@ -52,12 +49,14 @@ signals:
void reloadPassword();
protected:
void prepare() override;
void setInnerFocus() override;
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void doSetInnerFocus() override;
private:
void init();
void closeReplacedBy();
void setPasswordDone(const MTPBool &result);
bool setPasswordFail(const RPCError &error);
@ -68,7 +67,7 @@ private:
void recover();
QString _pattern;
AbstractBox *_replacedBy = nullptr;
QPointer<BoxContent> _replacedBy;
bool _turningOff = false;
bool _cloudPwd = false;
mtpRequestId _setRequest = 0;
@ -81,24 +80,22 @@ private:
Text _about, _hintText;
ChildWidget<Ui::RoundButton> _saveButton;
ChildWidget<Ui::RoundButton> _cancelButton;
ChildWidget<Ui::PasswordInput> _oldPasscode;
ChildWidget<Ui::PasswordInput> _newPasscode;
ChildWidget<Ui::PasswordInput> _reenterPasscode;
ChildWidget<Ui::InputField> _passwordHint;
ChildWidget<Ui::InputField> _recoverEmail;
ChildWidget<Ui::LinkButton> _recover;
object_ptr<Ui::PasswordInput> _oldPasscode;
object_ptr<Ui::PasswordInput> _newPasscode;
object_ptr<Ui::PasswordInput> _reenterPasscode;
object_ptr<Ui::InputField> _passwordHint;
object_ptr<Ui::InputField> _recoverEmail;
object_ptr<Ui::LinkButton> _recover;
QString _oldError, _newError, _emailError;
};
class RecoverBox : public AbstractBox, public RPCSender {
class RecoverBox : public BoxContent, public RPCSender {
Q_OBJECT
public:
RecoverBox(const QString &pattern);
RecoverBox(QWidget*, const QString &pattern);
public slots:
void onSubmit();
@ -109,22 +106,21 @@ signals:
void recoveryExpired();
protected:
void prepare() override;
void setInnerFocus() override;
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void doSetInnerFocus() override;
private:
void codeSubmitDone(bool recover, const MTPauth_Authorization &result);
bool codeSubmitFail(const RPCError &error);
mtpRequestId _submitRequest;
mtpRequestId _submitRequest = 0;
QString _pattern;
ChildWidget<Ui::RoundButton> _saveButton;
ChildWidget<Ui::RoundButton> _cancelButton;
ChildWidget<Ui::InputField> _recoverCode;
object_ptr<Ui::InputField> _recoverCode;
QString _error;

View File

@ -29,20 +29,14 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "ui/widgets/buttons.h"
#include "styles/style_boxes.h"
PhotoCropBox::PhotoCropBox(const QImage &img, const PeerId &peer) : AbstractBox()
, _downState(0)
, _done(this, lang(lng_settings_save), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _img(img)
PhotoCropBox::PhotoCropBox(QWidget*, const QImage &img, const PeerId &peer)
: _img(img)
, _peerId(peer) {
init(img, 0);
init(img, nullptr);
}
PhotoCropBox::PhotoCropBox(const QImage &img, PeerData *peer) : AbstractBox()
, _downState(0)
, _done(this, lang(lng_settings_save), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _img(img)
PhotoCropBox::PhotoCropBox(QWidget*, const QImage &img, PeerData *peer)
: _img(img)
, _peerId(peer->id) {
init(img, peer);
}
@ -55,15 +49,17 @@ void PhotoCropBox::init(const QImage &img, PeerData *peer) {
} else {
_title = lang(lng_settings_crop_profile);
}
}
connect(_done, SIGNAL(clicked()), this, SLOT(onSend()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
void PhotoCropBox::prepare() {
addButton(lang(lng_settings_save), [this] { sendPhoto(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
if (peerToBareInt(_peerId)) {
connect(this, SIGNAL(ready(const QImage&)), this, SLOT(onReady(const QImage&)));
}
int32 s = st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
_thumb = App::pixmapFromImageInPlace(img.scaled(s * cIntRetinaFactor(), s * cIntRetinaFactor(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
_thumb = App::pixmapFromImageInPlace(_img.scaled(s * cIntRetinaFactor(), s * cIntRetinaFactor(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
_thumb.setDevicePixelRatio(cRetinaFactor());
_mask = QImage(_thumb.size(), QImage::Format_ARGB32_Premultiplied);
_mask.setDevicePixelRatio(cRetinaFactor());
@ -83,23 +79,22 @@ void PhotoCropBox::init(const QImage &img, PeerData *peer) {
_thumby = st::boxPhotoPadding.top();
setMouseTracking(true);
resizeMaxHeight(st::boxWideWidth, st::boxPhotoPadding.top() + _thumbh + st::boxPhotoPadding.bottom() + st::boxTextFont->height + st::cropSkip + st::boxButtonPadding.top() + _done->height() + st::boxButtonPadding.bottom());
setDimensions(st::boxWideWidth, st::boxPhotoPadding.top() + _thumbh + st::boxPhotoPadding.bottom() + st::boxTextFont->height + st::cropSkip);
}
void PhotoCropBox::mousePressEvent(QMouseEvent *e) {
if (e->button() != Qt::LeftButton) return LayerWidget::mousePressEvent(e);
_downState = mouseState(e->pos());
_fromposx = e->pos().x();
_fromposy = e->pos().y();
_fromcropx = _cropx;
_fromcropy = _cropy;
_fromcropw = _cropw;
return LayerWidget::mousePressEvent(e);
if (e->button() == Qt::LeftButton) {
_downState = mouseState(e->pos());
_fromposx = e->pos().x();
_fromposy = e->pos().y();
_fromcropx = _cropx;
_fromcropy = _cropy;
_fromcropw = _cropw;
}
return BoxContent::mousePressEvent(e);
}
int32 PhotoCropBox::mouseState(QPoint p) {
int PhotoCropBox::mouseState(QPoint p) {
p -= QPoint(_thumbx, _thumby);
int32 delta = st::cropPointSize, mdelta(-delta / 2);
if (QRect(_cropx + mdelta, _cropy + mdelta, delta, delta).contains(p)) {
@ -225,14 +220,14 @@ void PhotoCropBox::mouseMoveEvent(QMouseEvent *e) {
void PhotoCropBox::keyPressEvent(QKeyEvent *e) {
if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
onSend();
sendPhoto();
} else {
AbstractBox::keyPressEvent(e);
BoxContent::keyPressEvent(e);
}
}
void PhotoCropBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e);
BoxContent::paintEvent(e);
Painter p(this);
@ -262,14 +257,8 @@ void PhotoCropBox::paintEvent(QPaintEvent *e) {
p.fillRect(QRect(_cropx + mdelta, _cropy + _cropw + mdelta, delta, delta), st::photoCropPointFg);
}
void PhotoCropBox::resizeEvent(QResizeEvent *e) {
_done->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _done->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _done->width() + st::boxButtonPadding.left(), _done->y());
AbstractBox::resizeEvent(e);
}
void PhotoCropBox::onSend() {
QImage from(_img);
void PhotoCropBox::sendPhoto() {
auto from = _img;
if (_img.width() < _thumb.width()) {
from = _thumb.toImage();
}
@ -302,7 +291,7 @@ void PhotoCropBox::onSend() {
}
emit ready(tosend);
onClose();
closeBox();
}
void PhotoCropBox::onReady(const QImage &tosend) {

View File

@ -22,44 +22,44 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "boxes/abstractbox.h"
namespace Ui {
class RoundButton;
} // namespace Ui
class PhotoCropBox : public AbstractBox {
class PhotoCropBox : public BoxContent {
Q_OBJECT
public:
PhotoCropBox(const QImage &img, const PeerId &peer);
PhotoCropBox(const QImage &img, PeerData *peer);
PhotoCropBox(QWidget*, const QImage &img, const PeerId &peer);
PhotoCropBox(QWidget*, const QImage &img, PeerData *peer);
int32 mouseState(QPoint p);
public slots:
void onSend();
void onReady(const QImage &tosend);
void closeHook() override {
emit closed();
}
signals:
void ready(const QImage &tosend);
void closed();
private slots:
void onReady(const QImage &tosend);
protected:
void prepare() override;
void keyPressEvent(QKeyEvent *e) override;
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override;
private:
void init(const QImage &img, PeerData *peer);
void sendPhoto();
QString _title;
int32 _downState;
int32 _downState = 0;
int32 _thumbx, _thumby, _thumbw, _thumbh;
int32 _cropx, _cropy, _cropw;
int32 _fromposx, _fromposy, _fromcropx, _fromcropy, _fromcropw;
ChildWidget<Ui::RoundButton> _done;
ChildWidget<Ui::RoundButton> _cancel;
QImage _img;
QPixmap _thumb;
QImage _mask, _fade;

View File

@ -30,18 +30,18 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "ui/widgets/input_fields.h"
#include "mainwindow.h"
ReportBox::ReportBox(PeerData *peer) : AbstractBox(st::boxWidth)
, _peer(peer)
ReportBox::ReportBox(QWidget*, PeerData *peer) : _peer(peer)
, _reasonSpam(this, qsl("report_reason"), ReasonSpam, lang(lng_report_reason_spam), true, st::defaultBoxCheckbox)
, _reasonViolence(this, qsl("report_reason"), ReasonViolence, lang(lng_report_reason_violence), false, st::defaultBoxCheckbox)
, _reasonPornography(this, qsl("report_reason"), ReasonPornography, lang(lng_report_reason_pornography), false, st::defaultBoxCheckbox)
, _reasonOther(this, qsl("report_reason"), ReasonOther, lang(lng_report_reason_other), false, st::defaultBoxCheckbox)
, _report(this, lang(lng_report_button), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
setTitleText(lang(_peer->isUser() ? lng_report_bot_title : (_peer->isMegagroup() ? lng_report_group_title : lng_report_title)));
, _reasonOther(this, qsl("report_reason"), ReasonOther, lang(lng_report_reason_other), false, st::defaultBoxCheckbox) {
}
connect(_report, SIGNAL(clicked()), this, SLOT(onReport()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
void ReportBox::prepare() {
setTitle(lang(_peer->isUser() ? lng_report_bot_title : (_peer->isMegagroup() ? lng_report_group_title : lng_report_title)));
addButton(lang(lng_report_button), [this] { onReport(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
connect(_reasonSpam, SIGNAL(changed()), this, SLOT(onChange()));
connect(_reasonViolence, SIGNAL(changed()), this, SLOT(onChange()));
@ -52,18 +52,16 @@ ReportBox::ReportBox(PeerData *peer) : AbstractBox(st::boxWidth)
}
void ReportBox::resizeEvent(QResizeEvent *e) {
_reasonSpam->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), titleHeight() + st::boxOptionListPadding.top());
_reasonViolence->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _reasonSpam->bottomNoMargins() + st::boxOptionListPadding.top());
_reasonPornography->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _reasonViolence->bottomNoMargins() + st::boxOptionListPadding.top());
_reasonOther->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _reasonPornography->bottomNoMargins() + st::boxOptionListPadding.top());
BoxContent::resizeEvent(e);
_reasonSpam->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), st::boxOptionListPadding.top());
_reasonViolence->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _reasonSpam->bottomNoMargins() + st::boxOptionListSkip);
_reasonPornography->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _reasonViolence->bottomNoMargins() + st::boxOptionListSkip);
_reasonOther->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _reasonPornography->bottomNoMargins() + st::boxOptionListSkip);
if (_reasonOtherText) {
_reasonOtherText->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left() - st::defaultInputField.textMargins.left(), _reasonOther->bottomNoMargins() + st::newGroupDescriptionPadding.top());
}
_report->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _report->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _report->width() + st::boxButtonPadding.left(), _report->y());
AbstractBox::resizeEvent(e);
}
void ReportBox::onChange() {
@ -87,7 +85,7 @@ void ReportBox::onChange() {
}
}
void ReportBox::doSetInnerFocus() {
void ReportBox::setInnerFocus() {
if (_reasonOtherText) {
_reasonOtherText->setFocus();
} else {
@ -124,7 +122,7 @@ void ReportBox::onReport() {
void ReportBox::reportDone(const MTPBool &result) {
_requestId = 0;
Ui::showLayer(new InformBox(lang(lng_report_thanks)));
Ui::show(Box<InformBox>(lang(lng_report_thanks)));
}
bool ReportBox::reportFail(const RPCError &error) {
@ -138,9 +136,9 @@ bool ReportBox::reportFail(const RPCError &error) {
}
void ReportBox::updateMaxHeight() {
int32 h = titleHeight() + 4 * (st::boxOptionListPadding.top() + _reasonSpam->heightNoMargins()) + st::boxButtonPadding.top() + _report->height() + st::boxButtonPadding.bottom();
auto newHeight = st::boxOptionListPadding.top() + 4 * _reasonSpam->heightNoMargins() + 3 * st::boxOptionListSkip + st::boxOptionListPadding.bottom();
if (_reasonOtherText) {
h += st::newGroupDescriptionPadding.top() + _reasonOtherText->height() + st::newGroupDescriptionPadding.bottom();
newHeight += st::newGroupDescriptionPadding.top() + _reasonOtherText->height() + st::newGroupDescriptionPadding.bottom();
}
setMaxHeight(h);
setDimensions(st::boxWidth, newHeight);
}

View File

@ -24,15 +24,14 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Ui {
class Radiobutton;
class RoundButton;
class InputArea;
} // namespace Ui
class ReportBox : public AbstractBox, public RPCSender {
class ReportBox : public BoxContent, public RPCSender {
Q_OBJECT
public:
ReportBox(PeerData *peer);
ReportBox(QWidget*, PeerData *peer);
private slots:
void onReport();
@ -40,9 +39,10 @@ private slots:
void onDescriptionResized();
protected:
void resizeEvent(QResizeEvent *e) override;
void prepare() override;
void setInnerFocus() override;
void doSetInnerFocus() override;
void resizeEvent(QResizeEvent *e) override;
private:
void updateMaxHeight();
@ -52,13 +52,11 @@ private:
PeerData *_peer;
ChildWidget<Ui::Radiobutton> _reasonSpam;
ChildWidget<Ui::Radiobutton> _reasonViolence;
ChildWidget<Ui::Radiobutton> _reasonPornography;
ChildWidget<Ui::Radiobutton> _reasonOther;
ChildWidget<Ui::InputArea> _reasonOtherText = { nullptr };
ChildWidget<Ui::RoundButton> _report, _cancel;
object_ptr<Ui::Radiobutton> _reasonSpam;
object_ptr<Ui::Radiobutton> _reasonViolence;
object_ptr<Ui::Radiobutton> _reasonPornography;
object_ptr<Ui::Radiobutton> _reasonOther;
object_ptr<Ui::InputArea> _reasonOtherText = { nullptr };
enum Reason {
ReasonSpam,

View File

@ -38,14 +38,12 @@ constexpr auto kMinPreviewWidth = 20;
} // namespace
SendFilesBox::SendFilesBox(const QString &filepath, QImage image, CompressConfirm compressed, bool animated) : AbstractBox(st::boxWideWidth)
, _files(filepath)
SendFilesBox::SendFilesBox(QWidget*, const QString &filepath, QImage image, CompressConfirm compressed, bool animated)
: _files(filepath)
, _image(image)
, _compressConfirm(compressed)
, _animated(image.isNull() ? false : animated)
, _caption(this, st::confirmCaptionArea, lang(lng_photo_caption))
, _send(this, lang(lng_send_button), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
, _caption(this, st::confirmCaptionArea, lang(lng_photo_caption)) {
if (!image.isNull()) {
if (!_animated && _compressConfirm == CompressConfirm::None) {
auto originalWidth = image.width();
@ -60,7 +58,7 @@ SendFilesBox::SendFilesBox(const QString &filepath, QImage image, CompressConfir
auto maxW = 0;
auto maxH = 0;
if (_animated) {
auto limitW = width() - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
auto limitW = st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
auto limitH = st::confirmMaxHeight;
maxW = qMax(image.width(), 1);
maxH = qMax(image.height(), 1);
@ -82,7 +80,7 @@ SendFilesBox::SendFilesBox(const QString &filepath, QImage image, CompressConfir
if (!originalWidth || !originalHeight) {
originalWidth = originalHeight = 1;
}
_previewWidth = width() - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
_previewWidth = st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
if (image.width() < _previewWidth) {
_previewWidth = qMax(image.width(), kMinPreviewWidth);
}
@ -93,7 +91,7 @@ SendFilesBox::SendFilesBox(const QString &filepath, QImage image, CompressConfir
accumulate_max(_previewWidth, kMinPreviewWidth);
_previewHeight = maxthumbh;
}
_previewLeft = (width() - _previewWidth) / 2;
_previewLeft = (st::boxWideWidth - _previewWidth) / 2;
image = std_::move(image).scaled(_previewWidth * cIntRetinaFactor(), _previewHeight * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
image = Images::prepareOpaque(std_::move(image));
@ -117,37 +115,30 @@ SendFilesBox::SendFilesBox(const QString &filepath, QImage image, CompressConfir
_fileIsImage = fileIsImage(filename, mimeTypeForFile(fileinfo).name());
}
}
setup();
}
SendFilesBox::SendFilesBox(const QStringList &files, CompressConfirm compressed) : AbstractBox(st::boxWideWidth)
, _files(files)
SendFilesBox::SendFilesBox(QWidget*, const QStringList &files, CompressConfirm compressed)
: _files(files)
, _compressConfirm(compressed)
, _caption(this, st::confirmCaptionArea, lang(lng_photos_comment))
, _send(this, lang(lng_send_button), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
updateTitleText();
setup();
, _caption(this, st::confirmCaptionArea, lang(lng_photos_comment)) {
}
SendFilesBox::SendFilesBox(const QString &phone, const QString &firstname, const QString &lastname) : AbstractBox(st::boxWideWidth)
, _contactPhone(phone)
SendFilesBox::SendFilesBox(QWidget*, const QString &phone, const QString &firstname, const QString &lastname)
: _contactPhone(phone)
, _contactFirstName(firstname)
, _contactLastName(lastname)
, _send(this, lang(lng_send_button), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
, _contactLastName(lastname) {
_nameText.setText(st::semiboldFont, lng_full_name(lt_first_name, _contactFirstName, lt_last_name, _contactLastName), _textNameOptions);
_statusText = _contactPhone;
_statusWidth = qMax(_nameText.maxWidth(), st::normalFont->width(_statusText));
setup();
}
void SendFilesBox::setup() {
_send->setClickedCallback([this] { onSend(); });
_cancel->setClickedCallback([this] { onClose(); });
void SendFilesBox::prepare() {
if (_files.size() > 1) {
updateTitleText();
}
_send = addButton(lang(lng_send_button), [this] { onSend(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
if (_compressConfirm != CompressConfirm::None) {
auto compressed = (_compressConfirm == CompressConfirm::Auto) ? cCompressPastedImage() : (_compressConfirm == CompressConfirm::Yes);
@ -163,6 +154,7 @@ void SendFilesBox::setup() {
connect(_caption, SIGNAL(cancelled()), this, SLOT(onClose()));
}
_send->setText(getSendButtonText());
updateButtonsGeometry();
updateBoxSize();
}
@ -176,8 +168,9 @@ QString SendFilesBox::getSendButtonText() const {
}
void SendFilesBox::onCompressedChange() {
doSetInnerFocus();
setInnerFocus();
_send->setText(getSendButtonText());
updateButtonsGeometry();
updateControlsGeometry();
}
@ -188,7 +181,7 @@ void SendFilesBox::onCaptionResized() {
}
void SendFilesBox::updateTitleText() {
_titleText = (_compressConfirm == CompressConfirm::None) ? lng_send_files_selected(lt_count, _files.size()) : lng_send_images_selected(lt_count, _files.size());
setTitle((_compressConfirm == CompressConfirm::None) ? lng_send_files_selected(lt_count, _files.size()) : lng_send_images_selected(lt_count, _files.size()));
update();
}
@ -199,7 +192,7 @@ void SendFilesBox::updateBoxSize() {
} else if (!_fileThumb.isNull()) {
newHeight += st::boxPhotoPadding.top() + st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom();
} else if (_files.size() > 1) {
newHeight += titleHeight();
newHeight += 0;
} else {
newHeight += st::boxPhotoPadding.top() + st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom();
}
@ -209,20 +202,19 @@ void SendFilesBox::updateBoxSize() {
if (_caption) {
newHeight += st::boxPhotoCaptionSkip + _caption->height();
}
newHeight += st::boxButtonPadding.top() + _send->height() + st::boxButtonPadding.bottom();
setMaxHeight(newHeight);
setDimensions(st::boxWideWidth, newHeight);
}
void SendFilesBox::keyPressEvent(QKeyEvent *e) {
if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
onSend((e->modifiers().testFlag(Qt::ControlModifier) || e->modifiers().testFlag(Qt::MetaModifier)) && e->modifiers().testFlag(Qt::ShiftModifier));
} else {
AbstractBox::keyPressEvent(e);
BoxContent::keyPressEvent(e);
}
}
void SendFilesBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e);
BoxContent::paintEvent(e);
Painter p(this);
@ -306,14 +298,12 @@ void SendFilesBox::paintEvent(QPaintEvent *e) {
}
void SendFilesBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e);
updateControlsGeometry();
AbstractBox::resizeEvent(e);
}
void SendFilesBox::updateControlsGeometry() {
_send->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _send->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _send->width() + st::boxButtonPadding.left(), _send->y());
auto bottom = _send->y() - st::boxButtonPadding.top();
auto bottom = height();
if (_caption) {
_caption->resize(st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right(), _caption->height());
_caption->moveToLeft(st::boxPhotoPadding.left(), bottom - _caption->height());
@ -325,7 +315,7 @@ void SendFilesBox::updateControlsGeometry() {
}
}
void SendFilesBox::doSetInnerFocus() {
void SendFilesBox::setInnerFocus() {
if (!_caption || _caption->isHidden()) {
setFocus();
} else {
@ -344,33 +334,17 @@ void SendFilesBox::onSend(bool ctrlShiftEnter) {
auto caption = _caption ? prepareText(_caption->getLastText(), true) : QString();
_confirmedCallback(_files, compressed, caption, ctrlShiftEnter);
}
onClose();
closeBox();
}
void SendFilesBox::closePressed() {
void SendFilesBox::closeHook() {
if (!_confirmed && _cancelledCallback) {
_cancelledCallback();
}
}
EditCaptionBox::EditCaptionBox(HistoryItem *msg) : AbstractBox(st::boxWideWidth)
, _msgId(msg->fullId())
, _animated(false)
, _photo(false)
, _doc(false)
, _save(this, lang(lng_settings_save), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _thumbx(0)
, _thumby(0)
, _thumbw(0)
, _thumbh(0)
, _statusw(0)
, _isImage(false)
, _previewCancelled(false)
, _saveRequestId(0) {
connect(_save, SIGNAL(clicked()), this, SLOT(onSave()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
EditCaptionBox::EditCaptionBox(QWidget*, HistoryItem *msg)
: _msgId(msg->fullId()) {
QSize dimensions;
ImagePtr image;
QString caption;
@ -437,7 +411,7 @@ EditCaptionBox::EditCaptionBox(HistoryItem *msg) : AbstractBox(st::boxWideWidth)
} else {
int32 maxW = 0, maxH = 0;
if (_animated) {
int32 limitW = width() - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
int32 limitW = st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
int32 limitH = st::confirmMaxHeight;
maxW = qMax(dimensions.width(), 1);
maxH = qMax(dimensions.height(), 1);
@ -462,7 +436,7 @@ EditCaptionBox::EditCaptionBox(HistoryItem *msg) : AbstractBox(st::boxWideWidth)
if (!tw || !th) {
tw = th = 1;
}
_thumbw = width() - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
_thumbw = st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
if (_thumb.width() < _thumbw) {
_thumbw = (_thumb.width() > 20) ? _thumb.width() : 20;
}
@ -475,35 +449,50 @@ EditCaptionBox::EditCaptionBox(HistoryItem *msg) : AbstractBox(st::boxWideWidth)
_thumbw = 10;
}
}
_thumbx = (width() - _thumbw) / 2;
_thumbx = (st::boxWideWidth - _thumbw) / 2;
_thumb = App::pixmapFromImageInPlace(_thumb.toImage().scaled(_thumbw * cIntRetinaFactor(), _thumbh * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
_thumb.setDevicePixelRatio(cRetinaFactor());
}
if (_animated || _photo || _doc) {
_field.create(this, st::confirmCaptionArea, lang(lng_photo_caption), caption);
_field->setMaxLength(MaxPhotoCaption);
_field->setCtrlEnterSubmit(Ui::CtrlEnterSubmit::Both);
} else {
auto original = msg->originalText();
QString text = textApplyEntities(original.text, original.entities);
auto text = textApplyEntities(original.text, original.entities);
_field.create(this, st::editTextArea, lang(lng_photo_caption), text);
// _field->setMaxLength(MaxMessageSize); // entities can make text in input field larger but still valid
_field->setCtrlEnterSubmit(cCtrlEnter() ? Ui::CtrlEnterSubmit::CtrlEnter : Ui::CtrlEnterSubmit::Enter);
}
}
bool EditCaptionBox::canEdit(HistoryItem *message) {
if (auto media = message->getMedia()) {
switch (media->type()) {
case MediaTypeGif:
case MediaTypePhoto:
case MediaTypeVideo:
case MediaTypeFile:
case MediaTypeMusicFile:
case MediaTypeVoiceFile: return true;
}
}
return false;
}
void EditCaptionBox::prepare() {
addButton(lang(lng_settings_save), [this] { onSave(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
updateBoxSize();
connect(_field, SIGNAL(submitted(bool)), this, SLOT(onSave(bool)));
connect(_field, SIGNAL(cancelled()), this, SLOT(onClose()));
connect(_field, SIGNAL(resized()), this, SLOT(onCaptionResized()));
QTextCursor c(_field->textCursor());
c.movePosition(QTextCursor::End);
_field->setTextCursor(c);
}
bool EditCaptionBox::captionFound() const {
return _animated || _photo || _doc;
auto cursor = _field->textCursor();
cursor.movePosition(QTextCursor::End);
_field->setTextCursor(cursor);
}
void EditCaptionBox::onCaptionResized() {
@ -513,29 +502,30 @@ void EditCaptionBox::onCaptionResized() {
}
void EditCaptionBox::updateBoxSize() {
auto bottomh = st::boxPhotoCaptionSkip + _field->height() + st::normalFont->height + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom();
auto newHeight = st::boxPhotoPadding.top() + st::boxPhotoCaptionSkip + _field->height() + st::normalFont->height;
if (_photo || _animated) {
setMaxHeight(st::boxPhotoPadding.top() + _thumbh + bottomh);
newHeight += _thumbh;
} else if (_thumbw) {
setMaxHeight(st::boxPhotoPadding.top() + 0 + st::msgFileThumbSize + 0 + bottomh);
newHeight += 0 + st::msgFileThumbSize + 0;
} else if (_doc) {
setMaxHeight(st::boxPhotoPadding.top() + 0 + st::msgFileSize + 0 + bottomh);
newHeight += 0 + st::msgFileSize + 0;
} else {
setMaxHeight(st::boxPhotoPadding.top() + st::boxTitleFont->height + bottomh);
newHeight += st::boxTitleFont->height;
}
setDimensions(st::boxWideWidth, newHeight);
}
void EditCaptionBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e);
BoxContent::paintEvent(e);
Painter p(this);
if (_photo || _animated) {
if (_thumbx > st::boxPhotoPadding.left()) {
p.fillRect(st::boxPhotoPadding.left(), st::boxPhotoPadding.top(), _thumbx - st::boxPhotoPadding.left(), _thumbh, st::confirmBg->b);
p.fillRect(st::boxPhotoPadding.left(), st::boxPhotoPadding.top(), _thumbx - st::boxPhotoPadding.left(), _thumbh, st::confirmBg);
}
if (_thumbx + _thumbw < width() - st::boxPhotoPadding.right()) {
p.fillRect(_thumbx + _thumbw, st::boxPhotoPadding.top(), width() - st::boxPhotoPadding.right() - _thumbx - _thumbw, _thumbh, st::confirmBg->b);
p.fillRect(_thumbx + _thumbw, st::boxPhotoPadding.top(), width() - st::boxPhotoPadding.right() - _thumbx - _thumbw, _thumbh, st::confirmBg);
}
p.drawPixmap(_thumbx, st::boxPhotoPadding.top(), _thumb);
if (_animated) {
@ -613,14 +603,12 @@ void EditCaptionBox::paintEvent(QPaintEvent *e) {
}
void EditCaptionBox::resizeEvent(QResizeEvent *e) {
_save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _save->width() + st::boxButtonPadding.left(), _save->y());
BoxContent::resizeEvent(e);
_field->resize(st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right(), _field->height());
_field->moveToLeft(st::boxPhotoPadding.left(), _save->y() - st::boxButtonPadding.top() - st::normalFont->height - _field->height());
AbstractBox::resizeEvent(e);
_field->moveToLeft(st::boxPhotoPadding.left(), height() - st::normalFont->height - _field->height());
}
void EditCaptionBox::doSetInnerFocus() {
void EditCaptionBox::setInnerFocus() {
_field->setFocus();
}
@ -648,7 +636,7 @@ void EditCaptionBox::onSave(bool ctrlShiftEnter) {
void EditCaptionBox::saveDone(const MTPUpdates &updates) {
_saveRequestId = 0;
onClose();
closeBox();
if (App::main()) {
App::main()->sentUpdatesReceived(updates);
}
@ -662,7 +650,7 @@ bool EditCaptionBox::saveFail(const RPCError &error) {
if (err == qstr("MESSAGE_ID_INVALID") || err == qstr("CHAT_ADMIN_REQUIRED") || err == qstr("MESSAGE_EDIT_TIME_EXPIRED")) {
_error = lang(lng_edit_error);
} else if (err == qstr("MESSAGE_NOT_MODIFIED")) {
onClose();
closeBox();
return true;
} else if (err == qstr("MESSAGE_EMPTY")) {
_field->setFocus();

View File

@ -29,13 +29,13 @@ class RoundButton;
class InputArea;
} // namespace Ui
class SendFilesBox : public AbstractBox {
class SendFilesBox : public BoxContent {
Q_OBJECT
public:
SendFilesBox(const QString &filepath, QImage image, CompressConfirm compressed, bool animated = false);
SendFilesBox(const QStringList &files, CompressConfirm compressed);
SendFilesBox(const QString &phone, const QString &firstname, const QString &lastname);
SendFilesBox(QWidget*, const QString &filepath, QImage image, CompressConfirm compressed, bool animated = false);
SendFilesBox(QWidget*, const QStringList &files, CompressConfirm compressed);
SendFilesBox(QWidget*, const QString &phone, const QString &firstname, const QString &lastname);
void setConfirmedCallback(base::lambda<void(const QStringList &files, bool compressed, const QString &caption, bool ctrlShiftEnter)> &&callback) {
_confirmedCallback = std_::move(callback);
@ -44,21 +44,22 @@ public:
_cancelledCallback = std_::move(callback);
}
public slots:
void onCompressedChange();
void onSend(bool ctrlShiftEnter = false);
void onCaptionResized();
void closeHook() override;
protected:
void prepare() override;
void setInnerFocus() override;
void keyPressEvent(QKeyEvent *e) override;
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void closePressed() override;
void doSetInnerFocus() override;
private slots:
void onCompressedChange();
void onSend(bool ctrlShiftEnter = false);
void onCaptionResized();
private:
void setup();
void updateTitleText();
void updateBoxSize();
void updateControlsGeometry();
@ -90,32 +91,31 @@ private:
base::lambda<void()> _cancelledCallback;
bool _confirmed = false;
ChildWidget<Ui::InputArea> _caption = { nullptr };
ChildWidget<Ui::Checkbox> _compressed = { nullptr };
object_ptr<Ui::InputArea> _caption = { nullptr };
object_ptr<Ui::Checkbox> _compressed = { nullptr };
ChildWidget<Ui::RoundButton> _send;
ChildWidget<Ui::RoundButton> _cancel;
QPointer<Ui::RoundButton> _send;
};
class EditCaptionBox : public AbstractBox, public RPCSender {
class EditCaptionBox : public BoxContent, public RPCSender {
Q_OBJECT
public:
EditCaptionBox(HistoryItem *msg);
bool captionFound() const;
EditCaptionBox(QWidget*, HistoryItem *msg);
static bool canEdit(HistoryItem *message);
public slots:
void onCaptionResized();
void onSave(bool ctrlShiftEnter = false);
protected:
void prepare() override;
void setInnerFocus() override;
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void doSetInnerFocus() override;
private:
void updateBoxSize();
@ -123,22 +123,25 @@ private:
bool saveFail(const RPCError &error);
FullMsgId _msgId;
bool _animated, _photo, _doc;
bool _animated = false;
bool _photo = false;
bool _doc = false;
QPixmap _thumb;
ChildWidget<Ui::InputArea> _field = { nullptr };
ChildWidget<Ui::RoundButton> _save;
ChildWidget<Ui::RoundButton> _cancel;
object_ptr<Ui::InputArea> _field = { nullptr };
int32 _thumbx, _thumby, _thumbw, _thumbh;
int _thumbx = 0;
int _thumby = 0;
int _thumbw = 0;
int _thumbh = 0;
Text _name;
QString _status;
int32 _statusw;
bool _isImage;
int _statusw = 0;
bool _isImage = false;
bool _previewCancelled;
mtpRequestId _saveRequestId;
bool _previewCancelled = false;
mtpRequestId _saveRequestId = 0;
QString _error;

View File

@ -31,53 +31,49 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "ui/widgets/scroll_area.h"
#include "styles/style_boxes.h"
SessionsBox::SessionsBox() : ScrollableBox(st::sessionsScroll)
, _loading(false)
, _inner(this, &_list, &_current)
, _shadow(this)
, _done(this, lang(lng_about_done), st::defaultBoxButton)
, _shortPollRequest(0) {
setMaxHeight(st::sessionsHeight);
setTitleText(lang(lng_sessions_other_header));
SessionsBox::SessionsBox(QWidget*)
: _shortPollTimer(this) {
}
void SessionsBox::prepare() {
setTitle(lang(lng_sessions_other_header));
addButton(lang(lng_close), [this] { closeBox(); });
setDimensions(st::boxWideWidth, st::sessionsHeight);
connect(_done, SIGNAL(clicked()), this, SLOT(onClose()));
connect(_inner, SIGNAL(oneTerminated()), this, SLOT(onOneTerminated()));
connect(_inner, SIGNAL(allTerminated()), this, SLOT(onAllTerminated()));
connect(_inner, SIGNAL(terminateAll()), this, SLOT(onTerminateAll()));
connect(App::wnd(), SIGNAL(checkNewAuthorization()), this, SLOT(onCheckNewAuthorization()));
connect(&_shortPollTimer, SIGNAL(timeout()), this, SLOT(onShortPollAuthorizations()));
connect(_shortPollTimer, SIGNAL(timeout()), this, SLOT(onShortPollAuthorizations()));
init(_inner, st::boxButtonPadding.bottom() + _done->height() + st::boxButtonPadding.top(), titleHeight());
_inner = setInnerWidget(object_ptr<Inner>(this, &_list, &_current), st::sessionsScroll);
_inner->resize(width(), st::noContactsHeight);
setLoading(true);
raiseShadow();
MTP::send(MTPaccount_GetAuthorizations(), rpcDone(&SessionsBox::gotAuthorizations));
}
void SessionsBox::setLoading(bool loading) {
if (_loading != loading) {
_loading = loading;
scrollArea()->setVisible(!_loading);
_shadow->setVisible(!_loading);
setInnerVisible(!_loading);
}
}
void SessionsBox::resizeEvent(QResizeEvent *e) {
ScrollableBox::resizeEvent(e);
_shadow->setGeometry(0, height() - st::boxButtonPadding.bottom() - _done->height() - st::boxButtonPadding.top() - st::lineWidth, width(), st::lineWidth);
_done->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _done->height());
BoxContent::resizeEvent(e);
_inner->resize(width(), _inner->height());
}
void SessionsBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e);
BoxContent::paintEvent(e);
Painter p(this);
p.translate(0, titleHeight());
if (_loading) {
p.setFont(st::noContactsFont);
p.setPen(st::noContactsColor);
@ -202,7 +198,7 @@ void SessionsBox::gotAuthorizations(const MTPaccount_Authorizations &result) {
update();
_shortPollTimer.start(SessionsShortPollTimeout);
_shortPollTimer->start(SessionsShortPollTimeout);
}
void SessionsBox::onOneTerminated() {
@ -236,9 +232,7 @@ void SessionsBox::onTerminateAll() {
SessionsBox::Inner::Inner(QWidget *parent, SessionsBox::List *list, SessionsBox::Data *current) : TWidget(parent)
, _list(list)
, _current(current)
, _terminating(0)
, _terminateAll(this, lang(lng_sessions_terminate_all), st::sessionTerminateAllButton)
, _terminateBox(0) {
, _terminateAll(this, lang(lng_sessions_terminate_all), st::sessionTerminateAllButton) {
connect(_terminateAll, SIGNAL(clicked()), this, SLOT(onTerminateAll()));
_terminateAll->hide();
setAttribute(Qt::WA_OpaquePaintEvent);
@ -312,49 +306,33 @@ void SessionsBox::Inner::paintEvent(QPaintEvent *e) {
void SessionsBox::Inner::onTerminate() {
for (TerminateButtons::iterator i = _terminateButtons.begin(), e = _terminateButtons.end(); i != e; ++i) {
if (i.value()->isOver()) {
_terminating = i.key();
if (_terminateBox) _terminateBox->deleteLater();
_terminateBox = new ConfirmBox(lang(lng_settings_reset_one_sure), lang(lng_settings_reset_button), st::attentionBoxButton);
connect(_terminateBox, SIGNAL(confirmed()), this, SLOT(onTerminateSure()));
connect(_terminateBox, SIGNAL(destroyed(QObject*)), this, SLOT(onNoTerminateBox(QObject*)));
Ui::showLayer(_terminateBox, KeepOtherLayers);
_terminateBox = Ui::show(Box<ConfirmBox>(lang(lng_settings_reset_one_sure), lang(lng_settings_reset_button), st::attentionBoxButton, base::lambda_guarded(this, [this, terminating = i.key()] {
if (_terminateBox) {
_terminateBox->closeBox();
_terminateBox = nullptr;
}
MTP::send(MTPaccount_ResetAuthorization(MTP_long(terminating)), rpcDone(&Inner::terminateDone, terminating), rpcFail(&Inner::terminateFail, terminating));
TerminateButtons::iterator i = _terminateButtons.find(terminating);
if (i != _terminateButtons.cend()) {
i.value()->clearState();
i.value()->hide();
}
})), KeepOtherLayers);
}
}
}
void SessionsBox::Inner::onTerminateSure() {
if (_terminateBox) {
_terminateBox->onClose();
_terminateBox = 0;
}
MTP::send(MTPaccount_ResetAuthorization(MTP_long(_terminating)), rpcDone(&Inner::terminateDone, _terminating), rpcFail(&Inner::terminateFail, _terminating));
TerminateButtons::iterator i = _terminateButtons.find(_terminating);
if (i != _terminateButtons.cend()) {
i.value()->clearState();
i.value()->hide();
}
}
void SessionsBox::Inner::onTerminateAll() {
if (_terminateBox) _terminateBox->deleteLater();
_terminateBox = new ConfirmBox(lang(lng_settings_reset_sure), lang(lng_settings_reset_button), st::attentionBoxButton);
connect(_terminateBox, SIGNAL(confirmed()), this, SLOT(onTerminateAllSure()));
connect(_terminateBox, SIGNAL(destroyed(QObject*)), this, SLOT(onNoTerminateBox(QObject*)));
Ui::showLayer(_terminateBox, KeepOtherLayers);
}
void SessionsBox::Inner::onTerminateAllSure() {
if (_terminateBox) {
_terminateBox->onClose();
_terminateBox = 0;
}
MTP::send(MTPauth_ResetAuthorizations(), rpcDone(&Inner::terminateAllDone), rpcFail(&Inner::terminateAllFail));
emit terminateAll();
}
void SessionsBox::Inner::onNoTerminateBox(QObject *obj) {
if (obj == _terminateBox) _terminateBox = 0;
_terminateBox = Ui::show(Box<ConfirmBox>(lang(lng_settings_reset_sure), lang(lng_settings_reset_button), st::attentionBoxButton, base::lambda_guarded(this, [this] {
if (_terminateBox) {
_terminateBox->closeBox();
_terminateBox = nullptr;
}
MTP::send(MTPauth_ResetAuthorizations(), rpcDone(&Inner::terminateAllDone), rpcFail(&Inner::terminateAllFail));
emit terminateAll();
})), KeepOtherLayers);
}
void SessionsBox::Inner::terminateDone(uint64 hash, const MTPBool &result) {

View File

@ -28,26 +28,27 @@ class ConfirmBox;
namespace Ui {
class IconButton;
class LinkButton;
class RoundButton;
} // namespace Ui
class SessionsBox : public ScrollableBox, public RPCSender {
class SessionsBox : public BoxContent, public RPCSender {
Q_OBJECT
public:
SessionsBox();
SessionsBox(QWidget*);
public slots:
protected:
void prepare() override;
void resizeEvent(QResizeEvent *e) override;
void paintEvent(QPaintEvent *e) override;
private slots:
void onOneTerminated();
void onAllTerminated();
void onTerminateAll();
void onShortPollAuthorizations();
void onCheckNewAuthorization();
protected:
void resizeEvent(QResizeEvent *e) override;
void paintEvent(QPaintEvent *e) override;
private:
void setLoading(bool loading);
struct Data {
@ -61,18 +62,16 @@ private:
void gotAuthorizations(const MTPaccount_Authorizations &result);
bool _loading;
bool _loading = false;
Data _current;
List _list;
class Inner;
ChildWidget<Inner> _inner;
ChildWidget<ScrollableBoxShadow> _shadow;
ChildWidget<Ui::RoundButton> _done;
QPointer<Inner> _inner;
SingleTimer _shortPollTimer;
mtpRequestId _shortPollRequest;
object_ptr<SingleTimer> _shortPollTimer;
mtpRequestId _shortPollRequest = 0;
};
@ -96,10 +95,7 @@ signals:
public slots:
void onTerminate();
void onTerminateSure();
void onTerminateAll();
void onTerminateAllSure();
void onNoTerminateBox(QObject *obj);
private:
void terminateDone(uint64 hash, const MTPBool &result);
@ -114,8 +110,7 @@ private:
typedef QMap<uint64, Ui::IconButton*> TerminateButtons;
TerminateButtons _terminateButtons;
uint64 _terminating;
ChildWidget<Ui::LinkButton> _terminateAll;
ConfirmBox *_terminateBox;
object_ptr<Ui::LinkButton> _terminateAll;
QPointer<ConfirmBox> _terminateBox;
};

View File

@ -39,29 +39,27 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "ui/widgets/scroll_area.h"
#include "boxes/contactsbox.h"
ShareBox::ShareBox(CopyCallback &&copyCallback, SubmitCallback &&submitCallback, FilterCallback &&filterCallback) : ItemListBox(st::boxScroll)
, _copyCallback(std_::move(copyCallback))
ShareBox::ShareBox(QWidget*, CopyCallback &&copyCallback, SubmitCallback &&submitCallback, FilterCallback &&filterCallback)
: _copyCallback(std_::move(copyCallback))
, _submitCallback(std_::move(submitCallback))
, _inner(this, std_::move(filterCallback))
, _filterCallback(std_::move(filterCallback))
, _select(this, st::contactsMultiSelect, lang(lng_participant_filter))
, _copy(this, lang(lng_share_copy_link), st::defaultBoxButton)
, _share(this, lang(lng_share_confirm), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _topShadow(this)
, _bottomShadow(this) {
, _searchTimer(this) {
}
void ShareBox::prepare() {
_select->resizeToWidth(st::boxWideWidth);
myEnsureResized(_select);
setTitleText(lang(lng_share_title));
auto topSkip = getTopScrollSkip();
auto bottomSkip = st::boxButtonPadding.top() + _share->height() + st::boxButtonPadding.bottom();
init(_inner, bottomSkip, topSkip);
setTitle(lang(lng_share_title));
_inner = setInnerWidget(object_ptr<Inner>(this, std_::move(_filterCallback)), getTopScrollSkip());
connect(_inner, SIGNAL(mustScrollTo(int,int)), this, SLOT(onMustScrollTo(int,int)));
connect(_copy, SIGNAL(clicked()), this, SLOT(onCopyLink()));
connect(_share, SIGNAL(clicked()), this, SLOT(onSubmit()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
connect(scrollArea(), SIGNAL(scrolled()), this, SLOT(onScroll()));
createButtons();
setDimensions(st::boxWideWidth, st::boxMaxListHeight);
_select->setQueryChangedCallback([this](const QString &query) { onFilterUpdate(query); });
_select->setItemRemovedCallback([this](uint64 itemId) {
if (auto peer = App::peerLoaded(itemId)) {
@ -77,16 +75,14 @@ ShareBox::ShareBox(CopyCallback &&copyCallback, SubmitCallback &&submitCallback,
onPeerSelectedChanged(peer, checked);
});
_searchTimer.setSingleShot(true);
connect(&_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchByUsername()));
_searchTimer->setSingleShot(true);
connect(_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchByUsername()));
updateButtonsVisibility();
raiseShadow();
_select->raise();
}
int ShareBox::getTopScrollSkip() const {
auto result = titleHeight();
auto result = 0;
if (!_select->isHidden()) {
result += _select->height();
}
@ -94,16 +90,7 @@ int ShareBox::getTopScrollSkip() const {
}
void ShareBox::updateScrollSkips() {
auto oldScrollHeight = scrollArea()->height();
auto topSkip = getTopScrollSkip();
auto bottomSkip = st::boxButtonPadding.top() + _share->height() + st::boxButtonPadding.bottom();
setScrollSkips(bottomSkip, topSkip);
auto scrollHeightDelta = scrollArea()->height() - oldScrollHeight;
if (scrollHeightDelta) {
scrollArea()->scrollToY(scrollArea()->scrollTop() - scrollHeightDelta);
}
_topShadow->setGeometry(0, topSkip, width(), st::lineWidth);
setInnerTopSkip(getTopScrollSkip(), true);
}
bool ShareBox::onSearchByUsername(bool searchCache) {
@ -135,7 +122,7 @@ bool ShareBox::onSearchByUsername(bool searchCache) {
void ShareBox::onNeedSearchByUsername() {
if (!onSearchByUsername(true)) {
_searchTimer.start(AutoSearchTimeout);
_searchTimer->start(AutoSearchTimeout);
}
}
@ -160,7 +147,6 @@ void ShareBox::peopleReceived(const MTPcontacts_Found &result, mtpRequestId requ
}
_peopleRequest = 0;
onScroll();
}
}
@ -174,22 +160,19 @@ bool ShareBox::peopleFailed(const RPCError &error, mtpRequestId requestId) {
return true;
}
void ShareBox::doSetInnerFocus() {
void ShareBox::setInnerFocus() {
_select->setInnerFocus();
}
void ShareBox::resizeEvent(QResizeEvent *e) {
ItemListBox::resizeEvent(e);
BoxContent::resizeEvent(e);
_select->resizeToWidth(width());
_select->moveToLeft(0, titleHeight());
_select->moveToLeft(0, 0);
updateScrollSkips();
_inner->resizeToWidth(width());
moveButtons();
_topShadow->setGeometry(0, getTopScrollSkip(), width(), st::lineWidth);
_bottomShadow->setGeometry(0, height() - st::boxButtonPadding.bottom() - _share->height() - st::boxButtonPadding.top() - st::lineWidth, width(), st::lineWidth);
}
void ShareBox::keyPressEvent(QKeyEvent *e) {
@ -200,32 +183,37 @@ void ShareBox::keyPressEvent(QKeyEvent *e) {
} else if (e->key() == Qt::Key_Down) {
_inner->activateSkipColumn(1);
} else if (e->key() == Qt::Key_PageUp) {
_inner->activateSkipPage(scrollArea()->height(), -1);
_inner->activateSkipPage(height() - getTopScrollSkip(), -1);
} else if (e->key() == Qt::Key_PageDown) {
_inner->activateSkipPage(scrollArea()->height(), 1);
_inner->activateSkipPage(height() - getTopScrollSkip(), 1);
} else {
ItemListBox::keyPressEvent(e);
BoxContent::keyPressEvent(e);
}
} else {
ItemListBox::keyPressEvent(e);
BoxContent::keyPressEvent(e);
}
}
void ShareBox::moveButtons() {
_copy->moveToRight(st::boxButtonPadding.right(), _share->y());
_share->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _share->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _share->width() + st::boxButtonPadding.left(), _share->y());
void ShareBox::updateButtons() {
auto hasSelected = _inner->hasSelected();
if (_hasSelected != hasSelected) {
_hasSelected = hasSelected;
createButtons();
}
}
void ShareBox::updateButtonsVisibility() {
auto hasSelected = _inner->hasSelected();
_copy->setVisible(!hasSelected);
_share->setVisible(hasSelected);
_cancel->setVisible(hasSelected);
void ShareBox::createButtons() {
clearButtons();
if (_hasSelected) {
addButton(lang(lng_share_confirm), [this] { onSubmit(); });
} else {
addButton(lang(lng_share_copy_link), [this] { onCopyLink(); });
}
addButton(lang(lng_cancel), [this] { closeBox(); });
}
void ShareBox::onFilterUpdate(const QString &query) {
scrollArea()->scrollToY(0);
onScrollToY(0);
_inner->updateFilter(query);
}
@ -259,33 +247,27 @@ void ShareBox::onCopyLink() {
}
void ShareBox::onSelectedChanged() {
updateButtonsVisibility();
moveButtons();
updateButtons();
update();
}
void ShareBox::onMustScrollTo(int top, int bottom) {
auto scrollTop = scrollArea()->scrollTop(), scrollBottom = scrollTop + scrollArea()->height();
auto from = scrollTop, to = scrollTop;
if (scrollTop > top) {
to = top;
} else if (scrollBottom < bottom) {
to = bottom - (scrollBottom - scrollTop);
}
if (from != to) {
_scrollAnimation.start([this]() { scrollAnimationCallback(); }, from, to, st::shareScrollDuration, anim::sineInOut);
}
onScrollToY(top, bottom);
//auto scrollTop = scrollArea()->scrollTop(), scrollBottom = scrollTop + scrollArea()->height();
//auto from = scrollTop, to = scrollTop;
//if (scrollTop > top) {
// to = top;
//} else if (scrollBottom < bottom) {
// to = bottom - (scrollBottom - scrollTop);
//}
//if (from != to) {
// _scrollAnimation.start([this]() { scrollAnimationCallback(); }, from, to, st::shareScrollDuration, anim::sineInOut);
//}
}
void ShareBox::scrollAnimationCallback() {
auto scrollTop = qRound(_scrollAnimation.current(scrollArea()->scrollTop()));
scrollArea()->scrollToY(scrollTop);
}
void ShareBox::onScroll() {
auto scroll = scrollArea();
auto scrollTop = scroll->scrollTop();
_inner->setVisibleTopBottom(scrollTop, scrollTop + scroll->height());
//auto scrollTop = qRound(_scrollAnimation.current(scrollArea()->scrollTop()));
//scrollArea()->scrollToY(scrollTop);
}
ShareBox::Inner::Inner(QWidget *parent, ShareBox::FilterCallback &&filterCallback) : TWidget(parent)
@ -928,7 +910,7 @@ void shareGameScoreFromItem(HistoryItem *item) {
}
return false;
};
Ui::showLayer(new ShareBox(std_::move(copyCallback), std_::move(submitCallback), std_::move(filterCallback)));
Ui::show(Box<ShareBox>(std_::move(copyCallback), std_::move(submitCallback), std_::move(filterCallback)));
}
} // namespace
@ -938,7 +920,7 @@ void shareGameScoreByHash(const QString &hash) {
auto hashEncrypted = QByteArray::fromBase64(hash.toLatin1(), QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
if (hashEncrypted.size() <= key128Size || (hashEncrypted.size() % 0x10) != 0) {
Ui::showLayer(new InformBox(lang(lng_confirm_phone_link_invalid)));
Ui::show(Box<InformBox>(lang(lng_confirm_phone_link_invalid)));
return;
}
@ -958,20 +940,20 @@ void shareGameScoreByHash(const QString &hash) {
// Check next 64 bits of SHA1() of data.
auto skipSha1Part = sizeof(channelAccessHash);
if (memcmp(dataSha1 + skipSha1Part, hashEncrypted.constData() + skipSha1Part, key128Size - skipSha1Part) != 0) {
Ui::showLayer(new InformBox(lang(lng_share_wrong_user)));
Ui::show(Box<InformBox>(lang(lng_share_wrong_user)));
return;
}
auto hashDataInts = reinterpret_cast<int32*>(hashData.data());
if (hashDataInts[0] != MTP::authedId()) {
Ui::showLayer(new InformBox(lang(lng_share_wrong_user)));
Ui::show(Box<InformBox>(lang(lng_share_wrong_user)));
return;
}
// Check first 32 bits of channel access hash.
auto channelAccessHashInts = reinterpret_cast<int32*>(&channelAccessHash);
if (channelAccessHashInts[0] != hashDataInts[3]) {
Ui::showLayer(new InformBox(lang(lng_share_wrong_user)));
Ui::show(Box<InformBox>(lang(lng_share_wrong_user)));
return;
}
@ -979,7 +961,7 @@ void shareGameScoreByHash(const QString &hash) {
auto msgId = hashDataInts[2];
if (!channelId && channelAccessHash) {
// If there is no channel id, there should be no channel access_hash.
Ui::showLayer(new InformBox(lang(lng_share_wrong_user)));
Ui::show(Box<InformBox>(lang(lng_share_wrong_user)));
return;
}
@ -991,7 +973,7 @@ void shareGameScoreByHash(const QString &hash) {
if (auto item = App::histItemById(channel, msgId)) {
shareGameScoreFromItem(item);
} else {
Ui::showLayer(new InformBox(lang(lng_edit_deleted)));
Ui::show(Box<InformBox>(lang(lng_edit_deleted)));
}
});
};

View File

@ -36,24 +36,28 @@ struct PeerUpdate;
namespace Ui {
class MultiSelect;
class RoundButton;
} // namespace Ui
QString appendShareGameScoreUrl(const QString &url, const FullMsgId &fullId);
void shareGameScoreByHash(const QString &hash);
class ShareBox : public ItemListBox, public RPCSender {
class ShareBox : public BoxContent, public RPCSender {
Q_OBJECT
public:
using CopyCallback = base::lambda<void()>;
using SubmitCallback = base::lambda<void(const QVector<PeerData*> &)>;
using FilterCallback = base::lambda<bool(PeerData*)>;
ShareBox(CopyCallback &&copyCallback, SubmitCallback &&submitCallback, FilterCallback &&filterCallback);
ShareBox(QWidget*, CopyCallback &&copyCallback, SubmitCallback &&submitCallback, FilterCallback &&filterCallback);
protected:
void prepare() override;
void setInnerFocus() override;
void resizeEvent(QResizeEvent *e) override;
void keyPressEvent(QKeyEvent *e) override;
private slots:
void onScroll();
bool onSearchByUsername(bool searchCache = false);
void onNeedSearchByUsername();
@ -62,19 +66,13 @@ private slots:
void onMustScrollTo(int top, int bottom);
protected:
void resizeEvent(QResizeEvent *e) override;
void keyPressEvent(QKeyEvent *e) override;
void doSetInnerFocus() override;
private:
void scrollAnimationCallback();
void onFilterUpdate(const QString &query);
void onSelectedChanged();
void moveButtons();
void updateButtonsVisibility();
void updateButtons();
void createButtons();
int getTopScrollSkip() const;
void updateScrollSkips();
@ -86,19 +84,16 @@ private:
CopyCallback _copyCallback;
SubmitCallback _submitCallback;
FilterCallback _filterCallback;
object_ptr<Ui::MultiSelect> _select;
class Inner;
ChildWidget<Inner> _inner;
ChildWidget<Ui::MultiSelect> _select;
QPointer<Inner> _inner;
ChildWidget<Ui::RoundButton> _copy;
ChildWidget<Ui::RoundButton> _share;
ChildWidget<Ui::RoundButton> _cancel;
bool _hasSelected = false;
ChildWidget<ScrollableBoxShadow> _topShadow;
ChildWidget<ScrollableBoxShadow> _bottomShadow;
QTimer _searchTimer;
object_ptr<QTimer> _searchTimer;
QString _peopleQuery;
bool _peopleFull = false;
mtpRequestId _peopleRequest = 0;

View File

@ -39,8 +39,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace {
constexpr int kArchivedLimitFirstRequest = 10;
constexpr int kArchivedLimitPerPage = 30;
constexpr int kArchivedLimitFirstRequest = 1;// 10;
constexpr int kArchivedLimitPerPage = 1;// 30;
} // namespace
@ -89,7 +89,6 @@ StickersBox::CounterWidget::CounterWidget(QWidget *parent) : TWidget(parent) {
updateCounter();
}
void StickersBox::CounterWidget::setCounter(int counter) {
_text = (counter > 0) ? QString::number(counter) : QString();
auto dummy = QImage(1, 1, QImage::Format_ARGB32_Premultiplied);
@ -116,24 +115,40 @@ void StickersBox::CounterWidget::updateCounter() {
update();
}
StickersBox::StickersBox(Section section) : ItemListBox(st::boxScroll)
, _topShadow(this, st::shadowColor)
, _tabs(this, st::defaultTabsSlider)
template <typename ...Args>
StickersBox::Tab::Tab(int index, Args&&... args)
: _index(index)
, _widget(std_::forward<Args>(args)...)
, _weak(_widget) {
}
object_ptr<StickersBox::Inner> StickersBox::Tab::takeWidget() {
return std_::move(_widget);
}
void StickersBox::Tab::returnWidget(object_ptr<Inner> widget) {
_widget = std_::move(widget);
t_assert(_widget == _weak);
}
void StickersBox::Tab::saveScrollTop() {
_scrollTop = widget()->getVisibleTop();
}
StickersBox::StickersBox(QWidget*, Section section)
: _tabs(this, st::stickersTabs)
, _unreadBadge(this)
, _section(section)
, _installed(0, this, Section::Installed)
, _featured(1, this, Section::Featured)
, _archived(2, this, Section::Archived) {
setup();
}
StickersBox::StickersBox(const Stickers::Order &archivedIds) : ItemListBox(st::boxScroll)
, _topShadow(this, st::shadowColor)
, _section(Section::ArchivedPart)
StickersBox::StickersBox(QWidget*, const Stickers::Order &archivedIds)
: _section(Section::ArchivedPart)
, _archived(0, this, archivedIds)
, _aboutWidth(st::boxWideWidth - 2 * st::stickersReorderPadding.top())
, _about(st::boxTextFont, lang(lng_stickers_packs_archived), _defaultOptions, _aboutWidth) {
setup();
}
void StickersBox::getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedStickers &result) {
@ -154,7 +169,8 @@ void StickersBox::getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedSti
archived.clear();
}
bool addedSet = false;
auto addedSet = false;
auto changedSets = false;
auto &v = stickers.vsets.c_vector().v;
for_const (auto &stickerSet, v) {
const MTPDstickerSet *setData = nullptr;
@ -177,12 +193,13 @@ void StickersBox::getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedSti
if (auto set = Stickers::feedSet(*setData)) {
auto index = archived.indexOf(set->id);
if (archived.isEmpty() || index != archived.size() - 1) {
changedSets = true;
if (index < archived.size() - 1) {
archived.removeAt(index);
}
archived.push_back(set->id);
}
if (_archived.widget->appendSet(*set)) {
if (_archived.widget()->appendSet(*set)) {
addedSet = true;
if (set->stickers.isEmpty() || (set->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
App::api()->scheduleStickerSetRequest(set->id, set->access);
@ -191,10 +208,12 @@ void StickersBox::getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedSti
}
}
if (addedSet) {
_archived.widget->updateSize();
_archived.widget->setVisibleScrollbar((scrollArea()->scrollTopMax() > 0) ? (st::boxScroll.width - st::boxScroll.deltax) : 0);
_archived.widget()->updateSize();
} else {
_allArchivedLoaded = v.isEmpty() || (offsetId != 0);
if (changedSets && !_allArchivedLoaded) {
loadMoreArchived();
}
}
refreshTabs();
@ -202,69 +221,63 @@ void StickersBox::getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedSti
if (_section == Section::Archived && addedSet) {
App::api()->requestStickerSets();
}
checkLoadMoreArchived();
}
void StickersBox::setup() {
void StickersBox::prepare() {
if (_section == Section::Installed) {
Local::readArchivedStickers();
} else if (_section == Section::Archived) {
requestArchivedSets();
} else if (_section == Section::ArchivedPart) {
setTitleText(lang(lng_stickers_archived));
setTitle(lang(lng_stickers_archived));
}
if (Global::ArchivedStickerSetsOrder().isEmpty()) {
preloadArchivedSets();
}
if (_tabs) {
setNoContentMargin(true);
_tabs->setSectionActivatedCallback([this] {
switchTab();
});
refreshTabs();
}
if (_installed.widget && _section != Section::Installed) _installed.widget->hide();
if (_featured.widget && _section != Section::Featured) _featured.widget->hide();
if (_section != Section::Archived && _section != Section::ArchivedPart) _archived.widget->hide();
if (_installed.widget() && _section != Section::Installed) _installed.widget()->hide();
if (_featured.widget() && _section != Section::Featured) _featured.widget()->hide();
if (_section != Section::Archived && _section != Section::ArchivedPart) _archived.widget()->hide();
if (_featured.widget) {
_featured.widget->setInstallSetCallback([this](uint64 setId) { installSet(setId); });
if (_featured.widget()) {
_featured.widget()->setInstallSetCallback([this](uint64 setId) { installSet(setId); });
}
_archived.widget->setInstallSetCallback([this](uint64 setId) { installSet(setId); });
_archived.widget()->setInstallSetCallback([this](uint64 setId) { installSet(setId); });
_archived.widget()->setLoadMoreCallback([this] { loadMoreArchived(); });
_done.create(this, lang(lng_about_done), st::defaultBoxButton);
connect(_done, SIGNAL(clicked()), this, SLOT(onClose()));
addButton(lang(lng_about_done), [this] { closeBox(); });
auto bottomSkip = st::boxButtonPadding.top() + _done->height() + st::boxButtonPadding.bottom();
if (_section == Section::Installed) {
_bottomShadow.create(this);
_tab = &_installed;
} else if (_section == Section::ArchivedPart) {
_aboutHeight = st::stickersReorderPadding.top() + _about.countHeight(_aboutWidth) + st::stickersReorderPadding.bottom();
_titleShadow.create(this);
_tab = &_archived;
} else if (_section == Section::Archived) {
_bottomShadow.create(this);
_tab = &_archived;
} else { // _section == Section::Featured
_bottomShadow.create(this);
_tab = &_featured;
}
ItemListBox::init(_tab->widget, bottomSkip, titleHeight() + _aboutHeight);
setMaxHeight((_section == Section::ArchivedPart) ? st::sessionsHeight : st::boxMaxListHeight);
setInnerWidget(_tab->takeWidget(), getTopSkip());
setDimensions(st::boxWideWidth, (_section == Section::ArchivedPart) ? st::sessionsHeight : st::boxMaxListHeight);
connect(App::main(), SIGNAL(stickersUpdated()), this, SLOT(onStickersUpdated()));
App::main()->updateStickers();
if (_installed.widget) {
connect(_installed.widget, SIGNAL(checkDraggingScroll(int)), this, SLOT(onCheckDraggingScroll(int)));
connect(_installed.widget, SIGNAL(noDraggingScroll()), this, SLOT(onNoDraggingScroll()));
if (_installed.widget()) {
connect(_installed.widget(), SIGNAL(draggingScrollDelta(int)), this, SLOT(onDraggingScrollDelta(int)));
}
connect(&_scrollTimer, SIGNAL(timeout()), this, SLOT(onScrollTimer()));
connect(scrollArea(), SIGNAL(scrolled()), this, SLOT(onScroll()));
_scrollTimer.setSingleShot(false);
if (_tabs) {
_tabs->raise();
}
rebuildList();
raiseShadow();
}
void StickersBox::refreshTabs() {
@ -288,61 +301,44 @@ void StickersBox::refreshTabs() {
switchTab();
}
updateTabsGeometry();
setBlockTitle(true, (sections.size() < 3), false);
}
void StickersBox::onScroll() {
updateVisibleTopBottom();
checkLoadMoreArchived();
}
void StickersBox::loadMoreArchived() {
if (_section != Section::Archived || _allArchivedLoaded || _archivedRequestId) {
return;
}
void StickersBox::updateVisibleTopBottom() {
auto visibleTop = scrollArea()->scrollTop();
auto visibleBottom = visibleTop + scrollArea()->height();
_tab->widget->setVisibleTopBottom(visibleTop, visibleBottom);
}
void StickersBox::checkLoadMoreArchived() {
if (_section != Section::Archived) return;
int scrollTop = scrollArea()->scrollTop(), scrollTopMax = scrollArea()->scrollTopMax();
if (scrollTop + PreloadHeightsCount * scrollArea()->height() >= scrollTopMax) {
if (!_archivedRequestId && !_allArchivedLoaded) {
uint64 lastId = 0;
for (auto setId = Global::ArchivedStickerSetsOrder().cend(), e = Global::ArchivedStickerSetsOrder().cbegin(); setId != e;) {
--setId;
auto it = Global::StickerSets().constFind(*setId);
if (it != Global::StickerSets().cend()) {
if (it->flags & MTPDstickerSet::Flag::f_archived) {
lastId = it->id;
break;
}
}
uint64 lastId = 0;
for (auto setIt = Global::ArchivedStickerSetsOrder().cend(), e = Global::ArchivedStickerSetsOrder().cbegin(); setIt != e;) {
--setIt;
auto it = Global::StickerSets().constFind(*setIt);
if (it != Global::StickerSets().cend()) {
if (it->flags & MTPDstickerSet::Flag::f_archived) {
lastId = it->id;
break;
}
MTPmessages_GetArchivedStickers::Flags flags = 0;
_archivedRequestId = MTP::send(MTPmessages_GetArchivedStickers(MTP_flags(flags), MTP_long(lastId), MTP_int(kArchivedLimitPerPage)), rpcDone(&StickersBox::getArchivedDone, lastId));
}
}
MTPmessages_GetArchivedStickers::Flags flags = 0;
_archivedRequestId = MTP::send(MTPmessages_GetArchivedStickers(MTP_flags(flags), MTP_long(lastId), MTP_int(kArchivedLimitPerPage)), rpcDone(&StickersBox::getArchivedDone, lastId));
}
void StickersBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e);
BoxContent::paintEvent(e);
Painter p(this);
p.translate(0, titleHeight());
if (_aboutHeight > 0) {
p.fillRect(0, 0, width(), _aboutHeight, st::contactsAboutBg);
p.fillRect(0, st::lineWidth, width(), _aboutHeight - st::lineWidth, st::contactsAboutBg);
p.setPen(st::stickersReorderFg);
_about.draw(p, st::stickersReorderPadding.top(), st::stickersReorderPadding.top(), _aboutWidth, style::al_center);
}
if (_slideAnimation) {
_slideAnimation->paintFrame(p, scrollArea()->x(), scrollArea()->y() - titleHeight(), width(), getms());
_slideAnimation->paintFrame(p, 0, getTopSkip(), width(), getms());
if (!_slideAnimation->animating()) {
_slideAnimation.reset();
scrollArea()->show();
setInnerVisible(true);
update();
}
}
@ -354,9 +350,11 @@ void StickersBox::updateTabsGeometry() {
_tabs->resizeToWidth(_tabIndices.size() * width() / 3);
_unreadBadge->setVisible(_tabIndices.contains(Section::Featured));
setInnerTopSkip(getTopSkip());
auto featuredLeft = width() / 3;
auto featuredRight = 2 * width() / 3;
auto featuredTextWidth = st::defaultTabsSlider.labelFont->width(lang(lng_stickers_featured_tab).toUpper());
auto featuredTextWidth = st::stickersTabs.labelFont->width(lang(lng_stickers_featured_tab).toUpper());
auto featuredTextRight = featuredLeft + (featuredRight - featuredLeft - featuredTextWidth) / 2 + featuredTextWidth;
auto unreadBadgeLeft = featuredTextRight - st::stickersFeaturedBadgeSkip;
auto unreadBadgeTop = st::stickersFeaturedBadgeTop;
@ -368,6 +366,10 @@ void StickersBox::updateTabsGeometry() {
_tabs->moveToLeft(0, 0);
}
int StickersBox::getTopSkip() const {
return (_tabs ? (_tabs->height() - st::lineWidth) : 0) + _aboutHeight;
}
void StickersBox::switchTab() {
if (!_tabs) return;
@ -386,41 +388,37 @@ void StickersBox::switchTab() {
}
if (_tab != newTab) {
if (_tab == &_installed) {
_localOrder = _tab->widget->getFullOrder();
_localRemoved = _tab->widget->getRemovedSets();
_localOrder = _tab->widget()->getFullOrder();
_localRemoved = _tab->widget()->getRemovedSets();
}
auto scroll = scrollArea();
auto wasCache = grabContentCache();
auto wasIndex = _tab->index;
_tab->scrollTop = scroll->scrollTop();
auto widget = scroll->takeWidget();
auto wasIndex = _tab->index();
_tab->saveScrollTop();
auto widget = takeInnerWidget<Inner>();
widget->setParent(this);
widget->hide();
_tab->returnWidget(std_::move(widget));
_tab = newTab;
_section = newSection;
scroll->setOwnedWidget(newTab->widget);
_tab->widget->show();
setInnerWidget(_tab->takeWidget(), getTopSkip());
_tab->widget()->show();
rebuildList();
scroll->scrollToY(_tab->scrollTop);
onScrollToY(_tab->getScrollTop());
auto nowCache = grabContentCache();
auto nowIndex = _tab->index;
auto nowIndex = _tab->index();
_slideAnimation = std_::make_unique<Ui::SlideAnimation>();
_slideAnimation->setSnapshots(std_::move(wasCache), std_::move(nowCache));
auto slideLeft = wasIndex > nowIndex;
_slideAnimation->start(slideLeft, [this] { update(); }, st::slideDuration);
scrollArea()->hide();
setInnerVisible(false);
update();
}
}
QPixmap StickersBox::grabContentCache() {
_topShadow->hide();
_bottomShadow->hide();
_tabs->hide();
auto result = myGrab(this, scrollArea()->geometry());
_topShadow->show();
_bottomShadow->show();
auto result = grabInnerCache();
_tabs->show();
return std_::move(result);
}
@ -435,9 +433,9 @@ void StickersBox::installSet(uint64 setId) {
if (_localRemoved.contains(setId)) {
_localRemoved.removeOne(setId);
if (_installed.widget) _installed.widget->setRemovedSets(_localRemoved);
if (_featured.widget) _featured.widget->setRemovedSets(_localRemoved);
_archived.widget->setRemovedSets(_localRemoved);
if (_installed.widget()) _installed.widget()->setRemovedSets(_localRemoved);
if (_featured.widget()) _featured.widget()->setRemovedSets(_localRemoved);
_archived.widget()->setRemovedSets(_localRemoved);
}
if (!(it->flags & MTPDstickerSet::Flag::f_installed) || (it->flags & MTPDstickerSet::Flag::f_archived)) {
MTP::send(MTPmessages_InstallStickerSet(Stickers::inputSetId(*it), MTP_boolFalse()), rpcDone(&StickersBox::installDone), rpcFail(&StickersBox::installFail, setId));
@ -449,6 +447,8 @@ void StickersBox::installSet(uint64 setId) {
void StickersBox::installDone(const MTPmessages_StickerSetInstallResult &result) {
if (result.type() == mtpc_messages_stickerSetInstallResultArchive) {
Stickers::applyArchivedResult(result.c_messages_stickerSetInstallResultArchive());
} else {
Stickers::applyArchivedResultFake();
}
}
@ -492,31 +492,24 @@ void StickersBox::requestArchivedSets() {
}
void StickersBox::resizeEvent(QResizeEvent *e) {
ItemListBox::resizeEvent(e);
BoxContent::resizeEvent(e);
if (_tabs) {
updateTabsGeometry();
_topShadow->setGeometryToLeft(0, _tabs->height() - st::lineWidth, width(), st::lineWidth);
} else {
_topShadow->setGeometryToLeft(0, scrollArea()->y(), width(), st::lineWidth);
}
if (_installed.widget) _installed.widget->resize(width(), _installed.widget->height());
if (_featured.widget) _featured.widget->resize(width(), _featured.widget->height());
_archived.widget->resize(width(), _archived.widget->height());
_tab->widget->setVisibleScrollbar((scrollArea()->scrollTopMax() > 0) ? (st::boxScroll.width - st::boxScroll.deltax) : 0);
updateVisibleTopBottom();
if (_done) {
_done->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _done->height());
}
if (_bottomShadow) {
_bottomShadow->setGeometry(0, height() - st::boxButtonPadding.bottom() - _done->height() - st::boxButtonPadding.top() - st::lineWidth, width(), st::lineWidth);
if (_titleShadow) {
_titleShadow->setGeometry(0, 0, width(), st::lineWidth);
}
if (_installed.widget()) _installed.widget()->resize(width(), _installed.widget()->height());
if (_featured.widget()) _featured.widget()->resize(width(), _featured.widget()->height());
_archived.widget()->resize(width(), _archived.widget()->height());
}
void StickersBox::onStickersUpdated() {
if (_section == Section::Installed || _section == Section::Featured) {
rebuildList();
} else {
_tab->widget->updateRows();
_tab->widget()->updateRows();
}
if (Global::ArchivedStickerSetsOrder().isEmpty()) {
preloadArchivedSets();
@ -527,50 +520,25 @@ void StickersBox::onStickersUpdated() {
void StickersBox::rebuildList() {
if (_tab == &_installed) {
_localOrder = _tab->widget->getFullOrder();
_localRemoved = _tab->widget->getRemovedSets();
_localOrder = _tab->widget()->getFullOrder();
_localRemoved = _tab->widget()->getRemovedSets();
}
_tab->widget->rebuild();
_tab->widget()->rebuild();
if (_tab == &_installed) {
_tab->widget->setFullOrder(_localOrder);
_tab->widget()->setFullOrder(_localOrder);
}
_tab->widget->setRemovedSets(_localRemoved);
_tab->widget->setVisibleScrollbar((scrollArea()->scrollTopMax() > 0) ? (st::boxScroll.width - st::boxScroll.deltax) : 0);
_tab->widget()->setRemovedSets(_localRemoved);
}
void StickersBox::onCheckDraggingScroll(int localY) {
if (localY < scrollArea()->scrollTop()) {
_scrollDelta = localY - scrollArea()->scrollTop();
} else if (localY >= scrollArea()->scrollTop() + scrollArea()->height()) {
_scrollDelta = localY - scrollArea()->scrollTop() - scrollArea()->height() + 1;
} else {
_scrollDelta = 0;
}
if (_scrollDelta) {
_scrollTimer.start(15);
} else {
_scrollTimer.stop();
}
}
void StickersBox::onNoDraggingScroll() {
_scrollTimer.stop();
}
void StickersBox::onScrollTimer() {
int32 d = (_scrollDelta > 0) ? qMin(_scrollDelta * 3 / 20 + 1, int32(MaxScrollSpeed)) : qMax(_scrollDelta * 3 / 20 - 1, -int32(MaxScrollSpeed));
scrollArea()->scrollToY(scrollArea()->scrollTop() + d);
}
void StickersBox::closePressed() {
if (!_installed.widget) {
void StickersBox::closeHook() {
if (!_installed.widget()) {
return;
}
if (_someArchivedLoaded) {
Local::writeArchivedStickers();
}
if (auto api = App::api()) {
api->saveStickerSets(_installed.widget->getOrder(), _installed.widget->getRemovedSets());
api->saveStickerSets(_installed.widget()->getOrder(), _installed.widget()->getRemovedSets());
}
}
@ -580,12 +548,11 @@ StickersBox::Inner::Inner(QWidget *parent, StickersBox::Section section) : TWidg
, _section(section)
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
, _a_shifting(animation(this, &Inner::step_shifting))
, _itemsTop(st::membersPadding.top())
, _itemsTop(st::membersMarginTop)
, _addText(lang(lng_stickers_featured_add).toUpper())
, _addWidth(st::stickersTrendingAdd.font->width(_addText))
, _undoText(lang(lng_stickers_return).toUpper())
, _undoWidth(st::stickersUndoRemove.font->width(_undoText))
, _aboveShadow(st::boxShadow) {
, _undoWidth(st::stickersUndoRemove.font->width(_undoText)) {
setup();
}
@ -594,10 +561,9 @@ StickersBox::Inner::Inner(QWidget *parent, const Stickers::Order &archivedIds) :
, _archivedIds(archivedIds)
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
, _a_shifting(animation(this, &Inner::step_shifting))
, _itemsTop(st::membersPadding.top())
, _itemsTop(st::membersMarginTop)
, _addText(lang(lng_stickers_featured_add).toUpper())
, _addWidth(st::stickersTrendingAdd.font->width(_addText))
, _aboveShadow(st::boxShadow) {
, _addWidth(st::stickersTrendingAdd.font->width(_addText)) {
setup();
}
@ -619,7 +585,7 @@ void StickersBox::Inner::paintEvent(QPaintEvent *e) {
p.fillRect(r, st::boxBg);
p.setClipRect(r);
int y = st::membersPadding.top();
auto y = _itemsTop;
if (_rows.isEmpty()) {
p.setFont(st::noContactsFont);
p.setPen(st::noContactsColor);
@ -667,21 +633,27 @@ void StickersBox::Inner::paintRow(Painter &p, int index, TimeMs ms) {
if (xadd || yadd) p.translate(xadd, yadd);
if (_section == Section::Installed) {
paintFakeButton(p, index, ms);
if (index == _above) {
float64 current = _aboveShadowFadeOpacity.current();
auto current = _aboveShadowFadeOpacity.current();
if (_started >= 0) {
float64 o = aboveShadowOpacity();
if (o > current) {
_aboveShadowFadeOpacity = anim::value(o, o);
current = o;
auto reachedOpacity = aboveShadowOpacity();
if (reachedOpacity > current) {
_aboveShadowFadeOpacity = anim::value(reachedOpacity, reachedOpacity);
current = reachedOpacity;
}
}
auto row = myrtlrect(st::contactsPadding.left() / 2, st::contactsPadding.top() / 2, width() - (st::contactsPadding.left() / 2) - _scrollbar - st::contactsPadding.left() / 2, _rowHeight - ((st::contactsPadding.top() + st::contactsPadding.bottom()) / 2));
p.setOpacity(current);
QRect row(myrtlrect(_aboveShadow.getDimensions(st::boxShadowShift).left(), st::contactsPadding.top() / 2, width() - (st::contactsPadding.left() / 2) - _scrollbar - _aboveShadow.getDimensions(st::boxShadowShift).right(), _rowHeight - ((st::contactsPadding.top() + st::contactsPadding.bottom()) / 2)));
_aboveShadow.paint(p, row, st::boxShadowShift);
p.fillRect(row, st::boxBg);
Ui::Shadow::paint(p, row, width(), st::boxRoundShadow);
p.setOpacity(1);
App::roundRect(p, row, st::boxBg, BoxCorners);
p.setOpacity(1. - current);
paintFakeButton(p, index, ms);
p.setOpacity(1.);
} else {
paintFakeButton(p, index, ms);
}
} else {
paintFakeButton(p, index, ms);
@ -881,9 +853,18 @@ void StickersBox::Inner::onUpdateSelected() {
_animStartTimes[_dragging] = 0;
_a_shifting.step(getms(), true);
emit checkDraggingScroll(local.y());
auto countDraggingScrollDelta = [this, local] {
if (local.y() < _visibleTop) {
return local.y() - _visibleTop;
} else if (local.y() >= _visibleBottom) {
return local.y() + 1 - _visibleBottom;
}
return 0;
};
emit draggingScrollDelta(countDraggingScrollDelta());
} else {
bool in = rect().marginsRemoved(QMargins(0, _itemsTop, 0, st::membersPadding.bottom())).contains(local);
bool in = rect().marginsRemoved(QMargins(0, _itemsTop, 0, st::membersMarginBottom)).contains(local);
auto selected = -1;
auto actionSel = -1;
auto inDragArea = false;
@ -919,7 +900,7 @@ void StickersBox::Inner::onUpdateSelected() {
setCursor(_inDragArea ? style::cur_sizeall : (_selected >= 0 || _pressed >= 0) ? style::cur_pointer : style::cur_default);
}
setActionSel(actionSel);
emit noDraggingScroll();
emit draggingScrollDelta(0);
}
}
@ -964,7 +945,7 @@ void StickersBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
auto it = sets.find(row->id);
if (it != sets.cend()) {
_selected = -1;
Ui::showLayer(new StickerSetBox(Stickers::inputSetId(*it)), KeepOtherLayers);
Ui::show(Box<StickerSetBox>(Stickers::inputSetId(*it)), KeepOtherLayers);
}
}
}
@ -1018,9 +999,14 @@ void StickersBox::Inner::step_shifting(TimeMs ms, bool timer) {
}
if (timer) {
if (_dragging >= 0) {
if (updateMin < 0 || updateMin > _dragging) updateMin = _dragging;
if (updateMin < 0 || updateMin > _dragging) {
updateMin = _dragging;
}
if (updateMax < _dragging) updateMax = _dragging;
}
if (updateMin == 1 && _rows[0]->isRecentSet()) {
updateMin = 0; // Repaint from the very top of the content.
}
if (updateMin >= 0) {
update(0, _itemsTop + _rowHeight * (updateMin - 1), width(), _rowHeight * (updateMax - updateMin + 3));
}
@ -1060,7 +1046,7 @@ void StickersBox::Inner::setActionSel(int32 actionSel) {
}
void StickersBox::Inner::rebuild() {
_itemsTop = st::membersPadding.top();
_itemsTop = st::membersMarginTop;
int maxNameWidth = countMaxNameWidth();
@ -1102,7 +1088,8 @@ void StickersBox::Inner::rebuild() {
}
void StickersBox::Inner::updateSize() {
resize(width(), _itemsTop + _rows.size() * _rowHeight + st::membersPadding.bottom());
resize(width(), _itemsTop + _rows.size() * _rowHeight + st::membersMarginBottom);
checkLoadMore();
}
void StickersBox::Inner::updateRows() {
@ -1314,11 +1301,23 @@ void StickersBox::Inner::setRemovedSets(const Stickers::Order &removed) {
}
void StickersBox::Inner::setVisibleTopBottom(int visibleTop, int visibleBottom) {
_visibleTop = visibleTop;
_visibleBottom = visibleBottom;
updateScrollbarWidth();
if (_section == Section::Featured) {
_visibleTop = visibleTop;
_visibleBottom = visibleBottom;
readVisibleSets();
}
checkLoadMore();
}
void StickersBox::Inner::checkLoadMore() {
if (_loadMoreCallback) {
auto scrollHeight = (_visibleBottom - _visibleTop);
int scrollTop = _visibleTop, scrollTopMax = height() - scrollHeight;
if (scrollTop + PreloadHeightsCount * scrollHeight >= scrollTopMax) {
_loadMoreCallback();
}
}
}
void StickersBox::Inner::readVisibleSets() {
@ -1339,8 +1338,12 @@ void StickersBox::Inner::readVisibleSets() {
}
}
void StickersBox::Inner::setVisibleScrollbar(int32 width) {
_scrollbar = width;
void StickersBox::Inner::updateScrollbarWidth() {
auto width = (_visibleBottom - _visibleTop < height()) ? (st::boxLayerScroll.width - st::boxLayerScroll.deltax) : 0;
if (_scrollbar != width) {
_scrollbar = width;
update();
}
}
StickersBox::Inner::~Inner() {

View File

@ -30,13 +30,12 @@ struct RippleAnimation;
namespace Ui {
class PlainShadow;
class RoundButton;
class RippleAnimation;
class SettingsSlider;
class SlideAnimation;
} // namespace Ui
class StickersBox : public ItemListBox, public RPCSender {
class StickersBox : public BoxContent, public RPCSender {
Q_OBJECT
public:
@ -46,78 +45,85 @@ public:
Archived,
ArchivedPart,
};
StickersBox(Section section = Section::Installed);
StickersBox(const Stickers::Order &archivedIds);
StickersBox(QWidget*, Section section);
StickersBox(QWidget*, const Stickers::Order &archivedIds);
void closeHook() override;
~StickersBox();
public slots:
void onStickersUpdated();
void onCheckDraggingScroll(int localY);
void onNoDraggingScroll();
void onScrollTimer();
private slots:
void onScroll();
protected:
void prepare() override;
void resizeEvent(QResizeEvent *e) override;
void paintEvent(QPaintEvent *e) override;
void closePressed() override;
private slots:
void onStickersUpdated();
private:
void refreshTabs();
void setup();
void rebuildList();
void updateTabsGeometry();
void switchTab();
void installSet(uint64 setId);
int getTopSkip() const;
QPixmap grabContentCache();
void installDone(const MTPmessages_StickerSetInstallResult &result);
bool installFail(uint64 setId, const RPCError &error);
void updateVisibleTopBottom();
void preloadArchivedSets();
void requestArchivedSets();
void checkLoadMoreArchived();
void loadMoreArchived();
void getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedStickers &result);
ChildWidget<Ui::PlainShadow> _topShadow;
ChildWidget<Ui::SettingsSlider> _tabs = { nullptr };
object_ptr<Ui::SettingsSlider> _tabs = { nullptr };
QList<Section> _tabIndices;
class CounterWidget;
ChildWidget<CounterWidget> _unreadBadge = { nullptr };
object_ptr<CounterWidget> _unreadBadge = { nullptr };
Section _section;
class Inner;
struct Tab {
Tab() : widget(nullptr) {
}
class Tab {
public:
Tab() = default;
template <typename ...Args>
Tab(int index, Args&&... args) : index(index), widget(std_::forward<Args>(args)...) {
Tab(int index, Args&&... args);
object_ptr<Inner> takeWidget();
void returnWidget(object_ptr<Inner> widget);
Inner *widget() {
return _weak;
}
int index() const {
return _index;
}
int index = 0;
ChildWidget<Inner> widget = { nullptr };
int scrollTop = 0;
void saveScrollTop();
int getScrollTop() const {
return _scrollTop;
}
private:
int _index = 0;
object_ptr<Inner> _widget = { nullptr };
QPointer<Inner> _weak;
int _scrollTop = 0;
};
Tab _installed;
Tab _featured;
Tab _archived;
Tab *_tab = nullptr;
ChildWidget<Ui::RoundButton> _done = { nullptr };
ChildWidget<ScrollableBoxShadow> _bottomShadow = { nullptr };
std_::unique_ptr<Ui::SlideAnimation> _slideAnimation;
QTimer _scrollTimer;
int32 _scrollDelta = 0;
object_ptr<BoxLayerTitleShadow> _titleShadow = { nullptr };
int _aboutWidth = 0;
Text _about;
@ -159,10 +165,16 @@ public:
void setInstallSetCallback(base::lambda<void(uint64 setId)> &&callback) {
_installSetCallback = std_::move(callback);
}
void setLoadMoreCallback(base::lambda<void()> &&callback) {
_loadMoreCallback = std_::move(callback);
}
void setVisibleScrollbar(int32 width);
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
int getVisibleTop() const {
return _visibleTop;
}
~Inner();
protected:
@ -173,8 +185,7 @@ protected:
void leaveEvent(QEvent *e) override;
signals:
void checkDraggingScroll(int localY);
void noDraggingScroll();
void draggingScrollDelta(int delta);
public slots:
void onUpdateSelected();
@ -183,6 +194,8 @@ private:
template <typename Check>
Stickers::Order collectSets(Check check) const;
void checkLoadMore();
void updateScrollbarWidth();
int getRowIndex(uint64 setId) const;
void setRowRemoved(int index, bool removed);
@ -249,6 +262,7 @@ private:
BasicAnimation _a_shifting;
base::lambda<void(uint64 setId)> _installSetCallback;
base::lambda<void()> _loadMoreCallback;
int _visibleTop = 0;
int _visibleBottom = 0;
@ -273,8 +287,6 @@ private:
int _dragging = -1;
int _above = -1;
Ui::RectShadow _aboveShadow;
int _scrollbar = 0;
};

View File

@ -34,45 +34,33 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "ui/widgets/buttons.h"
#include "ui/widgets/scroll_area.h"
StickerSetBox::StickerSetBox(const MTPInputStickerSet &set) : ScrollableBox(st::stickersScroll)
, _inner(this, set)
, _shadow(this)
, _add(this, lang(lng_stickers_add_pack), st::defaultBoxButton)
, _share(this, lang(lng_stickers_share_pack), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _done(this, lang(lng_about_done), st::defaultBoxButton) {
setTitleText(lang(lng_contacts_loading));
StickerSetBox::StickerSetBox(QWidget*, const MTPInputStickerSet &set)
: _set(set) {
}
setMaxHeight(st::stickersMaxHeight);
void StickerSetBox::prepare() {
setTitle(lang(lng_contacts_loading));
_inner = setInnerWidget(object_ptr<Inner>(this, _set), st::stickersScroll);
connect(App::main(), SIGNAL(stickersUpdated()), this, SLOT(onStickersUpdated()));
init(_inner, st::boxButtonPadding.bottom() + _cancel->height() + st::boxButtonPadding.top());
setDimensions(st::boxWideWidth, st::stickersMaxHeight);
connect(_add, SIGNAL(clicked()), this, SLOT(onAddStickers()));
connect(_share, SIGNAL(clicked()), this, SLOT(onShareStickers()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
connect(_done, SIGNAL(clicked()), this, SLOT(onClose()));
onUpdateButtons();
connect(_inner, SIGNAL(updateButtons()), this, SLOT(onUpdateButtons()));
connect(scrollArea(), SIGNAL(scrolled()), this, SLOT(onScroll()));
connect(_inner, SIGNAL(installed(uint64)), this, SLOT(onInstalled(uint64)));
onStickersUpdated();
updateControlsVisibility();
onScroll();
raiseShadow();
}
void StickerSetBox::onInstalled(uint64 setId) {
emit installed(setId);
onClose();
closeBox();
}
void StickerSetBox::onStickersUpdated() {
updateControlsVisibility();
updateButtons();
}
void StickerSetBox::onAddStickers() {
@ -82,66 +70,35 @@ void StickerSetBox::onAddStickers() {
void StickerSetBox::onShareStickers() {
QString url = qsl("https://telegram.me/addstickers/") + _inner->shortName();
QApplication::clipboard()->setText(url);
Ui::showLayer(new InformBox(lang(lng_stickers_copied)));
Ui::show(Box<InformBox>(lang(lng_stickers_copied)));
}
void StickerSetBox::onUpdateButtons() {
setTitleText(_inner->title());
if (!_cancel->isHidden() || !_done->isHidden()) {
updateControlsVisibility();
}
setTitle(_inner->title());
updateButtons();
}
void StickerSetBox::onScroll() {
auto scroll = scrollArea();
auto scrollTop = scroll->scrollTop();
_inner->setVisibleTopBottom(scrollTop, scrollTop + scroll->height());
}
void StickerSetBox::updateControlsVisibility() {
void StickerSetBox::updateButtons() {
clearButtons();
if (_inner->loaded()) {
_shadow.show();
if (_inner->notInstalled()) {
_add->show();
_cancel->show();
_share->hide();
_done->hide();
addButton(lang(lng_stickers_add_pack), [this] { onAddStickers(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
} else if (_inner->official()) {
_add->hide();
_share->hide();
_cancel->hide();
_done->show();
addButton(lang(lng_about_done), [this] { closeBox(); });
} else {
_share->show();
_cancel->show();
_add->hide();
_done->hide();
addButton(lang(lng_stickers_share_pack), [this] { onShareStickers(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
}
} else {
_shadow.hide();
_add->hide();
_share->hide();
_cancel->show();
_done->hide();
addButton(lang(lng_cancel), [this] { closeBox(); });
}
resizeEvent(0);
update();
}
void StickerSetBox::resizeEvent(QResizeEvent *e) {
ScrollableBox::resizeEvent(e);
BoxContent::resizeEvent(e);
_inner->resize(width(), _inner->height());
_shadow.setGeometry(0, height() - st::boxButtonPadding.bottom() - _cancel->height() - st::boxButtonPadding.top() - st::lineWidth, width(), st::lineWidth);
_add->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _add->height());
_share->moveToRight(st::boxButtonPadding.right(), _add->y());
_done->moveToRight(st::boxButtonPadding.right(), _add->y());
if (_add->isHidden() && _share->isHidden()) {
_cancel->moveToRight(st::boxButtonPadding.right(), _add->y());
} else if (_add->isHidden()) {
_cancel->moveToRight(st::boxButtonPadding.right() + _share->width() + st::boxButtonPadding.left(), _add->y());
} else {
_cancel->moveToRight(st::boxButtonPadding.right() + _add->width() + st::boxButtonPadding.left(), _add->y());
}
}
StickerSetBox::Inner::Inner(QWidget *parent, const MTPInputStickerSet &set) : TWidget(parent)
@ -199,7 +156,7 @@ void StickerSetBox::Inner::gotSet(const MTPmessages_StickerSet &set) {
if (d.vset.type() == mtpc_stickerSet) {
auto &s = d.vset.c_stickerSet();
_setTitle = stickerSetTitle(s);
_title = st::boxBlockTitleFont->elided(_setTitle, width() - st::boxBlockTitlePosition.x() - st::boxBlockTitleHeight);
_title = st::boxTitleFont->elided(_setTitle, width() - st::boxTitlePosition.x() - st::boxTitleHeight);
_setShortName = qs(s.vshort_name);
_setId = s.vid.v;
_setAccess = s.vaccess_hash.v;
@ -219,7 +176,7 @@ void StickerSetBox::Inner::gotSet(const MTPmessages_StickerSet &set) {
}
if (_pack.isEmpty()) {
Ui::showLayer(new InformBox(lang(lng_stickers_not_found)));
Ui::show(Box<InformBox>(lang(lng_stickers_not_found)));
} else {
int32 rows = _pack.size() / StickerPanPerRow + ((_pack.size() % StickerPanPerRow) ? 1 : 0);
resize(st::stickersPadding.left() + StickerPanPerRow * st::stickersSize.width(), st::stickersPadding.top() + rows * st::stickersSize.height() + st::stickersPadding.bottom());
@ -236,7 +193,7 @@ bool StickerSetBox::Inner::failedSet(const RPCError &error) {
_loaded = true;
Ui::showLayer(new InformBox(lang(lng_stickers_not_found)));
Ui::show(Box<InformBox>(lang(lng_stickers_not_found)));
return true;
}
@ -297,7 +254,7 @@ void StickerSetBox::Inner::installDone(const MTPmessages_StickerSetInstallResult
bool StickerSetBox::Inner::installFail(const RPCError &error) {
if (MTP::isDefaultHandledError(error)) return false;
Ui::showLayer(new InformBox(lang(lng_stickers_not_found)));
Ui::show(Box<InformBox>(lang(lng_stickers_not_found)));
return true;
}
@ -467,7 +424,7 @@ QString StickerSetBox::Inner::shortName() const {
void StickerSetBox::Inner::install() {
if (isMasksSet()) {
Ui::showLayer(new InformBox(lang(lng_stickers_masks_pack)), KeepOtherLayers);
Ui::show(Box<InformBox>(lang(lng_stickers_masks_pack)), KeepOtherLayers);
return;
}
if (_installRequest) return;

View File

@ -27,42 +27,38 @@ class ConfirmBox;
namespace Ui {
class PlainShadow;
class RoundButton;
} // namespace Ui
class StickerSetBox : public ScrollableBox, public RPCSender {
class StickerSetBox : public BoxContent, public RPCSender {
Q_OBJECT
public:
StickerSetBox(const MTPInputStickerSet &set);
public slots:
void onStickersUpdated();
void onAddStickers();
void onShareStickers();
void onUpdateButtons();
void onScroll();
private slots:
void onInstalled(uint64 id);
StickerSetBox(QWidget*, const MTPInputStickerSet &set);
signals:
void installed(uint64 id);
protected:
void prepare() override;
void resizeEvent(QResizeEvent *e) override;
private slots:
void onStickersUpdated();
void onAddStickers();
void onShareStickers();
void onUpdateButtons();
void onInstalled(uint64 id);
private:
void updateControlsVisibility();
void updateButtons();
MTPInputStickerSet _set;
class Inner;
ChildWidget<Inner> _inner;
ScrollableBoxShadow _shadow;
ChildWidget<Ui::RoundButton> _add;
ChildWidget<Ui::RoundButton> _share;
ChildWidget<Ui::RoundButton> _cancel;
ChildWidget<Ui::RoundButton> _done;
QPointer<Inner> _inner;
QString _title;
};

View File

@ -29,42 +29,42 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "ui/widgets/input_fields.h"
#include "styles/style_boxes.h"
UsernameBox::UsernameBox() : AbstractBox(st::boxWidth, lang(lng_username_title))
, _save(this, lang(lng_settings_save), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _username(this, st::defaultInputField, qsl("@username"), App::self()->username, false)
UsernameBox::UsernameBox(QWidget*)
: _username(this, st::defaultInputField, qsl("@username"), App::self()->username, false)
, _link(this, QString(), st::boxLinkButton)
, _about(st::boxWidth - st::usernamePadding.left()) {
setBlockTitle(true);
, _about(st::boxWidth - st::usernamePadding.left())
, _checkTimer(this) {
}
void UsernameBox::prepare() {
_goodText = App::self()->username.isEmpty() ? QString() : lang(lng_username_available);
setTitle(lang(lng_username_title));
addButton(lang(lng_settings_save), [this] { onSave(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
connect(_username, SIGNAL(changed()), this, SLOT(onChanged()));
connect(_username, SIGNAL(submitted(bool)), this, SLOT(onSave()));
connect(_link, SIGNAL(clicked()), this, SLOT(onLinkClick()));
textstyleSet(&st::usernameTextStyle);
_about.setRichText(st::boxTextFont, lang(lng_username_about));
resizeMaxHeight(st::boxWidth, titleHeight() + st::usernamePadding.top() + _username->height() + st::usernameSkip + _about.countHeight(st::boxWidth - st::usernamePadding.left()) + 3 * st::usernameTextStyle.lineHeight + st::usernamePadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom());
setDimensions(st::boxWidth, st::usernamePadding.top() + _username->height() + st::usernameSkip + _about.countHeight(st::boxWidth - st::usernamePadding.left()) + 3 * st::usernameTextStyle.lineHeight + st::usernamePadding.bottom());
textstyleRestore();
connect(_save, SIGNAL(clicked()), this, SLOT(onSave()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
connect(_username, SIGNAL(changed()), this, SLOT(onChanged()));
connect(_username, SIGNAL(submitted(bool)), this, SLOT(onSave()));
connect(_link, SIGNAL(clicked()), this, SLOT(onLinkClick()));
_checkTimer.setSingleShot(true);
connect(&_checkTimer, SIGNAL(timeout()), this, SLOT(onCheck()));
_checkTimer->setSingleShot(true);
connect(_checkTimer, SIGNAL(timeout()), this, SLOT(onCheck()));
updateLinkText();
raiseShadow();
}
void UsernameBox::doSetInnerFocus() {
void UsernameBox::setInnerFocus() {
_username->setFocus();
}
void UsernameBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e);
BoxContent::paintEvent(e);
Painter p(this);
@ -99,19 +99,16 @@ void UsernameBox::paintEvent(QPaintEvent *e) {
}
void UsernameBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e);
_username->resize(width() - st::usernamePadding.left() - st::usernamePadding.right(), _username->height());
_username->moveToLeft(st::usernamePadding.left(), titleHeight() + st::usernamePadding.top());
_username->moveToLeft(st::usernamePadding.left(), st::usernamePadding.top());
textstyleSet(&st::usernameTextStyle);
int32 availw = st::boxWidth - st::usernamePadding.left(), h = _about.countHeight(availw);
textstyleRestore();
int32 linky = _username->y() + _username->height() + st::usernameSkip + h + st::usernameTextStyle.lineHeight + ((st::usernameTextStyle.lineHeight - st::boxTextFont->height) / 2);
_link->moveToLeft(st::usernamePadding.left(), linky + st::usernameTextStyle.lineHeight + ((st::usernameTextStyle.lineHeight - st::boxTextFont->height) / 2));
_save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _save->width() + st::boxButtonPadding.left(), _save->y());
AbstractBox::resizeEvent(e);
}
void UsernameBox::onSave() {
@ -140,7 +137,7 @@ void UsernameBox::onChanged() {
_copiedTextLink = _errorText = _goodText = QString();
update();
}
_checkTimer.stop();
_checkTimer->stop();
} else {
int32 len = name.size();
for (int32 i = 0; i < len; ++i) {
@ -151,7 +148,7 @@ void UsernameBox::onChanged() {
_errorText = lang(lng_username_bad_symbols);
update();
}
_checkTimer.stop();
_checkTimer->stop();
return;
}
}
@ -161,13 +158,13 @@ void UsernameBox::onChanged() {
_errorText = lang(lng_username_too_short);
update();
}
_checkTimer.stop();
_checkTimer->stop();
} else {
if (!_errorText.isEmpty() || !_goodText.isEmpty() || !_copiedTextLink.isEmpty()) {
_copiedTextLink = _errorText = _goodText = QString();
update();
}
_checkTimer.start(UsernameCheckTimeout);
_checkTimer->start(UsernameCheckTimeout);
}
}
}
@ -180,7 +177,7 @@ void UsernameBox::onLinkClick() {
void UsernameBox::onUpdateDone(const MTPUser &user) {
App::feedUsers(MTP_vector<MTPUser>(1, user));
onClose();
closeBox();
}
bool UsernameBox::onUpdateFail(const RPCError &error) {
@ -190,7 +187,7 @@ bool UsernameBox::onUpdateFail(const RPCError &error) {
QString err(error.type());
if (err == qstr("USERNAME_NOT_MODIFIED") || _sentUsername == App::self()->username) {
App::self()->setName(textOneLine(App::self()->firstName), textOneLine(App::self()->lastName), textOneLine(App::self()->nameOrPhone), textOneLine(_sentUsername));
onClose();
closeBox();
return true;
} else if (err == qstr("USERNAME_INVALID")) {
_username->setFocus();

View File

@ -24,17 +24,23 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Ui {
class UsernameInput;
class RoundButton;
class LinkButton;
} // namespace Ui
class UsernameBox : public AbstractBox, public RPCSender {
class UsernameBox : public BoxContent, public RPCSender {
Q_OBJECT
public:
UsernameBox();
UsernameBox(QWidget*);
public slots:
protected:
void prepare() override;
void setInnerFocus() override;
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
private slots:
void onSave();
void onCheck();
@ -42,12 +48,6 @@ public slots:
void onLinkClick();
protected:
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void doSetInnerFocus() override;
private:
void onUpdateDone(const MTPUser &result);
bool onUpdateFail(const RPCError &error);
@ -58,16 +58,14 @@ private:
QString getName() const;
void updateLinkText();
ChildWidget<Ui::RoundButton> _save;
ChildWidget<Ui::RoundButton> _cancel;
ChildWidget<Ui::UsernameInput> _username;
ChildWidget<Ui::LinkButton> _link;
object_ptr<Ui::UsernameInput> _username;
object_ptr<Ui::LinkButton> _link;
mtpRequestId _saveRequestId = 0;
mtpRequestId _checkRequestId = 0;
QString _sentUsername, _checkUsername, _errorText, _goodText, _copiedTextLink;
Text _about;
QTimer _checkTimer;
object_ptr<QTimer> _checkTimer;
};

View File

@ -104,24 +104,31 @@ TextWithEntities UrlClickHandler::getExpandedLinkTextWithEntities(ExpandLinksMod
}
void HiddenUrlClickHandler::onClick(Qt::MouseButton button) const {
auto u = tryConvertUrlToLocal(url());
auto urlText = tryConvertUrlToLocal(url());
if (u.startsWith(qstr("tg://"))) {
App::openLocalUrl(u);
if (urlText.startsWith(qstr("tg://"))) {
App::openLocalUrl(urlText);
} else {
Ui::showLayer(new ConfirmLinkBox(u));
Ui::show(Box<ConfirmBox>(lang(lng_open_this_link) + qsl("\n\n") + urlText, lang(lng_open_link), [urlText] {
Ui::hideLayer();
UrlClickHandler::doOpen(urlText);
}));
}
}
void BotGameUrlClickHandler::onClick(Qt::MouseButton button) const {
auto u = tryConvertUrlToLocal(url());
auto urlText = tryConvertUrlToLocal(url());
if (u.startsWith(qstr("tg://"))) {
App::openLocalUrl(u);
if (urlText.startsWith(qstr("tg://"))) {
App::openLocalUrl(urlText);
} else if (!_bot || _bot->isVerified() || Local::isBotTrusted(_bot)) {
doOpen(u);
doOpen(urlText);
} else {
Ui::showLayer(new ConfirmBotGameBox(_bot, u));
Ui::show(Box<ConfirmBox>(lng_allow_bot_pass(lt_bot_name, _bot->name), lang(lng_allow_bot), [bot = _bot, urlText] {
Ui::hideLayer();
Local::makeBotTrusted(bot);
UrlClickHandler::doOpen(urlText);
}));
}
}

View File

@ -23,7 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "application.h"
SingleTimer::SingleTimer() {
SingleTimer::SingleTimer(QObject *parent) : QTimer(parent) {
QTimer::setSingleShot(true);
if (App::app()) {
connect(App::app(), SIGNAL(adjustSingleTimers()), this, SLOT(adjust()));

View File

@ -26,7 +26,7 @@ class SingleTimer : public QTimer { // single shot timer with check
Q_OBJECT
public:
SingleTimer();
SingleTimer(QObject *parent = nullptr);
void setSingleShot(bool); // is not available
void start(); // is not available

View File

@ -22,7 +22,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "core/utils.h"
#define BETA_VERSION_MACRO (10019014ULL)
#define BETA_VERSION_MACRO (10020001ULL)
constexpr int AppVersion = 10020;
constexpr str_const AppVersionStr = "0.10.20";

View File

@ -50,7 +50,7 @@ dialogsSkip: 8px;
dialogsWidthMin: 260px;
dialogsWidthMax: 540px;
dialogsTextWidthMin: 150px;
dialogsScroll: FlatScroll(defaultFlatScroll) {
dialogsScroll: ScrollArea(defaultScrollArea) {
topsh: 0px;
bottomsh: 0px;
}

View File

@ -1887,9 +1887,8 @@ DialogsWidget::DialogsWidget(QWidget *parent) : TWidget(parent)
, _filter(this, st::dialogsFilter, lang(lng_dlg_filter))
, _cancelSearch(this, st::dialogsCancelSearch)
, _lockUnlock(this, st::dialogsLock)
, _scroll(this, st::dialogsScroll)
, _inner(this, parent) {
_scroll->setOwnedWidget(_inner);
, _scroll(this, st::dialogsScroll) {
_inner = _scroll->setOwnedWidget(object_ptr<DialogsInner>(this, parent));
connect(_inner, SIGNAL(mustScrollTo(int,int)), _scroll, SLOT(scrollToY(int,int)));
connect(_inner, SIGNAL(dialogMoved(int,int)), this, SLOT(onDialogMoved(int,int)));
connect(_inner, SIGNAL(searchMessages()), this, SLOT(onNeedSearchMessages()));

View File

@ -254,8 +254,8 @@ private:
State _state = DefaultState;
ChildWidget<Ui::LinkButton> _addContactLnk;
ChildWidget<Ui::IconButton> _cancelSearchInPeer;
object_ptr<Ui::LinkButton> _addContactLnk;
object_ptr<Ui::IconButton> _cancelSearchInPeer;
PeerData *_searchInPeer = nullptr;
PeerData *_searchInMigrated = nullptr;
@ -382,14 +382,14 @@ private:
mtpRequestId _contactsRequestId = 0;
bool _pinnedDialogsReceived = false;
ChildWidget<Ui::IconButton> _forwardCancel = { nullptr };
ChildWidget<Ui::IconButton> _mainMenuToggle;
ChildWidget<Ui::FlatInput> _filter;
ChildWidget<Ui::CrossButton> _cancelSearch;
ChildWidget<Ui::IconButton> _lockUnlock;
ChildWidget<Ui::ScrollArea> _scroll;
ChildWidget<DialogsInner> _inner;
ChildWidget<Ui::FlatButton> _updateTelegram = { nullptr };
object_ptr<Ui::IconButton> _forwardCancel = { nullptr };
object_ptr<Ui::IconButton> _mainMenuToggle;
object_ptr<Ui::FlatInput> _filter;
object_ptr<Ui::CrossButton> _cancelSearch;
object_ptr<Ui::IconButton> _lockUnlock;
object_ptr<Ui::ScrollArea> _scroll;
QPointer<DialogsInner> _inner;
object_ptr<Ui::FlatButton> _updateTelegram = { nullptr };
Animation _a_show;
Window::SlideDirection _showDirection;

View File

@ -99,14 +99,16 @@ void activateBotCommand(const HistoryItem *msg, int row, int col) {
case ButtonType::RequestLocation: {
hideSingleUseKeyboard(msg);
Ui::showLayer(new InformBox(lang(lng_bot_share_location_unavailable)));
Ui::show(Box<InformBox>(lang(lng_bot_share_location_unavailable)));
} break;
case ButtonType::RequestPhone: {
hideSingleUseKeyboard(msg);
auto box = new SharePhoneConfirmBox(msg->history()->peer);
box->connect(box, SIGNAL(confirmed(PeerData*)), App::main(), SLOT(onSharePhoneWithBot(PeerData*)));
Ui::showLayer(box);
Ui::show(Box<ConfirmBox>(lang(lng_bot_share_phone), lang(lng_bot_share_phone_confirm), [peerId = msg->history()->peer->id] {
if (auto m = App::main()) {
m->onShareContact(peerId, App::self());
}
}));
} break;
case ButtonType::SwitchInlineSame:
@ -188,6 +190,15 @@ void logOutDelayed() {
} // namespace App
namespace Ui {
namespace internal {
void showBox(object_ptr<BoxContent> content, ShowLayerOptions options) {
if (auto w = App::wnd()) {
w->ui_showBox(std_::move(content), options);
}
}
} // namespace internal
void showMediaPreview(DocumentData *document) {
if (auto w = App::wnd()) {
@ -207,20 +218,16 @@ void hideMediaPreview() {
}
}
void showLayer(LayerWidget *box, ShowLayerOptions options) {
void hideLayer(bool fast) {
if (auto w = App::wnd()) {
w->ui_showLayer(box, options);
} else {
delete box;
w->ui_showBox({ nullptr }, CloseOtherLayers | (fast ? ForceFastShowLayer : AnimatedShowLayer));
}
}
void hideLayer(bool fast) {
if (auto w = App::wnd()) w->ui_showLayer(0, CloseOtherLayers | (fast ? ForceFastShowLayer : AnimatedShowLayer));
}
void hideSettingsAndLayer(bool fast) {
if (auto w = App::wnd()) w->ui_hideSettingsAndLayer(fast ? ForceFastShowLayer : AnimatedShowLayer);
if (auto w = App::wnd()) {
w->ui_hideSettingsAndLayer(fast ? ForceFastShowLayer : AnimatedShowLayer);
}
}
bool isLayerShown() {

View File

@ -24,6 +24,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "core/observer.h"
class LayerWidget;
class BoxContent;
namespace InlineBots {
namespace Layout {
@ -76,12 +77,23 @@ void logOutDelayed();
} // namespace App
namespace Ui {
namespace internal {
void showBox(object_ptr<BoxContent> content, ShowLayerOptions options);
} // namespace internal
void showMediaPreview(DocumentData *document);
void showMediaPreview(PhotoData *photo);
void hideMediaPreview();
void showLayer(LayerWidget *box, ShowLayerOptions options = CloseOtherLayers);
template <typename BoxType>
QPointer<BoxType> show(object_ptr<BoxType> content, ShowLayerOptions options = CloseOtherLayers) {
auto result = QPointer<BoxType>(content.data());
internal::showBox(std_::move(content), options);
return result;
}
void hideLayer(bool fast = false);
void hideSettingsAndLayer(bool fast = false);
bool isLayerShown();

View File

@ -30,18 +30,18 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "styles/style_stickers.h"
FieldAutocomplete::FieldAutocomplete(QWidget *parent) : TWidget(parent)
, _scroll(this, st::mentionScroll)
, _inner(this, &_mrows, &_hrows, &_brows, &_srows) {
connect(_inner, SIGNAL(mentionChosen(UserData*,FieldAutocomplete::ChooseMethod)), this, SIGNAL(mentionChosen(UserData*,FieldAutocomplete::ChooseMethod)));
connect(_inner, SIGNAL(hashtagChosen(QString,FieldAutocomplete::ChooseMethod)), this, SIGNAL(hashtagChosen(QString,FieldAutocomplete::ChooseMethod)));
connect(_inner, SIGNAL(botCommandChosen(QString,FieldAutocomplete::ChooseMethod)), this, SIGNAL(botCommandChosen(QString,FieldAutocomplete::ChooseMethod)));
connect(_inner, SIGNAL(stickerChosen(DocumentData*,FieldAutocomplete::ChooseMethod)), this, SIGNAL(stickerChosen(DocumentData*,FieldAutocomplete::ChooseMethod)));
connect(_inner, SIGNAL(mustScrollTo(int, int)), _scroll, SLOT(scrollToY(int, int)));
_inner->setGeometry(rect());
, _scroll(this, st::mentionScroll) {
_scroll->setGeometry(rect());
_scroll->setOwnedWidget(_inner);
_inner = _scroll->setOwnedWidget(object_ptr<internal::FieldAutocompleteInner>(this, &_mrows, &_hrows, &_brows, &_srows));
_inner->setGeometry(rect());
connect(_inner, SIGNAL(mentionChosen(UserData*, FieldAutocomplete::ChooseMethod)), this, SIGNAL(mentionChosen(UserData*, FieldAutocomplete::ChooseMethod)));
connect(_inner, SIGNAL(hashtagChosen(QString, FieldAutocomplete::ChooseMethod)), this, SIGNAL(hashtagChosen(QString, FieldAutocomplete::ChooseMethod)));
connect(_inner, SIGNAL(botCommandChosen(QString, FieldAutocomplete::ChooseMethod)), this, SIGNAL(botCommandChosen(QString, FieldAutocomplete::ChooseMethod)));
connect(_inner, SIGNAL(stickerChosen(DocumentData*, FieldAutocomplete::ChooseMethod)), this, SIGNAL(stickerChosen(DocumentData*, FieldAutocomplete::ChooseMethod)));
connect(_inner, SIGNAL(mustScrollTo(int, int)), _scroll, SLOT(scrollToY(int, int)));
_scroll->show();
_inner->show();
@ -412,7 +412,7 @@ void FieldAutocomplete::hideAnimated() {
}
_scroll->hide();
_hiding = true;
_a_opacity.start([this] { animationCallback(); }, 1., 0., st::defaultDropdownDuration);
_a_opacity.start([this] { animationCallback(); }, 1., 0., st::emojiPanDuration);
setAttribute(Qt::WA_OpaquePaintEvent, false);
}
@ -434,7 +434,7 @@ void FieldAutocomplete::showAnimated() {
_scroll->hide();
_hiding = false;
show();
_a_opacity.start([this] { animationCallback(); }, 0., 1., st::defaultDropdownDuration);
_a_opacity.start([this] { animationCallback(); }, 0., 1., st::emojiPanDuration);
setAttribute(Qt::WA_OpaquePaintEvent, false);
}

View File

@ -21,7 +21,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#pragma once
#include "ui/twidget.h"
#include "ui/effects/rect_shadow.h"
namespace Ui {
class ScrollArea;
@ -109,8 +108,8 @@ private:
void rowsUpdated(const internal::MentionRows &mrows, const internal::HashtagRows &hrows, const internal::BotCommandRows &brows, const StickerPack &srows, bool resetScroll);
ChildWidget<Ui::ScrollArea> _scroll;
ChildWidget<internal::FieldAutocompleteInner> _inner;
object_ptr<Ui::ScrollArea> _scroll;
QPointer<internal::FieldAutocompleteInner> _inner;
ChatData *_chat = nullptr;
UserData *_user = nullptr;

View File

@ -22,7 +22,7 @@ using "basic.style";
using "dialogs/dialogs.style";
using "ui/widgets/widgets.style";
historyScroll: FlatScroll(defaultFlatScroll) {
historyScroll: ScrollArea(defaultScrollArea) {
barColor: #89a0b47a;
bgColor: #89a0b44c;
barOverColor: #89a0b4bc;
@ -70,7 +70,7 @@ historyToDownDuration: 150;
membersInnerWidth: 310px;
membersInnerHeightMax: 360px;
membersInnerDropdown: InnerDropdown(defaultInnerDropdown) {
scroll: FlatScroll(defaultSolidScroll) {
scroll: ScrollArea(defaultSolidScroll) {
deltat: 3px;
deltab: 3px;
round: 1px;
@ -389,7 +389,7 @@ botKbTinyButton: BotKeyboardButton {
botKbScroll: defaultSolidScroll;
mentionHeight: 40px;
mentionScroll: FlatScroll(defaultFlatScroll) {
mentionScroll: ScrollArea(defaultScrollArea) {
topsh: 0px;
bottomsh: 0px;
}

View File

@ -35,14 +35,23 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "apiwrap.h"
#include "mainwidget.h"
DragArea::DragArea(QWidget *parent) : TWidget(parent)
, _hiding(false)
, _in(false)
, _shadow(st::boxShadow) {
DragArea::DragArea(QWidget *parent) : TWidget(parent) {
setMouseTracking(true);
setAcceptDrops(true);
}
bool DragArea::overlaps(const QRect &globalRect) {
if (isHidden() || _a_opacity.animating()) {
return false;
}
auto inner = innerRect();
auto testRect = QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size());
return inner.marginsRemoved(QMargins(st::boxRadius, 0, st::boxRadius, 0)).contains(testRect)
|| inner.marginsRemoved(QMargins(0, st::boxRadius, 0, st::boxRadius)).contains(testRect);
}
void DragArea::mouseMoveEvent(QMouseEvent *e) {
if (_hiding) return;
@ -60,7 +69,7 @@ void DragArea::dragMoveEvent(QDragMoveEvent *e) {
void DragArea::setIn(bool in) {
if (_in != in) {
_in = in;
_a_in.start([this] { update(); }, _in ? 0. : 1., _in ? 1. : 0., st::defaultDropdownDuration);
_a_in.start([this] { update(); }, _in ? 0. : 1., _in ? 1. : 0., st::boxDuration);
}
}
@ -79,13 +88,15 @@ void DragArea::paintEvent(QPaintEvent *e) {
return;
}
p.setOpacity(opacity);
auto inner = innerRect();
QRect r(st::dragPadding.left(), st::dragPadding.top(), width() - st::dragPadding.left() - st::dragPadding.right(), height() - st::dragPadding.top() - st::dragPadding.bottom());
if (!_cache.isNull()) {
p.drawPixmapLeft(inner.x() - st::boxRoundShadow.extend.left(), inner.y() - st::boxRoundShadow.extend.top(), width(), _cache);
return;
}
// draw shadow
_shadow.paint(p, r, st::boxShadowShift);
p.fillRect(r, st::dragBg);
Ui::Shadow::paint(p, inner, width(), st::boxRoundShadow);
App::roundRect(p, inner, st::boxBg, BoxCorners);
p.setPen(anim::pen(st::dragColor, st::dragDropColor, _a_in.current(ms, _in ? 1. : 0.)));
@ -128,9 +139,15 @@ void DragArea::hideFast() {
}
void DragArea::hideStart() {
if (_hiding || isHidden()) {
return;
}
if (_cache.isNull()) {
_cache = myGrab(this, innerRect().marginsAdded(st::boxRoundShadow.extend));
}
_hiding = true;
setIn(false);
_a_opacity.start([this] { opacityAnimationCallback(); }, 1., 0., st::defaultDropdownDuration);
_a_opacity.start([this] { opacityAnimationCallback(); }, 1., 0., st::boxDuration);
}
void DragArea::hideFinish() {
@ -140,14 +157,21 @@ void DragArea::hideFinish() {
}
void DragArea::showStart() {
if (!_hiding && !isHidden()) {
return;
}
_hiding = false;
if (_cache.isNull()) {
_cache = myGrab(this, innerRect().marginsAdded(st::boxRoundShadow.extend));
}
show();
_a_opacity.start([this] { opacityAnimationCallback(); }, 0., 1., st::defaultDropdownDuration);
_a_opacity.start([this] { opacityAnimationCallback(); }, 0., 1., st::boxDuration);
}
void DragArea::opacityAnimationCallback() {
update();
if (!_a_opacity.animating()) {
_cache = QPixmap();
if (_hiding) {
hideFinish();
}

View File

@ -21,7 +21,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#pragma once
#include "ui/twidget.h"
#include "ui/effects/rect_shadow.h"
class DragArea : public TWidget {
Q_OBJECT
@ -34,15 +33,7 @@ public:
void otherEnter();
void otherLeave();
bool overlaps(const QRect &globalRect) {
if (isHidden() || _a_opacity.animating()) return false;
return QRect(st::dragPadding.left(),
st::dragPadding.top(),
width() - st::dragPadding.left() - st::dragPadding.right(),
height() - st::dragPadding.top() - st::dragPadding.bottom()
).contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size()));
}
bool overlaps(const QRect &globalRect);
void hideFast();
@ -67,16 +58,23 @@ public slots:
private:
void setIn(bool in);
void opacityAnimationCallback();
QRect innerRect() const {
return QRect(
st::dragPadding.left(),
st::dragPadding.top(),
width() - st::dragPadding.left() - st::dragPadding.right(),
height() - st::dragPadding.top() - st::dragPadding.bottom()
);
}
bool _hiding = false;
bool _in = false;
QPixmap _cache;
base::lambda<void(const QMimeData *data)> _droppedCallback;
Animation _a_opacity;
Animation _a_in;
Ui::RectShadow _shadow;
QString _text, _subtext;
};

View File

@ -1554,7 +1554,7 @@ void HistoryGif::initDimensions() {
int32 tw = 0, th = 0;
if (_gif && _gif->state() == Media::Clip::State::Error) {
if (!_gif->autoplay()) {
Ui::showLayer(new InformBox(lang(lng_gif_error)));
Ui::show(Box<InformBox>(lang(lng_gif_error)));
}
App::unregGifItem(_gif.get());
_gif.setBad();
@ -2204,7 +2204,7 @@ ClickHandlerPtr addContactClickHandler(HistoryItem *item) {
auto fname = contact->fname();
auto lname = contact->lname();
auto phone = contact->phone();
Ui::showLayer(new AddContactBox(fname, lname, phone));
Ui::show(Box<AddContactBox>(fname, lname, phone));
}
}
}

View File

@ -29,6 +29,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "history/history_service_layout.h"
#include "history/history_media_types.h"
#include "styles/style_dialogs.h"
#include "styles/style_widgets.h"
#include "styles/style_history.h"
namespace {

View File

@ -2677,32 +2677,28 @@ void BotKeyboard::updateSelected() {
HistoryHider::HistoryHider(MainWidget *parent, bool forwardSelected) : TWidget(parent)
, _forwardSelected(forwardSelected)
, _send(this, lang(lng_forward_send), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _shadow(st::boxShadow) {
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
init();
}
HistoryHider::HistoryHider(MainWidget *parent, UserData *sharedContact) : TWidget(parent)
, _sharedContact(sharedContact)
, _send(this, lang(lng_forward_send), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _shadow(st::boxShadow) {
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
init();
}
HistoryHider::HistoryHider(MainWidget *parent) : TWidget(parent)
, _sendPath(true)
, _send(this, lang(lng_forward_send), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _shadow(st::boxShadow) {
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
init();
}
HistoryHider::HistoryHider(MainWidget *parent, const QString &botAndQuery) : TWidget(parent)
, _botAndQuery(botAndQuery)
, _send(this, lang(lng_forward_send), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _shadow(st::boxShadow) {
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
init();
}
@ -2710,8 +2706,7 @@ HistoryHider::HistoryHider(MainWidget *parent, const QString &url, const QString
, _shareUrl(url)
, _shareText(text)
, _send(this, lang(lng_forward_send), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _shadow(st::boxShadow) {
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
init();
}
@ -2747,15 +2742,16 @@ void HistoryHider::paintEvent(QPaintEvent *e) {
if (_cacheForAnim.isNull() || !_offered) {
p.setFont(st::forwardFont);
if (_offered) {
_shadow.paint(p, _box, st::boxShadowShift);
// fill bg
p.fillRect(_box, st::boxBg);
Ui::Shadow::paint(p, _box, width(), st::boxRoundShadow);
App::roundRect(p, _box, st::boxBg, BoxCorners);
p.setPen(st::boxTextFg);
_toText.drawElided(p, _box.left() + st::boxPadding.left(), _box.top() + st::boxPadding.top(), _toTextWidth + 2);
textstyleSet(&st::boxTextStyle);
_toText.drawLeftElided(p, _box.left() + st::boxPadding.left(), _box.y() + st::boxTopMargin + st::boxPadding.top(), _toTextWidth + 2, width(), 1, style::al_left);
textstyleRestore();
} else {
int32 w = st::forwardMargins.left() + _chooseWidth + st::forwardMargins.right(), h = st::forwardMargins.top() + st::forwardFont->height + st::forwardMargins.bottom();
auto w = st::forwardMargins.left() + _chooseWidth + st::forwardMargins.right();
auto h = st::forwardMargins.top() + st::forwardFont->height + st::forwardMargins.bottom();
App::roundRect(p, (width() - w) / 2, (height() - h) / 2, w, h, st::forwardBg, ForwardCorners);
p.setPen(st::forwardFg);
@ -2839,20 +2835,21 @@ MainWidget *HistoryHider::parent() {
}
void HistoryHider::resizeEvent(QResizeEvent *e) {
int32 w = st::boxWidth, h = st::boxPadding.top() + st::boxPadding.bottom();
auto w = st::boxWidth;
auto h = st::boxPadding.top() + st::boxPadding.bottom();
if (_offered) {
if (!_hiding) {
_send->show();
_cancel->show();
}
h += st::boxTextFont->height + st::boxButtonPadding.top() + _send->height() + st::boxButtonPadding.bottom();
h += st::boxTopMargin + qMax(st::boxTextFont->height, st::boxTextStyle.lineHeight) + st::boxButtonPadding.top() + _send->height() + st::boxButtonPadding.bottom();
} else {
h += st::forwardFont->height;
_send->hide();
_cancel->hide();
}
_box = QRect((width() - w) / 2, (height() - h) / 2, w, h);
_send->moveToRight(width() - (_box.x() + _box.width()) + st::boxButtonPadding.right(), _box.y() + h - st::boxButtonPadding.bottom() - _send->height());
_send->moveToRight(width() - (_box.x() + _box.width()) + st::boxButtonPadding.right(), _box.y() + _box.height() - st::boxButtonPadding.bottom() - _send->height());
_cancel->moveToRight(width() - (_box.x() + _box.width()) + st::boxButtonPadding.right() + _send->width() + st::boxButtonPadding.left(), _send->y());
}
@ -2899,10 +2896,12 @@ bool HistoryHider::offerPeer(PeerId peer) {
return false;
}
textstyleSet(&st::boxTextStyle);
_toText.setText(st::boxTextFont, phrase, _textNameOptions);
textstyleRestore();
_toTextWidth = _toText.maxWidth();
if (_toTextWidth > _box.width() - st::boxPadding.left() - st::boxButtonPadding.right()) {
_toTextWidth = _box.width() - st::boxPadding.left() - st::boxButtonPadding.right();
if (_toTextWidth > _box.width() - st::boxPadding.left() - st::boxLayerButtonPadding.right()) {
_toTextWidth = _box.width() - st::boxPadding.left() - st::boxLayerButtonPadding.right();
}
resizeEvent(nullptr);
@ -3047,7 +3046,6 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
, _recordCancelWidth(st::historyRecordFont->width(lang(lng_record_cancel)))
, _a_recording(animation(this, &HistoryWidget::step_recording))
, _kbScroll(this, st::botKbScroll)
, _keyboard(this)
, _emojiPan(this)
, _attachDragDocument(this)
, _attachDragPhoto(this)
@ -3123,7 +3121,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
_scroll->hide();
_kbScroll->setOwnedWidget(_keyboard);
_keyboard = _kbScroll->setOwnedWidget(object_ptr<BotKeyboard>(this));
_kbScroll->hide();
updateScrollColors();
@ -4233,9 +4231,8 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re
_fieldBarCancel->hide();
_membersDropdownShowTimer.stop();
if (_list) _list->deleteLater();
_scroll->takeWidget<HistoryInner>().destroyDelayed();
_list = nullptr;
_scroll->takeWidget();
clearInlineBot();
@ -4299,10 +4296,8 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re
}
}
_list = new HistoryInner(this, _scroll, _history);
_list->hide();
_scroll->hide();
_scroll->setWidget(_list);
_list = _scroll->setOwnedWidget(object_ptr<HistoryInner>(this, _scroll, _history));
_list->show();
_updateHistoryItems.stop();
@ -4790,7 +4785,7 @@ bool HistoryWidget::messagesFailed(const RPCError &error, mtpRequestId requestId
if (error.type() == qstr("CHANNEL_PRIVATE") || error.type() == qstr("CHANNEL_PUBLIC_GROUP_NA") || error.type() == qstr("USER_BANNED_IN_CHANNEL")) {
PeerData *was = _peer;
App::main()->showBackFromStack();
Ui::showLayer(new InformBox(lang((was && was->isMegagroup()) ? lng_group_not_accessible : lng_channel_not_accessible)));
Ui::show(Box<InformBox>(lang((was && was->isMegagroup()) ? lng_group_not_accessible : lng_channel_not_accessible)));
return true;
}
@ -5175,7 +5170,7 @@ void HistoryWidget::saveEditMsg() {
_field->setFocus();
return;
} else if (!leftText.isEmpty()) {
Ui::showLayer(new InformBox(lang(lng_edit_too_long)));
Ui::show(Box<InformBox>(lang(lng_edit_too_long)));
return;
}
@ -5219,14 +5214,14 @@ bool HistoryWidget::saveEditMsgFail(History *history, const RPCError &error, mtp
QString err = error.type();
if (err == qstr("MESSAGE_ID_INVALID") || err == qstr("CHAT_ADMIN_REQUIRED") || err == qstr("MESSAGE_EDIT_TIME_EXPIRED")) {
Ui::showLayer(new InformBox(lang(lng_edit_error)));
Ui::show(Box<InformBox>(lang(lng_edit_error)));
} else if (err == qstr("MESSAGE_NOT_MODIFIED")) {
cancelEdit();
} else if (err == qstr("MESSAGE_EMPTY")) {
_field->selectAll();
_field->setFocus();
} else {
Ui::showLayer(new InformBox(lang(lng_edit_error)));
Ui::show(Box<InformBox>(lang(lng_edit_error)));
}
update();
return true;
@ -5347,10 +5342,10 @@ bool HistoryWidget::joinFail(const RPCError &error, mtpRequestId req) {
if (_unblockRequest == req) _unblockRequest = 0;
if (error.type() == qstr("CHANNEL_PRIVATE") || error.type() == qstr("CHANNEL_PUBLIC_GROUP_NA") || error.type() == qstr("USER_BANNED_IN_CHANNEL")) {
Ui::showLayer(new InformBox(lang((_peer && _peer->isMegagroup()) ? lng_group_not_accessible : lng_channel_not_accessible)));
Ui::show(Box<InformBox>(lang((_peer && _peer->isMegagroup()) ? lng_group_not_accessible : lng_channel_not_accessible)));
return true;
} else if (error.type() == qstr("CHANNELS_TOO_MUCH")) {
Ui::showLayer(new InformBox(lang(lng_join_channel_error)));
Ui::show(Box<InformBox>(lang(lng_join_channel_error)));
}
return false;
@ -5779,7 +5774,7 @@ void HistoryWidget::botCallbackDone(BotCallbackInfo info, const MTPmessages_BotC
auto &answerData = answer.c_messages_botCallbackAnswer();
if (answerData.has_message()) {
if (answerData.is_alert()) {
Ui::showLayer(new InformBox(qs(answerData.vmessage)));
Ui::show(Box<InformBox>(qs(answerData.vmessage)));
} else if (App::wnd()) {
Ui::Toast::Config toast;
toast.text = qs(answerData.vmessage);
@ -5923,29 +5918,30 @@ DragState HistoryWidget::getDragState(const QMimeData *d) {
void HistoryWidget::updateDragAreas() {
_field->setAcceptDrops(!_attachDrag);
updateControlsGeometry();
switch (_attachDrag) {
case DragStateNone:
_attachDragDocument->otherLeave();
_attachDragPhoto->otherLeave();
break;
case DragStateFiles:
_attachDragDocument->otherEnter();
_attachDragDocument->setText(lang(lng_drag_files_here), lang(lng_drag_to_send_files));
_attachDragDocument->otherEnter();
_attachDragPhoto->hideFast();
break;
case DragStatePhotoFiles:
_attachDragDocument->otherEnter();
_attachDragDocument->setText(lang(lng_drag_images_here), lang(lng_drag_to_send_no_compression));
_attachDragPhoto->otherEnter();
_attachDragPhoto->setText(lang(lng_drag_photos_here), lang(lng_drag_to_send_quick));
_attachDragDocument->otherEnter();
_attachDragPhoto->otherEnter();
break;
case DragStateImage:
_attachDragPhoto->setText(lang(lng_drag_images_here), lang(lng_drag_to_send_quick));
_attachDragDocument->hideFast();
_attachDragPhoto->otherEnter();
_attachDragPhoto->setText(lang(lng_drag_images_here), lang(lng_drag_to_send_quick));
break;
};
resizeEvent(0);
}
bool HistoryWidget::canSendMessages(PeerData *peer) const {
@ -6157,13 +6153,6 @@ void HistoryWidget::selectMessage() {
if (_list) _list->selectItem(item);
}
void HistoryWidget::onForwardHere() {
HistoryItem *item = App::contextItem();
if (!item || item->type() != HistoryItemMsg || item->serviceMsg()) return;
App::forward(_peer->id, ForwardContextMessage);
}
bool HistoryWidget::paintTopBar(Painter &p, int decreaseWidth, TimeMs ms) {
if (_a_show.animating()) {
auto progress = _a_show.current(1.);
@ -6462,7 +6451,7 @@ void HistoryWidget::updateFieldPlaceholder() {
}
template <typename SendCallback>
bool HistoryWidget::showSendFilesBox(SendFilesBox *box, const QString &insertTextOnCancel, const QString *addedComment, SendCallback callback) {
bool HistoryWidget::showSendFilesBox(object_ptr<SendFilesBox> box, const QString &insertTextOnCancel, const QString *addedComment, SendCallback callback) {
App::wnd()->activateWindow();
auto withComment = (addedComment != nullptr);
@ -6488,7 +6477,7 @@ bool HistoryWidget::showSendFilesBox(SendFilesBox *box, const QString &insertTex
}));
}
Ui::showLayer(box);
Ui::show(std_::move(box));
return true;
}
@ -6498,11 +6487,11 @@ bool HistoryWidget::validateSendingFiles(const SendingFilesLists &lists, Callbac
App::wnd()->activateWindow();
if (!lists.nonLocalUrls.isEmpty()) {
Ui::showLayer(new InformBox(lng_send_image_non_local(lt_name, lists.nonLocalUrls.front().toDisplayString())));
Ui::show(Box<InformBox>(lng_send_image_non_local(lt_name, lists.nonLocalUrls.front().toDisplayString())));
} else if (!lists.emptyFiles.isEmpty()) {
Ui::showLayer(new InformBox(lng_send_image_empty(lt_name, lists.emptyFiles.front())));
Ui::show(Box<InformBox>(lng_send_image_empty(lt_name, lists.emptyFiles.front())));
} else if (!lists.tooLargeFiles.isEmpty()) {
Ui::showLayer(new InformBox(lng_send_image_too_large(lt_name, lists.tooLargeFiles.front())));
Ui::show(Box<InformBox>(lng_send_image_too_large(lt_name, lists.tooLargeFiles.front())));
} else if (!lists.filesToSend.isEmpty()) {
return callback(lists.filesToSend);
}
@ -6523,12 +6512,12 @@ bool HistoryWidget::confirmSendingFiles(const SendingFilesLists &lists, Compress
auto insertTextOnCancel = QString();
auto prepareBox = [this, &files, &lists, compressed, &image] {
if (files.size() > 1) {
return new SendFilesBox(files, lists.allFilesForCompress ? compressed : CompressConfirm::None);
return Box<SendFilesBox>(files, lists.allFilesForCompress ? compressed : CompressConfirm::None);
}
auto filepath = files.front();
auto animated = false;
image = App::readImage(filepath, nullptr, false, &animated);
return new SendFilesBox(filepath, image, imageCompressConfirm(image, compressed, animated), animated);
return Box<SendFilesBox>(filepath, image, imageCompressConfirm(image, compressed, animated), animated);
};
auto sendCallback = [this, image](const QStringList &files, bool compressed, const QString &caption, MsgId replyTo) {
auto type = compressed ? SendMediaType::Photo : SendMediaType::File;
@ -6543,12 +6532,12 @@ bool HistoryWidget::confirmSendingFiles(const QImage &image, const QByteArray &c
App::wnd()->activateWindow();
auto animated = false;
auto box = new SendFilesBox(QString(), image, imageCompressConfirm(image, compressed), animated);
auto sendCallback = [this, content, image](const QStringList &files, bool compressed, const QString &caption, MsgId replyTo) {
auto type = compressed ? SendMediaType::Photo : SendMediaType::File;
uploadFilesAfterConfirmation(files, image, content, type, caption);
};
return showSendFilesBox(box, insertTextOnCancel, nullptr, std_::move(sendCallback));
auto box = Box<SendFilesBox>(QString(), image, imageCompressConfirm(image, compressed), animated);
return showSendFilesBox(std_::move(box), insertTextOnCancel, nullptr, std_::move(sendCallback));
}
bool HistoryWidget::confirmSendingFiles(const QMimeData *data, CompressConfirm compressed, const QString &insertTextOnCancel) {
@ -6578,12 +6567,12 @@ bool HistoryWidget::confirmSendingFiles(const QMimeData *data, CompressConfirm c
bool HistoryWidget::confirmShareContact(const QString &phone, const QString &fname, const QString &lname, const QString *addedComment) {
if (!canWriteMessage()) return false;
auto box = new SendFilesBox(phone, fname, lname);
auto box = Box<SendFilesBox>(phone, fname, lname);
auto sendCallback = [this, phone, fname, lname](const QStringList &files, bool compressed, const QString &caption, MsgId replyTo) {
shareContact(_peer->id, phone, fname, lname, replyTo);
};
auto insertTextOnCancel = QString();
return showSendFilesBox(box, insertTextOnCancel, addedComment, std_::move(sendCallback));
return showSendFilesBox(std_::move(box), insertTextOnCancel, addedComment, std_::move(sendCallback));
}
HistoryWidget::SendingFilesLists HistoryWidget::getSendingFilesLists(const QList<QUrl> &files) {
@ -6901,18 +6890,15 @@ void HistoryWidget::onDocumentFailed(const FullMsgId &newId) {
}
void HistoryWidget::onReportSpamClicked() {
ConfirmBox *box = new ConfirmBox(lang(_peer->isUser() ? lng_report_spam_sure : ((_peer->isChat() || _peer->isMegagroup()) ? lng_report_spam_sure_group : lng_report_spam_sure_channel)), lang(lng_report_spam_ok), st::attentionBoxButton);
connect(box, SIGNAL(confirmed()), this, SLOT(onReportSpamSure()));
Ui::showLayer(box);
_clearPeer = _peer;
}
auto text = lang(_peer->isUser() ? lng_report_spam_sure : ((_peer->isChat() || _peer->isMegagroup()) ? lng_report_spam_sure_group : lng_report_spam_sure_channel));
Ui::show(Box<ConfirmBox>(text, lang(lng_report_spam_ok), st::attentionBoxButton, base::lambda_guarded(this, [this] {
if (_reportSpamRequest) return;
void HistoryWidget::onReportSpamSure() {
if (_reportSpamRequest) return;
Ui::hideLayer();
if (_clearPeer->isUser()) MTP::send(MTPcontacts_Block(_clearPeer->asUser()->inputUser), rpcDone(&HistoryWidget::blockDone, _clearPeer), RPCFailHandlerPtr(), 0, 5);
_reportSpamRequest = MTP::send(MTPmessages_ReportSpam(_clearPeer->input), rpcDone(&HistoryWidget::reportSpamDone, _clearPeer), rpcFail(&HistoryWidget::reportSpamFail));
Ui::hideLayer();
if (_clearPeer->isUser()) MTP::send(MTPcontacts_Block(_clearPeer->asUser()->inputUser), rpcDone(&HistoryWidget::blockDone, _clearPeer), RPCFailHandlerPtr(), 0, 5);
_reportSpamRequest = MTP::send(MTPmessages_ReportSpam(_clearPeer->input), rpcDone(&HistoryWidget::reportSpamDone, _clearPeer), rpcFail(&HistoryWidget::reportSpamFail));
})));
}
void HistoryWidget::reportSpamDone(PeerData *peer, const MTPBool &result, mtpRequestId req) {
@ -7091,7 +7077,7 @@ void HistoryWidget::updateControlsGeometry() {
updateHistoryDownPosition();
_emojiPan->setMaxHeight(height() - st::defaultDropdownPadding.top() - st::defaultDropdownPadding.bottom() - _attachEmoji->height());
_emojiPan->setMaxHeight(height() - _attachEmoji->height());
if (_membersDropdown) {
_membersDropdown->setMaxHeight(countMembersDropdownHeightMax());
}
@ -7855,14 +7841,16 @@ void HistoryWidget::onReplyToMessage() {
onReplyToMessage();
App::contextItem(to);
} else {
LayerWidget *box = nullptr;
if (to->type() != HistoryItemMsg || to->serviceMsg()) {
box = new InformBox(lang(lng_reply_cant));
Ui::show(Box<InformBox>(lang(lng_reply_cant)));
} else {
box = new ConfirmBox(lang(lng_reply_cant_forward), lang(lng_selected_forward));
connect(box, SIGNAL(confirmed()), this, SLOT(onForwardHere()));
Ui::show(Box<ConfirmBox>(lang(lng_reply_cant_forward), lang(lng_selected_forward), base::lambda_guarded(this, [this] {
auto item = App::contextItem();
if (!item || item->type() != HistoryItemMsg || item->serviceMsg()) return;
App::forward(_peer->id, ForwardContextMessage);
})));
}
Ui::showLayer(box);
}
return;
}
@ -7897,15 +7885,12 @@ void HistoryWidget::onReplyToMessage() {
}
void HistoryWidget::onEditMessage() {
HistoryItem *to = App::contextItem();
auto to = App::contextItem();
if (!to) return;
EditCaptionBox *box = new EditCaptionBox(to);
if (box->captionFound()) {
Ui::showLayer(box);
if (EditCaptionBox::canEdit(to)) {
Ui::show(Box<EditCaptionBox>(to));
} else {
delete box;
if (!_editMsgId) {
if (_replyToId || !_field->isEmpty()) {
_history->setLocalDraft(std_::make_unique<Data::Draft>(_field, _replyToId, _previewCancelled));
@ -7954,29 +7939,25 @@ void HistoryWidget::onPinMessage() {
HistoryItem *to = App::contextItem();
if (!to || !to->canPin() || !_peer || !_peer->isMegagroup()) return;
Ui::showLayer(new PinMessageBox(_peer->asChannel(), to->id));
Ui::show(Box<PinMessageBox>(_peer->asChannel(), to->id));
}
void HistoryWidget::onUnpinMessage() {
if (!_peer || !_peer->isMegagroup()) return;
ConfirmBox *box = new ConfirmBox(lang(lng_pinned_unpin_sure), lang(lng_pinned_unpin));
connect(box, SIGNAL(confirmed()), this, SLOT(onUnpinMessageSure()));
Ui::showLayer(box);
}
Ui::show(Box<ConfirmBox>(lang(lng_pinned_unpin_sure), lang(lng_pinned_unpin), base::lambda_guarded(this, [this] {
if (!_peer || !_peer->isMegagroup()) return;
void HistoryWidget::onUnpinMessageSure() {
if (!_peer || !_peer->isMegagroup()) return;
_peer->asChannel()->mgInfo->pinnedMsgId = 0;
if (pinnedMsgVisibilityUpdated()) {
resizeEvent(0);
update();
}
_peer->asChannel()->mgInfo->pinnedMsgId = 0;
if (pinnedMsgVisibilityUpdated()) {
resizeEvent(0);
update();
}
Ui::hideLayer();
MTPchannels_UpdatePinnedMessage::Flags flags = 0;
MTP::send(MTPchannels_UpdatePinnedMessage(MTP_flags(flags), _peer->asChannel()->inputChannel, MTP_int(0)), rpcDone(&HistoryWidget::unpinDone));
Ui::hideLayer();
MTPchannels_UpdatePinnedMessage::Flags flags = 0;
MTP::send(MTPchannels_UpdatePinnedMessage(MTP_flags(flags), _peer->asChannel()->inputChannel, MTP_int(0)), rpcDone(&HistoryWidget::unpinDone));
})));
}
void HistoryWidget::unpinDone(const MTPUpdates &updates) {
@ -8279,9 +8260,13 @@ void HistoryWidget::onCancel() {
auto editTags = textTagsFromEntities(original.entities);
TextWithTags editData = { editText, editTags };
if (_replyEditMsg && editData != _field->getTextWithTags()) {
auto box = new ConfirmBox(lang(lng_cancel_edit_post_sure), lang(lng_cancel_edit_post_yes), st::defaultBoxButton, lang(lng_cancel_edit_post_no));
connect(box, SIGNAL(confirmed()), this, SLOT(onFieldBarCancel()));
Ui::showLayer(box);
Ui::show(Box<ConfirmBox>(
lang(lng_cancel_edit_post_sure),
lang(lng_cancel_edit_post_yes),
lang(lng_cancel_edit_post_no),
base::lambda_guarded(this, [this] {
onFieldBarCancel();
})));
} else {
onFieldBarCancel();
}
@ -8326,7 +8311,7 @@ void HistoryWidget::peerUpdated(PeerData *data) {
QString restriction = _peer->restrictionReason();
if (!restriction.isEmpty()) {
App::main()->showBackFromStack();
Ui::showLayer(new InformBox(restriction));
Ui::show(Box<InformBox>(restriction));
return;
}
bool resize = false;
@ -8926,7 +8911,3 @@ bool HistoryWidget::touchScroll(const QPoint &delta) {
_scroll->scrollToY(scNew);
return true;
}
HistoryWidget::~HistoryWidget() {
delete base::take(_list);
}

View File

@ -22,7 +22,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "localimageloader.h"
#include "ui/filedialog.h"
#include "ui/effects/rect_shadow.h"
#include "ui/widgets/tooltip.h"
#include "ui/widgets/input_fields.h"
#include "ui/widgets/scroll_area.h"
@ -365,9 +364,9 @@ protected:
void paintEvent(QPaintEvent *e) override;
private:
ChildWidget<Ui::FlatButton> _report;
ChildWidget<Ui::FlatButton> _hide;
ChildWidget<Ui::LinkButton> _clear;
object_ptr<Ui::FlatButton> _report;
object_ptr<Ui::FlatButton> _hide;
object_ptr<Ui::LinkButton> _clear;
};
@ -506,8 +505,8 @@ private:
QString _shareUrl, _shareText;
QString _botAndQuery;
ChildWidget<Ui::RoundButton> _send;
ChildWidget<Ui::RoundButton> _cancel;
object_ptr<Ui::RoundButton> _send;
object_ptr<Ui::RoundButton> _cancel;
PeerData *_offered = nullptr;
Animation _a_opacity;
@ -523,8 +522,6 @@ private:
int32 _toTextWidth = 0;
QPixmap _cacheForAnim;
Ui::RectShadow _shadow;
};
EntitiesInText entitiesFromTextTags(const TextWithTags::Tags &tags);
@ -724,8 +721,6 @@ public:
bool cmd_next_chat();
bool cmd_previous_chat();
~HistoryWidget();
protected:
void resizeEvent(QResizeEvent *e) override;
void keyPressEvent(QKeyEvent *e) override;
@ -746,7 +741,6 @@ public slots:
void onEditMessage();
void onPinMessage();
void onUnpinMessage();
void onUnpinMessageSure();
void onPinnedHide();
void onCopyPostLink();
void onFieldBarCancel();
@ -773,7 +767,6 @@ public slots:
void onDocumentFailed(const FullMsgId &msgId);
void onReportSpamClicked();
void onReportSpamSure();
void onReportSpamHide();
void onReportSpamClear();
@ -805,8 +798,6 @@ public slots:
void forwardMessage();
void selectMessage();
void onForwardHere(); // instead of a reply
void onFieldFocused();
void onFieldResize();
void onCheckFieldAutocomplete();
@ -867,7 +858,7 @@ private:
template <typename Callback>
bool validateSendingFiles(const SendingFilesLists &lists, Callback callback);
template <typename SendCallback>
bool showSendFilesBox(SendFilesBox *box, const QString &insertTextOnCancel, const QString *addedComment, SendCallback callback);
bool showSendFilesBox(object_ptr<SendFilesBox> box, const QString &insertTextOnCancel, const QString *addedComment, SendCallback callback);
CompressConfirm imageCompressConfirm(const QImage &image, CompressConfirm compressed, bool animated = false);
// If an empty filepath is found we upload (possible) "image" with (possible) "content".
@ -908,7 +899,7 @@ private:
Text _replyEditMsgText;
mutable SingleTimer _updateEditTimeLeftDisplay;
ChildWidget<Ui::IconButton> _fieldBarCancel;
object_ptr<Ui::IconButton> _fieldBarCancel;
void updateReplyEditTexts(bool force = false);
struct PinnedBar {
@ -918,8 +909,8 @@ private:
MsgId msgId = 0;
HistoryItem *msg = nullptr;
Text text;
ChildWidget<Ui::IconButton> cancel;
ChildWidget<Ui::PlainShadow> shadow;
object_ptr<Ui::IconButton> cancel;
object_ptr<Ui::PlainShadow> shadow;
};
std_::unique_ptr<PinnedBar> _pinnedBar;
void updatePinnedBar(bool force = false);
@ -1078,8 +1069,8 @@ private:
MsgId _activeAnimMsgId = 0;
ChildWidget<Ui::ScrollArea> _scroll;
HistoryInner *_list = nullptr;
object_ptr<Ui::ScrollArea> _scroll;
QPointer<HistoryInner> _list;
History *_migrated = nullptr;
History *_history = nullptr;
bool _histInited = false; // initial updateListSize() called
@ -1091,9 +1082,9 @@ private:
Animation _historyDownShown;
bool _historyDownIsShown = false;
ChildWidget<Ui::HistoryDownButton> _historyDown;
object_ptr<Ui::HistoryDownButton> _historyDown;
ChildWidget<FieldAutocomplete> _fieldAutocomplete;
object_ptr<FieldAutocomplete> _fieldAutocomplete;
UserData *_inlineBot = nullptr;
QString _inlineBotUsername;
@ -1108,23 +1099,23 @@ private:
bool isMuteUnmute() const;
bool updateCmdStartShown();
ChildWidget<ReportSpamPanel> _reportSpamPanel;
object_ptr<ReportSpamPanel> _reportSpamPanel;
ChildWidget<Ui::IconButton> _send;
ChildWidget<Ui::FlatButton> _unblock;
ChildWidget<Ui::FlatButton> _botStart;
ChildWidget<Ui::FlatButton> _joinChannel;
ChildWidget<Ui::FlatButton> _muteUnmute;
object_ptr<Ui::IconButton> _send;
object_ptr<Ui::FlatButton> _unblock;
object_ptr<Ui::FlatButton> _botStart;
object_ptr<Ui::FlatButton> _joinChannel;
object_ptr<Ui::FlatButton> _muteUnmute;
mtpRequestId _unblockRequest = 0;
mtpRequestId _reportSpamRequest = 0;
ChildWidget<Ui::IconButton> _attachToggle;
ChildWidget<Ui::EmojiButton> _attachEmoji;
ChildWidget<Ui::IconButton> _botKeyboardShow;
ChildWidget<Ui::IconButton> _botKeyboardHide;
ChildWidget<Ui::IconButton> _botCommandStart;
ChildWidget<SilentToggle> _silent;
object_ptr<Ui::IconButton> _attachToggle;
object_ptr<Ui::EmojiButton> _attachEmoji;
object_ptr<Ui::IconButton> _botKeyboardShow;
object_ptr<Ui::IconButton> _botKeyboardHide;
object_ptr<Ui::IconButton> _botCommandStart;
object_ptr<SilentToggle> _silent;
bool _cmdStartShown = false;
ChildWidget<MessageField> _field;
object_ptr<MessageField> _field;
bool _recording = false;
bool _inRecord = false;
bool _inField = false;
@ -1147,15 +1138,15 @@ private:
bool _kbShown = false;
HistoryItem *_kbReplyTo = nullptr;
ChildWidget<Ui::ScrollArea> _kbScroll;
ChildWidget<BotKeyboard> _keyboard;
object_ptr<Ui::ScrollArea> _kbScroll;
QPointer<BotKeyboard> _keyboard;
ChildWidget<Ui::InnerDropdown> _membersDropdown = { nullptr };
object_ptr<Ui::InnerDropdown> _membersDropdown = { nullptr };
QTimer _membersDropdownShowTimer;
ChildWidget<EmojiPan> _emojiPan;
object_ptr<EmojiPan> _emojiPan;
DragState _attachDrag = DragStateNone;
ChildWidget<DragArea> _attachDragDocument, _attachDragPhoto;
object_ptr<DragArea> _attachDragDocument, _attachDragPhoto;
int32 _selCount; // < 0 - text selected, focus list, not _field
@ -1186,7 +1177,7 @@ private:
bool _saveDraftText = false;
QTimer _saveDraftTimer, _saveCloudDraftTimer;
ChildWidget<Ui::PlainShadow> _topShadow;
object_ptr<Ui::PlainShadow> _topShadow;
bool _inGrab = false;
};

View File

@ -91,20 +91,20 @@ private:
void stopCheck();
ChildWidget<Ui::LinkButton> _noTelegramCode;
object_ptr<Ui::LinkButton> _noTelegramCode;
mtpRequestId _noTelegramCodeRequestId = 0;
ChildWidget<CodeInput> _code;
object_ptr<CodeInput> _code;
QString _sentCode;
mtpRequestId _sentRequest = 0;
ChildObject<QTimer> _callTimer;
object_ptr<QTimer> _callTimer;
Widget::Data::CallStatus _callStatus;
int _callTimeout;
mtpRequestId _callRequestId = 0;
ChildWidget<Ui::FlatLabel> _callLabel;
object_ptr<Ui::FlatLabel> _callLabel;
ChildObject<QTimer> _checkRequest;
object_ptr<QTimer> _checkRequest;
};

View File

@ -81,7 +81,7 @@ void PhoneWidget::showPhoneError(const QString &text) {
void PhoneWidget::hidePhoneError() {
hideError();
if (_signup) {
_signup->fadeOut();
_signup->hideAnimated();
showDescription();
}
}
@ -90,8 +90,8 @@ void PhoneWidget::showSignup() {
showPhoneError(lang(lng_bad_phone_noreg));
if (!_signup) {
auto signupText = lng_phone_notreg(lt_link_start, textcmdStartLink(1), lt_link_end, textcmdStopLink(), lt_signup_start, textcmdStartLink(2), lt_signup_end, textcmdStopLink());
auto inner = new Ui::FlatLabel(this, signupText, Ui::FlatLabel::InitType::Rich, st::introDescription, st::introDescriptionTextStyle);
_signup.create(this, inner, base::lambda<void()>(), st::introErrorDuration);
auto inner = object_ptr<Ui::FlatLabel>(this, signupText, Ui::FlatLabel::InitType::Rich, st::introDescription, st::introDescriptionTextStyle);
_signup.create(this, std_::move(inner), st::introErrorDuration);
_signup->entity()->setLink(1, MakeShared<UrlClickHandler>(qsl("https://telegram.org"), false));
_signup->entity()->setLink(2, MakeShared<LambdaClickHandler>([this] {
toSignUp();
@ -99,7 +99,7 @@ void PhoneWidget::showSignup() {
_signup->hideFast();
updateSignupGeometry();
}
_signup->fadeIn();
_signup->showAnimated();
hideDescription();
}

View File

@ -76,16 +76,16 @@ private:
bool _changed = false;
ChildWidget<CountryInput> _country;
ChildWidget<Ui::CountryCodeInput> _code;
ChildWidget<Ui::PhonePartInput> _phone;
object_ptr<CountryInput> _country;
object_ptr<Ui::CountryCodeInput> _code;
object_ptr<Ui::PhonePartInput> _phone;
ChildWidget<Ui::WidgetFadeWrap<Ui::FlatLabel>> _signup = { nullptr };
object_ptr<Ui::WidgetFadeWrap<Ui::FlatLabel>> _signup = { nullptr };
QString _sentPhone;
mtpRequestId _sentRequest = 0;
ChildObject<QTimer> _checkRequest;
object_ptr<QTimer> _checkRequest;
};

View File

@ -229,19 +229,15 @@ void PwdCheckWidget::onToRecover() {
MTP::send(MTPauth_RequestPasswordRecovery(), rpcDone(&PwdCheckWidget::recoverStarted), rpcFail(&PwdCheckWidget::recoverStartFail));
}
} else {
ConfirmBox *box = new InformBox(lang(lng_signin_no_email_forgot));
Ui::showLayer(box);
connect(box, SIGNAL(destroyed(QObject*)), this, SLOT(onToReset()));
Ui::show(Box<InformBox>(lang(lng_signin_no_email_forgot), [this] { showReset(); }));
}
}
void PwdCheckWidget::onToPassword() {
ConfirmBox *box = new InformBox(lang(lng_signin_cant_email_forgot));
Ui::showLayer(box);
connect(box, SIGNAL(destroyed(QObject*)), this, SLOT(onToReset()));
Ui::show(Box<InformBox>(lang(lng_signin_cant_email_forgot), [this] { showReset(); }));
}
void PwdCheckWidget::onToReset() {
void PwdCheckWidget::showReset() {
if (_sentRequest) {
MTP::cancel(base::take(_sentRequest));
}

View File

@ -51,9 +51,10 @@ private slots:
void onToPassword();
void onInputChange();
void onCheckRequest();
void onToReset();
private:
void showReset();
void pwdSubmitDone(bool recover, const MTPauth_Authorization &result);
bool pwdSubmitFail(const RPCError &error);
bool codeSubmitFail(const RPCError &error);
@ -68,16 +69,16 @@ private:
bool _hasRecovery;
QString _hint, _emailPattern;
ChildWidget<Ui::PasswordInput> _pwdField;
ChildWidget<Ui::FlatLabel> _pwdHint;
ChildWidget<Ui::InputField> _codeField;
ChildWidget<Ui::LinkButton> _toRecover;
ChildWidget<Ui::LinkButton> _toPassword;
object_ptr<Ui::PasswordInput> _pwdField;
object_ptr<Ui::FlatLabel> _pwdHint;
object_ptr<Ui::InputField> _codeField;
object_ptr<Ui::LinkButton> _toRecover;
object_ptr<Ui::LinkButton> _toPassword;
mtpRequestId _sentRequest = 0;
QByteArray _pwdSalt;
ChildObject<QTimer> _checkRequest;
object_ptr<QTimer> _checkRequest;
};

View File

@ -81,9 +81,8 @@ void SignupWidget::notifyFileQueryUpdated(const FileDialog::QueryUpdate &update)
showError(lang(lng_bad_photo));
return;
}
auto box = new PhotoCropBox(img, PeerId(0));
connect(box, SIGNAL(ready(const QImage &)), this, SLOT(onPhotoReady(const QImage &)));
Ui::showLayer(box);
auto box = Ui::show(Box<PhotoCropBox>(img, PeerId(0)));
connect(box, SIGNAL(ready(const QImage&)), this, SLOT(onPhotoReady(const QImage&)));
}
void SignupWidget::resizeEvent(QResizeEvent *e) {

View File

@ -61,9 +61,9 @@ private:
QImage _photoImage;
ChildWidget<Ui::NewAvatarButton> _photo;
ChildWidget<Ui::InputField> _first;
ChildWidget<Ui::InputField> _last;
object_ptr<Ui::NewAvatarButton> _photo;
object_ptr<Ui::InputField> _first;
object_ptr<Ui::InputField> _last;
QString _firstName, _lastName;
mtpRequestId _sentRequest = 0;
@ -71,7 +71,7 @@ private:
bool _invertOrder = false;
ChildObject<QTimer> _checkRequest;
object_ptr<QTimer> _checkRequest;
};

View File

@ -47,8 +47,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Intro {
Widget::Widget(QWidget *parent) : TWidget(parent)
, _back(this, new Ui::IconButton(this, st::introBackButton), base::lambda<void()>(), st::introSlideDuration)
, _settings(this, new Ui::RoundButton(this, lang(lng_menu_settings), st::defaultBoxButton), base::lambda<void()>(), st::introCoverDuration)
, _back(this, object_ptr<Ui::IconButton>(this, st::introBackButton), st::introSlideDuration)
, _settings(this, object_ptr<Ui::RoundButton>(this, lang(lng_menu_settings), st::defaultBoxButton), st::introCoverDuration)
, _next(this, QString(), st::introNextButton) {
getData()->country = psCurrentCountry();
@ -65,12 +65,12 @@ Widget::Widget(QWidget *parent) : TWidget(parent)
LangLoaderPlain loader(qsl(":/langs/lang_") + LanguageCodes[systemLangId].c_str() + qsl(".strings"), langLoaderRequest(lng_switch_to_this));
QString text = loader.found().value(lng_switch_to_this);
if (!text.isEmpty()) {
_changeLanguage.create(this, new Ui::LinkButton(this, text), base::lambda<void()>(), st::introCoverDuration);
_changeLanguage.create(this, object_ptr<Ui::LinkButton>(this, text), st::introCoverDuration);
_changeLanguage->entity()->setClickedCallback([this, systemLangId] { changeLanguage(systemLangId); });
}
}
} else {
_changeLanguage.create(this, new Ui::LinkButton(this, langOriginal(lng_switch_to_this)), base::lambda<void()>(), st::introCoverDuration);
_changeLanguage.create(this, object_ptr<Ui::LinkButton>(this, langOriginal(lng_switch_to_this)), st::introCoverDuration);
_changeLanguage->entity()->setClickedCallback([this] { changeLanguage(languageDefault); });
}
@ -98,7 +98,7 @@ Widget::Widget(QWidget *parent) : TWidget(parent)
void Widget::onCheckUpdateStatus() {
if (Sandbox::updatingState() == Application::UpdatingReady) {
if (_update) return;
_update.create(this, new Ui::RoundButton(this, lang(lng_menu_update).toUpper(), st::defaultBoxButton), base::lambda<void()>(), st::introCoverDuration);
_update.create(this, object_ptr<Ui::RoundButton>(this, lang(lng_menu_update).toUpper(), st::defaultBoxButton), st::introCoverDuration);
if (!_a_show.animating()) _update->show();
_update->entity()->setClickedCallback([] {
checkReadyUpdate();
@ -152,21 +152,21 @@ void Widget::historyMove(Direction direction) {
delete base::take(wasStep);
}
if (getStep()->hasBack()) {
_back->fadeIn();
_back->showAnimated();
} else {
_back->fadeOut();
_back->hideAnimated();
}
if (getStep()->hasCover()) {
_settings->fadeOut();
if (_update) _update->fadeOut();
if (_changeLanguage) _changeLanguage->fadeIn();
_settings->hideAnimated();
if (_update) _update->hideAnimated();
if (_changeLanguage) _changeLanguage->showAnimated();
} else {
_settings->fadeIn();
if (_update) _update->fadeIn();
if (_changeLanguage) _changeLanguage->fadeOut();
_settings->showAnimated();
if (_update) _update->showAnimated();
if (_changeLanguage) _changeLanguage->hideAnimated();
}
_next->setText(getStep()->nextButtonText());
if (_resetAccount) _resetAccount->fadeOut();
if (_resetAccount) _resetAccount->hideAnimated();
getStep()->showAnimated(direction);
fixOrder();
}
@ -206,25 +206,22 @@ void Widget::appendStep(Step *step) {
void Widget::showResetButton() {
if (!_resetAccount) {
_resetAccount.create(this, new Ui::RoundButton(this, lang(lng_signin_reset_account), st::introResetButton), base::lambda<void()>(), st::introErrorDuration);
auto entity = object_ptr<Ui::RoundButton>(this, lang(lng_signin_reset_account), st::introResetButton);
_resetAccount.create(this, std_::move(entity), st::introErrorDuration);
_resetAccount->hideFast();
_resetAccount->entity()->setClickedCallback([this] { resetAccount(); });
updateControlsGeometry();
}
_resetAccount->fadeIn();
_resetAccount->showAnimated();
}
void Widget::resetAccount() {
if (_resetRequest) return;
auto box = new ConfirmBox(lang(lng_signin_sure_reset), lang(lng_signin_reset), st::attentionBoxButton);
box->setConfirmedCallback([this] { resetAccountSure(); });
Ui::showLayer(box);
}
void Widget::resetAccountSure() {
if (_resetRequest) return;
_resetRequest = MTP::send(MTPaccount_DeleteAccount(MTP_string("Forgot password")), rpcDone(&Widget::resetDone), rpcFail(&Widget::resetFail));
Ui::show(Box<ConfirmBox>(lang(lng_signin_sure_reset), lang(lng_signin_reset), st::attentionBoxButton, base::lambda_guarded(this, [this] {
if (_resetRequest) return;
_resetRequest = MTP::send(MTPaccount_DeleteAccount(MTP_string("Forgot password")), rpcDone(&Widget::resetDone), rpcFail(&Widget::resetFail));
})));
}
void Widget::resetDone(const MTPBool &result) {
@ -251,9 +248,9 @@ bool Widget::resetFail(const RPCError &error) {
} else {
when = lng_signin_reset_in_minutes(lt_count_minutes, minutes);
}
Ui::showLayer(new InformBox(lng_signin_reset_wait(lt_phone_number, App::formatPhone(getData()->phone), lt_when, when)));
Ui::show(Box<InformBox>(lng_signin_reset_wait(lt_phone_number, App::formatPhone(getData()->phone), lt_when, when)));
} else if (type == qstr("2FA_RECENT_CONFIRM")) {
Ui::showLayer(new InformBox(lang(lng_signin_reset_cancelled)));
Ui::show(Box<InformBox>(lang(lng_signin_reset_cancelled)));
} else {
Ui::hideLayer();
getStep()->showError(lang(lng_server_error));
@ -544,11 +541,11 @@ void Widget::Step::fillSentCodeData(const MTPauth_SentCodeType &type) {
}
void Widget::Step::showDescription() {
_description->fadeIn();
_description->showAnimated();
}
void Widget::Step::hideDescription() {
_description->fadeOut();
_description->hideAnimated();
}
void Widget::Step::paintContentSnapshot(Painter &p, const QPixmap &snapshot, float64 alpha, float64 howMuchHidden) {
@ -647,16 +644,16 @@ void Widget::Step::setErrorBelowLink(bool below) {
void Widget::Step::showError(const QString &text) {
_errorText = text;
if (_errorText.isEmpty()) {
if (_error) _error->fadeOut();
if (_error) _error->hideAnimated();
} else {
if (!_error) {
auto &st = _errorCentered ? st::introErrorCentered : st::introError;
_error.create(this, new Ui::FlatLabel(this, st, st::introErrorTextStyle), base::lambda<void()>(), st::introErrorDuration);
_error.create(this, object_ptr<Ui::FlatLabel>(this, st, st::introErrorTextStyle), st::introErrorDuration);
_error->hideFast();
}
_error->entity()->setText(text);
updateLabelsPosition();
_error->fadeIn();
_error->showAnimated();
}
}
@ -664,7 +661,7 @@ Widget::Step::Step(QWidget *parent, Data *data, bool hasCover) : TWidget(parent)
, _data(data)
, _hasCover(hasCover)
, _title(this, _hasCover ? st::introCoverTitle : st::introTitle, st::defaultTextStyle)
, _description(this, new Ui::FlatLabel(this, _hasCover ? st::introCoverDescription : st::introDescription, _hasCover ? st::introCoverDescriptionTextStyle : st::introDescriptionTextStyle), base::lambda<void()>(), st::introErrorDuration) {
, _description(this, object_ptr<Ui::FlatLabel>(this, _hasCover ? st::introCoverDescription : st::introDescription, _hasCover ? st::introCoverDescriptionTextStyle : st::introDescriptionTextStyle), st::introErrorDuration) {
hide();
}

View File

@ -190,13 +190,13 @@ public:
base::lambda<void(Step *step, Direction direction)> _goCallback;
base::lambda<void()> _showResetCallback;
ChildWidget<Ui::FlatLabel> _title;
ChildWidget<Ui::WidgetFadeWrap<Ui::FlatLabel>> _description;
object_ptr<Ui::FlatLabel> _title;
object_ptr<Ui::WidgetFadeWrap<Ui::FlatLabel>> _description;
bool _errorCentered = false;
bool _errorBelowLink = false;
QString _errorText;
ChildWidget<Ui::WidgetFadeWrap<Ui::FlatLabel>> _error = { nullptr };
object_ptr<Ui::WidgetFadeWrap<Ui::FlatLabel>> _error = { nullptr };
Animation _a_show;
CoverAnimation _coverAnimation;
@ -222,7 +222,6 @@ private:
void showResetButton();
void resetAccount();
void resetAccountSure();
void resetDone(const MTPBool &result);
bool resetFail(const RPCError &error);
@ -247,13 +246,13 @@ private:
int _nextTopFrom = 0;
int _controlsTopFrom = 0;
ChildWidget<Ui::WidgetFadeWrap<Ui::IconButton>> _back;
ChildWidget<Ui::WidgetFadeWrap<Ui::RoundButton>> _update = { nullptr };
ChildWidget<Ui::WidgetFadeWrap<Ui::RoundButton>> _settings;
object_ptr<Ui::WidgetFadeWrap<Ui::IconButton>> _back;
object_ptr<Ui::WidgetFadeWrap<Ui::RoundButton>> _update = { nullptr };
object_ptr<Ui::WidgetFadeWrap<Ui::RoundButton>> _settings;
ChildWidget<Ui::RoundButton> _next;
ChildWidget<Ui::WidgetFadeWrap<Ui::LinkButton>> _changeLanguage = { nullptr };
ChildWidget<Ui::WidgetFadeWrap<Ui::RoundButton>> _resetAccount = { nullptr };
object_ptr<Ui::RoundButton> _next;
object_ptr<Ui::WidgetFadeWrap<Ui::LinkButton>> _changeLanguage = { nullptr };
object_ptr<Ui::WidgetFadeWrap<Ui::RoundButton>> _resetAccount = { nullptr };
mtpRequestId _resetRequest = 0;

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