/* This file is part of Telegram Desktop, the official desktop version of Telegram messaging app, see https://telegram.org Telegram Desktop is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. In addition, as a special exception, the copyright holders give permission to link the code of portions of this program with the OpenSSL library. Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org */ #include "stdafx.h" #include "profile/profile_fixed_bar.h" #include "styles/style_profile.h" #include "styles/style_window.h" #include "ui/widgets/buttons.h" #include "lang.h" #include "mainwidget.h" #include "boxes/addcontactbox.h" #include "boxes/confirmbox.h" #include "observer_peer.h" #include "window/top_bar_widget.h" #include "styles/style_boxes.h" namespace Profile { class BackButton final : public Ui::AbstractButton, private base::Subscriber { public: BackButton(QWidget *parent) : Ui::AbstractButton(parent) , _text(lang(lng_menu_back).toUpper()) { setCursor(style::cur_pointer); subscribe(Adaptive::Changed(), [this] { updateAdaptiveLayout(); }); updateAdaptiveLayout(); } protected: int resizeGetHeight(int newWidth) override { return st::profileTopBarHeight; } void paintEvent(QPaintEvent *e) override { Painter p(this); p.fillRect(e->rect(), st::profileBg); st::topBarBack.paint(p, (st::topBarArrowPadding.left() - st::topBarBack.width()) / 2, (st::topBarHeight - st::topBarBack.height()) / 2, width()); p.setFont(st::topBarButton.font); p.setPen(st::topBarButton.textFg); p.drawTextLeft(st::topBarArrowPadding.left(), st::topBarButton.padding.top() + st::topBarButton.textTop, width(), _text); Window::TopBarWidget::paintUnreadCounter(p, width()); } void onStateChanged(int oldState, StateChangeSource source) override { if ((_state & StateDown) && !(oldState & StateDown)) { emit clicked(); } } private: void updateAdaptiveLayout() { if (!Adaptive::OneColumn()) { unsubscribe(base::take(_unreadCounterSubscription)); } else if (!_unreadCounterSubscription) { _unreadCounterSubscription = subscribe(Global::RefUnreadCounterUpdate(), [this] { rtlupdate(0, 0, st::titleUnreadCounterRight, st::titleUnreadCounterTop); }); } } int _unreadCounterSubscription = 0; QString _text; }; namespace { using UpdateFlag = Notify::PeerUpdate::Flag; const auto ButtonsUpdateFlags = UpdateFlag::UserCanShareContact | UpdateFlag::UserIsContact | UpdateFlag::ChatCanEdit | UpdateFlag::ChannelAmEditor; } // namespace FixedBar::FixedBar(QWidget *parent, PeerData *peer) : TWidget(parent) , _peer(peer) , _peerUser(peer->asUser()) , _peerChat(peer->asChat()) , _peerChannel(peer->asChannel()) , _peerMegagroup(peer->isMegagroup() ? _peerChannel : nullptr) , _backButton(this) { _backButton->moveToLeft(0, 0); connect(_backButton, SIGNAL(clicked()), this, SLOT(onBack())); auto observeEvents = ButtonsUpdateFlags | UpdateFlag::MigrationChanged; subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(observeEvents, [this](const Notify::PeerUpdate &update) { notifyPeerUpdate(update); })); refreshRightActions(); } void FixedBar::notifyPeerUpdate(const Notify::PeerUpdate &update) { if (update.peer != _peer) { return; } if ((update.flags & ButtonsUpdateFlags) != 0) { refreshRightActions(); } if (update.flags & UpdateFlag::MigrationChanged) { if (_peerChat && _peerChat->migrateTo()) { auto channel = _peerChat->migrateTo(); onBack(); Ui::showPeerProfile(channel); } } } void FixedBar::refreshRightActions() { _currentAction = 0; if (_peerUser) { setUserActions(); } else if (_peerChat) { setChatActions(); } else if (_peerMegagroup) { setMegagroupActions(); } else if (_peerChannel) { setChannelActions(); } while (_rightActions.size() > _currentAction) { delete _rightActions.back().button; _rightActions.pop_back(); } resizeToWidth(width()); } void FixedBar::setUserActions() { if (_peerUser->canShareThisContact()) { addRightAction(RightActionType::ShareContact, lang(lng_profile_top_bar_share_contact), SLOT(onShareContact())); } if (_peerUser->isContact()) { addRightAction(RightActionType::EditContact, lang(lng_profile_edit_contact), SLOT(onEditContact())); addRightAction(RightActionType::DeleteContact, lang(lng_profile_delete_contact), SLOT(onDeleteContact())); } else if (_peerUser->canAddContact()) { addRightAction(RightActionType::AddContact, lang(lng_profile_add_contact), SLOT(onAddContact())); } } void FixedBar::setChatActions() { if (_peerChat->canEdit()) { addRightAction(RightActionType::EditGroup, lang(lng_profile_edit_contact), SLOT(onEditGroup())); } addRightAction(RightActionType::LeaveGroup, lang(lng_profile_delete_and_exit), SLOT(onLeaveGroup())); } void FixedBar::setMegagroupActions() { if (_peerMegagroup->amCreator() || _peerMegagroup->amEditor()) { addRightAction(RightActionType::EditChannel, lang(lng_profile_edit_contact), SLOT(onEditChannel())); } } void FixedBar::setChannelActions() { if (_peerChannel->amCreator()) { addRightAction(RightActionType::EditChannel, lang(lng_profile_edit_contact), SLOT(onEditChannel())); } } void FixedBar::addRightAction(RightActionType type, const QString &text, const char *slot) { if (_rightActions.size() > _currentAction) { if (_rightActions.at(_currentAction).type == type) { ++_currentAction; return; } } else { t_assert(_rightActions.size() == _currentAction); _rightActions.push_back(RightAction()); } _rightActions[_currentAction].type = type; delete _rightActions[_currentAction].button; _rightActions[_currentAction].button = new Ui::RoundButton(this, text, st::profileFixedBarButton); connect(_rightActions[_currentAction].button, SIGNAL(clicked()), this, slot); bool showButton = !_animatingMode && (type != RightActionType::ShareContact || !_hideShareContactButton); _rightActions[_currentAction].button->setVisible(showButton); ++_currentAction; } void FixedBar::onBack() { App::main()->showBackFromStack(); } void FixedBar::onEditChannel() { Ui::showLayer(new EditChannelBox(_peerMegagroup ? _peerMegagroup : _peerChannel)); } void FixedBar::onEditGroup() { Ui::showLayer(new EditNameTitleBox(_peerChat)); } void FixedBar::onAddContact() { auto firstName = _peerUser->firstName; auto lastName = _peerUser->lastName; auto phone = _peerUser->phone().isEmpty() ? App::phoneFromSharedContact(peerToUser(_peer->id)) : _peerUser->phone(); Ui::showLayer(new AddContactBox(firstName, lastName, phone)); } void FixedBar::onEditContact() { Ui::showLayer(new AddContactBox(_peerUser)); } void FixedBar::onShareContact() { App::main()->shareContactLayer(_peerUser); } void FixedBar::onDeleteContact() { ConfirmBox *box = new ConfirmBox(lng_sure_delete_contact(lt_contact, App::peerName(_peerUser)), lang(lng_box_delete)); connect(box, SIGNAL(confirmed()), this, SLOT(onDeleteContactSure())); Ui::showLayer(box); } void FixedBar::onDeleteContactSure() { Ui::showChatsList(); Ui::hideLayer(); MTP::send(MTPcontacts_DeleteContact(_peerUser->inputUser), App::main()->rpcDone(&MainWidget::deletedContact, _peerUser)); } void FixedBar::onLeaveGroup() { ConfirmBox *box = new ConfirmBox(lng_sure_delete_and_exit(lt_group, App::peerName(_peerChat)), lang(lng_box_leave), st::attentionBoxButton); connect(box, SIGNAL(confirmed()), this, SLOT(onLeaveGroupSure())); Ui::showLayer(box); } void FixedBar::onLeaveGroupSure() { Ui::showChatsList(); Ui::hideLayer(); App::main()->deleteAndExit(_peerChat); } int FixedBar::resizeGetHeight(int newWidth) { int newHeight = 0; int buttonLeft = newWidth; for (auto i = _rightActions.cend(), b = _rightActions.cbegin(); i != b;) { --i; buttonLeft -= i->button->width(); i->button->moveToLeft(buttonLeft, 0); } _backButton->resizeToWidth(newWidth); _backButton->moveToLeft(0, 0); newHeight += _backButton->height(); return newHeight; } void FixedBar::setAnimatingMode(bool enabled) { if (_animatingMode != enabled) { _animatingMode = enabled; setCursor(_animatingMode ? style::cur_pointer : style::cur_default); if (_animatingMode) { setAttribute(Qt::WA_OpaquePaintEvent, false); hideChildren(); } else { setAttribute(Qt::WA_OpaquePaintEvent); showChildren(); if (_hideShareContactButton) { applyHideShareContactButton(); } } show(); } } void FixedBar::setHideShareContactButton(bool hideButton) { _hideShareContactButton = hideButton; if (!_animatingMode) { applyHideShareContactButton(); } } void FixedBar::applyHideShareContactButton() { for_const (auto &action, _rightActions) { if (action.type == RightActionType::ShareContact) { action.button->setVisible(!_hideShareContactButton); } } } void FixedBar::mousePressEvent(QMouseEvent *e) { if (e->button() == Qt::LeftButton) { onBack(); } else { TWidget::mousePressEvent(e); } } } // namespace Profile