mirror of https://github.com/procxx/kepka.git
Apply clang-format
This commit is contained in:
parent
49982a33a5
commit
b9cd813127
File diff suppressed because it is too large
Load Diff
|
@ -20,16 +20,16 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "base/timer.h"
|
||||
#include <QtCore/QObject>
|
||||
#include "mtproto/rpc_sender.h"
|
||||
#include "mtproto/core_types.h"
|
||||
#include "core/single_timer.h"
|
||||
#include "mtproto/sender.h"
|
||||
#include "base/flat_map.h"
|
||||
#include "base/flat_set.h"
|
||||
#include "structs.h"
|
||||
#include "base/timer.h"
|
||||
#include "core/single_timer.h"
|
||||
#include "facades.h"
|
||||
#include "mtproto/core_types.h"
|
||||
#include "mtproto/rpc_sender.h"
|
||||
#include "mtproto/sender.h"
|
||||
#include "structs.h"
|
||||
#include <QtCore/QObject>
|
||||
|
||||
class AuthSession;
|
||||
|
||||
|
@ -49,17 +49,17 @@ class History;
|
|||
|
||||
class ApiWrap : private MTP::Sender, private base::Subscriber {
|
||||
public:
|
||||
ApiWrap(not_null<AuthSession*> session);
|
||||
ApiWrap(not_null<AuthSession *> session);
|
||||
|
||||
void start();
|
||||
void applyUpdates(const MTPUpdates &updates, quint64 sentMessageRandomId = 0);
|
||||
|
||||
using RequestMessageDataCallback = base::lambda<void(ChannelData*, MsgId)>;
|
||||
using RequestMessageDataCallback = base::lambda<void(ChannelData *, MsgId)>;
|
||||
void requestMessageData(ChannelData *channel, MsgId msgId, RequestMessageDataCallback callback);
|
||||
|
||||
void requestFullPeer(PeerData *peer);
|
||||
void requestPeer(PeerData *peer);
|
||||
void requestPeers(const QList<PeerData*> &peers);
|
||||
void requestPeers(const QList<PeerData *> &peers);
|
||||
void requestLastParticipants(ChannelData *channel, bool fromStart = true);
|
||||
void requestBots(ChannelData *channel);
|
||||
void requestParticipantsCountDelayed(ChannelData *channel);
|
||||
|
@ -79,7 +79,7 @@ public:
|
|||
void requestStickerSets();
|
||||
void saveStickerSets(const Stickers::Order &localOrder, const Stickers::Order &localRemoved);
|
||||
void updateStickers();
|
||||
void setGroupStickerSet(not_null<ChannelData*> megagroup, const MTPInputStickerSet &set);
|
||||
void setGroupStickerSet(not_null<ChannelData *> megagroup, const MTPInputStickerSet &set);
|
||||
|
||||
void joinChannel(ChannelData *channel);
|
||||
void leaveChannel(ChannelData *channel);
|
||||
|
@ -96,7 +96,7 @@ public:
|
|||
void handlePrivacyChange(mtpTypeId keyTypeId, const MTPVector<MTPPrivacyRule> &rules);
|
||||
int onlineTillFromStatus(const MTPUserStatus &status, int currentOnlineTill);
|
||||
|
||||
base::Observable<PeerData*> &fullPeerUpdated() {
|
||||
base::Observable<PeerData *> &fullPeerUpdated() {
|
||||
return _fullPeerUpdated;
|
||||
}
|
||||
|
||||
|
@ -105,15 +105,12 @@ public:
|
|||
void applyUpdatesNoPtsCheck(const MTPUpdates &updates);
|
||||
void applyUpdateNoPtsCheck(const MTPUpdate &update);
|
||||
|
||||
void jumpToDate(not_null<PeerData*> peer, const QDate &date);
|
||||
void jumpToDate(not_null<PeerData *> peer, const QDate &date);
|
||||
|
||||
void preloadEnoughUnreadMentions(not_null<History*> history);
|
||||
void preloadEnoughUnreadMentions(not_null<History *> history);
|
||||
void checkForUnreadMentions(const base::flat_set<MsgId> &possiblyReadMentions, ChannelData *channel = nullptr);
|
||||
|
||||
void editChatAdmins(
|
||||
not_null<ChatData*> chat,
|
||||
bool adminsEnabled,
|
||||
base::flat_set<not_null<UserData*>> &&admins);
|
||||
void editChatAdmins(not_null<ChatData *> chat, bool adminsEnabled, base::flat_set<not_null<UserData *>> &&admins);
|
||||
|
||||
~ApiWrap();
|
||||
|
||||
|
@ -156,18 +153,18 @@ private:
|
|||
void requestFeaturedStickers(TimeId now);
|
||||
void requestSavedGifs(TimeId now);
|
||||
|
||||
void cancelEditChatAdmins(not_null<ChatData*> chat);
|
||||
void saveChatAdmins(not_null<ChatData*> chat);
|
||||
void sendSaveChatAdminsRequests(not_null<ChatData*> chat);
|
||||
void cancelEditChatAdmins(not_null<ChatData *> chat);
|
||||
void saveChatAdmins(not_null<ChatData *> chat);
|
||||
void sendSaveChatAdminsRequests(not_null<ChatData *> chat);
|
||||
|
||||
not_null<AuthSession*> _session;
|
||||
not_null<AuthSession *> _session;
|
||||
mtpRequestId _changelogSubscription = 0;
|
||||
|
||||
MessageDataRequests _messageDataRequests;
|
||||
QMap<ChannelData*, MessageDataRequests> _channelMessageDataRequests;
|
||||
QMap<ChannelData *, MessageDataRequests> _channelMessageDataRequests;
|
||||
SingleQueuedInvokation _messageDataResolveDelayed;
|
||||
|
||||
using PeerRequests = QMap<PeerData*, mtpRequestId>;
|
||||
using PeerRequests = QMap<PeerData *, mtpRequestId>;
|
||||
PeerRequests _fullPeerRequests;
|
||||
PeerRequests _peerRequests;
|
||||
|
||||
|
@ -175,24 +172,24 @@ private:
|
|||
PeerRequests _botsRequests;
|
||||
base::DelayedCallTimer _participantsCountRequestTimer;
|
||||
|
||||
typedef QPair<PeerData*, UserData*> KickRequest;
|
||||
typedef QPair<PeerData *, UserData *> KickRequest;
|
||||
typedef QMap<KickRequest, mtpRequestId> KickRequests;
|
||||
KickRequests _kickRequests;
|
||||
|
||||
QMap<ChannelData*, mtpRequestId> _selfParticipantRequests;
|
||||
QMap<ChannelData *, mtpRequestId> _selfParticipantRequests;
|
||||
|
||||
QMap<WebPageData*, mtpRequestId> _webPagesPending;
|
||||
QMap<WebPageData *, mtpRequestId> _webPagesPending;
|
||||
base::Timer _webPagesTimer;
|
||||
|
||||
QMap<quint64, QPair<quint64, mtpRequestId> > _stickerSetRequests;
|
||||
QMap<quint64, QPair<quint64, mtpRequestId>> _stickerSetRequests;
|
||||
|
||||
QMap<ChannelData*, mtpRequestId> _channelAmInRequests;
|
||||
QMap<UserData*, mtpRequestId> _blockRequests;
|
||||
QMap<PeerData*, mtpRequestId> _exportInviteRequests;
|
||||
QMap<ChannelData *, mtpRequestId> _channelAmInRequests;
|
||||
QMap<UserData *, mtpRequestId> _blockRequests;
|
||||
QMap<PeerData *, mtpRequestId> _exportInviteRequests;
|
||||
|
||||
QMap<PeerData*, mtpRequestId> _notifySettingRequests;
|
||||
QMap<PeerData *, mtpRequestId> _notifySettingRequests;
|
||||
|
||||
QMap<History*, mtpRequestId> _draftsSaveRequestIds;
|
||||
QMap<History *, mtpRequestId> _draftsSaveRequestIds;
|
||||
base::Timer _draftsSaveTimer;
|
||||
|
||||
OrderedSet<mtpRequestId> _stickerSetDisenableRequests;
|
||||
|
@ -210,12 +207,11 @@ private:
|
|||
|
||||
mtpRequestId _contactsStatusesRequestId = 0;
|
||||
|
||||
base::flat_map<not_null<History*>, mtpRequestId> _unreadMentionsRequests;
|
||||
base::flat_map<not_null<History *>, mtpRequestId> _unreadMentionsRequests;
|
||||
|
||||
base::flat_map<not_null<ChatData*>, mtpRequestId> _chatAdminsEnabledRequests;
|
||||
base::flat_map<not_null<ChatData*>, base::flat_set<not_null<UserData*>>> _chatAdminsToSave;
|
||||
base::flat_map<not_null<ChatData*>, base::flat_set<mtpRequestId>> _chatAdminsSaveRequests;
|
||||
|
||||
base::Observable<PeerData*> _fullPeerUpdated;
|
||||
base::flat_map<not_null<ChatData *>, mtpRequestId> _chatAdminsEnabledRequests;
|
||||
base::flat_map<not_null<ChatData *>, base::flat_set<not_null<UserData *>>> _chatAdminsToSave;
|
||||
base::flat_map<not_null<ChatData *>, base::flat_set<mtpRequestId>> _chatAdminsSaveRequests;
|
||||
|
||||
base::Observable<PeerData *> _fullPeerUpdated;
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -20,288 +20,304 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QString>
|
||||
|
||||
#include "ui/animation.h"
|
||||
#include "core/basic_types.h"
|
||||
#include "history/history.h"
|
||||
#include "history/history_item.h"
|
||||
#include "layout.h"
|
||||
#include "media/media_clip_reader.h"
|
||||
#include "ui/animation.h"
|
||||
|
||||
class Messenger;
|
||||
class MainWindow;
|
||||
class MainWidget;
|
||||
|
||||
using HistoryItemsMap = OrderedSet<HistoryItem*>;
|
||||
using PhotoItems = QHash<PhotoData*, HistoryItemsMap>;
|
||||
using DocumentItems = QHash<DocumentData*, HistoryItemsMap>;
|
||||
using WebPageItems = QHash<WebPageData*, HistoryItemsMap>;
|
||||
using GameItems = QHash<GameData*, HistoryItemsMap>;
|
||||
using HistoryItemsMap = OrderedSet<HistoryItem *>;
|
||||
using PhotoItems = QHash<PhotoData *, HistoryItemsMap>;
|
||||
using DocumentItems = QHash<DocumentData *, HistoryItemsMap>;
|
||||
using WebPageItems = QHash<WebPageData *, HistoryItemsMap>;
|
||||
using GameItems = QHash<GameData *, HistoryItemsMap>;
|
||||
using SharedContactItems = QHash<qint32, HistoryItemsMap>;
|
||||
using GifItems = QHash<Media::Clip::Reader*, HistoryItem*>;
|
||||
using GifItems = QHash<Media::Clip::Reader *, HistoryItem *>;
|
||||
|
||||
using PhotosData = QHash<PhotoId, PhotoData*>;
|
||||
using DocumentsData = QHash<DocumentId, DocumentData*>;
|
||||
using PhotosData = QHash<PhotoId, PhotoData *>;
|
||||
using DocumentsData = QHash<DocumentId, DocumentData *>;
|
||||
|
||||
class LocationCoords;
|
||||
struct LocationData;
|
||||
|
||||
namespace App {
|
||||
MainWindow *wnd();
|
||||
MainWidget *main();
|
||||
bool passcoded();
|
||||
MainWindow *wnd();
|
||||
MainWidget *main();
|
||||
bool passcoded();
|
||||
|
||||
void logOut();
|
||||
void logOut();
|
||||
|
||||
QString formatPhone(QString phone);
|
||||
QString formatPhone(QString phone);
|
||||
|
||||
TimeId onlineForSort(UserData *user, TimeId now);
|
||||
qint32 onlineWillChangeIn(UserData *user, TimeId now);
|
||||
qint32 onlineWillChangeIn(TimeId online, TimeId now);
|
||||
QString onlineText(UserData *user, TimeId now, bool precise = false);
|
||||
QString onlineText(TimeId online, TimeId now, bool precise = false);
|
||||
bool onlineColorUse(UserData *user, TimeId now);
|
||||
bool onlineColorUse(TimeId online, TimeId now);
|
||||
TimeId onlineForSort(UserData *user, TimeId now);
|
||||
qint32 onlineWillChangeIn(UserData *user, TimeId now);
|
||||
qint32 onlineWillChangeIn(TimeId online, TimeId now);
|
||||
QString onlineText(UserData *user, TimeId now, bool precise = false);
|
||||
QString onlineText(TimeId online, TimeId now, bool precise = false);
|
||||
bool onlineColorUse(UserData *user, TimeId now);
|
||||
bool onlineColorUse(TimeId online, TimeId now);
|
||||
|
||||
UserData *feedUser(const MTPUser &user);
|
||||
UserData *feedUsers(const MTPVector<MTPUser> &users); // returns last user
|
||||
PeerData *feedChat(const MTPChat &chat);
|
||||
PeerData *feedChats(const MTPVector<MTPChat> &chats); // returns last chat
|
||||
UserData *feedUser(const MTPUser &user);
|
||||
UserData *feedUsers(const MTPVector<MTPUser> &users); // returns last user
|
||||
PeerData *feedChat(const MTPChat &chat);
|
||||
PeerData *feedChats(const MTPVector<MTPChat> &chats); // returns last chat
|
||||
|
||||
void feedParticipants(const MTPChatParticipants &p, bool requestBotInfos);
|
||||
void feedParticipantAdd(const MTPDupdateChatParticipantAdd &d);
|
||||
void feedParticipantDelete(const MTPDupdateChatParticipantDelete &d);
|
||||
void feedChatAdmins(const MTPDupdateChatAdmins &d);
|
||||
void feedParticipantAdmin(const MTPDupdateChatParticipantAdmin &d);
|
||||
bool checkEntitiesAndViewsUpdate(const MTPDmessage &m); // returns true if item found and it is not detached
|
||||
void updateEditedMessage(const MTPMessage &m);
|
||||
void addSavedGif(DocumentData *doc);
|
||||
void checkSavedGif(HistoryItem *item);
|
||||
void feedMsgs(const QVector<MTPMessage> &msgs, NewMessageType type);
|
||||
void feedMsgs(const MTPVector<MTPMessage> &msgs, NewMessageType type);
|
||||
void feedInboxRead(const PeerId &peer, MsgId upTo);
|
||||
void feedOutboxRead(const PeerId &peer, MsgId upTo, TimeId when);
|
||||
void feedWereDeleted(ChannelId channelId, const QVector<MTPint> &msgsIds);
|
||||
void feedUserLink(MTPint userId, const MTPContactLink &myLink, const MTPContactLink &foreignLink);
|
||||
void feedParticipants(const MTPChatParticipants &p, bool requestBotInfos);
|
||||
void feedParticipantAdd(const MTPDupdateChatParticipantAdd &d);
|
||||
void feedParticipantDelete(const MTPDupdateChatParticipantDelete &d);
|
||||
void feedChatAdmins(const MTPDupdateChatAdmins &d);
|
||||
void feedParticipantAdmin(const MTPDupdateChatParticipantAdmin &d);
|
||||
bool checkEntitiesAndViewsUpdate(const MTPDmessage &m); // returns true if item found and it is not detached
|
||||
void updateEditedMessage(const MTPMessage &m);
|
||||
void addSavedGif(DocumentData *doc);
|
||||
void checkSavedGif(HistoryItem *item);
|
||||
void feedMsgs(const QVector<MTPMessage> &msgs, NewMessageType type);
|
||||
void feedMsgs(const MTPVector<MTPMessage> &msgs, NewMessageType type);
|
||||
void feedInboxRead(const PeerId &peer, MsgId upTo);
|
||||
void feedOutboxRead(const PeerId &peer, MsgId upTo, TimeId when);
|
||||
void feedWereDeleted(ChannelId channelId, const QVector<MTPint> &msgsIds);
|
||||
void feedUserLink(MTPint userId, const MTPContactLink &myLink, const MTPContactLink &foreignLink);
|
||||
|
||||
ImagePtr image(const MTPPhotoSize &size);
|
||||
StorageImageLocation imageLocation(qint32 w, qint32 h, const MTPFileLocation &loc);
|
||||
StorageImageLocation imageLocation(const MTPPhotoSize &size);
|
||||
ImagePtr image(const MTPPhotoSize &size);
|
||||
StorageImageLocation imageLocation(qint32 w, qint32 h, const MTPFileLocation &loc);
|
||||
StorageImageLocation imageLocation(const MTPPhotoSize &size);
|
||||
|
||||
PhotoData *feedPhoto(const MTPPhoto &photo, const PreparedPhotoThumbs &thumbs);
|
||||
PhotoData *feedPhoto(const MTPPhoto &photo, PhotoData *convert = nullptr);
|
||||
PhotoData *feedPhoto(const MTPDphoto &photo, PhotoData *convert = nullptr);
|
||||
DocumentData *feedDocument(const MTPdocument &document, const QPixmap &thumb);
|
||||
DocumentData *feedDocument(const MTPdocument &document, DocumentData *convert = nullptr);
|
||||
DocumentData *feedDocument(const MTPDdocument &document, DocumentData *convert = nullptr);
|
||||
WebPageData *feedWebPage(const MTPDwebPage &webpage, WebPageData *convert = nullptr);
|
||||
WebPageData *feedWebPage(const MTPDwebPagePending &webpage, WebPageData *convert = nullptr);
|
||||
WebPageData *feedWebPage(const MTPWebPage &webpage);
|
||||
WebPageData *feedWebPage(WebPageId webPageId, const QString &siteName, const TextWithEntities &content);
|
||||
GameData *feedGame(const MTPDgame &game, GameData *convert = nullptr);
|
||||
PhotoData *feedPhoto(const MTPPhoto &photo, const PreparedPhotoThumbs &thumbs);
|
||||
PhotoData *feedPhoto(const MTPPhoto &photo, PhotoData *convert = nullptr);
|
||||
PhotoData *feedPhoto(const MTPDphoto &photo, PhotoData *convert = nullptr);
|
||||
DocumentData *feedDocument(const MTPdocument &document, const QPixmap &thumb);
|
||||
DocumentData *feedDocument(const MTPdocument &document, DocumentData *convert = nullptr);
|
||||
DocumentData *feedDocument(const MTPDdocument &document, DocumentData *convert = nullptr);
|
||||
WebPageData *feedWebPage(const MTPDwebPage &webpage, WebPageData *convert = nullptr);
|
||||
WebPageData *feedWebPage(const MTPDwebPagePending &webpage, WebPageData *convert = nullptr);
|
||||
WebPageData *feedWebPage(const MTPWebPage &webpage);
|
||||
WebPageData *feedWebPage(WebPageId webPageId, const QString &siteName, const TextWithEntities &content);
|
||||
GameData *feedGame(const MTPDgame &game, GameData *convert = nullptr);
|
||||
|
||||
PeerData *peer(const PeerId &id, PeerData::LoadedStatus restriction = PeerData::NotLoaded);
|
||||
inline UserData *user(const PeerId &id, PeerData::LoadedStatus restriction = PeerData::NotLoaded) {
|
||||
return asUser(peer(id, restriction));
|
||||
}
|
||||
inline ChatData *chat(const PeerId &id, PeerData::LoadedStatus restriction = PeerData::NotLoaded) {
|
||||
return asChat(peer(id, restriction));
|
||||
}
|
||||
inline ChannelData *channel(const PeerId &id, PeerData::LoadedStatus restriction = PeerData::NotLoaded) {
|
||||
return asChannel(peer(id, restriction));
|
||||
}
|
||||
inline UserData *user(UserId userId, PeerData::LoadedStatus restriction = PeerData::NotLoaded) {
|
||||
return asUser(peer(peerFromUser(userId), restriction));
|
||||
}
|
||||
inline ChatData *chat(ChatId chatId, PeerData::LoadedStatus restriction = PeerData::NotLoaded) {
|
||||
return asChat(peer(peerFromChat(chatId), restriction));
|
||||
}
|
||||
inline ChannelData *channel(ChannelId channelId, PeerData::LoadedStatus restriction = PeerData::NotLoaded) {
|
||||
return asChannel(peer(peerFromChannel(channelId), restriction));
|
||||
}
|
||||
inline PeerData *peerLoaded(const PeerId &id) {
|
||||
return peer(id, PeerData::FullLoaded);
|
||||
}
|
||||
inline UserData *userLoaded(const PeerId &id) {
|
||||
return user(id, PeerData::FullLoaded);
|
||||
}
|
||||
inline ChatData *chatLoaded(const PeerId &id) {
|
||||
return chat(id, PeerData::FullLoaded);
|
||||
}
|
||||
inline ChannelData *channelLoaded(const PeerId &id) {
|
||||
return channel(id, PeerData::FullLoaded);
|
||||
}
|
||||
inline UserData *userLoaded(UserId userId) {
|
||||
return user(userId, PeerData::FullLoaded);
|
||||
}
|
||||
inline ChatData *chatLoaded(ChatId chatId) {
|
||||
return chat(chatId, PeerData::FullLoaded);
|
||||
}
|
||||
inline ChannelData *channelLoaded(ChannelId channelId) {
|
||||
return channel(channelId, PeerData::FullLoaded);
|
||||
}
|
||||
void enumerateUsers(base::lambda<void(UserData*)> action);
|
||||
PeerData *peer(const PeerId &id, PeerData::LoadedStatus restriction = PeerData::NotLoaded);
|
||||
inline UserData *user(const PeerId &id, PeerData::LoadedStatus restriction = PeerData::NotLoaded) {
|
||||
return asUser(peer(id, restriction));
|
||||
}
|
||||
inline ChatData *chat(const PeerId &id, PeerData::LoadedStatus restriction = PeerData::NotLoaded) {
|
||||
return asChat(peer(id, restriction));
|
||||
}
|
||||
inline ChannelData *channel(const PeerId &id, PeerData::LoadedStatus restriction = PeerData::NotLoaded) {
|
||||
return asChannel(peer(id, restriction));
|
||||
}
|
||||
inline UserData *user(UserId userId, PeerData::LoadedStatus restriction = PeerData::NotLoaded) {
|
||||
return asUser(peer(peerFromUser(userId), restriction));
|
||||
}
|
||||
inline ChatData *chat(ChatId chatId, PeerData::LoadedStatus restriction = PeerData::NotLoaded) {
|
||||
return asChat(peer(peerFromChat(chatId), restriction));
|
||||
}
|
||||
inline ChannelData *channel(ChannelId channelId, PeerData::LoadedStatus restriction = PeerData::NotLoaded) {
|
||||
return asChannel(peer(peerFromChannel(channelId), restriction));
|
||||
}
|
||||
inline PeerData *peerLoaded(const PeerId &id) {
|
||||
return peer(id, PeerData::FullLoaded);
|
||||
}
|
||||
inline UserData *userLoaded(const PeerId &id) {
|
||||
return user(id, PeerData::FullLoaded);
|
||||
}
|
||||
inline ChatData *chatLoaded(const PeerId &id) {
|
||||
return chat(id, PeerData::FullLoaded);
|
||||
}
|
||||
inline ChannelData *channelLoaded(const PeerId &id) {
|
||||
return channel(id, PeerData::FullLoaded);
|
||||
}
|
||||
inline UserData *userLoaded(UserId userId) {
|
||||
return user(userId, PeerData::FullLoaded);
|
||||
}
|
||||
inline ChatData *chatLoaded(ChatId chatId) {
|
||||
return chat(chatId, PeerData::FullLoaded);
|
||||
}
|
||||
inline ChannelData *channelLoaded(ChannelId channelId) {
|
||||
return channel(channelId, PeerData::FullLoaded);
|
||||
}
|
||||
void enumerateUsers(base::lambda<void(UserData *)> action);
|
||||
|
||||
UserData *self();
|
||||
PeerData *peerByName(const QString &username);
|
||||
QString peerName(const PeerData *peer, bool forDialogs = false);
|
||||
PhotoData *photo(const PhotoId &photo);
|
||||
PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const quint64 &access, qint32 date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full);
|
||||
DocumentData *document(const DocumentId &document);
|
||||
DocumentData *documentSet(const DocumentId &document, DocumentData *convert, const quint64 &access, qint32 version, qint32 date, const QVector<MTPDocumentAttribute> &attributes, const QString &mime, const ImagePtr &thumb, qint32 dc, qint32 size, const StorageImageLocation &thumbLocation);
|
||||
WebPageData *webPage(const WebPageId &webPage);
|
||||
WebPageData *webPageSet(const WebPageId &webPage, WebPageData *convert, const QString &type, const QString &url, const QString &displayUrl, const QString &siteName, const QString &title, const TextWithEntities &description, PhotoData *photo, DocumentData *doc, qint32 duration, const QString &author, qint32 pendingTill);
|
||||
GameData *game(const GameId &game);
|
||||
GameData *gameSet(const GameId &game, GameData *convert, const quint64 &accessHash, const QString &shortName, const QString &title, const QString &description, PhotoData *photo, DocumentData *doc);
|
||||
LocationData *location(const LocationCoords &coords);
|
||||
void forgetMedia();
|
||||
UserData *self();
|
||||
PeerData *peerByName(const QString &username);
|
||||
QString peerName(const PeerData *peer, bool forDialogs = false);
|
||||
PhotoData *photo(const PhotoId &photo);
|
||||
PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const quint64 &access, qint32 date, const ImagePtr &thumb,
|
||||
const ImagePtr &medium, const ImagePtr &full);
|
||||
DocumentData *document(const DocumentId &document);
|
||||
DocumentData *documentSet(const DocumentId &document, DocumentData *convert, const quint64 &access, qint32 version,
|
||||
qint32 date, const QVector<MTPDocumentAttribute> &attributes, const QString &mime,
|
||||
const ImagePtr &thumb, qint32 dc, qint32 size, const StorageImageLocation &thumbLocation);
|
||||
WebPageData *webPage(const WebPageId &webPage);
|
||||
WebPageData *webPageSet(const WebPageId &webPage, WebPageData *convert, const QString &type, const QString &url,
|
||||
const QString &displayUrl, const QString &siteName, const QString &title,
|
||||
const TextWithEntities &description, PhotoData *photo, DocumentData *doc, qint32 duration,
|
||||
const QString &author, qint32 pendingTill);
|
||||
GameData *game(const GameId &game);
|
||||
GameData *gameSet(const GameId &game, GameData *convert, const quint64 &accessHash, const QString &shortName,
|
||||
const QString &title, const QString &description, PhotoData *photo, DocumentData *doc);
|
||||
LocationData *location(const LocationCoords &coords);
|
||||
void forgetMedia();
|
||||
|
||||
MTPPhoto photoFromUserPhoto(MTPint userId, MTPint date, const MTPUserProfilePhoto &photo);
|
||||
MTPPhoto photoFromUserPhoto(MTPint userId, MTPint date, const MTPUserProfilePhoto &photo);
|
||||
|
||||
Histories &histories();
|
||||
not_null<History*> history(const PeerId &peer);
|
||||
History *historyFromDialog(const PeerId &peer, qint32 unreadCnt, qint32 maxInboxRead, qint32 maxOutboxRead);
|
||||
History *historyLoaded(const PeerId &peer);
|
||||
HistoryItem *histItemById(ChannelId channelId, MsgId itemId);
|
||||
inline not_null<History*> history(const PeerData *peer) {
|
||||
Assert(peer != nullptr);
|
||||
return history(peer->id);
|
||||
}
|
||||
inline History *historyLoaded(const PeerData *peer) {
|
||||
return peer ? historyLoaded(peer->id) : nullptr;
|
||||
}
|
||||
inline HistoryItem *histItemById(const ChannelData *channel, MsgId itemId) {
|
||||
return histItemById(channel ? peerToChannel(channel->id) : 0, itemId);
|
||||
}
|
||||
inline HistoryItem *histItemById(const FullMsgId &msgId) {
|
||||
return histItemById(msgId.channel, msgId.msg);
|
||||
}
|
||||
void historyRegItem(HistoryItem *item);
|
||||
void historyItemDetached(HistoryItem *item);
|
||||
void historyUnregItem(HistoryItem *item);
|
||||
void historyUpdateDependent(HistoryItem *item);
|
||||
void historyClearMsgs();
|
||||
void historyClearItems();
|
||||
void historyRegDependency(HistoryItem *dependent, HistoryItem *dependency);
|
||||
void historyUnregDependency(HistoryItem *dependent, HistoryItem *dependency);
|
||||
Histories &histories();
|
||||
not_null<History *> history(const PeerId &peer);
|
||||
History *historyFromDialog(const PeerId &peer, qint32 unreadCnt, qint32 maxInboxRead, qint32 maxOutboxRead);
|
||||
History *historyLoaded(const PeerId &peer);
|
||||
HistoryItem *histItemById(ChannelId channelId, MsgId itemId);
|
||||
inline not_null<History *> history(const PeerData *peer) {
|
||||
Assert(peer != nullptr);
|
||||
return history(peer->id);
|
||||
}
|
||||
inline History *historyLoaded(const PeerData *peer) {
|
||||
return peer ? historyLoaded(peer->id) : nullptr;
|
||||
}
|
||||
inline HistoryItem *histItemById(const ChannelData *channel, MsgId itemId) {
|
||||
return histItemById(channel ? peerToChannel(channel->id) : 0, itemId);
|
||||
}
|
||||
inline HistoryItem *histItemById(const FullMsgId &msgId) {
|
||||
return histItemById(msgId.channel, msgId.msg);
|
||||
}
|
||||
void historyRegItem(HistoryItem *item);
|
||||
void historyItemDetached(HistoryItem *item);
|
||||
void historyUnregItem(HistoryItem *item);
|
||||
void historyUpdateDependent(HistoryItem *item);
|
||||
void historyClearMsgs();
|
||||
void historyClearItems();
|
||||
void historyRegDependency(HistoryItem *dependent, HistoryItem *dependency);
|
||||
void historyUnregDependency(HistoryItem *dependent, HistoryItem *dependency);
|
||||
|
||||
void historyRegRandom(quint64 randomId, const FullMsgId &itemId);
|
||||
void historyUnregRandom(quint64 randomId);
|
||||
FullMsgId histItemByRandom(quint64 randomId);
|
||||
void historyRegSentData(quint64 randomId, const PeerId &peerId, const QString &text);
|
||||
void historyUnregSentData(quint64 randomId);
|
||||
void histSentDataByItem(quint64 randomId, PeerId &peerId, QString &text);
|
||||
void historyRegRandom(quint64 randomId, const FullMsgId &itemId);
|
||||
void historyUnregRandom(quint64 randomId);
|
||||
FullMsgId histItemByRandom(quint64 randomId);
|
||||
void historyRegSentData(quint64 randomId, const PeerId &peerId, const QString &text);
|
||||
void historyUnregSentData(quint64 randomId);
|
||||
void histSentDataByItem(quint64 randomId, PeerId &peerId, QString &text);
|
||||
|
||||
void hoveredItem(HistoryItem *item);
|
||||
HistoryItem *hoveredItem();
|
||||
void pressedItem(HistoryItem *item);
|
||||
HistoryItem *pressedItem();
|
||||
void hoveredLinkItem(HistoryItem *item);
|
||||
HistoryItem *hoveredLinkItem();
|
||||
void pressedLinkItem(HistoryItem *item);
|
||||
HistoryItem *pressedLinkItem();
|
||||
void contextItem(HistoryItem *item);
|
||||
HistoryItem *contextItem();
|
||||
void mousedItem(HistoryItem *item);
|
||||
HistoryItem *mousedItem();
|
||||
void clearMousedItems();
|
||||
void hoveredItem(HistoryItem *item);
|
||||
HistoryItem *hoveredItem();
|
||||
void pressedItem(HistoryItem *item);
|
||||
HistoryItem *pressedItem();
|
||||
void hoveredLinkItem(HistoryItem *item);
|
||||
HistoryItem *hoveredLinkItem();
|
||||
void pressedLinkItem(HistoryItem *item);
|
||||
HistoryItem *pressedLinkItem();
|
||||
void contextItem(HistoryItem *item);
|
||||
HistoryItem *contextItem();
|
||||
void mousedItem(HistoryItem *item);
|
||||
HistoryItem *mousedItem();
|
||||
void clearMousedItems();
|
||||
|
||||
const style::font &monofont();
|
||||
const QPixmap &emoji();
|
||||
const QPixmap &emojiLarge();
|
||||
const QPixmap &emojiSingle(EmojiPtr emoji, qint32 fontHeight);
|
||||
const style::font &monofont();
|
||||
const QPixmap &emoji();
|
||||
const QPixmap &emojiLarge();
|
||||
const QPixmap &emojiSingle(EmojiPtr emoji, qint32 fontHeight);
|
||||
|
||||
void clearHistories();
|
||||
void clearHistories();
|
||||
|
||||
void initMedia();
|
||||
void deinitMedia();
|
||||
void initMedia();
|
||||
void deinitMedia();
|
||||
|
||||
void checkImageCacheSize();
|
||||
void checkImageCacheSize();
|
||||
|
||||
bool isValidPhone(QString phone);
|
||||
|
||||
enum LaunchState {
|
||||
Launched = 0,
|
||||
QuitRequested = 1,
|
||||
QuitProcessed = 2,
|
||||
};
|
||||
void quit();
|
||||
bool quitting();
|
||||
LaunchState launchState();
|
||||
void setLaunchState(LaunchState state);
|
||||
void restart();
|
||||
|
||||
constexpr auto kFileSizeLimit = 1500 * 1024 * 1024; // Load files up to 1500mb
|
||||
constexpr auto kImageSizeLimit = 64 * 1024 * 1024; // Open images up to 64mb jpg/png/gif
|
||||
QImage readImage(QByteArray data, QByteArray *format = nullptr, bool opaque = true, bool *animated = nullptr);
|
||||
QImage readImage(const QString &file, QByteArray *format = nullptr, bool opaque = true, bool *animated = nullptr, QByteArray *content = 0);
|
||||
QPixmap pixmapFromImageInPlace(QImage &&image);
|
||||
|
||||
void regPhotoItem(PhotoData *data, HistoryItem *item);
|
||||
void unregPhotoItem(PhotoData *data, HistoryItem *item);
|
||||
const PhotoItems &photoItems();
|
||||
const PhotosData &photosData();
|
||||
|
||||
void regDocumentItem(DocumentData *data, HistoryItem *item);
|
||||
void unregDocumentItem(DocumentData *data, HistoryItem *item);
|
||||
const DocumentItems &documentItems();
|
||||
const DocumentsData &documentsData();
|
||||
|
||||
void regWebPageItem(WebPageData *data, HistoryItem *item);
|
||||
void unregWebPageItem(WebPageData *data, HistoryItem *item);
|
||||
const WebPageItems &webPageItems();
|
||||
|
||||
void regGameItem(GameData *data, HistoryItem *item);
|
||||
void unregGameItem(GameData *data, HistoryItem *item);
|
||||
const GameItems &gameItems();
|
||||
|
||||
void regSharedContactItem(qint32 userId, HistoryItem *item);
|
||||
void unregSharedContactItem(qint32 userId, HistoryItem *item);
|
||||
const SharedContactItems &sharedContactItems();
|
||||
QString phoneFromSharedContact(qint32 userId);
|
||||
|
||||
void regGifItem(Media::Clip::Reader *reader, HistoryItem *item);
|
||||
void unregGifItem(Media::Clip::Reader *reader);
|
||||
void stopRoundVideoPlayback();
|
||||
void stopGifItems();
|
||||
|
||||
void regMuted(PeerData *peer, qint32 changeIn);
|
||||
void unregMuted(PeerData *peer);
|
||||
void updateMuted();
|
||||
|
||||
void setProxySettings(QNetworkAccessManager &manager);
|
||||
#ifndef TDESKTOP_DISABLE_NETWORK_PROXY
|
||||
QNetworkProxy getHttpProxySettings();
|
||||
#endif // !TDESKTOP_DISABLE_NETWORK_PROXY
|
||||
void setProxySettings(QTcpSocket &socket);
|
||||
|
||||
void complexOverlayRect(Painter &p, QRect rect, ImageRoundRadius radius, ImageRoundCorners corners);
|
||||
void complexLocationRect(Painter &p, QRect rect, ImageRoundRadius radius, ImageRoundCorners corners);
|
||||
|
||||
QImage *cornersMask(ImageRoundRadius radius);
|
||||
void roundRect(Painter &p, qint32 x, qint32 y, qint32 w, qint32 h, style::color bg, RoundCorners index, const style::color *shadow = nullptr, RectParts parts = RectPart::Full);
|
||||
inline void roundRect(Painter &p, const QRect &rect, style::color bg, RoundCorners index, const style::color *shadow = nullptr, RectParts parts = RectPart::Full) {
|
||||
return roundRect(p, rect.x(), rect.y(), rect.width(), rect.height(), bg, index, shadow, parts);
|
||||
}
|
||||
void roundShadow(Painter &p, qint32 x, qint32 y, qint32 w, qint32 h, style::color shadow, RoundCorners index, RectParts parts = RectPart::Full);
|
||||
inline void roundShadow(Painter &p, const QRect &rect, style::color shadow, RoundCorners index, RectParts parts = RectPart::Full) {
|
||||
return roundShadow(p, rect.x(), rect.y(), rect.width(), rect.height(), shadow, index, parts);
|
||||
}
|
||||
void roundRect(Painter &p, qint32 x, qint32 y, qint32 w, qint32 h, style::color bg, ImageRoundRadius radius, RectParts parts = RectPart::Full);
|
||||
inline void roundRect(Painter &p, const QRect &rect, style::color bg, ImageRoundRadius radius, RectParts parts = RectPart::Full) {
|
||||
return roundRect(p, rect.x(), rect.y(), rect.width(), rect.height(), bg, radius, parts);
|
||||
}
|
||||
|
||||
struct WallPaper {
|
||||
WallPaper(qint32 id, ImagePtr thumb, ImagePtr full) : id(id), thumb(thumb), full(full) {
|
||||
}
|
||||
qint32 id;
|
||||
ImagePtr thumb;
|
||||
ImagePtr full;
|
||||
};
|
||||
typedef QList<WallPaper> WallPapers;
|
||||
DeclareSetting(WallPapers, ServerBackgrounds);
|
||||
bool isValidPhone(QString phone);
|
||||
|
||||
enum LaunchState {
|
||||
Launched = 0,
|
||||
QuitRequested = 1,
|
||||
QuitProcessed = 2,
|
||||
};
|
||||
void quit();
|
||||
bool quitting();
|
||||
LaunchState launchState();
|
||||
void setLaunchState(LaunchState state);
|
||||
void restart();
|
||||
|
||||
constexpr auto kFileSizeLimit = 1500 * 1024 * 1024; // Load files up to 1500mb
|
||||
constexpr auto kImageSizeLimit = 64 * 1024 * 1024; // Open images up to 64mb jpg/png/gif
|
||||
QImage readImage(QByteArray data, QByteArray *format = nullptr, bool opaque = true, bool *animated = nullptr);
|
||||
QImage readImage(const QString &file, QByteArray *format = nullptr, bool opaque = true, bool *animated = nullptr,
|
||||
QByteArray *content = 0);
|
||||
QPixmap pixmapFromImageInPlace(QImage &&image);
|
||||
|
||||
void regPhotoItem(PhotoData *data, HistoryItem *item);
|
||||
void unregPhotoItem(PhotoData *data, HistoryItem *item);
|
||||
const PhotoItems &photoItems();
|
||||
const PhotosData &photosData();
|
||||
|
||||
void regDocumentItem(DocumentData *data, HistoryItem *item);
|
||||
void unregDocumentItem(DocumentData *data, HistoryItem *item);
|
||||
const DocumentItems &documentItems();
|
||||
const DocumentsData &documentsData();
|
||||
|
||||
void regWebPageItem(WebPageData *data, HistoryItem *item);
|
||||
void unregWebPageItem(WebPageData *data, HistoryItem *item);
|
||||
const WebPageItems &webPageItems();
|
||||
|
||||
void regGameItem(GameData *data, HistoryItem *item);
|
||||
void unregGameItem(GameData *data, HistoryItem *item);
|
||||
const GameItems &gameItems();
|
||||
|
||||
void regSharedContactItem(qint32 userId, HistoryItem *item);
|
||||
void unregSharedContactItem(qint32 userId, HistoryItem *item);
|
||||
const SharedContactItems &sharedContactItems();
|
||||
QString phoneFromSharedContact(qint32 userId);
|
||||
|
||||
void regGifItem(Media::Clip::Reader *reader, HistoryItem *item);
|
||||
void unregGifItem(Media::Clip::Reader *reader);
|
||||
void stopRoundVideoPlayback();
|
||||
void stopGifItems();
|
||||
|
||||
void regMuted(PeerData *peer, qint32 changeIn);
|
||||
void unregMuted(PeerData *peer);
|
||||
void updateMuted();
|
||||
|
||||
void setProxySettings(QNetworkAccessManager &manager);
|
||||
#ifndef TDESKTOP_DISABLE_NETWORK_PROXY
|
||||
QNetworkProxy getHttpProxySettings();
|
||||
#endif // !TDESKTOP_DISABLE_NETWORK_PROXY
|
||||
void setProxySettings(QTcpSocket &socket);
|
||||
|
||||
void complexOverlayRect(Painter &p, QRect rect, ImageRoundRadius radius, ImageRoundCorners corners);
|
||||
void complexLocationRect(Painter &p, QRect rect, ImageRoundRadius radius, ImageRoundCorners corners);
|
||||
|
||||
QImage *cornersMask(ImageRoundRadius radius);
|
||||
void roundRect(Painter &p, qint32 x, qint32 y, qint32 w, qint32 h, style::color bg, RoundCorners index,
|
||||
const style::color *shadow = nullptr, RectParts parts = RectPart::Full);
|
||||
inline void roundRect(Painter &p, const QRect &rect, style::color bg, RoundCorners index,
|
||||
const style::color *shadow = nullptr, RectParts parts = RectPart::Full) {
|
||||
return roundRect(p, rect.x(), rect.y(), rect.width(), rect.height(), bg, index, shadow, parts);
|
||||
}
|
||||
void roundShadow(Painter &p, qint32 x, qint32 y, qint32 w, qint32 h, style::color shadow, RoundCorners index,
|
||||
RectParts parts = RectPart::Full);
|
||||
inline void roundShadow(Painter &p, const QRect &rect, style::color shadow, RoundCorners index,
|
||||
RectParts parts = RectPart::Full) {
|
||||
return roundShadow(p, rect.x(), rect.y(), rect.width(), rect.height(), shadow, index, parts);
|
||||
}
|
||||
void roundRect(Painter &p, qint32 x, qint32 y, qint32 w, qint32 h, style::color bg, ImageRoundRadius radius,
|
||||
RectParts parts = RectPart::Full);
|
||||
inline void roundRect(Painter &p, const QRect &rect, style::color bg, ImageRoundRadius radius,
|
||||
RectParts parts = RectPart::Full) {
|
||||
return roundRect(p, rect.x(), rect.y(), rect.width(), rect.height(), bg, radius, parts);
|
||||
}
|
||||
|
||||
struct WallPaper {
|
||||
WallPaper(qint32 id, ImagePtr thumb, ImagePtr full)
|
||||
: id(id)
|
||||
, thumb(thumb)
|
||||
, full(full) {}
|
||||
qint32 id;
|
||||
ImagePtr thumb;
|
||||
ImagePtr full;
|
||||
};
|
||||
typedef QList<WallPaper> WallPapers;
|
||||
DeclareSetting(WallPapers, ServerBackgrounds);
|
||||
|
||||
}; // namespace App
|
||||
|
|
|
@ -20,13 +20,13 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#include "application.h"
|
||||
|
||||
#include "platform/platform_specific.h"
|
||||
#include "base/timer.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
#include "messenger.h"
|
||||
#include "platform/platform_specific.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "window/notifications_manager.h"
|
||||
#include "messenger.h"
|
||||
#include "base/timer.h"
|
||||
|
||||
#include <QDesktopWidget>
|
||||
#include <QScreen>
|
||||
|
@ -50,7 +50,11 @@ QString _escapeTo7bit(const QString &str) {
|
|||
QChar ch(str.at(i));
|
||||
ushort uch(ch.unicode());
|
||||
if (uch < 32 || uch > 127 || uch == ushort(uchar('%'))) {
|
||||
result.append('%').append(_toHex(uch >> 12)).append(_toHex(uch >> 8)).append(_toHex(uch >> 4)).append(_toHex(uch));
|
||||
result.append('%')
|
||||
.append(_toHex(uch >> 12))
|
||||
.append(_toHex(uch >> 8))
|
||||
.append(_toHex(uch >> 4))
|
||||
.append(_toHex(uch));
|
||||
} else {
|
||||
result.append(ch);
|
||||
}
|
||||
|
@ -64,7 +68,8 @@ QString _escapeFrom7bit(const QString &str) {
|
|||
for (int i = 0, l = str.size(); i != l; ++i) {
|
||||
QChar ch(str.at(i));
|
||||
if (ch == QChar::fromLatin1('%') && i + 4 < l) {
|
||||
result.append(QChar(ushort((_fromHex(str.at(i + 1)) << 12) | (_fromHex(str.at(i + 2)) << 8) | (_fromHex(str.at(i + 3)) << 4) | _fromHex(str.at(i + 4)))));
|
||||
result.append(QChar(ushort((_fromHex(str.at(i + 1)) << 12) | (_fromHex(str.at(i + 2)) << 8) |
|
||||
(_fromHex(str.at(i + 3)) << 4) | _fromHex(str.at(i + 4)))));
|
||||
i += 4;
|
||||
} else {
|
||||
result.append(ch);
|
||||
|
@ -75,9 +80,10 @@ QString _escapeFrom7bit(const QString &str) {
|
|||
|
||||
} // namespace
|
||||
|
||||
Application::Application(int &argc, char **argv) : QApplication(argc, argv) {
|
||||
Application::Application(int &argc, char **argv)
|
||||
: QApplication(argc, argv) {
|
||||
QByteArray d(QFile::encodeName(QDir(cWorkingDir()).absolutePath()));
|
||||
char h[33] = { 0 };
|
||||
char h[33] = {0};
|
||||
hashMd5Hex(d.constData(), d.size(), h);
|
||||
#ifndef OS_MAC_STORE
|
||||
_localServerName = psServerPrefix() + h + '-' + cGUIDStr();
|
||||
|
@ -88,7 +94,8 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) {
|
|||
|
||||
connect(&_localSocket, SIGNAL(connected()), this, SLOT(socketConnected()));
|
||||
connect(&_localSocket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));
|
||||
connect(&_localSocket, SIGNAL(error(QLocalSocket::LocalSocketError)), this, SLOT(socketError(QLocalSocket::LocalSocketError)));
|
||||
connect(&_localSocket, SIGNAL(error(QLocalSocket::LocalSocketError)), this,
|
||||
SLOT(socketError(QLocalSocket::LocalSocketError)));
|
||||
connect(&_localSocket, SIGNAL(bytesWritten(qint64)), this, SLOT(socketWritten(qint64)));
|
||||
connect(&_localSocket, SIGNAL(readyRead()), this, SLOT(socketReading()));
|
||||
connect(&_localServer, SIGNAL(newConnection()), this, SLOT(newInstanceConnected()));
|
||||
|
@ -100,7 +107,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) {
|
|||
LOG(("Many instance allowed, starting..."));
|
||||
singleInstanceChecked();
|
||||
} else {
|
||||
LOG(("Connecting local socket to %1...").arg(_localServerName));
|
||||
LOG(("Connecting local socket to %1...").arg(_localServerName));
|
||||
_localSocket.connectToServer(_localServerName);
|
||||
}
|
||||
}
|
||||
|
@ -132,7 +139,7 @@ void Application::socketConnected() {
|
|||
_localSocket.write(commands.toLatin1());
|
||||
}
|
||||
|
||||
void Application::socketWritten(qint64/* bytes*/) {
|
||||
void Application::socketWritten(qint64 /* bytes*/) {
|
||||
if (_localSocket.state() != QLocalSocket::ConnectedState) {
|
||||
LOG(("Socket is not connected %1").arg(_localSocket.state()));
|
||||
return;
|
||||
|
@ -177,7 +184,9 @@ void Application::socketError(QLocalSocket::LocalSocketError e) {
|
|||
psCheckLocalSocket(_localServerName);
|
||||
|
||||
if (!_localServer.listen(_localServerName)) {
|
||||
LOG(("Failed to start listening to %1 server, error %2").arg(_localServerName).arg(int(_localServer.serverError())));
|
||||
LOG(("Failed to start listening to %1 server, error %2")
|
||||
.arg(_localServerName)
|
||||
.arg(int(_localServer.serverError())));
|
||||
return App::quit();
|
||||
}
|
||||
#endif // !Q_OS_WINRT
|
||||
|
@ -223,7 +232,8 @@ void Application::socketDisconnected() {
|
|||
|
||||
void Application::newInstanceConnected() {
|
||||
DEBUG_LOG(("Application Info: new local socket connected"));
|
||||
for (QLocalSocket *client = _localServer.nextPendingConnection(); client; client = _localServer.nextPendingConnection()) {
|
||||
for (QLocalSocket *client = _localServer.nextPendingConnection(); client;
|
||||
client = _localServer.nextPendingConnection()) {
|
||||
_localClients.push_back(LocalClient(client, QByteArray()));
|
||||
connect(client, SIGNAL(readyRead()), this, SLOT(readClients()));
|
||||
connect(client, SIGNAL(disconnected()), this, SLOT(removeClients()));
|
||||
|
@ -239,7 +249,8 @@ void Application::readClients() {
|
|||
if (i->second.size()) {
|
||||
QString cmds(QString::fromLatin1(i->second));
|
||||
qint32 from = 0, l = cmds.length();
|
||||
for (qint32 to = cmds.indexOf(QChar(';'), from); to >= from; to = (from < l) ? cmds.indexOf(QChar(';'), from) : -1) {
|
||||
for (qint32 to = cmds.indexOf(QChar(';'), from); to >= from;
|
||||
to = (from < l) ? cmds.indexOf(QChar(';'), from) : -1) {
|
||||
QStringRef cmd(&cmds, from, to - from);
|
||||
if (cmd.startsWith(qsl("CMD:"))) {
|
||||
Sandbox::execExternal(cmds.mid(from + 4, to - from - 4));
|
||||
|
@ -254,7 +265,8 @@ void Application::readClients() {
|
|||
startUrl = _escapeFrom7bit(cmds.mid(from + 5, to - from - 5)).mid(0, 8192);
|
||||
}
|
||||
} else {
|
||||
LOG(("Application Error: unknown command %1 passed in local socket").arg(QString(cmd.constData(), cmd.length())));
|
||||
LOG(("Application Error: unknown command %1 passed in local socket")
|
||||
.arg(QString(cmd.constData(), cmd.length())));
|
||||
}
|
||||
from = to + 1;
|
||||
}
|
||||
|
@ -324,7 +336,7 @@ void Application::closeApplication() {
|
|||
}
|
||||
|
||||
inline Application *application() {
|
||||
return qobject_cast<Application*>(QApplication::instance());
|
||||
return qobject_cast<Application *>(QApplication::instance());
|
||||
}
|
||||
|
||||
namespace Sandbox {
|
||||
|
@ -398,10 +410,13 @@ void launch() {
|
|||
if (devicePixelRatio > 1.) {
|
||||
if ((cPlatform() != dbipMac && cPlatform() != dbipMacOld) || (devicePixelRatio != 2.)) {
|
||||
LOG(("Found non-trivial Device Pixel Ratio: %1").arg(devicePixelRatio));
|
||||
LOG(("Environmental variables: QT_DEVICE_PIXEL_RATIO='%1'").arg(QString::fromLatin1(qgetenv("QT_DEVICE_PIXEL_RATIO"))));
|
||||
LOG(("Environmental variables: QT_DEVICE_PIXEL_RATIO='%1'")
|
||||
.arg(QString::fromLatin1(qgetenv("QT_DEVICE_PIXEL_RATIO"))));
|
||||
LOG(("Environmental variables: QT_SCALE_FACTOR='%1'").arg(QString::fromLatin1(qgetenv("QT_SCALE_FACTOR"))));
|
||||
LOG(("Environmental variables: QT_AUTO_SCREEN_SCALE_FACTOR='%1'").arg(QString::fromLatin1(qgetenv("QT_AUTO_SCREEN_SCALE_FACTOR"))));
|
||||
LOG(("Environmental variables: QT_SCREEN_SCALE_FACTORS='%1'").arg(QString::fromLatin1(qgetenv("QT_SCREEN_SCALE_FACTORS"))));
|
||||
LOG(("Environmental variables: QT_AUTO_SCREEN_SCALE_FACTOR='%1'")
|
||||
.arg(QString::fromLatin1(qgetenv("QT_AUTO_SCREEN_SCALE_FACTOR"))));
|
||||
LOG(("Environmental variables: QT_SCREEN_SCALE_FACTORS='%1'")
|
||||
.arg(QString::fromLatin1(qgetenv("QT_SCREEN_SCALE_FACTORS"))));
|
||||
}
|
||||
cSetRetina(true);
|
||||
cSetRetinaFactor(devicePixelRatio);
|
||||
|
|
|
@ -23,8 +23,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
#include <memory>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QLocalSocket>
|
||||
#include <QLocalServer>
|
||||
#include <QLocalSocket>
|
||||
|
||||
class Messenger;
|
||||
|
||||
|
@ -43,7 +43,7 @@ public:
|
|||
signals:
|
||||
void adjustSingleTimers();
|
||||
|
||||
// Single instance application
|
||||
// Single instance application
|
||||
public slots:
|
||||
void socketConnected();
|
||||
void socketError(QLocalSocket::LocalSocketError e);
|
||||
|
@ -59,7 +59,7 @@ public slots:
|
|||
void closeApplication(); // will be done in aboutToQuit()
|
||||
|
||||
private:
|
||||
typedef QPair<QLocalSocket*, QByteArray> LocalClient;
|
||||
typedef QPair<QLocalSocket *, QByteArray> LocalClient;
|
||||
typedef QList<LocalClient> LocalClients;
|
||||
|
||||
std::unique_ptr<Messenger> _messengerInstance;
|
||||
|
|
|
@ -21,16 +21,16 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
#include "auth_session.h"
|
||||
|
||||
#include "apiwrap.h"
|
||||
#include "calls/calls_instance.h"
|
||||
#include "chat_helpers/tabbed_selector.h"
|
||||
#include "messenger.h"
|
||||
#include "platform/platform_specific.h"
|
||||
#include "storage/file_download.h"
|
||||
#include "storage/file_upload.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "storage/serialize_common.h"
|
||||
#include "window/notifications_manager.h"
|
||||
#include "platform/platform_specific.h"
|
||||
#include "calls/calls_instance.h"
|
||||
#include "window/section_widget.h"
|
||||
#include "chat_helpers/tabbed_selector.h"
|
||||
|
||||
#include "app.h" // App::user
|
||||
|
||||
|
@ -41,10 +41,9 @@ constexpr auto kAutoLockTimeoutLateMs = TimeMs(3000);
|
|||
} // namespace
|
||||
|
||||
AuthSessionData::Variables::Variables()
|
||||
: selectorTab(ChatHelpers::SelectorTab::Emoji)
|
||||
, floatPlayerColumn(Window::Column::Second)
|
||||
, floatPlayerCorner(RectPart::TopRight) {
|
||||
}
|
||||
: selectorTab(ChatHelpers::SelectorTab::Emoji)
|
||||
, floatPlayerColumn(Window::Column::Second)
|
||||
, floatPlayerCorner(RectPart::TopRight) {}
|
||||
|
||||
QByteArray AuthSessionData::serialize() const {
|
||||
auto size = sizeof(qint32) * 8;
|
||||
|
@ -170,17 +169,15 @@ AuthSession &Auth() {
|
|||
}
|
||||
|
||||
AuthSession::AuthSession(UserId userId)
|
||||
: _userId(userId)
|
||||
, _autoLockTimer([this] { checkAutoLock(); })
|
||||
, _api(std::make_unique<ApiWrap>(this))
|
||||
, _calls(std::make_unique<Calls::Instance>())
|
||||
, _downloader(std::make_unique<Storage::Downloader>())
|
||||
, _uploader(std::make_unique<Storage::Uploader>())
|
||||
, _notifications(std::make_unique<Window::Notifications::System>(this)) {
|
||||
: _userId(userId)
|
||||
, _autoLockTimer([this] { checkAutoLock(); })
|
||||
, _api(std::make_unique<ApiWrap>(this))
|
||||
, _calls(std::make_unique<Calls::Instance>())
|
||||
, _downloader(std::make_unique<Storage::Downloader>())
|
||||
, _uploader(std::make_unique<Storage::Uploader>())
|
||||
, _notifications(std::make_unique<Window::Notifications::System>(this)) {
|
||||
Expects(_userId != 0);
|
||||
_saveDataTimer.setCallback([this] {
|
||||
Local::writeUserSettings();
|
||||
});
|
||||
_saveDataTimer.setCallback([this] { Local::writeUserSettings(); });
|
||||
subscribe(Messenger::Instance().passcodedChanged(), [this] {
|
||||
_shouldLockAt = 0;
|
||||
notifications().updateAll();
|
||||
|
|
|
@ -64,18 +64,18 @@ public:
|
|||
base::Observable<void> &savedGifsUpdated() {
|
||||
return _savedGifsUpdated;
|
||||
}
|
||||
base::Observable<not_null<History*>> &historyCleared() {
|
||||
base::Observable<not_null<History *>> &historyCleared() {
|
||||
return _historyCleared;
|
||||
}
|
||||
base::Observable<not_null<const HistoryItem*>> &repaintLogEntry() {
|
||||
base::Observable<not_null<const HistoryItem *>> &repaintLogEntry() {
|
||||
return _repaintLogEntry;
|
||||
}
|
||||
base::Observable<void> &pendingHistoryResize() {
|
||||
return _pendingHistoryResize;
|
||||
}
|
||||
struct ItemVisibilityQuery {
|
||||
not_null<HistoryItem*> item;
|
||||
not_null<bool*> isVisible;
|
||||
not_null<HistoryItem *> item;
|
||||
not_null<bool *> isVisible;
|
||||
};
|
||||
base::Observable<ItemVisibilityQuery> &queryItemVisibility() {
|
||||
return _queryItemVisibility;
|
||||
|
@ -160,18 +160,17 @@ private:
|
|||
OrderedSet<PeerId> groupStickersSectionHidden;
|
||||
};
|
||||
|
||||
base::Variable<bool> _contactsLoaded = { false };
|
||||
base::Variable<bool> _allChatsLoaded = { false };
|
||||
base::Variable<bool> _contactsLoaded = {false};
|
||||
base::Variable<bool> _allChatsLoaded = {false};
|
||||
base::Observable<void> _moreChatsLoaded;
|
||||
base::Observable<void> _stickersUpdated;
|
||||
base::Observable<void> _savedGifsUpdated;
|
||||
base::Observable<not_null<History*>> _historyCleared;
|
||||
base::Observable<not_null<const HistoryItem*>> _repaintLogEntry;
|
||||
base::Observable<not_null<History *>> _historyCleared;
|
||||
base::Observable<not_null<const HistoryItem *>> _repaintLogEntry;
|
||||
base::Observable<void> _pendingHistoryResize;
|
||||
base::Observable<ItemVisibilityQuery> _queryItemVisibility;
|
||||
Variables _variables;
|
||||
TimeMs _lastTimeVideoPlayedAt = 0;
|
||||
|
||||
};
|
||||
|
||||
// One per Messenger.
|
||||
|
@ -225,8 +224,8 @@ public:
|
|||
void checkAutoLock();
|
||||
void checkAutoLockIn(TimeMs time);
|
||||
|
||||
base::Observable<DocumentData*> documentUpdated;
|
||||
base::Observable<std::pair<HistoryItem*, MsgId>> messageIdChanging;
|
||||
base::Observable<DocumentData *> documentUpdated;
|
||||
base::Observable<std::pair<HistoryItem *, MsgId>> messageIdChanging;
|
||||
|
||||
~AuthSession();
|
||||
|
||||
|
@ -243,5 +242,4 @@ private:
|
|||
const std::unique_ptr<Storage::Downloader> _downloader;
|
||||
const std::unique_ptr<Storage::Uploader> _uploader;
|
||||
const std::unique_ptr<Window::Notifications::System> _notifications;
|
||||
|
||||
};
|
||||
|
|
|
@ -20,22 +20,18 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
namespace base {
|
||||
|
||||
// @todo use ranges-v3 here
|
||||
template <typename Range, typename Method>
|
||||
decltype(auto) for_each(Range &&range, Method &&method) {
|
||||
return std::for_each(
|
||||
std::begin(std::forward<Range>(range)),
|
||||
std::end(std::forward<Range>(range)),
|
||||
std::forward<Method>(method));
|
||||
template <typename Range, typename Method> decltype(auto) for_each(Range &&range, Method &&method) {
|
||||
return std::for_each(std::begin(std::forward<Range>(range)), std::end(std::forward<Range>(range)),
|
||||
std::forward<Method>(method));
|
||||
}
|
||||
|
||||
template <typename Method>
|
||||
decltype(auto) for_each_apply(Method &&method) {
|
||||
template <typename Method> decltype(auto) for_each_apply(Method &&method) {
|
||||
return [&method](auto &&range) {
|
||||
return for_each(std::forward<decltype(range)>(range), std::forward<Method>(method));
|
||||
};
|
||||
|
|
|
@ -31,15 +31,15 @@ void log(const char *message, const char *file, int line);
|
|||
|
||||
// Release build assertions.
|
||||
inline constexpr void noop() {
|
||||
// MSVC2015 requires return to suppress warning: a constexpr function must contain exactly one return statement
|
||||
return void();
|
||||
// MSVC2015 requires return to suppress warning: a constexpr function must contain exactly one return statement
|
||||
return void();
|
||||
}
|
||||
|
||||
[[noreturn]] inline void fail(const char *message, const char *file, int line) {
|
||||
log(message, file, line);
|
||||
|
||||
// Crash with access violation and generate crash report.
|
||||
volatile auto nullptr_value = (int*)nullptr;
|
||||
volatile auto nullptr_value = (int *)nullptr;
|
||||
*nullptr_value = 0;
|
||||
|
||||
// Silent the possible failure to comply noreturn warning.
|
||||
|
@ -47,8 +47,8 @@ inline constexpr void noop() {
|
|||
}
|
||||
|
||||
inline constexpr void validate(bool condition, const char *message, const char *file, int line) {
|
||||
// MSVC2015 requires return to suppress error C3249: illegal statement or sub-expression for 'constexpr' function
|
||||
return (GSL_UNLIKELY(!(condition))) ? fail(message, file, line) : noop();
|
||||
// MSVC2015 requires return to suppress error C3249: illegal statement or sub-expression for 'constexpr' function
|
||||
return (GSL_UNLIKELY(!(condition))) ? fail(message, file, line) : noop();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -30,49 +30,41 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
|
||||
namespace base {
|
||||
|
||||
template <typename EnumType>
|
||||
class flags;
|
||||
template <typename EnumType> class flags;
|
||||
|
||||
template <typename ExtendedEnum>
|
||||
struct extended_flags;
|
||||
template <typename ExtendedEnum> struct extended_flags;
|
||||
|
||||
template <typename ExtendedEnum>
|
||||
using extended_flags_t = typename extended_flags<ExtendedEnum>::type;
|
||||
template <typename ExtendedEnum> using extended_flags_t = typename extended_flags<ExtendedEnum>::type;
|
||||
|
||||
namespace details {
|
||||
|
||||
struct flags_zero_helper_struct {
|
||||
};
|
||||
struct flags_zero_helper_struct {};
|
||||
|
||||
using flags_zero_helper = void(base::details::flags_zero_helper_struct::*)();
|
||||
using flags_zero_helper = void (base::details::flags_zero_helper_struct::*)();
|
||||
|
||||
template <typename ExtendedEnum,
|
||||
typename Enum = typename base::extended_flags<ExtendedEnum>::type>
|
||||
template <typename ExtendedEnum, typename Enum = typename base::extended_flags<ExtendedEnum>::type>
|
||||
inline constexpr auto extended_flag_convert(ExtendedEnum value) {
|
||||
return static_cast<Enum>(value);
|
||||
}
|
||||
|
||||
template <typename ExtendedEnum,
|
||||
typename Enum = typename base::extended_flags<ExtendedEnum>::type>
|
||||
template <typename ExtendedEnum, typename Enum = typename base::extended_flags<ExtendedEnum>::type>
|
||||
inline constexpr auto extended_flags_convert(ExtendedEnum value) {
|
||||
return flags<Enum>(extended_flag_convert(value));
|
||||
}
|
||||
|
||||
} // namespace details
|
||||
|
||||
template <typename EnumType>
|
||||
class flags {
|
||||
template <typename EnumType> class flags {
|
||||
public:
|
||||
using Enum = EnumType;
|
||||
using Type = std::underlying_type_t<Enum>;
|
||||
|
||||
constexpr flags() = default;
|
||||
constexpr flags(details::flags_zero_helper) noexcept {
|
||||
}
|
||||
constexpr flags(Enum value) noexcept : _value(static_cast<Type>(value)) {
|
||||
}
|
||||
explicit constexpr flags(Type value) noexcept : _value(value) {
|
||||
}
|
||||
constexpr flags(details::flags_zero_helper) noexcept {}
|
||||
constexpr flags(Enum value) noexcept
|
||||
: _value(static_cast<Type>(value)) {}
|
||||
explicit constexpr flags(Type value) noexcept
|
||||
: _value(value) {}
|
||||
|
||||
constexpr auto value() const noexcept {
|
||||
return _value;
|
||||
|
@ -139,157 +131,131 @@ public:
|
|||
|
||||
private:
|
||||
Type _value = 0;
|
||||
|
||||
};
|
||||
|
||||
template <typename Enum>
|
||||
constexpr auto make_flags(Enum value) noexcept {
|
||||
template <typename Enum> constexpr auto make_flags(Enum value) noexcept {
|
||||
return flags<Enum>(value);
|
||||
}
|
||||
|
||||
template <typename Enum,
|
||||
typename = std::enable_if_t<std::is_enum<Enum>::value>,
|
||||
typename = std::enable_if_t<is_flag_type(Enum{})>>
|
||||
template <typename Enum, typename = std::enable_if_t<std::is_enum<Enum>::value>,
|
||||
typename = std::enable_if_t<is_flag_type(Enum{})>>
|
||||
inline constexpr auto operator|(Enum a, flags<Enum> b) noexcept {
|
||||
return b | a;
|
||||
}
|
||||
|
||||
template <typename Enum,
|
||||
typename = std::enable_if_t<std::is_enum<Enum>::value>,
|
||||
typename = std::enable_if_t<is_flag_type(Enum{})>>
|
||||
template <typename Enum, typename = std::enable_if_t<std::is_enum<Enum>::value>,
|
||||
typename = std::enable_if_t<is_flag_type(Enum{})>>
|
||||
inline constexpr auto operator&(Enum a, flags<Enum> b) noexcept {
|
||||
return b & a;
|
||||
}
|
||||
|
||||
template <typename Enum,
|
||||
typename = std::enable_if_t<std::is_enum<Enum>::value>,
|
||||
typename = std::enable_if_t<is_flag_type(Enum{})>>
|
||||
template <typename Enum, typename = std::enable_if_t<std::is_enum<Enum>::value>,
|
||||
typename = std::enable_if_t<is_flag_type(Enum{})>>
|
||||
inline constexpr auto operator^(Enum a, flags<Enum> b) noexcept {
|
||||
return b ^ a;
|
||||
}
|
||||
|
||||
template <typename ExtendedEnum,
|
||||
typename = typename extended_flags<ExtendedEnum>::type>
|
||||
template <typename ExtendedEnum, typename = typename extended_flags<ExtendedEnum>::type>
|
||||
inline constexpr auto operator|(flags<extended_flags_t<ExtendedEnum>> a, ExtendedEnum b) {
|
||||
return a | details::extended_flags_convert(b);
|
||||
}
|
||||
|
||||
template <typename ExtendedEnum,
|
||||
typename = typename extended_flags<ExtendedEnum>::type>
|
||||
template <typename ExtendedEnum, typename = typename extended_flags<ExtendedEnum>::type>
|
||||
inline constexpr auto operator|(ExtendedEnum a, flags<extended_flags_t<ExtendedEnum>> b) {
|
||||
return b | a;
|
||||
}
|
||||
|
||||
template <typename ExtendedEnum,
|
||||
typename = extended_flags_t<ExtendedEnum>>
|
||||
template <typename ExtendedEnum, typename = extended_flags_t<ExtendedEnum>>
|
||||
inline constexpr auto operator&(flags<extended_flags_t<ExtendedEnum>> a, ExtendedEnum b) {
|
||||
return a & details::extended_flags_convert(b);
|
||||
}
|
||||
|
||||
template <typename ExtendedEnum,
|
||||
typename = typename extended_flags<ExtendedEnum>::type>
|
||||
template <typename ExtendedEnum, typename = typename extended_flags<ExtendedEnum>::type>
|
||||
inline constexpr auto operator&(ExtendedEnum a, flags<extended_flags_t<ExtendedEnum>> b) {
|
||||
return b & a;
|
||||
}
|
||||
|
||||
template <typename ExtendedEnum,
|
||||
typename = extended_flags_t<ExtendedEnum>>
|
||||
template <typename ExtendedEnum, typename = extended_flags_t<ExtendedEnum>>
|
||||
inline constexpr auto operator^(flags<extended_flags_t<ExtendedEnum>> a, ExtendedEnum b) {
|
||||
return a ^ details::extended_flags_convert(b);
|
||||
}
|
||||
|
||||
template <typename ExtendedEnum,
|
||||
typename = typename extended_flags<ExtendedEnum>::type>
|
||||
template <typename ExtendedEnum, typename = typename extended_flags<ExtendedEnum>::type>
|
||||
inline constexpr auto operator^(ExtendedEnum a, flags<extended_flags_t<ExtendedEnum>> b) {
|
||||
return b ^ a;
|
||||
}
|
||||
|
||||
template <typename ExtendedEnum,
|
||||
typename = typename extended_flags<ExtendedEnum>::type>
|
||||
template <typename ExtendedEnum, typename = typename extended_flags<ExtendedEnum>::type>
|
||||
inline constexpr auto &operator&=(flags<extended_flags_t<ExtendedEnum>> &a, ExtendedEnum b) {
|
||||
return (a &= details::extended_flags_convert(b));
|
||||
}
|
||||
|
||||
template <typename ExtendedEnum,
|
||||
typename = typename extended_flags<ExtendedEnum>::type>
|
||||
template <typename ExtendedEnum, typename = typename extended_flags<ExtendedEnum>::type>
|
||||
inline constexpr auto &operator|=(flags<extended_flags_t<ExtendedEnum>> &a, ExtendedEnum b) {
|
||||
return (a |= details::extended_flags_convert(b));
|
||||
}
|
||||
|
||||
template <typename ExtendedEnum,
|
||||
typename = typename extended_flags<ExtendedEnum>::type>
|
||||
template <typename ExtendedEnum, typename = typename extended_flags<ExtendedEnum>::type>
|
||||
inline constexpr auto &operator^=(flags<extended_flags_t<ExtendedEnum>> &a, ExtendedEnum b) {
|
||||
return (a ^= details::extended_flags_convert(b));
|
||||
}
|
||||
|
||||
template <typename ExtendedEnum,
|
||||
typename = typename extended_flags<ExtendedEnum>::type>
|
||||
template <typename ExtendedEnum, typename = typename extended_flags<ExtendedEnum>::type>
|
||||
inline constexpr auto operator==(flags<extended_flags_t<ExtendedEnum>> a, ExtendedEnum b) {
|
||||
return a == details::extended_flags_convert(b);
|
||||
}
|
||||
|
||||
template <typename ExtendedEnum,
|
||||
typename = typename extended_flags<ExtendedEnum>::type>
|
||||
template <typename ExtendedEnum, typename = typename extended_flags<ExtendedEnum>::type>
|
||||
inline constexpr auto operator==(ExtendedEnum a, flags<extended_flags_t<ExtendedEnum>> b) {
|
||||
return (b == a);
|
||||
}
|
||||
|
||||
template <typename ExtendedEnum,
|
||||
typename = typename extended_flags<ExtendedEnum>::type>
|
||||
template <typename ExtendedEnum, typename = typename extended_flags<ExtendedEnum>::type>
|
||||
inline constexpr auto operator!=(flags<extended_flags_t<ExtendedEnum>> a, ExtendedEnum b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
template <typename ExtendedEnum,
|
||||
typename = typename extended_flags<ExtendedEnum>::type>
|
||||
template <typename ExtendedEnum, typename = typename extended_flags<ExtendedEnum>::type>
|
||||
inline constexpr auto operator!=(ExtendedEnum a, flags<extended_flags_t<ExtendedEnum>> b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
template <typename ExtendedEnum,
|
||||
typename = typename extended_flags<ExtendedEnum>::type>
|
||||
template <typename ExtendedEnum, typename = typename extended_flags<ExtendedEnum>::type>
|
||||
inline constexpr auto operator<(flags<extended_flags_t<ExtendedEnum>> a, ExtendedEnum b) {
|
||||
return a < details::extended_flags_convert(b);
|
||||
}
|
||||
|
||||
template <typename ExtendedEnum,
|
||||
typename = typename extended_flags<ExtendedEnum>::type>
|
||||
template <typename ExtendedEnum, typename = typename extended_flags<ExtendedEnum>::type>
|
||||
inline constexpr auto operator<(ExtendedEnum a, flags<extended_flags_t<ExtendedEnum>> b) {
|
||||
return details::extended_flags_convert(a) < b;
|
||||
}
|
||||
|
||||
template <typename ExtendedEnum,
|
||||
typename = typename extended_flags<ExtendedEnum>::type>
|
||||
template <typename ExtendedEnum, typename = typename extended_flags<ExtendedEnum>::type>
|
||||
inline constexpr auto operator>(flags<extended_flags_t<ExtendedEnum>> a, ExtendedEnum b) {
|
||||
return (b < a);
|
||||
}
|
||||
|
||||
template <typename ExtendedEnum,
|
||||
typename = typename extended_flags<ExtendedEnum>::type>
|
||||
template <typename ExtendedEnum, typename = typename extended_flags<ExtendedEnum>::type>
|
||||
inline constexpr auto operator>(ExtendedEnum a, flags<extended_flags_t<ExtendedEnum>> b) {
|
||||
return (b < a);
|
||||
}
|
||||
|
||||
template <typename ExtendedEnum,
|
||||
typename = typename extended_flags<ExtendedEnum>::type>
|
||||
template <typename ExtendedEnum, typename = typename extended_flags<ExtendedEnum>::type>
|
||||
inline constexpr auto operator<=(flags<extended_flags_t<ExtendedEnum>> a, ExtendedEnum b) {
|
||||
return !(b < a);
|
||||
}
|
||||
|
||||
template <typename ExtendedEnum,
|
||||
typename = typename extended_flags<ExtendedEnum>::type>
|
||||
template <typename ExtendedEnum, typename = typename extended_flags<ExtendedEnum>::type>
|
||||
inline constexpr auto operator<=(ExtendedEnum a, flags<extended_flags_t<ExtendedEnum>> b) {
|
||||
return !(b < a);
|
||||
}
|
||||
|
||||
template <typename ExtendedEnum,
|
||||
typename = typename extended_flags<ExtendedEnum>::type>
|
||||
template <typename ExtendedEnum, typename = typename extended_flags<ExtendedEnum>::type>
|
||||
inline constexpr auto operator>=(flags<extended_flags_t<ExtendedEnum>> a, ExtendedEnum b) {
|
||||
return !(a < b);
|
||||
}
|
||||
|
||||
template <typename ExtendedEnum,
|
||||
typename = typename extended_flags<ExtendedEnum>::type>
|
||||
template <typename ExtendedEnum, typename = typename extended_flags<ExtendedEnum>::type>
|
||||
inline constexpr auto operator>=(ExtendedEnum a, flags<extended_flags_t<ExtendedEnum>> b) {
|
||||
return !(a < b);
|
||||
}
|
||||
|
@ -298,73 +264,62 @@ inline constexpr auto operator>=(ExtendedEnum a, flags<extended_flags_t<Extended
|
|||
|
||||
#undef FLAGS_CONSTEXPR
|
||||
|
||||
template <typename Enum,
|
||||
typename = std::enable_if_t<std::is_enum<Enum>::value>,
|
||||
typename = std::enable_if_t<is_flag_type(Enum{})>>
|
||||
template <typename Enum, typename = std::enable_if_t<std::is_enum<Enum>::value>,
|
||||
typename = std::enable_if_t<is_flag_type(Enum{})>>
|
||||
inline constexpr auto operator!(Enum a) noexcept {
|
||||
return !base::make_flags(a);
|
||||
}
|
||||
|
||||
template <typename Enum,
|
||||
typename = std::enable_if_t<std::is_enum<Enum>::value>,
|
||||
typename = std::enable_if_t<is_flag_type(Enum{})>>
|
||||
template <typename Enum, typename = std::enable_if_t<std::is_enum<Enum>::value>,
|
||||
typename = std::enable_if_t<is_flag_type(Enum{})>>
|
||||
inline constexpr auto operator~(Enum a) noexcept {
|
||||
return ~base::make_flags(a);
|
||||
}
|
||||
|
||||
template <typename Enum,
|
||||
typename = std::enable_if_t<std::is_enum<Enum>::value>,
|
||||
typename = std::enable_if_t<is_flag_type(Enum{})>>
|
||||
template <typename Enum, typename = std::enable_if_t<std::is_enum<Enum>::value>,
|
||||
typename = std::enable_if_t<is_flag_type(Enum{})>>
|
||||
inline constexpr auto operator|(Enum a, Enum b) noexcept {
|
||||
return base::make_flags(a) | b;
|
||||
}
|
||||
|
||||
template <typename Enum,
|
||||
typename = std::enable_if_t<std::is_enum<Enum>::value>,
|
||||
typename = std::enable_if_t<is_flag_type(Enum{})>>
|
||||
template <typename Enum, typename = std::enable_if_t<std::is_enum<Enum>::value>,
|
||||
typename = std::enable_if_t<is_flag_type(Enum{})>>
|
||||
inline constexpr auto operator|(Enum a, base::details::flags_zero_helper) noexcept {
|
||||
return base::make_flags(a);
|
||||
}
|
||||
|
||||
template <typename Enum,
|
||||
typename = std::enable_if_t<std::is_enum<Enum>::value>,
|
||||
typename = std::enable_if_t<is_flag_type(Enum{})>>
|
||||
template <typename Enum, typename = std::enable_if_t<std::is_enum<Enum>::value>,
|
||||
typename = std::enable_if_t<is_flag_type(Enum{})>>
|
||||
inline constexpr auto operator|(base::details::flags_zero_helper, Enum b) noexcept {
|
||||
return base::make_flags(b);
|
||||
}
|
||||
|
||||
template <typename ExtendedEnum,
|
||||
typename = typename base::extended_flags<ExtendedEnum>::type>
|
||||
template <typename ExtendedEnum, typename = typename base::extended_flags<ExtendedEnum>::type>
|
||||
inline constexpr auto operator|(ExtendedEnum a, ExtendedEnum b) {
|
||||
return base::details::extended_flags_convert(a) | b;
|
||||
}
|
||||
|
||||
template <typename ExtendedEnum,
|
||||
typename = typename base::extended_flags<ExtendedEnum>::type>
|
||||
template <typename ExtendedEnum, typename = typename base::extended_flags<ExtendedEnum>::type>
|
||||
inline constexpr auto operator|(ExtendedEnum a, typename base::extended_flags<ExtendedEnum>::type b) {
|
||||
return base::details::extended_flags_convert(a) | b;
|
||||
}
|
||||
|
||||
template <typename ExtendedEnum,
|
||||
typename = typename base::extended_flags<ExtendedEnum>::type>
|
||||
template <typename ExtendedEnum, typename = typename base::extended_flags<ExtendedEnum>::type>
|
||||
inline constexpr auto operator|(typename base::extended_flags<ExtendedEnum>::type a, ExtendedEnum b) {
|
||||
return b | a;
|
||||
}
|
||||
|
||||
template <typename ExtendedEnum,
|
||||
typename = typename base::extended_flags<ExtendedEnum>::type>
|
||||
template <typename ExtendedEnum, typename = typename base::extended_flags<ExtendedEnum>::type>
|
||||
inline constexpr auto operator|(base::details::flags_zero_helper, ExtendedEnum b) {
|
||||
return 0 | base::details::extended_flag_convert(b);
|
||||
}
|
||||
|
||||
template <typename ExtendedEnum,
|
||||
typename = typename base::extended_flags<ExtendedEnum>::type>
|
||||
template <typename ExtendedEnum, typename = typename base::extended_flags<ExtendedEnum>::type>
|
||||
inline constexpr auto operator|(ExtendedEnum a, base::details::flags_zero_helper) {
|
||||
return base::details::extended_flag_convert(a) | 0;
|
||||
}
|
||||
|
||||
template <typename ExtendedEnum,
|
||||
typename = typename base::extended_flags<ExtendedEnum>::type>
|
||||
template <typename ExtendedEnum, typename = typename base::extended_flags<ExtendedEnum>::type>
|
||||
inline constexpr auto operator~(ExtendedEnum b) {
|
||||
return ~base::details::extended_flags_convert(b);
|
||||
}
|
||||
|
|
|
@ -20,17 +20,15 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include <deque>
|
||||
#include <algorithm>
|
||||
#include "base/optional.h"
|
||||
#include <algorithm>
|
||||
#include <deque>
|
||||
|
||||
namespace base {
|
||||
|
||||
template <typename Key, typename Type>
|
||||
class flat_map;
|
||||
template <typename Key, typename Type> class flat_map;
|
||||
|
||||
template <typename Key, typename Type>
|
||||
class flat_multi_map;
|
||||
template <typename Key, typename Type> class flat_multi_map;
|
||||
|
||||
template <typename Key, typename Type, typename iterator_impl, typename pointer_impl, typename reference_impl>
|
||||
class flat_multi_map_iterator_base_impl;
|
||||
|
@ -47,8 +45,8 @@ public:
|
|||
using reference = reference_impl;
|
||||
using const_reference = typename flat_multi_map<Key, Type>::const_reference;
|
||||
|
||||
flat_multi_map_iterator_base_impl(iterator_impl impl = iterator_impl()) : _impl(impl) {
|
||||
}
|
||||
flat_multi_map_iterator_base_impl(iterator_impl impl = iterator_impl())
|
||||
: _impl(impl) {}
|
||||
|
||||
reference operator*() {
|
||||
return *_impl;
|
||||
|
@ -113,89 +111,87 @@ public:
|
|||
private:
|
||||
iterator_impl _impl;
|
||||
friend class flat_multi_map<Key, Type>;
|
||||
|
||||
};
|
||||
|
||||
template <typename Key, typename Type>
|
||||
class flat_multi_map {
|
||||
template <typename Key, typename Type> class flat_multi_map {
|
||||
using self = flat_multi_map<Key, Type>;
|
||||
class key_const_wrap {
|
||||
public:
|
||||
key_const_wrap(const Key &value) : _value(value) {
|
||||
}
|
||||
key_const_wrap(Key &&value) : _value(std::move(value)) {
|
||||
}
|
||||
inline operator const Key&() const {
|
||||
key_const_wrap(const Key &value)
|
||||
: _value(value) {}
|
||||
key_const_wrap(Key &&value)
|
||||
: _value(std::move(value)) {}
|
||||
inline operator const Key &() const {
|
||||
return _value;
|
||||
}
|
||||
|
||||
friend inline bool operator<(const Key &a, const key_const_wrap &b) {
|
||||
return a < ((const Key&)b);
|
||||
return a < ((const Key &)b);
|
||||
}
|
||||
friend inline bool operator<(const key_const_wrap &a, const Key &b) {
|
||||
return ((const Key&)a) < b;
|
||||
return ((const Key &)a) < b;
|
||||
}
|
||||
friend inline bool operator<(const key_const_wrap &a, const key_const_wrap &b) {
|
||||
return ((const Key&)a) < ((const Key&)b);
|
||||
return ((const Key &)a) < ((const Key &)b);
|
||||
}
|
||||
|
||||
private:
|
||||
Key _value;
|
||||
|
||||
};
|
||||
|
||||
using pair_type = std::pair<key_const_wrap, Type>;
|
||||
using impl = std::deque<pair_type>;
|
||||
|
||||
using iterator_base = flat_multi_map_iterator_base_impl<Key, Type, typename impl::iterator, pair_type*, pair_type&>;
|
||||
using const_iterator_base = flat_multi_map_iterator_base_impl<Key, Type, typename impl::const_iterator, const pair_type*, const pair_type&>;
|
||||
using reverse_iterator_base = flat_multi_map_iterator_base_impl<Key, Type, typename impl::reverse_iterator, pair_type*, pair_type&>;
|
||||
using const_reverse_iterator_base = flat_multi_map_iterator_base_impl<Key, Type, typename impl::const_reverse_iterator, const pair_type*, const pair_type&>;
|
||||
using iterator_base =
|
||||
flat_multi_map_iterator_base_impl<Key, Type, typename impl::iterator, pair_type *, pair_type &>;
|
||||
using const_iterator_base = flat_multi_map_iterator_base_impl<Key, Type, typename impl::const_iterator,
|
||||
const pair_type *, const pair_type &>;
|
||||
using reverse_iterator_base =
|
||||
flat_multi_map_iterator_base_impl<Key, Type, typename impl::reverse_iterator, pair_type *, pair_type &>;
|
||||
using const_reverse_iterator_base =
|
||||
flat_multi_map_iterator_base_impl<Key, Type, typename impl::const_reverse_iterator, const pair_type *,
|
||||
const pair_type &>;
|
||||
|
||||
public:
|
||||
using value_type = pair_type;
|
||||
using size_type = typename impl::size_type;
|
||||
using difference_type = typename impl::difference_type;
|
||||
using pointer = pair_type*;
|
||||
using const_pointer = const pair_type*;
|
||||
using reference = pair_type&;
|
||||
using const_reference = const pair_type&;
|
||||
using pointer = pair_type *;
|
||||
using const_pointer = const pair_type *;
|
||||
using reference = pair_type &;
|
||||
using const_reference = const pair_type &;
|
||||
|
||||
class const_iterator;
|
||||
class iterator : public iterator_base {
|
||||
public:
|
||||
using iterator_base::iterator_base;
|
||||
iterator(const iterator_base &other) : iterator_base(other) {
|
||||
}
|
||||
iterator(const iterator_base &other)
|
||||
: iterator_base(other) {}
|
||||
friend class const_iterator;
|
||||
|
||||
};
|
||||
class const_iterator : public const_iterator_base {
|
||||
public:
|
||||
using const_iterator_base::const_iterator_base;
|
||||
const_iterator(const_iterator_base other) : const_iterator_base(other) {
|
||||
}
|
||||
const_iterator(const iterator &other) : const_iterator_base(other._impl) {
|
||||
}
|
||||
|
||||
const_iterator(const_iterator_base other)
|
||||
: const_iterator_base(other) {}
|
||||
const_iterator(const iterator &other)
|
||||
: const_iterator_base(other._impl) {}
|
||||
};
|
||||
class const_reverse_iterator;
|
||||
class reverse_iterator : public reverse_iterator_base {
|
||||
public:
|
||||
using reverse_iterator_base::reverse_iterator_base;
|
||||
reverse_iterator(reverse_iterator_base other) : reverse_iterator_base(other) {
|
||||
}
|
||||
reverse_iterator(reverse_iterator_base other)
|
||||
: reverse_iterator_base(other) {}
|
||||
friend class const_reverse_iterator;
|
||||
|
||||
};
|
||||
class const_reverse_iterator : public const_reverse_iterator_base {
|
||||
public:
|
||||
using const_reverse_iterator_base::const_reverse_iterator_base;
|
||||
const_reverse_iterator(const_reverse_iterator_base other) : const_reverse_iterator_base(other) {
|
||||
}
|
||||
const_reverse_iterator(const reverse_iterator &other) : const_reverse_iterator_base(other._impl) {
|
||||
}
|
||||
|
||||
const_reverse_iterator(const_reverse_iterator_base other)
|
||||
: const_reverse_iterator_base(other) {}
|
||||
const_reverse_iterator(const reverse_iterator &other)
|
||||
: const_reverse_iterator_base(other._impl) {}
|
||||
};
|
||||
|
||||
size_type size() const {
|
||||
|
@ -280,8 +276,7 @@ public:
|
|||
auto where = getUpperBound(value.first);
|
||||
return _impl.insert(where, std::move(value));
|
||||
}
|
||||
template <typename... Args>
|
||||
iterator emplace(Args&&... args) {
|
||||
template <typename... Args> iterator emplace(Args &&... args) {
|
||||
return insert(value_type(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
|
@ -372,11 +367,9 @@ private:
|
|||
std::pair<typename impl::const_iterator, typename impl::const_iterator> getEqualRange(const Key &key) const {
|
||||
return std::equal_range(_impl.begin(), _impl.end(), key, Comparator());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <typename Key, typename Type>
|
||||
class flat_map : public flat_multi_map<Key, Type> {
|
||||
template <typename Key, typename Type> class flat_map : public flat_multi_map<Key, Type> {
|
||||
using parent = flat_multi_map<Key, Type>;
|
||||
using pair_type = typename parent::pair_type;
|
||||
|
||||
|
@ -414,8 +407,7 @@ public:
|
|||
}
|
||||
return this->end();
|
||||
}
|
||||
template <typename... Args>
|
||||
iterator emplace(Args&&... args) {
|
||||
template <typename... Args> iterator emplace(Args &&... args) {
|
||||
return this->insert(value_type(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
|
@ -432,15 +424,15 @@ public:
|
|||
|
||||
Type &operator[](const Key &key) {
|
||||
if (this->empty() || (key < this->front().first)) {
|
||||
this->_impl.push_front({ key, Type() });
|
||||
this->_impl.push_front({key, Type()});
|
||||
return this->front().second;
|
||||
} else if (this->back().first < key) {
|
||||
this->_impl.push_back({ key, Type() });
|
||||
this->_impl.push_back({key, Type()});
|
||||
return this->back().second;
|
||||
}
|
||||
auto where = this->getLowerBound(key);
|
||||
if (key < where->first) {
|
||||
return this->_impl.insert(where, { key, Type() })->second;
|
||||
return this->_impl.insert(where, {key, Type()})->second;
|
||||
}
|
||||
return where->second;
|
||||
}
|
||||
|
@ -454,7 +446,6 @@ public:
|
|||
this->erase(it);
|
||||
return std::move(result);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
|
|
|
@ -20,22 +20,18 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include <deque>
|
||||
#include <algorithm>
|
||||
#include <deque>
|
||||
|
||||
namespace base {
|
||||
|
||||
template <typename Type>
|
||||
class flat_set;
|
||||
template <typename Type> class flat_set;
|
||||
|
||||
template <typename Type>
|
||||
class flat_multi_set;
|
||||
template <typename Type> class flat_multi_set;
|
||||
|
||||
template <typename Type, typename iterator_impl>
|
||||
class flat_multi_set_iterator_base_impl;
|
||||
template <typename Type, typename iterator_impl> class flat_multi_set_iterator_base_impl;
|
||||
|
||||
template <typename Type, typename iterator_impl>
|
||||
class flat_multi_set_iterator_base_impl {
|
||||
template <typename Type, typename iterator_impl> class flat_multi_set_iterator_base_impl {
|
||||
public:
|
||||
using iterator_category = typename iterator_impl::iterator_category;
|
||||
|
||||
|
@ -44,8 +40,8 @@ public:
|
|||
using pointer = typename flat_multi_set<Type>::pointer;
|
||||
using reference = typename flat_multi_set<Type>::reference;
|
||||
|
||||
flat_multi_set_iterator_base_impl(iterator_impl impl = iterator_impl()) : _impl(impl) {
|
||||
}
|
||||
flat_multi_set_iterator_base_impl(iterator_impl impl = iterator_impl())
|
||||
: _impl(impl) {}
|
||||
|
||||
reference operator*() const {
|
||||
return *_impl;
|
||||
|
@ -101,35 +97,32 @@ public:
|
|||
private:
|
||||
iterator_impl _impl;
|
||||
friend class flat_multi_set<Type>;
|
||||
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
class flat_multi_set {
|
||||
template <typename Type> class flat_multi_set {
|
||||
using self = flat_multi_set<Type>;
|
||||
class const_wrap {
|
||||
public:
|
||||
const_wrap(const Type &value) : _value(value) {
|
||||
}
|
||||
const_wrap(Type &&value) : _value(std::move(value)) {
|
||||
}
|
||||
inline operator const Type&() const {
|
||||
const_wrap(const Type &value)
|
||||
: _value(value) {}
|
||||
const_wrap(Type &&value)
|
||||
: _value(std::move(value)) {}
|
||||
inline operator const Type &() const {
|
||||
return _value;
|
||||
}
|
||||
|
||||
friend inline bool operator<(const Type &a, const const_wrap &b) {
|
||||
return a < ((const Type&)b);
|
||||
return a < ((const Type &)b);
|
||||
}
|
||||
friend inline bool operator<(const const_wrap &a, const Type &b) {
|
||||
return ((const Type&)a) < b;
|
||||
return ((const Type &)a) < b;
|
||||
}
|
||||
friend inline bool operator<(const const_wrap &a, const const_wrap &b) {
|
||||
return ((const Type&)a) < ((const Type&)b);
|
||||
return ((const Type &)a) < ((const Type &)b);
|
||||
}
|
||||
|
||||
private:
|
||||
Type _value;
|
||||
|
||||
};
|
||||
|
||||
using impl = std::deque<const_wrap>;
|
||||
|
@ -143,50 +136,47 @@ public:
|
|||
using value_type = Type;
|
||||
using size_type = typename impl::size_type;
|
||||
using difference_type = typename impl::difference_type;
|
||||
using pointer = const Type*;
|
||||
using reference = const Type&;
|
||||
using pointer = const Type *;
|
||||
using reference = const Type &;
|
||||
|
||||
class const_iterator;
|
||||
class iterator : public iterator_base {
|
||||
public:
|
||||
using iterator_base::iterator_base;
|
||||
iterator(const iterator_base &other) : iterator_base(other) {
|
||||
}
|
||||
iterator(const iterator_base &other)
|
||||
: iterator_base(other) {}
|
||||
friend class const_iterator;
|
||||
|
||||
};
|
||||
class const_iterator : public const_iterator_base {
|
||||
public:
|
||||
using const_iterator_base::const_iterator_base;
|
||||
const_iterator(const_iterator_base other) : const_iterator_base(other) {
|
||||
}
|
||||
const_iterator(const iterator &other) : const_iterator_base(other._impl) {
|
||||
}
|
||||
|
||||
const_iterator(const_iterator_base other)
|
||||
: const_iterator_base(other) {}
|
||||
const_iterator(const iterator &other)
|
||||
: const_iterator_base(other._impl) {}
|
||||
};
|
||||
class const_reverse_iterator;
|
||||
class reverse_iterator : public reverse_iterator_base {
|
||||
public:
|
||||
using reverse_iterator_base::reverse_iterator_base;
|
||||
reverse_iterator(reverse_iterator_base other) : reverse_iterator_base(other) {
|
||||
}
|
||||
reverse_iterator(reverse_iterator_base other)
|
||||
: reverse_iterator_base(other) {}
|
||||
friend class const_reverse_iterator;
|
||||
|
||||
};
|
||||
class const_reverse_iterator : public const_reverse_iterator_base {
|
||||
public:
|
||||
using const_reverse_iterator_base::const_reverse_iterator_base;
|
||||
const_reverse_iterator(const_reverse_iterator_base other) : const_reverse_iterator_base(other) {
|
||||
}
|
||||
const_reverse_iterator(const reverse_iterator &other) : const_reverse_iterator_base(other._impl) {
|
||||
}
|
||||
|
||||
const_reverse_iterator(const_reverse_iterator_base other)
|
||||
: const_reverse_iterator_base(other) {}
|
||||
const_reverse_iterator(const reverse_iterator &other)
|
||||
: const_reverse_iterator_base(other._impl) {}
|
||||
};
|
||||
|
||||
flat_multi_set() = default;
|
||||
|
||||
template <typename Iterator, typename = typename std::iterator_traits<Iterator>::iterator_category>
|
||||
flat_multi_set(Iterator first, Iterator last) : _impl(first, last) {
|
||||
flat_multi_set(Iterator first, Iterator last)
|
||||
: _impl(first, last) {
|
||||
std::sort(_impl.begin(), _impl.end());
|
||||
}
|
||||
|
||||
|
@ -266,8 +256,7 @@ public:
|
|||
auto where = getUpperBound(value);
|
||||
return _impl.insert(where, std::move(value));
|
||||
}
|
||||
template <typename... Args>
|
||||
iterator emplace(Args&&... args) {
|
||||
template <typename... Args> iterator emplace(Args &&... args) {
|
||||
return insert(Type(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
|
@ -350,11 +339,9 @@ private:
|
|||
std::pair<typename impl::const_iterator, typename impl::const_iterator> getEqualRange(const Type &value) const {
|
||||
return std::equal_range(_impl.begin(), _impl.end(), value);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
class flat_set : public flat_multi_set<Type> {
|
||||
template <typename Type> class flat_set : public flat_multi_set<Type> {
|
||||
using parent = flat_multi_set<Type>;
|
||||
|
||||
public:
|
||||
|
@ -365,10 +352,11 @@ public:
|
|||
flat_set() = default;
|
||||
|
||||
template <typename Iterator, typename = typename std::iterator_traits<Iterator>::iterator_category>
|
||||
flat_set(Iterator first, Iterator last) : parent(first, last) {
|
||||
this->_impl.erase(std::unique(this->_impl.begin(), this->_impl.end(), [](auto &&a, auto &&b) {
|
||||
return !(a < b);
|
||||
}), this->_impl.end());
|
||||
flat_set(Iterator first, Iterator last)
|
||||
: parent(first, last) {
|
||||
this->_impl.erase(
|
||||
std::unique(this->_impl.begin(), this->_impl.end(), [](auto &&a, auto &&b) { return !(a < b); }),
|
||||
this->_impl.end());
|
||||
}
|
||||
|
||||
iterator insert(const Type &value) {
|
||||
|
@ -399,8 +387,7 @@ public:
|
|||
}
|
||||
return this->end();
|
||||
}
|
||||
template <typename... Args>
|
||||
iterator emplace(Args&&... args) {
|
||||
template <typename... Args> iterator emplace(Args &&... args) {
|
||||
return this->insert(Type(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
|
@ -414,7 +401,6 @@ public:
|
|||
const_iterator find(const Type &value) const {
|
||||
return this->findFirst(value);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
|
|
|
@ -26,17 +26,14 @@ namespace base {
|
|||
namespace functors {
|
||||
|
||||
struct abs_helper {
|
||||
template <typename Type,
|
||||
typename = decltype(0 < std::declval<Type>()),
|
||||
typename = decltype(-std::declval<Type>())>
|
||||
constexpr Type operator()(Type value) const {
|
||||
template <typename Type, typename = decltype(0 < std::declval<Type>()), typename = decltype(-std::declval<Type>())>
|
||||
constexpr Type operator()(Type value) const {
|
||||
return (0 < value) ? value : (-value);
|
||||
}
|
||||
};
|
||||
constexpr auto abs = abs_helper {};
|
||||
constexpr auto abs = abs_helper{};
|
||||
|
||||
template <typename Type>
|
||||
inline auto add(Type a) {
|
||||
template <typename Type> inline auto add(Type a) {
|
||||
return [a](auto b) { return a + b; };
|
||||
};
|
||||
|
||||
|
|
|
@ -20,8 +20,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <cstddef> // std::max_align_t
|
||||
#include <memory>
|
||||
|
||||
#ifndef Assert
|
||||
#define LambdaAssertDefined
|
||||
|
@ -42,31 +42,26 @@ template <typename Function> class lambda;
|
|||
|
||||
namespace lambda_internal {
|
||||
|
||||
template <typename FunctionType>
|
||||
struct type_resolver;
|
||||
template <typename FunctionType> struct type_resolver;
|
||||
|
||||
template <typename Lambda, typename R, typename ...Args>
|
||||
struct type_resolver<R(Lambda::*)(Args...) const> {
|
||||
template <typename Lambda, typename R, typename... Args> struct type_resolver<R (Lambda::*)(Args...) const> {
|
||||
using type = lambda<R(Args...)>;
|
||||
static constexpr auto is_mutable = false;
|
||||
};
|
||||
|
||||
template <typename Lambda, typename R, typename ...Args>
|
||||
struct type_resolver<R(Lambda::*)(Args...)> {
|
||||
template <typename Lambda, typename R, typename... Args> struct type_resolver<R (Lambda::*)(Args...)> {
|
||||
using type = lambda_once<R(Args...)>;
|
||||
static constexpr auto is_mutable = true;
|
||||
};
|
||||
|
||||
template <typename Lambda>
|
||||
struct type_helper {
|
||||
template <typename Lambda> struct type_helper {
|
||||
using type = typename type_resolver<decltype(&Lambda::operator())>::type;
|
||||
static constexpr auto is_mutable = type_resolver<decltype(&Lambda::operator())>::is_mutable;
|
||||
};
|
||||
|
||||
} // namespace lambda_internal
|
||||
|
||||
template <typename Lambda>
|
||||
using lambda_type = typename lambda_internal::type_helper<std::decay_t<Lambda>>::type;
|
||||
template <typename Lambda> using lambda_type = typename lambda_internal::type_helper<std::decay_t<Lambda>>::type;
|
||||
|
||||
template <typename Lambda>
|
||||
constexpr bool lambda_is_mutable = lambda_internal::type_helper<std::decay_t<Lambda>>::is_mutable;
|
||||
|
@ -74,205 +69,165 @@ constexpr bool lambda_is_mutable = lambda_internal::type_helper<std::decay_t<Lam
|
|||
namespace lambda_internal {
|
||||
|
||||
constexpr auto kFullStorageSize = 32U;
|
||||
static_assert(kFullStorageSize % sizeof(void*) == 0, "Invalid pointer size!");
|
||||
static_assert(kFullStorageSize % sizeof(void *) == 0, "Invalid pointer size!");
|
||||
|
||||
constexpr auto kStorageSize = kFullStorageSize - sizeof(void*);
|
||||
constexpr auto kStorageSize = kFullStorageSize - sizeof(void *);
|
||||
using alignment = std::max_align_t;
|
||||
|
||||
template <typename Lambda>
|
||||
constexpr bool is_large = (sizeof(std::decay_t<Lambda>) > kStorageSize);
|
||||
template <typename Lambda> constexpr bool is_large = (sizeof(std::decay_t<Lambda>) > kStorageSize);
|
||||
|
||||
[[noreturn]] inline void bad_construct_copy(void *lambda, const void *source) {
|
||||
Unexpected("base::lambda bad_construct_copy() called!");
|
||||
}
|
||||
|
||||
template <typename Return, typename ...Args>
|
||||
[[noreturn]] Return bad_const_call(const void *lambda, Args...) {
|
||||
Unexpected("base::lambda bad_const_call() called!");
|
||||
}
|
||||
template <typename Return, typename... Args>
|
||||
[[noreturn]] Return bad_const_call(const void *lambda, Args...) { Unexpected("base::lambda bad_const_call() called!"); }
|
||||
|
||||
template <typename Return, typename ...Args>
|
||||
template <typename Return, typename... Args>
|
||||
struct vtable_base {
|
||||
using construct_copy_other_type = void(*)(void *, const void *); // dst, src
|
||||
using construct_move_other_type = void(*)(void *, void *); // dst, src
|
||||
using const_call_type = Return(*)(const void *, Args...);
|
||||
using call_type = Return(*)(void *, Args...);
|
||||
using destruct_type = void(*)(const void *);
|
||||
using construct_copy_other_type = void (*)(void *, const void *); // dst, src
|
||||
using construct_move_other_type = void (*)(void *, void *); // dst, src
|
||||
using const_call_type = Return (*)(const void *, Args...);
|
||||
using call_type = Return (*)(void *, Args...);
|
||||
using destruct_type = void (*)(const void *);
|
||||
|
||||
vtable_base() = delete;
|
||||
vtable_base(const vtable_base &other) = delete;
|
||||
vtable_base &operator=(const vtable_base &other) = delete;
|
||||
|
||||
vtable_base(
|
||||
construct_copy_other_type construct_copy_other,
|
||||
construct_move_other_type construct_move_other,
|
||||
const_call_type const_call,
|
||||
call_type call,
|
||||
destruct_type destruct)
|
||||
: construct_copy_other(construct_copy_other)
|
||||
, construct_move_other(construct_move_other)
|
||||
, const_call(const_call)
|
||||
, call(call)
|
||||
, destruct(destruct) {
|
||||
}
|
||||
vtable_base(construct_copy_other_type construct_copy_other, construct_move_other_type construct_move_other,
|
||||
const_call_type const_call, call_type call, destruct_type destruct)
|
||||
: construct_copy_other(construct_copy_other)
|
||||
, construct_move_other(construct_move_other)
|
||||
, const_call(const_call)
|
||||
, call(call)
|
||||
, destruct(destruct) {}
|
||||
|
||||
const construct_copy_other_type construct_copy_other;
|
||||
const construct_move_other_type construct_move_other;
|
||||
const const_call_type const_call;
|
||||
const call_type call;
|
||||
const destruct_type destruct;
|
||||
|
||||
};
|
||||
|
||||
template <typename Lambda, bool IsLarge, typename Return, typename ...Args> struct vtable_once_impl;
|
||||
template <typename Lambda, bool IsLarge, typename Return, typename... Args> struct vtable_once_impl;
|
||||
|
||||
template <typename Lambda, typename Return, typename ...Args>
|
||||
template <typename Lambda, typename Return, typename... Args>
|
||||
struct vtable_once_impl<Lambda, true, Return, Args...> : public vtable_base<Return, Args...> {
|
||||
using JustLambda = std::decay_t<Lambda>;
|
||||
using LambdaPtr = std::unique_ptr<JustLambda>;
|
||||
using Parent = vtable_base<Return, Args...>;
|
||||
static void construct_move_other_method(void *storage, void *source) {
|
||||
auto source_lambda_ptr = static_cast<LambdaPtr*>(source);
|
||||
auto source_lambda_ptr = static_cast<LambdaPtr *>(source);
|
||||
new (storage) LambdaPtr(std::move(*source_lambda_ptr));
|
||||
}
|
||||
static Return call_method(void *storage, Args... args) {
|
||||
return (**static_cast<LambdaPtr*>(storage))(std::forward<Args>(args)...);
|
||||
return (**static_cast<LambdaPtr *>(storage))(std::forward<Args>(args)...);
|
||||
}
|
||||
static void destruct_method(const void *storage) {
|
||||
static_cast<const LambdaPtr*>(storage)->~LambdaPtr();
|
||||
}
|
||||
vtable_once_impl() : Parent(
|
||||
&bad_construct_copy,
|
||||
&vtable_once_impl::construct_move_other_method,
|
||||
&bad_const_call<Return, Args...>,
|
||||
&vtable_once_impl::call_method,
|
||||
&vtable_once_impl::destruct_method) {
|
||||
static_cast<const LambdaPtr *>(storage)->~LambdaPtr();
|
||||
}
|
||||
vtable_once_impl()
|
||||
: Parent(&bad_construct_copy, &vtable_once_impl::construct_move_other_method, &bad_const_call<Return, Args...>,
|
||||
&vtable_once_impl::call_method, &vtable_once_impl::destruct_method) {}
|
||||
|
||||
// Used directly.
|
||||
static void construct_move_lambda_method(void *storage, void *source) {
|
||||
auto source_lambda = static_cast<JustLambda*>(source);
|
||||
new (storage) LambdaPtr(std::make_unique<JustLambda>(static_cast<JustLambda&&>(*source_lambda)));
|
||||
auto source_lambda = static_cast<JustLambda *>(source);
|
||||
new (storage) LambdaPtr(std::make_unique<JustLambda>(static_cast<JustLambda &&>(*source_lambda)));
|
||||
}
|
||||
|
||||
protected:
|
||||
vtable_once_impl(
|
||||
typename Parent::construct_copy_other_type construct_copy_other,
|
||||
typename Parent::const_call_type const_call
|
||||
) : Parent(
|
||||
construct_copy_other,
|
||||
&vtable_once_impl::construct_move_other_method,
|
||||
const_call,
|
||||
&vtable_once_impl::call_method,
|
||||
&vtable_once_impl::destruct_method) {
|
||||
}
|
||||
|
||||
vtable_once_impl(typename Parent::construct_copy_other_type construct_copy_other,
|
||||
typename Parent::const_call_type const_call)
|
||||
: Parent(construct_copy_other, &vtable_once_impl::construct_move_other_method, const_call,
|
||||
&vtable_once_impl::call_method, &vtable_once_impl::destruct_method) {}
|
||||
};
|
||||
|
||||
template <typename Lambda, typename Return, typename ...Args>
|
||||
template <typename Lambda, typename Return, typename... Args>
|
||||
struct vtable_once_impl<Lambda, false, Return, Args...> : public vtable_base<Return, Args...> {
|
||||
using JustLambda = std::decay_t<Lambda>;
|
||||
using Parent = vtable_base<Return, Args...>;
|
||||
static void construct_move_other_method(void *storage, void *source) {
|
||||
auto source_lambda = static_cast<JustLambda*>(source);
|
||||
new (storage) JustLambda(static_cast<JustLambda&&>(*source_lambda));
|
||||
auto source_lambda = static_cast<JustLambda *>(source);
|
||||
new (storage) JustLambda(static_cast<JustLambda &&>(*source_lambda));
|
||||
}
|
||||
static Return call_method(void *storage, Args... args) {
|
||||
return (*static_cast<JustLambda*>(storage))(std::forward<Args>(args)...);
|
||||
return (*static_cast<JustLambda *>(storage))(std::forward<Args>(args)...);
|
||||
}
|
||||
static void destruct_method(const void *storage) {
|
||||
static_cast<const JustLambda*>(storage)->~JustLambda();
|
||||
}
|
||||
vtable_once_impl() : Parent(
|
||||
&bad_construct_copy,
|
||||
&vtable_once_impl::construct_move_other_method,
|
||||
&bad_const_call<Return, Args...>,
|
||||
&vtable_once_impl::call_method,
|
||||
&vtable_once_impl::destruct_method) {
|
||||
static_cast<const JustLambda *>(storage)->~JustLambda();
|
||||
}
|
||||
vtable_once_impl()
|
||||
: Parent(&bad_construct_copy, &vtable_once_impl::construct_move_other_method, &bad_const_call<Return, Args...>,
|
||||
&vtable_once_impl::call_method, &vtable_once_impl::destruct_method) {}
|
||||
|
||||
// Used directly.
|
||||
static void construct_move_lambda_method(void *storage, void *source) {
|
||||
auto source_lambda = static_cast<JustLambda*>(source);
|
||||
new (storage) JustLambda(static_cast<JustLambda&&>(*source_lambda));
|
||||
auto source_lambda = static_cast<JustLambda *>(source);
|
||||
new (storage) JustLambda(static_cast<JustLambda &&>(*source_lambda));
|
||||
}
|
||||
|
||||
protected:
|
||||
vtable_once_impl(
|
||||
typename Parent::construct_copy_other_type construct_copy_other,
|
||||
typename Parent::const_call_type const_call
|
||||
) : Parent(
|
||||
construct_copy_other,
|
||||
&vtable_once_impl::construct_move_other_method,
|
||||
const_call,
|
||||
&vtable_once_impl::call_method,
|
||||
&vtable_once_impl::destruct_method) {
|
||||
}
|
||||
|
||||
vtable_once_impl(typename Parent::construct_copy_other_type construct_copy_other,
|
||||
typename Parent::const_call_type const_call)
|
||||
: Parent(construct_copy_other, &vtable_once_impl::construct_move_other_method, const_call,
|
||||
&vtable_once_impl::call_method, &vtable_once_impl::destruct_method) {}
|
||||
};
|
||||
|
||||
template <typename Lambda, typename Return, typename ...Args>
|
||||
template <typename Lambda, typename Return, typename... Args>
|
||||
struct vtable_once : public vtable_once_impl<Lambda, is_large<Lambda>, Return, Args...> {
|
||||
static const vtable_once instance;
|
||||
};
|
||||
|
||||
template <typename Lambda, typename Return, typename ...Args>
|
||||
template <typename Lambda, typename Return, typename... Args>
|
||||
const vtable_once<Lambda, Return, Args...> vtable_once<Lambda, Return, Args...>::instance = {};
|
||||
|
||||
template <typename Lambda, bool IsLarge, typename Return, typename ...Args> struct vtable_impl;
|
||||
template <typename Lambda, bool IsLarge, typename Return, typename... Args> struct vtable_impl;
|
||||
|
||||
template <typename Lambda, typename Return, typename ...Args>
|
||||
template <typename Lambda, typename Return, typename... Args>
|
||||
struct vtable_impl<Lambda, true, Return, Args...> : public vtable_once_impl<Lambda, true, Return, Args...> {
|
||||
using JustLambda = std::decay_t<Lambda>;
|
||||
using LambdaPtr = std::unique_ptr<JustLambda>;
|
||||
using Parent = vtable_once_impl<Lambda, true, Return, Args...>;
|
||||
static void construct_copy_other_method(void *storage, const void *source) {
|
||||
auto source_lambda = static_cast<const LambdaPtr*>(source);
|
||||
auto source_lambda = static_cast<const LambdaPtr *>(source);
|
||||
new (storage) LambdaPtr(std::make_unique<JustLambda>(*source_lambda->get()));
|
||||
}
|
||||
static Return const_call_method(const void *storage, Args... args) {
|
||||
auto lambda_ptr = static_cast<const LambdaPtr*>(storage)->get();
|
||||
return (*static_cast<const JustLambda*>(lambda_ptr))(std::forward<Args>(args)...);
|
||||
auto lambda_ptr = static_cast<const LambdaPtr *>(storage)->get();
|
||||
return (*static_cast<const JustLambda *>(lambda_ptr))(std::forward<Args>(args)...);
|
||||
}
|
||||
vtable_impl() : Parent(
|
||||
&vtable_impl::construct_copy_other_method,
|
||||
&vtable_impl::const_call_method
|
||||
) {
|
||||
}
|
||||
|
||||
vtable_impl()
|
||||
: Parent(&vtable_impl::construct_copy_other_method, &vtable_impl::const_call_method) {}
|
||||
};
|
||||
|
||||
template <typename Lambda, typename Return, typename ...Args>
|
||||
template <typename Lambda, typename Return, typename... Args>
|
||||
struct vtable_impl<Lambda, false, Return, Args...> : public vtable_once_impl<Lambda, false, Return, Args...> {
|
||||
using JustLambda = std::decay_t<Lambda>;
|
||||
using Parent = vtable_once_impl<Lambda, false, Return, Args...>;
|
||||
static void construct_copy_other_method(void *storage, const void *source) {
|
||||
auto source_lambda = static_cast<const JustLambda*>(source);
|
||||
auto source_lambda = static_cast<const JustLambda *>(source);
|
||||
new (storage) JustLambda(static_cast<const JustLambda &>(*source_lambda));
|
||||
}
|
||||
static Return const_call_method(const void *storage, Args... args) {
|
||||
return (*static_cast<const JustLambda*>(storage))(std::forward<Args>(args)...);
|
||||
return (*static_cast<const JustLambda *>(storage))(std::forward<Args>(args)...);
|
||||
}
|
||||
vtable_impl() : Parent(
|
||||
&vtable_impl::construct_copy_other_method,
|
||||
&vtable_impl::const_call_method
|
||||
) {
|
||||
}
|
||||
|
||||
vtable_impl()
|
||||
: Parent(&vtable_impl::construct_copy_other_method, &vtable_impl::const_call_method) {}
|
||||
};
|
||||
|
||||
template <typename Lambda, typename Return, typename ...Args>
|
||||
template <typename Lambda, typename Return, typename... Args>
|
||||
struct vtable : public vtable_impl<Lambda, is_large<Lambda>, Return, Args...> {
|
||||
static const vtable instance;
|
||||
};
|
||||
|
||||
template <typename Lambda, typename Return, typename ...Args>
|
||||
template <typename Lambda, typename Return, typename... Args>
|
||||
const vtable<Lambda, Return, Args...> vtable<Lambda, Return, Args...>::instance = {};
|
||||
|
||||
} // namespace lambda_internal
|
||||
|
||||
template <typename Return, typename ...Args>
|
||||
class lambda_once<Return(Args...)> {
|
||||
template <typename Return, typename... Args> class lambda_once<Return(Args...)> {
|
||||
using VTable = lambda_internal::vtable_base<Return, Args...>;
|
||||
|
||||
public:
|
||||
|
@ -345,12 +300,14 @@ public:
|
|||
}
|
||||
|
||||
// Copy / move construct / assign from an arbitrary type.
|
||||
template <typename Lambda, typename = std::enable_if_t<std::is_convertible<decltype(std::declval<Lambda>()(std::declval<Args>()...)),Return>::value>>
|
||||
template <typename Lambda, typename = std::enable_if_t<std::is_convertible<
|
||||
decltype(std::declval<Lambda>()(std::declval<Args>()...)), Return>::value>>
|
||||
lambda_once(Lambda other) {
|
||||
data_.vtable = &lambda_internal::vtable_once<Lambda, Return, Args...>::instance;
|
||||
lambda_internal::vtable_once<Lambda, Return, Args...>::construct_move_lambda_method(data_.storage, &other);
|
||||
}
|
||||
template <typename Lambda, typename = std::enable_if_t<std::is_convertible<decltype(std::declval<Lambda>()(std::declval<Args>()...)),Return>::value>>
|
||||
template <typename Lambda, typename = std::enable_if_t<std::is_convertible<
|
||||
decltype(std::declval<Lambda>()(std::declval<Args>()...)), Return>::value>>
|
||||
lambda_once &operator=(Lambda other) {
|
||||
if (data_.vtable) {
|
||||
data_.vtable->destruct(data_.storage);
|
||||
|
@ -382,8 +339,7 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
struct Private {
|
||||
};
|
||||
struct Private {};
|
||||
lambda_once(const VTable *vtable, const Private &) {
|
||||
data_.vtable = vtable;
|
||||
}
|
||||
|
@ -397,38 +353,39 @@ protected:
|
|||
char raw_[lambda_internal::kFullStorageSize];
|
||||
Data data_;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
template <typename Return, typename ...Args>
|
||||
class lambda<Return(Args...)> final : public lambda_once<Return(Args...)> {
|
||||
template <typename Return, typename... Args> class lambda<Return(Args...)> final : public lambda_once<Return(Args...)> {
|
||||
using Parent = lambda_once<Return(Args...)>;
|
||||
|
||||
public:
|
||||
lambda() = default;
|
||||
|
||||
// Move construct / assign from the same type.
|
||||
lambda(lambda<Return(Args...)> &&other) : Parent(std::move(other)) {
|
||||
}
|
||||
lambda(lambda<Return(Args...)> &&other)
|
||||
: Parent(std::move(other)) {}
|
||||
lambda &operator=(lambda<Return(Args...)> &&other) {
|
||||
Parent::operator=(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Copy construct / assign from the same type.
|
||||
lambda(const lambda<Return(Args...)> &other) : Parent(other) {
|
||||
}
|
||||
lambda(const lambda<Return(Args...)> &other)
|
||||
: Parent(other) {}
|
||||
lambda &operator=(const lambda<Return(Args...)> &other) {
|
||||
Parent::operator=(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Copy / move construct / assign from an arbitrary type.
|
||||
template <typename Lambda, typename = std::enable_if_t<std::is_convertible<decltype(std::declval<Lambda>()(std::declval<Args>()...)),Return>::value>>
|
||||
lambda(Lambda other) : Parent(&lambda_internal::vtable<Lambda, Return, Args...>::instance, typename Parent::Private()) {
|
||||
template <typename Lambda, typename = std::enable_if_t<std::is_convertible<
|
||||
decltype(std::declval<Lambda>()(std::declval<Args>()...)), Return>::value>>
|
||||
lambda(Lambda other)
|
||||
: Parent(&lambda_internal::vtable<Lambda, Return, Args...>::instance, typename Parent::Private()) {
|
||||
lambda_internal::vtable<Lambda, Return, Args...>::construct_move_lambda_method(this->data_.storage, &other);
|
||||
}
|
||||
template <typename Lambda, typename = std::enable_if_t<std::is_convertible<decltype(std::declval<Lambda>()(std::declval<Args>()...)),Return>::value>>
|
||||
template <typename Lambda, typename = std::enable_if_t<std::is_convertible<
|
||||
decltype(std::declval<Lambda>()(std::declval<Args>()...)), Return>::value>>
|
||||
lambda &operator=(Lambda other) {
|
||||
if (this->data_.vtable) {
|
||||
this->data_.vtable->destruct(this->data_.storage);
|
||||
|
@ -448,7 +405,6 @@ public:
|
|||
std::swap(*this, other);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
|
|
|
@ -20,8 +20,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QPointer>
|
||||
#include "base/lambda.h"
|
||||
#include <QPointer>
|
||||
|
||||
namespace base {
|
||||
|
||||
|
@ -29,23 +29,22 @@ namespace base {
|
|||
|
||||
namespace lambda_internal {
|
||||
|
||||
template <int N, typename Lambda>
|
||||
class guard_data {
|
||||
template <int N, typename Lambda> class guard_data {
|
||||
public:
|
||||
using return_type = typename lambda_type<Lambda>::return_type;
|
||||
|
||||
template <typename ...PointersAndLambda>
|
||||
inline guard_data(PointersAndLambda&&... qobjectsAndLambda) : _lambda(init(_pointers, std::forward<PointersAndLambda>(qobjectsAndLambda)...)) {
|
||||
}
|
||||
template <typename... PointersAndLambda>
|
||||
inline guard_data(PointersAndLambda &&... qobjectsAndLambda)
|
||||
: _lambda(init(_pointers, std::forward<PointersAndLambda>(qobjectsAndLambda)...)) {}
|
||||
|
||||
inline guard_data(const guard_data &other) : _lambda(other._lambda) {
|
||||
inline guard_data(const guard_data &other)
|
||||
: _lambda(other._lambda) {
|
||||
for (auto i = 0; i != N; ++i) {
|
||||
_pointers[i] = other._pointers[i];
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ...Args>
|
||||
inline return_type operator()(Args&&... args) {
|
||||
template <typename... Args> inline return_type operator()(Args &&... args) {
|
||||
for (int i = 0; i != N; ++i) {
|
||||
if (!_pointers[i]) {
|
||||
return return_type();
|
||||
|
@ -54,8 +53,7 @@ public:
|
|||
return _lambda(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename ...Args>
|
||||
inline return_type operator()(Args&&... args) const {
|
||||
template <typename... Args> inline return_type operator()(Args &&... args) const {
|
||||
for (int i = 0; i != N; ++i) {
|
||||
if (!_pointers[i]) {
|
||||
return return_type();
|
||||
|
@ -65,8 +63,8 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
template <typename ...PointersAndLambda>
|
||||
Lambda init(QPointer<QObject> *pointers, QObject *qobject, PointersAndLambda&&... qobjectsAndLambda) {
|
||||
template <typename... PointersAndLambda>
|
||||
Lambda init(QPointer<QObject> *pointers, QObject *qobject, PointersAndLambda &&... qobjectsAndLambda) {
|
||||
*pointers = qobject;
|
||||
return init(++pointers, std::forward<PointersAndLambda>(qobjectsAndLambda)...);
|
||||
}
|
||||
|
@ -76,24 +74,24 @@ private:
|
|||
|
||||
QPointer<QObject> _pointers[N];
|
||||
Lambda _lambda;
|
||||
|
||||
};
|
||||
|
||||
template <int N, typename Lambda>
|
||||
class guard {
|
||||
template <int N, typename Lambda> class guard {
|
||||
public:
|
||||
using return_type = typename lambda_type<Lambda>::return_type;
|
||||
|
||||
template <typename Pointer, typename Other, typename ...PointersAndLambda>
|
||||
inline guard(Pointer &&qobject, Other &&other, PointersAndLambda&&... qobjectsAndLambda) : _data(std::make_unique<guard_data<N, Lambda>>(std::forward<Pointer>(qobject), std::forward<Other>(other), std::forward<PointersAndLambda>(qobjectsAndLambda)...)) {
|
||||
template <typename Pointer, typename Other, typename... PointersAndLambda>
|
||||
inline guard(Pointer &&qobject, Other &&other, PointersAndLambda &&... qobjectsAndLambda)
|
||||
: _data(std::make_unique<guard_data<N, Lambda>>(std::forward<Pointer>(qobject), std::forward<Other>(other),
|
||||
std::forward<PointersAndLambda>(qobjectsAndLambda)...)) {
|
||||
static_assert(1 + 1 + sizeof...(PointersAndLambda) == N + 1, "Wrong argument count!");
|
||||
}
|
||||
|
||||
inline guard(const guard &other) : _data(std::make_unique<guard_data<N, Lambda>>(static_cast<const guard_data<N, Lambda> &>(*other._data))) {
|
||||
}
|
||||
inline guard(const guard &other)
|
||||
: _data(std::make_unique<guard_data<N, Lambda>>(static_cast<const guard_data<N, Lambda> &>(*other._data))) {}
|
||||
|
||||
inline guard(guard &&other) : _data(std::move(other._data)) {
|
||||
}
|
||||
inline guard(guard &&other)
|
||||
: _data(std::move(other._data)) {}
|
||||
|
||||
inline guard &operator=(const guard &&other) {
|
||||
_data = std::move(other._data);
|
||||
|
@ -105,13 +103,11 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
template <typename ...Args>
|
||||
inline return_type operator()(Args&&... args) {
|
||||
template <typename... Args> inline return_type operator()(Args &&... args) {
|
||||
return (*_data)(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename ...Args>
|
||||
inline return_type operator()(Args&&... args) const {
|
||||
template <typename... Args> inline return_type operator()(Args &&... args) const {
|
||||
return (*_data)(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
|
@ -121,41 +117,33 @@ public:
|
|||
|
||||
private:
|
||||
mutable std::unique_ptr<guard_data<N, Lambda>> _data;
|
||||
|
||||
};
|
||||
|
||||
template <int N, int K, typename ...PointersAndLambda>
|
||||
struct guard_type;
|
||||
template <int N, int K, typename... PointersAndLambda> struct guard_type;
|
||||
|
||||
template <int N, int K, typename Pointer, typename ...PointersAndLambda>
|
||||
template <int N, int K, typename Pointer, typename... PointersAndLambda>
|
||||
struct guard_type<N, K, Pointer, PointersAndLambda...> {
|
||||
using type = typename guard_type<N, K - 1, PointersAndLambda...>::type;
|
||||
};
|
||||
|
||||
template <int N, typename Lambda>
|
||||
struct guard_type<N, 0, Lambda> {
|
||||
using type = guard<N, Lambda>;
|
||||
};
|
||||
template <int N, typename Lambda> struct guard_type<N, 0, Lambda> { using type = guard<N, Lambda>; };
|
||||
|
||||
template <typename ...PointersAndLambda>
|
||||
struct guard_type_helper {
|
||||
template <typename... PointersAndLambda> struct guard_type_helper {
|
||||
static constexpr int N = sizeof...(PointersAndLambda);
|
||||
using type = typename guard_type<N - 1, N - 1, PointersAndLambda...>::type;
|
||||
};
|
||||
|
||||
template <typename ...PointersAndLambda>
|
||||
using guard_t = typename guard_type_helper<PointersAndLambda...>::type;
|
||||
template <typename... PointersAndLambda> using guard_t = typename guard_type_helper<PointersAndLambda...>::type;
|
||||
|
||||
template <int N, typename Lambda>
|
||||
struct type_helper<guard<N, Lambda>> {
|
||||
template <int N, typename Lambda> struct type_helper<guard<N, Lambda>> {
|
||||
using type = typename type_helper<Lambda>::type;
|
||||
static constexpr auto is_mutable = type_helper<Lambda>::is_mutable;
|
||||
};
|
||||
|
||||
} // namespace lambda_internal
|
||||
|
||||
template <typename ...PointersAndLambda>
|
||||
inline lambda_internal::guard_t<PointersAndLambda...> lambda_guarded(PointersAndLambda&&... qobjectsAndLambda) {
|
||||
template <typename... PointersAndLambda>
|
||||
inline lambda_internal::guard_t<PointersAndLambda...> lambda_guarded(PointersAndLambda &&... qobjectsAndLambda) {
|
||||
static_assert(sizeof...(PointersAndLambda) > 0, "Lambda should be passed here.");
|
||||
return lambda_internal::guard_t<PointersAndLambda...>(std::forward<PointersAndLambda>(qobjectsAndLambda)...);
|
||||
}
|
||||
|
|
|
@ -20,27 +20,25 @@ Copyright (c) 2018 pro.cxx Community
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "core/utils.h" // @todo used for base::take
|
||||
#include <QObject>
|
||||
#include <QPointer>
|
||||
#include "core/utils.h" // @todo used for base::take
|
||||
|
||||
// Smart pointer for QObject*, has move semantics, destroys object if it doesn't have a parent.
|
||||
template <typename Object>
|
||||
class object_ptr {
|
||||
template <typename Object> class object_ptr {
|
||||
public:
|
||||
object_ptr(std::nullptr_t) {
|
||||
}
|
||||
object_ptr(std::nullptr_t) {}
|
||||
|
||||
// No default constructor, but constructors with at least
|
||||
// one argument are simply make functions.
|
||||
template <typename Parent, typename... Args>
|
||||
explicit object_ptr(Parent &&parent, Args&&... args) : _object(new Object(std::forward<Parent>(parent), std::forward<Args>(args)...)) {
|
||||
}
|
||||
explicit object_ptr(Parent &&parent, Args &&... args)
|
||||
: _object(new Object(std::forward<Parent>(parent), std::forward<Args>(args)...)) {}
|
||||
|
||||
object_ptr(const object_ptr &other) = delete;
|
||||
object_ptr &operator=(const object_ptr &other) = delete;
|
||||
object_ptr(object_ptr &&other) : _object(base::take(other._object)) {
|
||||
}
|
||||
object_ptr(object_ptr &&other)
|
||||
: _object(base::take(other._object)) {}
|
||||
object_ptr &operator=(object_ptr &&other) {
|
||||
auto temp = std::move(other);
|
||||
destroy();
|
||||
|
@ -49,8 +47,8 @@ public:
|
|||
}
|
||||
|
||||
template <typename OtherObject, typename = std::enable_if_t<std::is_base_of<Object, OtherObject>::value>>
|
||||
object_ptr(object_ptr<OtherObject> &&other) : _object(base::take(other._object)) {
|
||||
}
|
||||
object_ptr(object_ptr<OtherObject> &&other)
|
||||
: _object(base::take(other._object)) {}
|
||||
|
||||
template <typename OtherObject, typename = std::enable_if_t<std::is_base_of<Object, OtherObject>::value>>
|
||||
object_ptr &operator=(object_ptr<OtherObject> &&other) {
|
||||
|
@ -65,9 +63,9 @@ public:
|
|||
|
||||
// So we can pass this pointer to methods like connect().
|
||||
Object *data() const {
|
||||
return static_cast<Object*>(_object.data());
|
||||
return static_cast<Object *>(_object.data());
|
||||
}
|
||||
operator Object*() const {
|
||||
operator Object *() const {
|
||||
return data();
|
||||
}
|
||||
|
||||
|
@ -83,8 +81,7 @@ public:
|
|||
}
|
||||
|
||||
// Use that instead "= new Object(parent, ...)"
|
||||
template <typename Parent, typename... Args>
|
||||
void create(Parent &&parent, Args&&... args) {
|
||||
template <typename Parent, typename... Args> void create(Parent &&parent, Args &&... args) {
|
||||
destroy();
|
||||
_object = new Object(std::forward<Parent>(parent), std::forward<Args>(args)...);
|
||||
}
|
||||
|
@ -93,7 +90,7 @@ public:
|
|||
}
|
||||
void destroyDelayed() {
|
||||
if (_object) {
|
||||
if (auto widget = base::up_cast<QWidget*>(data())) {
|
||||
if (auto widget = base::up_cast<QWidget *>(data())) {
|
||||
widget->hide();
|
||||
}
|
||||
base::take(_object)->deleteLater();
|
||||
|
@ -112,16 +109,14 @@ public:
|
|||
friend object_ptr<ResultType> static_object_cast(object_ptr<SourceType> source);
|
||||
|
||||
private:
|
||||
template <typename OtherObject>
|
||||
friend class object_ptr;
|
||||
template <typename OtherObject> friend class object_ptr;
|
||||
|
||||
QPointer<QObject> _object;
|
||||
|
||||
};
|
||||
|
||||
template <typename ResultType, typename SourceType>
|
||||
inline object_ptr<ResultType> static_object_cast(object_ptr<SourceType> source) {
|
||||
auto result = object_ptr<ResultType>(nullptr);
|
||||
result._object = static_cast<ResultType*>(base::take(source._object).data());
|
||||
result._object = static_cast<ResultType *>(base::take(source._object).data());
|
||||
return std::move(result);
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ struct ObservableListWrap {
|
|||
~ObservableListWrap() {
|
||||
CantUseObservables = true;
|
||||
}
|
||||
OrderedSet<ObservableCallHandlers*> list;
|
||||
OrderedSet<ObservableCallHandlers *> list;
|
||||
};
|
||||
|
||||
ObservableListWrap &PendingObservables() {
|
||||
|
|
|
@ -20,13 +20,13 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <QSharedPointer>
|
||||
#include "base/assertion.h"
|
||||
#include "base/lambda.h"
|
||||
#include "base/type_traits.h"
|
||||
#include "core/utils.h"
|
||||
#include <QSharedPointer>
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
|
||||
namespace base {
|
||||
namespace internal {
|
||||
|
@ -36,28 +36,20 @@ void RegisterPendingObservable(ObservableCallHandlers *handlers);
|
|||
void UnregisterActiveObservable(ObservableCallHandlers *handlers);
|
||||
void UnregisterObservable(ObservableCallHandlers *handlers);
|
||||
|
||||
template <typename EventType>
|
||||
struct SubscriptionHandlerHelper {
|
||||
template <typename EventType> struct SubscriptionHandlerHelper {
|
||||
using type = base::lambda<void(parameter_type<EventType>)>;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct SubscriptionHandlerHelper<void> {
|
||||
using type = base::lambda<void()>;
|
||||
};
|
||||
template <> struct SubscriptionHandlerHelper<void> { using type = base::lambda<void()>; };
|
||||
|
||||
template <typename EventType>
|
||||
using SubscriptionHandler = typename SubscriptionHandlerHelper<EventType>::type;
|
||||
template <typename EventType> using SubscriptionHandler = typename SubscriptionHandlerHelper<EventType>::type;
|
||||
|
||||
// Required because QShared/WeakPointer can't point to void.
|
||||
class BaseObservableData {
|
||||
};
|
||||
class BaseObservableData {};
|
||||
|
||||
template <typename EventType, typename Handler>
|
||||
class CommonObservableData;
|
||||
template <typename EventType, typename Handler> class CommonObservableData;
|
||||
|
||||
template <typename EventType, typename Handler>
|
||||
class ObservableData;
|
||||
template <typename EventType, typename Handler> class ObservableData;
|
||||
|
||||
} // namespace internal
|
||||
|
||||
|
@ -66,8 +58,9 @@ public:
|
|||
Subscription() = default;
|
||||
Subscription(const Subscription &) = delete;
|
||||
Subscription &operator=(const Subscription &) = delete;
|
||||
Subscription(Subscription &&other) : _node(base::take(other._node)), _removeAndDestroyMethod(other._removeAndDestroyMethod) {
|
||||
}
|
||||
Subscription(Subscription &&other)
|
||||
: _node(base::take(other._node))
|
||||
, _removeAndDestroyMethod(other._removeAndDestroyMethod) {}
|
||||
Subscription &operator=(Subscription &&other) {
|
||||
qSwap(_node, other._node);
|
||||
qSwap(_removeAndDestroyMethod, other._removeAndDestroyMethod);
|
||||
|
@ -87,34 +80,30 @@ public:
|
|||
|
||||
private:
|
||||
struct Node {
|
||||
Node(const QSharedPointer<internal::BaseObservableData> &observable) : observable(observable) {
|
||||
}
|
||||
Node(const QSharedPointer<internal::BaseObservableData> &observable)
|
||||
: observable(observable) {}
|
||||
Node *next = nullptr;
|
||||
Node *prev = nullptr;
|
||||
QWeakPointer<internal::BaseObservableData> observable;
|
||||
};
|
||||
using RemoveAndDestroyMethod = void(*)(Node*);
|
||||
Subscription(Node *node, RemoveAndDestroyMethod removeAndDestroyMethod) : _node(node), _removeAndDestroyMethod(removeAndDestroyMethod) {
|
||||
}
|
||||
using RemoveAndDestroyMethod = void (*)(Node *);
|
||||
Subscription(Node *node, RemoveAndDestroyMethod removeAndDestroyMethod)
|
||||
: _node(node)
|
||||
, _removeAndDestroyMethod(removeAndDestroyMethod) {}
|
||||
|
||||
Node *_node = nullptr;
|
||||
RemoveAndDestroyMethod _removeAndDestroyMethod;
|
||||
|
||||
template <typename EventType, typename Handler>
|
||||
friend class internal::CommonObservableData;
|
||||
|
||||
template <typename EventType, typename Handler>
|
||||
friend class internal::ObservableData;
|
||||
template <typename EventType, typename Handler> friend class internal::CommonObservableData;
|
||||
|
||||
template <typename EventType, typename Handler> friend class internal::ObservableData;
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <typename EventType, typename Handler, bool EventTypeIsSimple>
|
||||
class BaseObservable;
|
||||
template <typename EventType, typename Handler, bool EventTypeIsSimple> class BaseObservable;
|
||||
|
||||
template <typename EventType, typename Handler>
|
||||
class CommonObservable {
|
||||
template <typename EventType, typename Handler> class CommonObservable {
|
||||
public:
|
||||
Subscription add_subscription(Handler &&handler) {
|
||||
if (!_data) {
|
||||
|
@ -128,7 +117,6 @@ private:
|
|||
|
||||
friend class CommonObservableData<EventType, Handler>;
|
||||
friend class BaseObservable<EventType, Handler, base::type_traits<EventType>::is_fast_copy_type::value>;
|
||||
|
||||
};
|
||||
|
||||
template <typename EventType, typename Handler>
|
||||
|
@ -139,7 +127,6 @@ public:
|
|||
this->_data->notify(std::move(event), sync);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <typename EventType, typename Handler>
|
||||
|
@ -156,18 +143,16 @@ public:
|
|||
this->_data->notify(std::move(event_copy), sync);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <typename EventType, typename Handler>
|
||||
class CommonObservableData : public BaseObservableData {
|
||||
template <typename EventType, typename Handler> class CommonObservableData : public BaseObservableData {
|
||||
public:
|
||||
CommonObservableData(CommonObservable<EventType, Handler> *observable) : _observable(observable) {
|
||||
}
|
||||
CommonObservableData(CommonObservable<EventType, Handler> *observable)
|
||||
: _observable(observable) {}
|
||||
|
||||
Subscription append(Handler &&handler) {
|
||||
auto node = new Node(_observable->_data, std::move(handler));
|
||||
|
@ -178,7 +163,7 @@ public:
|
|||
} else {
|
||||
_begin = _end = node;
|
||||
}
|
||||
return { _end, &CommonObservableData::removeAndDestroyNode };
|
||||
return {_end, &CommonObservableData::removeAndDestroyNode};
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
|
@ -187,8 +172,9 @@ public:
|
|||
|
||||
private:
|
||||
struct Node : public Subscription::Node {
|
||||
Node(const QSharedPointer<BaseObservableData> &observer, Handler &&handler) : Subscription::Node(observer), handler(std::move(handler)) {
|
||||
}
|
||||
Node(const QSharedPointer<BaseObservableData> &observer, Handler &&handler)
|
||||
: Subscription::Node(observer)
|
||||
, handler(std::move(handler)) {}
|
||||
Handler handler;
|
||||
};
|
||||
|
||||
|
@ -200,13 +186,13 @@ private:
|
|||
node->next->prev = node->prev;
|
||||
}
|
||||
if (_begin == node) {
|
||||
_begin = static_cast<Node*>(node->next);
|
||||
_begin = static_cast<Node *>(node->next);
|
||||
}
|
||||
if (_end == node) {
|
||||
_end = static_cast<Node*>(node->prev);
|
||||
_end = static_cast<Node *>(node->prev);
|
||||
}
|
||||
if (_current == node) {
|
||||
_current = static_cast<Node*>(node->prev);
|
||||
_current = static_cast<Node *>(node->prev);
|
||||
} else if (!_begin) {
|
||||
_observable->_data.reset();
|
||||
}
|
||||
|
@ -214,18 +200,17 @@ private:
|
|||
|
||||
static void removeAndDestroyNode(Subscription::Node *node) {
|
||||
if (auto that = node->observable.toStrongRef()) {
|
||||
static_cast<CommonObservableData*>(that.data())->remove(node);
|
||||
static_cast<CommonObservableData *>(that.data())->remove(node);
|
||||
}
|
||||
delete static_cast<Node*>(node);
|
||||
delete static_cast<Node *>(node);
|
||||
}
|
||||
|
||||
template <typename CallCurrent>
|
||||
void notifyEnumerate(CallCurrent callCurrent) {
|
||||
template <typename CallCurrent> void notifyEnumerate(CallCurrent callCurrent) {
|
||||
_current = _begin;
|
||||
do {
|
||||
callCurrent();
|
||||
if (_current) {
|
||||
_current = static_cast<Node*>(_current->next);
|
||||
_current = static_cast<Node *>(_current->next);
|
||||
} else if (_begin) {
|
||||
_current = _begin;
|
||||
} else {
|
||||
|
@ -249,11 +234,9 @@ private:
|
|||
ObservableCallHandlers _callHandlers;
|
||||
|
||||
friend class ObservableData<EventType, Handler>;
|
||||
|
||||
};
|
||||
|
||||
template <typename EventType, typename Handler>
|
||||
class ObservableData : public CommonObservableData<EventType, Handler> {
|
||||
template <typename EventType, typename Handler> class ObservableData : public CommonObservableData<EventType, Handler> {
|
||||
public:
|
||||
using CommonObservableData<EventType, Handler>::CommonObservableData;
|
||||
|
||||
|
@ -266,9 +249,7 @@ public:
|
|||
callHandlers();
|
||||
} else {
|
||||
if (!this->_callHandlers) {
|
||||
this->_callHandlers = [this]() {
|
||||
callHandlers();
|
||||
};
|
||||
this->_callHandlers = [this]() { callHandlers(); };
|
||||
}
|
||||
if (_events.empty()) {
|
||||
RegisterPendingObservable(&this->_callHandlers);
|
||||
|
@ -286,9 +267,7 @@ private:
|
|||
_handling = true;
|
||||
auto events = base::take(_events);
|
||||
for (auto &event : events) {
|
||||
this->notifyEnumerate([this, &event]() {
|
||||
this->_current->handler(event);
|
||||
});
|
||||
this->notifyEnumerate([this, &event]() { this->_current->handler(event); });
|
||||
if (this->destroyMeIfEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
@ -299,11 +278,9 @@ private:
|
|||
|
||||
std::deque<EventType> _events;
|
||||
bool _handling = false;
|
||||
|
||||
};
|
||||
|
||||
template <class Handler>
|
||||
class ObservableData<void, Handler> : public CommonObservableData<void, Handler> {
|
||||
template <class Handler> class ObservableData<void, Handler> : public CommonObservableData<void, Handler> {
|
||||
public:
|
||||
using CommonObservableData<void, Handler>::CommonObservableData;
|
||||
|
||||
|
@ -316,9 +293,7 @@ public:
|
|||
callHandlers();
|
||||
} else {
|
||||
if (!this->_callHandlers) {
|
||||
this->_callHandlers = [this]() {
|
||||
callHandlers();
|
||||
};
|
||||
this->_callHandlers = [this]() { callHandlers(); };
|
||||
}
|
||||
if (!_eventsCount) {
|
||||
RegisterPendingObservable(&this->_callHandlers);
|
||||
|
@ -336,9 +311,7 @@ private:
|
|||
_handling = true;
|
||||
auto eventsCount = base::take(_eventsCount);
|
||||
for (int i = 0; i != eventsCount; ++i) {
|
||||
this->notifyEnumerate([this]() {
|
||||
this->_current->handler();
|
||||
});
|
||||
this->notifyEnumerate([this]() { this->_current->handler(); });
|
||||
if (this->destroyMeIfEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
@ -349,38 +322,36 @@ private:
|
|||
|
||||
int _eventsCount = 0;
|
||||
bool _handling = false;
|
||||
|
||||
};
|
||||
|
||||
template <typename Handler>
|
||||
class BaseObservable<void, Handler, base::type_traits<void>::is_fast_copy_type::value> : public internal::CommonObservable<void, Handler> {
|
||||
class BaseObservable<void, Handler, base::type_traits<void>::is_fast_copy_type::value>
|
||||
: public internal::CommonObservable<void, Handler> {
|
||||
public:
|
||||
void notify(bool sync = false) {
|
||||
if (this->_data) {
|
||||
this->_data->notify(sync);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
template <typename EventType, typename Handler = internal::SubscriptionHandler<EventType>>
|
||||
class Observable : public internal::BaseObservable<EventType, Handler, base::type_traits<EventType>::is_fast_copy_type::value> {
|
||||
class Observable
|
||||
: public internal::BaseObservable<EventType, Handler, base::type_traits<EventType>::is_fast_copy_type::value> {
|
||||
public:
|
||||
Observable() = default;
|
||||
Observable(const Observable &other) = delete;
|
||||
Observable(Observable &&other) = delete;
|
||||
Observable &operator=(const Observable &other) = delete;
|
||||
Observable &operator=(Observable &&other) = delete;
|
||||
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
class Variable {
|
||||
template <typename Type> class Variable {
|
||||
public:
|
||||
Variable(parameter_type<Type> startValue = Type()) : _value(startValue) {
|
||||
}
|
||||
Variable(parameter_type<Type> startValue = Type())
|
||||
: _value(startValue) {}
|
||||
Variable(Variable &&other) = default;
|
||||
Variable &operator=(Variable &&other) = default;
|
||||
|
||||
|
@ -399,8 +370,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
template <typename Callback>
|
||||
void process(Callback callback, bool sync = false) {
|
||||
template <typename Callback> void process(Callback callback, bool sync = false) {
|
||||
callback(_value);
|
||||
changed().notify(_value, sync);
|
||||
}
|
||||
|
@ -412,7 +382,6 @@ public:
|
|||
private:
|
||||
Type _value;
|
||||
mutable Observable<Type> _changed;
|
||||
|
||||
};
|
||||
|
||||
class Subscriber {
|
||||
|
@ -428,13 +397,11 @@ protected:
|
|||
return subscribe(*observable, std::forward<Lambda>(handler));
|
||||
}
|
||||
|
||||
template <typename Type, typename Lambda>
|
||||
size_t subscribe(const base::Variable<Type> &variable, Lambda &&handler) {
|
||||
template <typename Type, typename Lambda> size_t subscribe(const base::Variable<Type> &variable, Lambda &&handler) {
|
||||
return subscribe(variable.changed(), std::forward<Lambda>(handler));
|
||||
}
|
||||
|
||||
template <typename Type, typename Lambda>
|
||||
size_t subscribe(const base::Variable<Type> *variable, Lambda &&handler) {
|
||||
template <typename Type, typename Lambda> size_t subscribe(const base::Variable<Type> *variable, Lambda &&handler) {
|
||||
return subscribe(variable->changed(), std::forward<Lambda>(handler));
|
||||
}
|
||||
|
||||
|
@ -459,7 +426,6 @@ protected:
|
|||
|
||||
private:
|
||||
std::vector<base::Subscription> _subscriptions;
|
||||
|
||||
};
|
||||
|
||||
void HandleObservables();
|
||||
|
|
|
@ -21,8 +21,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
#pragma once
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include "base/assertion.h"
|
||||
#include "core/utils.h"
|
||||
|
@ -30,11 +30,11 @@ namespace openssl {
|
|||
|
||||
class Context {
|
||||
public:
|
||||
Context() : _data(BN_CTX_new()) {
|
||||
}
|
||||
Context()
|
||||
: _data(BN_CTX_new()) {}
|
||||
Context(const Context &other) = delete;
|
||||
Context(Context &&other) : _data(base::take(other._data)) {
|
||||
}
|
||||
Context(Context &&other)
|
||||
: _data(base::take(other._data)) {}
|
||||
Context &operator=(const Context &other) = delete;
|
||||
Context &operator=(Context &&other) {
|
||||
_data = base::take(other._data);
|
||||
|
@ -52,14 +52,14 @@ public:
|
|||
|
||||
private:
|
||||
BN_CTX *_data = nullptr;
|
||||
|
||||
};
|
||||
|
||||
class BigNum {
|
||||
public:
|
||||
BigNum() : _data(BN_new()) {
|
||||
}
|
||||
BigNum(const BigNum &other) : BigNum() {
|
||||
BigNum()
|
||||
: _data(BN_new()) {}
|
||||
BigNum(const BigNum &other)
|
||||
: BigNum() {
|
||||
*this = other;
|
||||
}
|
||||
BigNum &operator=(const BigNum &other) {
|
||||
|
@ -72,10 +72,12 @@ public:
|
|||
BN_clear_free(raw());
|
||||
}
|
||||
|
||||
explicit BigNum(unsigned int word) : BigNum() {
|
||||
explicit BigNum(unsigned int word)
|
||||
: BigNum() {
|
||||
setWord(word);
|
||||
}
|
||||
explicit BigNum(base::const_byte_span bytes) : BigNum() {
|
||||
explicit BigNum(base::const_byte_span bytes)
|
||||
: BigNum() {
|
||||
setBytes(bytes);
|
||||
}
|
||||
|
||||
|
@ -85,18 +87,11 @@ public:
|
|||
}
|
||||
}
|
||||
void setBytes(base::const_byte_span bytes) {
|
||||
if (!BN_bin2bn(
|
||||
reinterpret_cast<const unsigned char*>(bytes.data()),
|
||||
bytes.size(),
|
||||
raw())) {
|
||||
if (!BN_bin2bn(reinterpret_cast<const unsigned char *>(bytes.data()), bytes.size(), raw())) {
|
||||
_failed = true;
|
||||
}
|
||||
}
|
||||
void setModExp(
|
||||
const BigNum &a,
|
||||
const BigNum &p,
|
||||
const BigNum &m,
|
||||
const Context &context = Context()) {
|
||||
void setModExp(const BigNum &a, const BigNum &p, const BigNum &m, const Context &context = Context()) {
|
||||
if (a.failed() || p.failed() || m.failed()) {
|
||||
_failed = true;
|
||||
} else if (a.isNegative() || p.isNegative() || m.isNegative()) {
|
||||
|
@ -143,11 +138,7 @@ public:
|
|||
return false;
|
||||
}
|
||||
constexpr auto kMillerRabinIterationCount = 30;
|
||||
auto result = BN_is_prime_ex(
|
||||
raw(),
|
||||
kMillerRabinIterationCount,
|
||||
context.raw(),
|
||||
NULL);
|
||||
auto result = BN_is_prime_ex(raw(), kMillerRabinIterationCount, context.raw(), NULL);
|
||||
if (result == 1) {
|
||||
return true;
|
||||
} else if (result != 0) {
|
||||
|
@ -182,9 +173,7 @@ public:
|
|||
}
|
||||
auto length = BN_num_bytes(raw());
|
||||
auto result = base::byte_vector(length, gsl::byte());
|
||||
auto resultSize = BN_bn2bin(
|
||||
raw(),
|
||||
reinterpret_cast<unsigned char*>(result.data()));
|
||||
auto resultSize = BN_bn2bin(raw(), reinterpret_cast<unsigned char *>(result.data()));
|
||||
Assert(resultSize == length);
|
||||
return result;
|
||||
}
|
||||
|
@ -212,7 +201,6 @@ public:
|
|||
private:
|
||||
BIGNUM *_data = nullptr;
|
||||
mutable bool _failed = false;
|
||||
|
||||
};
|
||||
|
||||
inline BigNum operator-(const BigNum &a, const BigNum &b) {
|
||||
|
@ -223,18 +211,20 @@ inline BigNum operator-(const BigNum &a, const BigNum &b) {
|
|||
|
||||
inline base::byte_array<SHA256_DIGEST_LENGTH> Sha256(base::const_byte_span bytes) {
|
||||
auto result = base::byte_array<SHA256_DIGEST_LENGTH>();
|
||||
SHA256(reinterpret_cast<const unsigned char*>(bytes.data()), bytes.size(), reinterpret_cast<unsigned char*>(result.data()));
|
||||
SHA256(reinterpret_cast<const unsigned char *>(bytes.data()), bytes.size(),
|
||||
reinterpret_cast<unsigned char *>(result.data()));
|
||||
return result;
|
||||
}
|
||||
|
||||
inline base::byte_array<SHA_DIGEST_LENGTH> Sha1(base::const_byte_span bytes) {
|
||||
auto result = base::byte_array<SHA_DIGEST_LENGTH>();
|
||||
SHA1(reinterpret_cast<const unsigned char*>(bytes.data()), bytes.size(), reinterpret_cast<unsigned char*>(result.data()));
|
||||
SHA1(reinterpret_cast<const unsigned char *>(bytes.data()), bytes.size(),
|
||||
reinterpret_cast<unsigned char *>(result.data()));
|
||||
return result;
|
||||
}
|
||||
|
||||
inline int FillRandom(base::byte_span bytes) {
|
||||
return RAND_bytes(reinterpret_cast<unsigned char*>(bytes.data()), bytes.size());
|
||||
return RAND_bytes(reinterpret_cast<unsigned char *>(bytes.data()), bytes.size());
|
||||
}
|
||||
|
||||
} // namespace openssl
|
||||
|
|
|
@ -44,23 +44,21 @@ struct none_type {
|
|||
bool operator>=(none_type other) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
constexpr none_type none = {};
|
||||
|
||||
template <typename... Types>
|
||||
class optional_variant {
|
||||
template <typename... Types> class optional_variant {
|
||||
public:
|
||||
optional_variant() : _impl(none) {
|
||||
}
|
||||
optional_variant(const optional_variant &other) : _impl(other._impl) {
|
||||
}
|
||||
optional_variant(optional_variant &&other) : _impl(std::move(other._impl)) {
|
||||
}
|
||||
optional_variant()
|
||||
: _impl(none) {}
|
||||
optional_variant(const optional_variant &other)
|
||||
: _impl(other._impl) {}
|
||||
optional_variant(optional_variant &&other)
|
||||
: _impl(std::move(other._impl)) {}
|
||||
template <typename T, typename = std::enable_if_t<!std::is_base_of<optional_variant, std::decay_t<T>>::value>>
|
||||
optional_variant(T &&value) : _impl(std::forward<T>(value)) {
|
||||
}
|
||||
optional_variant(T &&value)
|
||||
: _impl(std::forward<T>(value)) {}
|
||||
optional_variant &operator=(const optional_variant &other) {
|
||||
_impl = other._impl;
|
||||
return *this;
|
||||
|
@ -97,65 +95,43 @@ public:
|
|||
return _impl >= other._impl;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
decltype(auto) is() const {
|
||||
template <typename T> decltype(auto) is() const {
|
||||
return _impl.template is<T>();
|
||||
}
|
||||
template <typename T>
|
||||
decltype(auto) get_unchecked() {
|
||||
template <typename T> decltype(auto) get_unchecked() {
|
||||
return _impl.template get_unchecked<T>();
|
||||
}
|
||||
template <typename T>
|
||||
decltype(auto) get_unchecked() const {
|
||||
template <typename T> decltype(auto) get_unchecked() const {
|
||||
return _impl.template get_unchecked<T>();
|
||||
}
|
||||
|
||||
private:
|
||||
variant<none_type, Types...> _impl;
|
||||
|
||||
};
|
||||
|
||||
template <typename T, typename... Types>
|
||||
inline T *get_if(optional_variant<Types...> *v) {
|
||||
template <typename T, typename... Types> inline T *get_if(optional_variant<Types...> *v) {
|
||||
return (v && v->template is<T>()) ? &v->template get_unchecked<T>() : nullptr;
|
||||
}
|
||||
|
||||
template <typename T, typename... Types>
|
||||
inline const T *get_if(const optional_variant<Types...> *v) {
|
||||
template <typename T, typename... Types> inline const T *get_if(const optional_variant<Types...> *v) {
|
||||
return (v && v->template is<T>()) ? &v->template get_unchecked<T>() : nullptr;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
class optional;
|
||||
template <typename Type> class optional;
|
||||
|
||||
template <typename Type>
|
||||
struct optional_wrap_once {
|
||||
using type = optional<Type>;
|
||||
};
|
||||
template <typename Type> struct optional_wrap_once { using type = optional<Type>; };
|
||||
|
||||
template <typename Type>
|
||||
struct optional_wrap_once<optional<Type>> {
|
||||
using type = optional<Type>;
|
||||
};
|
||||
template <typename Type> struct optional_wrap_once<optional<Type>> { using type = optional<Type>; };
|
||||
|
||||
template <typename Type>
|
||||
using optional_wrap_once_t = typename optional_wrap_once<std::decay_t<Type>>::type;
|
||||
template <typename Type> using optional_wrap_once_t = typename optional_wrap_once<std::decay_t<Type>>::type;
|
||||
|
||||
template <typename Type>
|
||||
struct optional_chain_result {
|
||||
using type = optional_wrap_once_t<Type>;
|
||||
};
|
||||
template <typename Type> struct optional_chain_result { using type = optional_wrap_once_t<Type>; };
|
||||
|
||||
template <>
|
||||
struct optional_chain_result<void> {
|
||||
using type = bool;
|
||||
};
|
||||
template <> struct optional_chain_result<void> { using type = bool; };
|
||||
|
||||
template <typename Type>
|
||||
using optional_chain_result_t = typename optional_chain_result<Type>::type;
|
||||
template <typename Type> using optional_chain_result_t = typename optional_chain_result<Type>::type;
|
||||
|
||||
template <typename Type>
|
||||
class optional : public optional_variant<Type> {
|
||||
template <typename Type> class optional : public optional_variant<Type> {
|
||||
public:
|
||||
using optional_variant<Type>::optional_variant;
|
||||
|
||||
|
@ -179,37 +155,28 @@ public:
|
|||
Expects(result != nullptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
optional_wrap_once_t<Type> make_optional(Type &&value) {
|
||||
return optional_wrap_once_t<Type> { std::forward<Type>(value) };
|
||||
template <typename Type> optional_wrap_once_t<Type> make_optional(Type &&value) {
|
||||
return optional_wrap_once_t<Type>{std::forward<Type>(value)};
|
||||
}
|
||||
|
||||
template <typename Type, typename Method>
|
||||
inline auto optional_chain(
|
||||
const optional<Type> &value,
|
||||
Method &method,
|
||||
std::false_type)
|
||||
-> optional_chain_result_t<decltype(method(*value))> {
|
||||
inline auto optional_chain(const optional<Type> &value, Method &method, std::false_type)
|
||||
-> optional_chain_result_t<decltype(method(*value))> {
|
||||
return value ? make_optional(method(*value)) : none;
|
||||
}
|
||||
|
||||
template <typename Type, typename Method>
|
||||
inline auto optional_chain(
|
||||
const optional<Type> &value,
|
||||
Method &method,
|
||||
std::true_type)
|
||||
-> optional_chain_result_t<decltype(method(*value))> {
|
||||
inline auto optional_chain(const optional<Type> &value, Method &method, std::true_type)
|
||||
-> optional_chain_result_t<decltype(method(*value))> {
|
||||
return value ? (method(*value), true) : false;
|
||||
}
|
||||
|
||||
template <typename Type, typename Method>
|
||||
inline auto operator|(const optional<Type> &value, Method method)
|
||||
-> optional_chain_result_t<decltype(method(*value))> {
|
||||
inline auto operator|(const optional<Type> &value, Method method) -> optional_chain_result_t<decltype(method(*value))> {
|
||||
using is_void_return = std::is_same<decltype(method(*value)), void>;
|
||||
return optional_chain(value, method, is_void_return {});
|
||||
return optional_chain(value, method, is_void_return{});
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
|
|
|
@ -23,10 +23,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
#include <QMap>
|
||||
|
||||
// ordered set template based on QMap
|
||||
template <typename T>
|
||||
class OrderedSet {
|
||||
struct NullType {
|
||||
};
|
||||
template <typename T> class OrderedSet {
|
||||
struct NullType {};
|
||||
using Self = OrderedSet<T>;
|
||||
using Impl = QMap<T, NullType>;
|
||||
using IteratorImpl = typename Impl::iterator;
|
||||
|
@ -41,16 +39,36 @@ public:
|
|||
OrderedSet &operator=(OrderedSet &&other) = default;
|
||||
~OrderedSet() = default;
|
||||
|
||||
inline bool operator==(const Self &other) const { return impl_ == other.impl_; }
|
||||
inline bool operator!=(const Self &other) const { return impl_ != other.impl_; }
|
||||
inline int size() const { return impl_.size(); }
|
||||
inline bool isEmpty() const { return impl_.isEmpty(); }
|
||||
inline void detach() { return impl_.detach(); }
|
||||
inline bool isDetached() const { return impl_.isDetached(); }
|
||||
inline void clear() { return impl_.clear(); }
|
||||
inline QList<T> values() const { return impl_.keys(); }
|
||||
inline const T &first() const { return impl_.firstKey(); }
|
||||
inline const T &last() const { return impl_.lastKey(); }
|
||||
inline bool operator==(const Self &other) const {
|
||||
return impl_ == other.impl_;
|
||||
}
|
||||
inline bool operator!=(const Self &other) const {
|
||||
return impl_ != other.impl_;
|
||||
}
|
||||
inline int size() const {
|
||||
return impl_.size();
|
||||
}
|
||||
inline bool isEmpty() const {
|
||||
return impl_.isEmpty();
|
||||
}
|
||||
inline void detach() {
|
||||
return impl_.detach();
|
||||
}
|
||||
inline bool isDetached() const {
|
||||
return impl_.isDetached();
|
||||
}
|
||||
inline void clear() {
|
||||
return impl_.clear();
|
||||
}
|
||||
inline QList<T> values() const {
|
||||
return impl_.keys();
|
||||
}
|
||||
inline const T &first() const {
|
||||
return impl_.firstKey();
|
||||
}
|
||||
inline const T &last() const {
|
||||
return impl_.lastKey();
|
||||
}
|
||||
|
||||
class const_iterator;
|
||||
class iterator {
|
||||
|
@ -64,29 +82,60 @@ public:
|
|||
iterator() = default;
|
||||
iterator(const iterator &other) = default;
|
||||
iterator &operator=(const iterator &other) = default;
|
||||
inline const T &operator*() const { return impl_.key(); }
|
||||
inline const T *operator->() const { return &impl_.key(); }
|
||||
inline bool operator==(const iterator &other) const { return impl_ == other.impl_; }
|
||||
inline bool operator!=(const iterator &other) const { return impl_ != other.impl_; }
|
||||
inline iterator &operator++() { ++impl_; return *this; }
|
||||
inline iterator operator++(int) { return iterator(impl_++); }
|
||||
inline iterator &operator--() { --impl_; return *this; }
|
||||
inline iterator operator--(int) { return iterator(impl_--); }
|
||||
inline iterator operator+(int j) const { return iterator(impl_ + j); }
|
||||
inline iterator operator-(int j) const { return iterator(impl_ - j); }
|
||||
inline iterator &operator+=(int j) { impl_ += j; return *this; }
|
||||
inline iterator &operator-=(int j) { impl_ -= j; return *this; }
|
||||
inline const T &operator*() const {
|
||||
return impl_.key();
|
||||
}
|
||||
inline const T *operator->() const {
|
||||
return &impl_.key();
|
||||
}
|
||||
inline bool operator==(const iterator &other) const {
|
||||
return impl_ == other.impl_;
|
||||
}
|
||||
inline bool operator!=(const iterator &other) const {
|
||||
return impl_ != other.impl_;
|
||||
}
|
||||
inline iterator &operator++() {
|
||||
++impl_;
|
||||
return *this;
|
||||
}
|
||||
inline iterator operator++(int) {
|
||||
return iterator(impl_++);
|
||||
}
|
||||
inline iterator &operator--() {
|
||||
--impl_;
|
||||
return *this;
|
||||
}
|
||||
inline iterator operator--(int) {
|
||||
return iterator(impl_--);
|
||||
}
|
||||
inline iterator operator+(int j) const {
|
||||
return iterator(impl_ + j);
|
||||
}
|
||||
inline iterator operator-(int j) const {
|
||||
return iterator(impl_ - j);
|
||||
}
|
||||
inline iterator &operator+=(int j) {
|
||||
impl_ += j;
|
||||
return *this;
|
||||
}
|
||||
inline iterator &operator-=(int j) {
|
||||
impl_ -= j;
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend class const_iterator;
|
||||
inline bool operator==(const const_iterator &other) const { return impl_ == other.impl_; }
|
||||
inline bool operator!=(const const_iterator &other) const { return impl_ != other.impl_; }
|
||||
inline bool operator==(const const_iterator &other) const {
|
||||
return impl_ == other.impl_;
|
||||
}
|
||||
inline bool operator!=(const const_iterator &other) const {
|
||||
return impl_ != other.impl_;
|
||||
}
|
||||
|
||||
private:
|
||||
explicit iterator(const IteratorImpl &impl) : impl_(impl) {
|
||||
}
|
||||
explicit iterator(const IteratorImpl &impl)
|
||||
: impl_(impl) {}
|
||||
IteratorImpl impl_;
|
||||
friend class OrderedSet<T>;
|
||||
|
||||
};
|
||||
friend class iterator;
|
||||
|
||||
|
@ -101,66 +150,136 @@ public:
|
|||
const_iterator() = default;
|
||||
const_iterator(const const_iterator &other) = default;
|
||||
const_iterator &operator=(const const_iterator &other) = default;
|
||||
const_iterator(const iterator &other) : impl_(other.impl_) {
|
||||
}
|
||||
const_iterator(const iterator &other)
|
||||
: impl_(other.impl_) {}
|
||||
const_iterator &operator=(const iterator &other) {
|
||||
impl_ = other.impl_;
|
||||
return *this;
|
||||
}
|
||||
inline const T &operator*() const { return impl_.key(); }
|
||||
inline const T *operator->() const { return &impl_.key(); }
|
||||
inline bool operator==(const const_iterator &other) const { return impl_ == other.impl_; }
|
||||
inline bool operator!=(const const_iterator &other) const { return impl_ != other.impl_; }
|
||||
inline const_iterator &operator++() { ++impl_; return *this; }
|
||||
inline const_iterator operator++(int) { return const_iterator(impl_++); }
|
||||
inline const_iterator &operator--() { --impl_; return *this; }
|
||||
inline const_iterator operator--(int) { return const_iterator(impl_--); }
|
||||
inline const_iterator operator+(int j) const { return const_iterator(impl_ + j); }
|
||||
inline const_iterator operator-(int j) const { return const_iterator(impl_ - j); }
|
||||
inline const_iterator &operator+=(int j) { impl_ += j; return *this; }
|
||||
inline const_iterator &operator-=(int j) { impl_ -= j; return *this; }
|
||||
inline const T &operator*() const {
|
||||
return impl_.key();
|
||||
}
|
||||
inline const T *operator->() const {
|
||||
return &impl_.key();
|
||||
}
|
||||
inline bool operator==(const const_iterator &other) const {
|
||||
return impl_ == other.impl_;
|
||||
}
|
||||
inline bool operator!=(const const_iterator &other) const {
|
||||
return impl_ != other.impl_;
|
||||
}
|
||||
inline const_iterator &operator++() {
|
||||
++impl_;
|
||||
return *this;
|
||||
}
|
||||
inline const_iterator operator++(int) {
|
||||
return const_iterator(impl_++);
|
||||
}
|
||||
inline const_iterator &operator--() {
|
||||
--impl_;
|
||||
return *this;
|
||||
}
|
||||
inline const_iterator operator--(int) {
|
||||
return const_iterator(impl_--);
|
||||
}
|
||||
inline const_iterator operator+(int j) const {
|
||||
return const_iterator(impl_ + j);
|
||||
}
|
||||
inline const_iterator operator-(int j) const {
|
||||
return const_iterator(impl_ - j);
|
||||
}
|
||||
inline const_iterator &operator+=(int j) {
|
||||
impl_ += j;
|
||||
return *this;
|
||||
}
|
||||
inline const_iterator &operator-=(int j) {
|
||||
impl_ -= j;
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend class iterator;
|
||||
inline bool operator==(const iterator &other) const { return impl_ == other.impl_; }
|
||||
inline bool operator!=(const iterator &other) const { return impl_ != other.impl_; }
|
||||
inline bool operator==(const iterator &other) const {
|
||||
return impl_ == other.impl_;
|
||||
}
|
||||
inline bool operator!=(const iterator &other) const {
|
||||
return impl_ != other.impl_;
|
||||
}
|
||||
|
||||
private:
|
||||
explicit const_iterator(const ConstIteratorImpl &impl) : impl_(impl) {
|
||||
}
|
||||
explicit const_iterator(const ConstIteratorImpl &impl)
|
||||
: impl_(impl) {}
|
||||
ConstIteratorImpl impl_;
|
||||
friend class OrderedSet<T>;
|
||||
|
||||
};
|
||||
friend class const_iterator;
|
||||
|
||||
// STL style
|
||||
inline iterator begin() { return iterator(impl_.begin()); }
|
||||
inline const_iterator begin() const { return const_iterator(impl_.cbegin()); }
|
||||
inline const_iterator constBegin() const { return const_iterator(impl_.cbegin()); }
|
||||
inline const_iterator cbegin() const { return const_iterator(impl_.cbegin()); }
|
||||
inline iterator end() { detach(); return iterator(impl_.end()); }
|
||||
inline const_iterator end() const { return const_iterator(impl_.cend()); }
|
||||
inline const_iterator constEnd() const { return const_iterator(impl_.cend()); }
|
||||
inline const_iterator cend() const { return const_iterator(impl_.cend()); }
|
||||
inline iterator erase(iterator it) { return iterator(impl_.erase(it.impl_)); }
|
||||
inline iterator begin() {
|
||||
return iterator(impl_.begin());
|
||||
}
|
||||
inline const_iterator begin() const {
|
||||
return const_iterator(impl_.cbegin());
|
||||
}
|
||||
inline const_iterator constBegin() const {
|
||||
return const_iterator(impl_.cbegin());
|
||||
}
|
||||
inline const_iterator cbegin() const {
|
||||
return const_iterator(impl_.cbegin());
|
||||
}
|
||||
inline iterator end() {
|
||||
detach();
|
||||
return iterator(impl_.end());
|
||||
}
|
||||
inline const_iterator end() const {
|
||||
return const_iterator(impl_.cend());
|
||||
}
|
||||
inline const_iterator constEnd() const {
|
||||
return const_iterator(impl_.cend());
|
||||
}
|
||||
inline const_iterator cend() const {
|
||||
return const_iterator(impl_.cend());
|
||||
}
|
||||
inline iterator erase(iterator it) {
|
||||
return iterator(impl_.erase(it.impl_));
|
||||
}
|
||||
|
||||
inline iterator insert(const T &value) { return iterator(impl_.insert(value, NullType())); }
|
||||
inline iterator insert(const_iterator pos, const T &value) { return iterator(impl_.insert(pos.impl_, value, NullType())); }
|
||||
inline int remove(const T &value) { return impl_.remove(value); }
|
||||
inline bool contains(const T &value) const { return impl_.contains(value); }
|
||||
inline iterator insert(const T &value) {
|
||||
return iterator(impl_.insert(value, NullType()));
|
||||
}
|
||||
inline iterator insert(const_iterator pos, const T &value) {
|
||||
return iterator(impl_.insert(pos.impl_, value, NullType()));
|
||||
}
|
||||
inline int remove(const T &value) {
|
||||
return impl_.remove(value);
|
||||
}
|
||||
inline bool contains(const T &value) const {
|
||||
return impl_.contains(value);
|
||||
}
|
||||
|
||||
// more Qt
|
||||
typedef iterator Iterator;
|
||||
typedef const_iterator ConstIterator;
|
||||
inline int count() const { return impl_.count(); }
|
||||
inline iterator find(const T &value) { return iterator(impl_.find(value)); }
|
||||
inline const_iterator find(const T &value) const { return const_iterator(impl_.constFind(value)); }
|
||||
inline const_iterator constFind(const T &value) const { return const_iterator(impl_.constFind(value)); }
|
||||
inline Self &unite(const Self &other) { impl_.unite(other.impl_); return *this; }
|
||||
inline int count() const {
|
||||
return impl_.count();
|
||||
}
|
||||
inline iterator find(const T &value) {
|
||||
return iterator(impl_.find(value));
|
||||
}
|
||||
inline const_iterator find(const T &value) const {
|
||||
return const_iterator(impl_.constFind(value));
|
||||
}
|
||||
inline const_iterator constFind(const T &value) const {
|
||||
return const_iterator(impl_.constFind(value));
|
||||
}
|
||||
inline Self &unite(const Self &other) {
|
||||
impl_.unite(other.impl_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// STL compatibility
|
||||
typedef typename Impl::difference_type difference_type;
|
||||
typedef typename Impl::size_type size_type;
|
||||
inline bool empty() const { return impl_.empty(); }
|
||||
|
||||
inline bool empty() const {
|
||||
return impl_.empty();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -20,9 +20,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "base/assertion.h"
|
||||
#include <QByteArray>
|
||||
#include <QLatin1String>
|
||||
#include "base/assertion.h"
|
||||
|
||||
|
||||
namespace base {
|
||||
|
@ -33,11 +33,7 @@ QByteArray stripComments(const QByteArray &content);
|
|||
|
||||
inline bool skipWhitespaces(const char *&from, const char *end) {
|
||||
Assert(from <= end);
|
||||
while (from != end && (
|
||||
(*from == ' ') ||
|
||||
(*from == '\n') ||
|
||||
(*from == '\t') ||
|
||||
(*from == '\r'))) {
|
||||
while (from != end && ((*from == ' ') || (*from == '\n') || (*from == '\t') || (*from == '\r'))) {
|
||||
++from;
|
||||
}
|
||||
return (from != end);
|
||||
|
@ -46,11 +42,8 @@ inline bool skipWhitespaces(const char *&from, const char *end) {
|
|||
inline QLatin1String readName(const char *&from, const char *end) {
|
||||
Assert(from <= end);
|
||||
auto start = from;
|
||||
while (from != end && (
|
||||
(*from >= 'a' && *from <= 'z') ||
|
||||
(*from >= 'A' && *from <= 'Z') ||
|
||||
(*from >= '0' && *from <= '9') ||
|
||||
(*from == '_'))) {
|
||||
while (from != end && ((*from >= 'a' && *from <= 'z') || (*from >= 'A' && *from <= 'Z') ||
|
||||
(*from >= '0' && *from <= '9') || (*from == '_'))) {
|
||||
++from;
|
||||
}
|
||||
return QLatin1String(start, from - start);
|
||||
|
|
|
@ -30,10 +30,10 @@ class RegularExpressionMatch {
|
|||
public:
|
||||
RegularExpressionMatch(const QRegularExpressionMatch &other) = delete;
|
||||
RegularExpressionMatch(const RegularExpressionMatch &other) = delete;
|
||||
RegularExpressionMatch(QRegularExpressionMatch &&match) : data_(std::move(match)) {
|
||||
}
|
||||
RegularExpressionMatch(RegularExpressionMatch &&other) : data_(std::move(other.data_)) {
|
||||
}
|
||||
RegularExpressionMatch(QRegularExpressionMatch &&match)
|
||||
: data_(std::move(match)) {}
|
||||
RegularExpressionMatch(RegularExpressionMatch &&other)
|
||||
: data_(std::move(other.data_)) {}
|
||||
RegularExpressionMatch &operator=(const QRegularExpressionMatch &match) = delete;
|
||||
RegularExpressionMatch &operator=(const RegularExpressionMatch &other) = delete;
|
||||
RegularExpressionMatch &operator=(QRegularExpressionMatch &&match) {
|
||||
|
@ -56,7 +56,6 @@ public:
|
|||
|
||||
private:
|
||||
QRegularExpressionMatch data_;
|
||||
|
||||
};
|
||||
|
||||
enum class RegExOption {
|
||||
|
@ -74,14 +73,17 @@ enum class RegExOption {
|
|||
#endif // OS_MAC_OLD
|
||||
};
|
||||
using RegExOptions = base::flags<RegExOption>;
|
||||
inline constexpr auto is_flag_type(RegExOption) { return true; };
|
||||
inline constexpr auto is_flag_type(RegExOption) {
|
||||
return true;
|
||||
};
|
||||
|
||||
inline RegularExpressionMatch regex_match(const QString &string, const QString &subject, RegExOptions options = 0) {
|
||||
auto qtOptions = QRegularExpression::PatternOptions(static_cast<int>(options));
|
||||
return RegularExpressionMatch(QRegularExpression(string, qtOptions).match(subject));
|
||||
}
|
||||
|
||||
inline RegularExpressionMatch regex_match(const QString &string, const QStringRef &subjectRef, RegExOptions options = 0) {
|
||||
inline RegularExpressionMatch regex_match(const QString &string, const QStringRef &subjectRef,
|
||||
RegExOptions options = 0) {
|
||||
auto qtOptions = QRegularExpression::PatternOptions(static_cast<int>(options));
|
||||
#ifndef OS_MAC_OLD
|
||||
return RegularExpressionMatch(QRegularExpression(string, qtOptions).match(subjectRef));
|
||||
|
|
|
@ -18,9 +18,9 @@ to link the code of portions of this program with the OpenSSL library.
|
|||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include <QStringList>
|
||||
#include "core/utils.h"
|
||||
#include "base/qthelp_url.h"
|
||||
#include "core/utils.h"
|
||||
#include <QStringList>
|
||||
|
||||
namespace qthelp {
|
||||
|
||||
|
@ -34,7 +34,7 @@ QMap<QString, QString> url_parse_params(const QString ¶ms, UrlParamNameTrans
|
|||
return name;
|
||||
};
|
||||
|
||||
auto paramsList = params.split('&');
|
||||
auto paramsList = params.split('&');
|
||||
for_const (auto ¶m, paramsList) {
|
||||
// Skip params without a name (starting with '=').
|
||||
if (auto separatorPosition = param.indexOf('=')) {
|
||||
|
|
|
@ -20,9 +20,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
#include <QMap>
|
||||
|
||||
namespace qthelp {
|
||||
|
||||
|
@ -39,6 +39,7 @@ enum class UrlParamNameTransform {
|
|||
ToLower,
|
||||
};
|
||||
// Parses a string like "p1=v1&p2=v2&..&pn=vn" to a map.
|
||||
QMap<QString, QString> url_parse_params(const QString ¶ms, UrlParamNameTransform transform = UrlParamNameTransform::NoTransform);
|
||||
QMap<QString, QString> url_parse_params(const QString ¶ms,
|
||||
UrlParamNameTransform transform = UrlParamNameTransform::NoTransform);
|
||||
|
||||
} // namespace qthelp
|
||||
|
|
|
@ -18,15 +18,13 @@ to link the code of portions of this program with the OpenSSL library.
|
|||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include <QMutexLocker>
|
||||
#include "base/runtime_composer.h"
|
||||
#include <QMutexLocker>
|
||||
|
||||
struct RuntimeComposerMetadatasMap {
|
||||
QMap<quint64, RuntimeComposerMetadata*> data;
|
||||
QMap<quint64, RuntimeComposerMetadata *> data;
|
||||
~RuntimeComposerMetadatasMap() {
|
||||
for_const (const RuntimeComposerMetadata *p, data) {
|
||||
delete p;
|
||||
}
|
||||
for_const (const RuntimeComposerMetadata *p, data) { delete p; }
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -19,28 +19,28 @@ Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
|||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
#include <cstddef>
|
||||
#include <QAtomicInt>
|
||||
#include <cstddef>
|
||||
|
||||
#include "base/assertion.h"
|
||||
#include "core/utils.h"
|
||||
|
||||
class RuntimeComposer;
|
||||
typedef void(*RuntimeComponentConstruct)(void *location, RuntimeComposer *composer);
|
||||
typedef void(*RuntimeComponentDestruct)(void *location);
|
||||
typedef void(*RuntimeComponentMove)(void *location, void *waslocation);
|
||||
typedef void (*RuntimeComponentConstruct)(void *location, RuntimeComposer *composer);
|
||||
typedef void (*RuntimeComponentDestruct)(void *location);
|
||||
typedef void (*RuntimeComponentMove)(void *location, void *waslocation);
|
||||
|
||||
struct RuntimeComponentWrapStruct {
|
||||
// Don't init any fields, because it is only created in
|
||||
// global scope, so it will be filled by zeros from the start.
|
||||
RuntimeComponentWrapStruct() = default;
|
||||
RuntimeComponentWrapStruct(std::size_t size, std::size_t align, RuntimeComponentConstruct construct, RuntimeComponentDestruct destruct, RuntimeComponentMove move)
|
||||
: Size(size)
|
||||
, Align(align)
|
||||
, Construct(construct)
|
||||
, Destruct(destruct)
|
||||
, Move(move) {
|
||||
}
|
||||
RuntimeComponentWrapStruct(std::size_t size, std::size_t align, RuntimeComponentConstruct construct,
|
||||
RuntimeComponentDestruct destruct, RuntimeComponentMove move)
|
||||
: Size(size)
|
||||
, Align(align)
|
||||
, Construct(construct)
|
||||
, Destruct(destruct)
|
||||
, Move(move) {}
|
||||
std::size_t Size;
|
||||
std::size_t Align;
|
||||
RuntimeComponentConstruct Construct;
|
||||
|
@ -48,16 +48,14 @@ struct RuntimeComponentWrapStruct {
|
|||
RuntimeComponentMove Move;
|
||||
};
|
||||
|
||||
template <int Value, int Denominator>
|
||||
struct CeilDivideMinimumOne {
|
||||
template <int Value, int Denominator> struct CeilDivideMinimumOne {
|
||||
static constexpr int Result = ((Value / Denominator) + ((!Value || (Value % Denominator)) ? 1 : 0));
|
||||
};
|
||||
|
||||
extern RuntimeComponentWrapStruct RuntimeComponentWraps[64];
|
||||
extern QAtomicInt RuntimeComponentIndexLast;
|
||||
|
||||
template <typename Type>
|
||||
struct RuntimeComponent {
|
||||
template <typename Type> struct RuntimeComponent {
|
||||
RuntimeComponent() {
|
||||
// While there is no std::aligned_alloc().
|
||||
static_assert(alignof(Type) <= alignof(std::max_align_t), "Components should align to std::max_align_t!");
|
||||
|
@ -77,12 +75,9 @@ struct RuntimeComponent {
|
|||
if (RuntimeComponentIndexLast.testAndSetOrdered(last, last + 1)) {
|
||||
Assert(last < 64);
|
||||
if (MyIndex.testAndSetOrdered(0, last + 1)) {
|
||||
RuntimeComponentWraps[last] = RuntimeComponentWrapStruct(
|
||||
sizeof(Type),
|
||||
alignof(Type),
|
||||
Type::RuntimeComponentConstruct,
|
||||
Type::RuntimeComponentDestruct,
|
||||
Type::RuntimeComponentMove);
|
||||
RuntimeComponentWraps[last] =
|
||||
RuntimeComponentWrapStruct(sizeof(Type), alignof(Type), Type::RuntimeComponentConstruct,
|
||||
Type::RuntimeComponentDestruct, Type::RuntimeComponentMove);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -98,17 +93,17 @@ protected:
|
|||
new (location) Type();
|
||||
}
|
||||
static void RuntimeComponentDestruct(void *location) {
|
||||
((Type*)location)->~Type();
|
||||
((Type *)location)->~Type();
|
||||
}
|
||||
static void RuntimeComponentMove(void *location, void *waslocation) {
|
||||
*(Type*)location = std::move(*(Type*)waslocation);
|
||||
*(Type *)location = std::move(*(Type *)waslocation);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class RuntimeComposerMetadata {
|
||||
public:
|
||||
RuntimeComposerMetadata(quint64 mask) : _mask(mask) {
|
||||
RuntimeComposerMetadata(quint64 mask)
|
||||
: _mask(mask) {
|
||||
for (int i = 0; i != 64; ++i) {
|
||||
auto componentBit = (1ULL << i);
|
||||
if (_mask & componentBit) {
|
||||
|
@ -130,9 +125,9 @@ public:
|
|||
}
|
||||
|
||||
// Meta pointer in the start.
|
||||
std::size_t size = sizeof(const RuntimeComposerMetadata*);
|
||||
std::size_t align = alignof(const RuntimeComposerMetadata*);
|
||||
std::size_t offsets[64] = { 0 };
|
||||
std::size_t size = sizeof(const RuntimeComposerMetadata *);
|
||||
std::size_t align = alignof(const RuntimeComposerMetadata *);
|
||||
std::size_t offsets[64] = {0};
|
||||
int last = 64;
|
||||
|
||||
bool equals(quint64 mask) const {
|
||||
|
@ -147,14 +142,14 @@ public:
|
|||
|
||||
private:
|
||||
quint64 _mask;
|
||||
|
||||
};
|
||||
|
||||
const RuntimeComposerMetadata *GetRuntimeComposerMetadata(quint64 mask);
|
||||
|
||||
class RuntimeComposer {
|
||||
public:
|
||||
RuntimeComposer(quint64 mask = 0) : _data(zerodata()) {
|
||||
RuntimeComposer(quint64 mask = 0)
|
||||
: _data(zerodata()) {
|
||||
if (mask) {
|
||||
auto meta = GetRuntimeComposerMetadata(mask);
|
||||
|
||||
|
@ -202,18 +197,15 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
bool Has() const {
|
||||
template <typename Type> bool Has() const {
|
||||
return (_meta()->offsets[Type::Index()] >= sizeof(_meta()));
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
Type *Get() {
|
||||
return static_cast<Type*>(_dataptr(_meta()->offsets[Type::Index()]));
|
||||
template <typename Type> Type *Get() {
|
||||
return static_cast<Type *>(_dataptr(_meta()->offsets[Type::Index()]));
|
||||
}
|
||||
template <typename Type>
|
||||
const Type *Get() const {
|
||||
return static_cast<const Type*>(_dataptr(_meta()->offsets[Type::Index()]));
|
||||
template <typename Type> const Type *Get() const {
|
||||
return static_cast<const Type *>(_dataptr(_meta()->offsets[Type::Index()]));
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -247,18 +239,17 @@ private:
|
|||
}
|
||||
|
||||
void *_dataptrunsafe(size_t skip) const {
|
||||
return (char*)_data + skip;
|
||||
return (char *)_data + skip;
|
||||
}
|
||||
void *_dataptr(size_t skip) const {
|
||||
return (skip >= sizeof(_meta())) ? _dataptrunsafe(skip) : nullptr;
|
||||
}
|
||||
const RuntimeComposerMetadata *&_meta() const {
|
||||
return *static_cast<const RuntimeComposerMetadata**>(_data);
|
||||
return *static_cast<const RuntimeComposerMetadata **>(_data);
|
||||
}
|
||||
void *_data = nullptr;
|
||||
|
||||
void swap(RuntimeComposer &other) {
|
||||
std::swap(_data, other._data);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -19,14 +19,14 @@ Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
|||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <thread>
|
||||
#include <condition_variable>
|
||||
#include "base/task_queue.h"
|
||||
#include "base/assertion.h"
|
||||
#include "facades.h"
|
||||
#include <QMutex>
|
||||
#include <QWaitCondition>
|
||||
#include "base/assertion.h"
|
||||
#include "base/task_queue.h"
|
||||
#include "facades.h"
|
||||
#include <algorithm>
|
||||
#include <condition_variable>
|
||||
#include <thread>
|
||||
|
||||
namespace base {
|
||||
namespace {
|
||||
|
@ -51,20 +51,22 @@ private:
|
|||
void Insert(TaskQueue *queue, int list_index_);
|
||||
void Remove(TaskQueue *queue, int list_index_);
|
||||
|
||||
TaskQueue *Tail() { return &tail_; }
|
||||
const TaskQueue *Tail() const { return &tail_; }
|
||||
TaskQueue *Tail() {
|
||||
return &tail_;
|
||||
}
|
||||
const TaskQueue *Tail() const {
|
||||
return &tail_;
|
||||
}
|
||||
|
||||
TaskQueue tail_ = { Type::Special, Priority::Normal };
|
||||
TaskQueue tail_ = {Type::Special, Priority::Normal};
|
||||
TaskQueue *(lists_[kQueuesListsCount]);
|
||||
|
||||
};
|
||||
|
||||
class TaskQueue::TaskThreadPool {
|
||||
struct Private {
|
||||
};
|
||||
struct Private {};
|
||||
|
||||
public:
|
||||
TaskThreadPool(const Private &) { }
|
||||
TaskThreadPool(const Private &) {}
|
||||
static const std::shared_ptr<TaskThreadPool> &Instance();
|
||||
|
||||
void AddQueueTask(TaskQueue *queue, Task &&task);
|
||||
|
@ -85,7 +87,6 @@ private:
|
|||
bool stopped_ = false;
|
||||
int tasks_in_process_ = 0;
|
||||
int background_tasks_in_process_ = 0;
|
||||
|
||||
};
|
||||
|
||||
TaskQueue::TaskQueueList::TaskQueueList() {
|
||||
|
@ -175,7 +176,7 @@ TaskQueue *TaskQueue::TaskQueueList::TakeFirst(int list_index_) {
|
|||
|
||||
auto queue = lists_[list_index_];
|
||||
Unregister(queue);
|
||||
// log_msgs.push_back("Unregistered from list in TakeFirst");
|
||||
// log_msgs.push_back("Unregistered from list in TakeFirst");
|
||||
return queue;
|
||||
}
|
||||
|
||||
|
@ -195,9 +196,7 @@ void TaskQueue::TaskThreadPool::AddQueueTask(TaskQueue *queue, Task &&task) {
|
|||
}
|
||||
}
|
||||
if (will_create_thread) {
|
||||
threads_.emplace_back([this]() {
|
||||
ThreadFunction();
|
||||
});
|
||||
threads_.emplace_back([this]() { ThreadFunction(); });
|
||||
} else if (some_threads_are_vacant) {
|
||||
Assert(threads_count > tasks_in_process_);
|
||||
thread_condition_.wakeOne();
|
||||
|
@ -309,8 +308,8 @@ void TaskQueue::TaskThreadPool::ThreadFunction() {
|
|||
}
|
||||
|
||||
TaskQueue::TaskQueue(Type type, Priority priority)
|
||||
: type_(type)
|
||||
, priority_(priority) {
|
||||
: type_(type)
|
||||
, priority_(priority) {
|
||||
if (type_ != Type::Main && type_ != Type::Special) {
|
||||
weak_thread_pool_ = TaskThreadPool::Instance();
|
||||
}
|
||||
|
@ -381,17 +380,17 @@ bool TaskQueue::IsMyThread() const {
|
|||
|
||||
// Default queues.
|
||||
TaskQueue &TaskQueue::Main() { // static
|
||||
static TaskQueue MainQueue { Type::Main, Priority::Normal };
|
||||
static TaskQueue MainQueue{Type::Main, Priority::Normal};
|
||||
return MainQueue;
|
||||
}
|
||||
|
||||
TaskQueue &TaskQueue::Normal() { // static
|
||||
static TaskQueue NormalQueue { Type::Concurrent, Priority::Normal };
|
||||
static TaskQueue NormalQueue{Type::Concurrent, Priority::Normal};
|
||||
return NormalQueue;
|
||||
}
|
||||
|
||||
TaskQueue &TaskQueue::Background() { // static
|
||||
static TaskQueue BackgroundQueue { Type::Concurrent, Priority::Background };
|
||||
static TaskQueue BackgroundQueue{Type::Concurrent, Priority::Background};
|
||||
return BackgroundQueue;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,11 +20,11 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <deque>
|
||||
#include <QMutex>
|
||||
#include "base/lambda.h"
|
||||
#include "base/timer.h"
|
||||
#include <QMutex>
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
|
||||
namespace base {
|
||||
|
||||
|
@ -47,8 +47,8 @@ public:
|
|||
};
|
||||
|
||||
// Creating custom serial queues.
|
||||
TaskQueue(Priority priority) : TaskQueue(Type::Serial, priority) {
|
||||
}
|
||||
TaskQueue(Priority priority)
|
||||
: TaskQueue(Type::Serial, priority) {}
|
||||
|
||||
// Default main and two concurrent queues.
|
||||
static TaskQueue &Main();
|
||||
|
@ -100,7 +100,6 @@ private:
|
|||
|
||||
// Only for Serial queues: non-null value means a task is currently processed.
|
||||
bool *destroyed_flag_ = nullptr;
|
||||
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
|
|
|
@ -25,8 +25,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
|
||||
namespace MethodNamespace {
|
||||
|
||||
template <typename Enum>
|
||||
void TestFlags(Enum a, Enum b, Enum c) {
|
||||
template <typename Enum> void TestFlags(Enum a, Enum b, Enum c) {
|
||||
auto abc = a | b;
|
||||
abc |= c;
|
||||
auto test = abc != a;
|
||||
|
@ -66,7 +65,9 @@ enum class Flag : int {
|
|||
two = (1 << 1),
|
||||
three = (1 << 2),
|
||||
};
|
||||
inline constexpr auto is_flag_type(Flag) { return true; }
|
||||
inline constexpr auto is_flag_type(Flag) {
|
||||
return true;
|
||||
}
|
||||
|
||||
class Class {
|
||||
public:
|
||||
|
@ -75,7 +76,9 @@ public:
|
|||
two = (1 << 1),
|
||||
three = (1 << 0),
|
||||
};
|
||||
friend inline constexpr auto is_flag_type(Public) { return true; }
|
||||
friend inline constexpr auto is_flag_type(Public) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static void TestPrivate();
|
||||
|
||||
|
@ -85,8 +88,9 @@ private:
|
|||
two = (1 << 1),
|
||||
three = (1 << 2),
|
||||
};
|
||||
friend inline constexpr auto is_flag_type(Private) { return true; }
|
||||
|
||||
friend inline constexpr auto is_flag_type(Private) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void Class::TestPrivate() {
|
||||
|
@ -107,34 +111,24 @@ enum class Flag : int {
|
|||
|
||||
namespace base {
|
||||
|
||||
template<>
|
||||
struct extended_flags<ExtendedNamespace::Flag> {
|
||||
using type = FlagsNamespace::Flag;
|
||||
};
|
||||
template <> struct extended_flags<ExtendedNamespace::Flag> { using type = FlagsNamespace::Flag; };
|
||||
|
||||
} // namespace base
|
||||
|
||||
TEST_CASE("flags operators on scoped enums", "[flags]") {
|
||||
SECTION("testing non-member flags") {
|
||||
MethodNamespace::TestFlags(
|
||||
FlagsNamespace::Flag::one,
|
||||
FlagsNamespace::Flag::two,
|
||||
FlagsNamespace::Flag::three);
|
||||
MethodNamespace::TestFlags(FlagsNamespace::Flag::one, FlagsNamespace::Flag::two, FlagsNamespace::Flag::three);
|
||||
}
|
||||
SECTION("testing public member flags") {
|
||||
MethodNamespace::TestFlags(
|
||||
FlagsNamespace::Class::Public::one,
|
||||
FlagsNamespace::Class::Public::two,
|
||||
FlagsNamespace::Class::Public::three);
|
||||
MethodNamespace::TestFlags(FlagsNamespace::Class::Public::one, FlagsNamespace::Class::Public::two,
|
||||
FlagsNamespace::Class::Public::three);
|
||||
}
|
||||
SECTION("testing private member flags") {
|
||||
FlagsNamespace::Class::TestPrivate();
|
||||
}
|
||||
SECTION("testing extended flags") {
|
||||
MethodNamespace::TestFlags(
|
||||
ExtendedNamespace::Flag::one,
|
||||
ExtendedNamespace::Flag::two,
|
||||
ExtendedNamespace::Flag::three);
|
||||
MethodNamespace::TestFlags(ExtendedNamespace::Flag::one, ExtendedNamespace::Flag::two,
|
||||
ExtendedNamespace::Flag::three);
|
||||
|
||||
auto onetwo = FlagsNamespace::Flag::one | ExtendedNamespace::Flag::two;
|
||||
auto twoone = ExtendedNamespace::Flag::two | FlagsNamespace::Flag::one;
|
||||
|
|
|
@ -18,8 +18,8 @@ to link the code of portions of this program with the OpenSSL library.
|
|||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include <QTimerEvent>
|
||||
#include "base/timer.h"
|
||||
#include <QTimerEvent>
|
||||
|
||||
namespace base {
|
||||
namespace {
|
||||
|
@ -31,10 +31,11 @@ QObject *TimersAdjuster() {
|
|||
|
||||
} // namespace
|
||||
|
||||
Timer::Timer(base::lambda<void()> callback) : QObject(nullptr)
|
||||
, _callback(std::move(callback))
|
||||
, _type(Qt::PreciseTimer)
|
||||
, _adjusted(false) {
|
||||
Timer::Timer(base::lambda<void()> callback)
|
||||
: QObject(nullptr)
|
||||
, _callback(std::move(callback))
|
||||
, _type(Qt::PreciseTimer)
|
||||
, _adjusted(false) {
|
||||
setRepeat(Repeat::Interval);
|
||||
connect(TimersAdjuster(), &QObject::destroyed, this, [this] { adjust(); }, Qt::QueuedConnection);
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ protected:
|
|||
|
||||
private:
|
||||
enum class Repeat : unsigned {
|
||||
Interval = 0,
|
||||
Interval = 0,
|
||||
SingleShot = 1,
|
||||
};
|
||||
void start(TimeMs timeout, Qt::TimerType type, Repeat repeat);
|
||||
|
@ -94,7 +94,6 @@ private:
|
|||
Qt::TimerType _type : 2;
|
||||
bool _adjusted : 1;
|
||||
unsigned _repeat : 1;
|
||||
|
||||
};
|
||||
|
||||
class DelayedCallTimer final : private QObject {
|
||||
|
@ -111,7 +110,6 @@ protected:
|
|||
|
||||
private:
|
||||
std::map<int, lambda_once<void()>> _callbacks; // Better to use flatmap.
|
||||
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
|
|
|
@ -24,9 +24,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
|
||||
namespace base {
|
||||
|
||||
template <typename T>
|
||||
struct custom_is_fast_copy_type : public std::false_type {
|
||||
};
|
||||
template <typename T> struct custom_is_fast_copy_type : public std::false_type {};
|
||||
// To make your own type a fast copy type just write:
|
||||
// template <>
|
||||
// struct base::custom_is_fast_copy_type<MyTinyType> : public std::true_type {
|
||||
|
@ -34,28 +32,24 @@ struct custom_is_fast_copy_type : public std::false_type {
|
|||
|
||||
namespace internal {
|
||||
|
||||
template <typename ...Types>
|
||||
struct type_list_contains;
|
||||
template <typename... Types> struct type_list_contains;
|
||||
|
||||
template <typename T>
|
||||
struct type_list_contains<T> : public std::false_type {
|
||||
};
|
||||
template <typename T> struct type_list_contains<T> : public std::false_type {};
|
||||
|
||||
template <typename T, typename Head, typename ...Types>
|
||||
struct type_list_contains<T, Head, Types...> : public std::integral_constant<bool, std::is_same<Head, T>::value || type_list_contains<T, Types...>::value> {
|
||||
};
|
||||
template <typename T, typename Head, typename... Types>
|
||||
struct type_list_contains<T, Head, Types...>
|
||||
: public std::integral_constant<bool, std::is_same<Head, T>::value || type_list_contains<T, Types...>::value> {};
|
||||
|
||||
template <typename T>
|
||||
using is_std_unsigned_int = type_list_contains<T, unsigned char, unsigned short int, unsigned int, unsigned long int>;
|
||||
|
||||
template <typename T>
|
||||
using is_std_signed_int = type_list_contains<T, signed char, short int, int, long int>;
|
||||
template <typename T> using is_std_signed_int = type_list_contains<T, signed char, short int, int, long int>;
|
||||
|
||||
template <typename T>
|
||||
using is_std_integral = std::integral_constant<bool, is_std_unsigned_int<T>::value || is_std_signed_int<T>::value || type_list_contains<T, bool, char, wchar_t>::value>;
|
||||
using is_std_integral = std::integral_constant<bool, is_std_unsigned_int<T>::value || is_std_signed_int<T>::value ||
|
||||
type_list_contains<T, bool, char, wchar_t>::value>;
|
||||
|
||||
template <typename T>
|
||||
using is_std_float = type_list_contains<T, float, double, long double>;
|
||||
template <typename T> using is_std_float = type_list_contains<T, float, double, long double>;
|
||||
|
||||
template <typename T>
|
||||
using is_std_arith = std::integral_constant<bool, is_std_integral<T>::value || is_std_float<T>::value>;
|
||||
|
@ -63,55 +57,34 @@ using is_std_arith = std::integral_constant<bool, is_std_integral<T>::value || i
|
|||
template <typename T>
|
||||
using is_std_fundamental = std::integral_constant<bool, is_std_arith<T>::value || std::is_same<T, void>::value>;
|
||||
|
||||
template <typename T>
|
||||
struct is_pointer : public std::false_type {
|
||||
};
|
||||
template <typename T> struct is_pointer : public std::false_type {};
|
||||
|
||||
template <typename T> struct is_pointer<T *> : public std::true_type {};
|
||||
|
||||
template <typename T> struct is_member_pointer : public std::false_type {};
|
||||
|
||||
template <typename T, typename C> struct is_member_pointer<T C::*> : public std::true_type {};
|
||||
|
||||
template <typename T>
|
||||
struct is_pointer<T*> : public std::true_type {
|
||||
};
|
||||
using is_fast_copy_type =
|
||||
std::integral_constant<bool, is_std_fundamental<T>::value || is_pointer<T>::value || is_member_pointer<T>::value ||
|
||||
custom_is_fast_copy_type<T>::value>;
|
||||
|
||||
template <typename T>
|
||||
struct is_member_pointer : public std::false_type {
|
||||
};
|
||||
template <typename T> struct add_const_reference { using type = const T &; };
|
||||
|
||||
template <typename T, typename C>
|
||||
struct is_member_pointer<T C::*> : public std::true_type {
|
||||
};
|
||||
template <> struct add_const_reference<void> { using type = void; };
|
||||
|
||||
template <typename T>
|
||||
using is_fast_copy_type = std::integral_constant<bool, is_std_fundamental<T>::value || is_pointer<T>::value || is_member_pointer<T>::value || custom_is_fast_copy_type<T>::value>;
|
||||
template <typename T> using add_const_reference_t = typename add_const_reference<T>::type;
|
||||
|
||||
template <typename T>
|
||||
struct add_const_reference {
|
||||
using type = const T &;
|
||||
};
|
||||
template <typename T> struct remove_pointer { using type = T; };
|
||||
|
||||
template <>
|
||||
struct add_const_reference<void> {
|
||||
using type = void;
|
||||
};
|
||||
template <typename T> struct remove_pointer<T *> { using type = T; };
|
||||
|
||||
template <typename T>
|
||||
using add_const_reference_t = typename add_const_reference<T>::type;
|
||||
|
||||
template <typename T>
|
||||
struct remove_pointer {
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct remove_pointer<T*> {
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using remove_pointer_t = typename remove_pointer<T>::type;
|
||||
template <typename T> using remove_pointer_t = typename remove_pointer<T>::type;
|
||||
|
||||
} // namespace internal
|
||||
|
||||
template <typename T>
|
||||
struct type_traits {
|
||||
template <typename T> struct type_traits {
|
||||
using is_std_unsigned_int = internal::is_std_unsigned_int<T>;
|
||||
using is_std_signed_int = internal::is_std_signed_int<T>;
|
||||
using is_std_integral = internal::is_std_integral<T>;
|
||||
|
@ -126,7 +99,6 @@ struct type_traits {
|
|||
using pointed_type = internal::remove_pointer_t<T>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using parameter_type = typename type_traits<T>::parameter_type;
|
||||
template <typename T> using parameter_type = typename type_traits<T>::parameter_type;
|
||||
|
||||
} // namespace base
|
||||
|
|
|
@ -25,16 +25,13 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
// We use base::variant<> alias and base::get_if() helper while we don't have std::variant<>.
|
||||
namespace base {
|
||||
|
||||
template <typename... Types>
|
||||
using variant = mapbox::util::variant<Types...>;
|
||||
template <typename... Types> using variant = mapbox::util::variant<Types...>;
|
||||
|
||||
template <typename T, typename... Types>
|
||||
inline T *get_if(variant<Types...> *v) {
|
||||
template <typename T, typename... Types> inline T *get_if(variant<Types...> *v) {
|
||||
return (v && v->template is<T>()) ? &v->template get_unchecked<T>() : nullptr;
|
||||
}
|
||||
|
||||
template <typename T, typename... Types>
|
||||
inline const T *get_if(const variant<Types...> *v) {
|
||||
template <typename T, typename... Types> inline const T *get_if(const variant<Types...> *v) {
|
||||
return (v && v->template is<T>()) ? &v->template get_unchecked<T>() : nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,23 +22,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
|
||||
#include <memory>
|
||||
// @todo replace this with std::experimental::observer_ptr
|
||||
#include <utility>
|
||||
#include <QCoreApplication>
|
||||
#include <utility>
|
||||
|
||||
namespace base {
|
||||
|
||||
class enable_weak_from_this;
|
||||
|
||||
template <typename T>
|
||||
class weak_unique_ptr;
|
||||
template <typename T> class weak_unique_ptr;
|
||||
|
||||
class enable_weak_from_this {
|
||||
public:
|
||||
enable_weak_from_this() = default;
|
||||
enable_weak_from_this(const enable_weak_from_this &other) noexcept {
|
||||
}
|
||||
enable_weak_from_this(enable_weak_from_this &&other) noexcept {
|
||||
}
|
||||
enable_weak_from_this(const enable_weak_from_this &other) noexcept {}
|
||||
enable_weak_from_this(enable_weak_from_this &&other) noexcept {}
|
||||
enable_weak_from_this &operator=(const enable_weak_from_this &other) noexcept {
|
||||
return *this;
|
||||
}
|
||||
|
@ -47,31 +44,28 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
template <typename Child>
|
||||
friend class weak_unique_ptr;
|
||||
template <typename Child> friend class weak_unique_ptr;
|
||||
|
||||
std::shared_ptr<enable_weak_from_this*> getGuarded() {
|
||||
std::shared_ptr<enable_weak_from_this *> getGuarded() {
|
||||
if (!_guarded) {
|
||||
_guarded = std::make_shared<enable_weak_from_this*>(static_cast<enable_weak_from_this*>(this));
|
||||
_guarded = std::make_shared<enable_weak_from_this *>(static_cast<enable_weak_from_this *>(this));
|
||||
}
|
||||
return _guarded;
|
||||
}
|
||||
|
||||
std::shared_ptr<enable_weak_from_this*> _guarded;
|
||||
|
||||
std::shared_ptr<enable_weak_from_this *> _guarded;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class weak_unique_ptr {
|
||||
template <typename T> class weak_unique_ptr {
|
||||
public:
|
||||
weak_unique_ptr() = default;
|
||||
weak_unique_ptr(T *value) : _guarded(value ? value->getGuarded() : std::shared_ptr<enable_weak_from_this*>()) {
|
||||
}
|
||||
weak_unique_ptr(const std::unique_ptr<T> &value) : weak_unique_ptr(value.get()) {
|
||||
}
|
||||
weak_unique_ptr(T *value)
|
||||
: _guarded(value ? value->getGuarded() : std::shared_ptr<enable_weak_from_this *>()) {}
|
||||
weak_unique_ptr(const std::unique_ptr<T> &value)
|
||||
: weak_unique_ptr(value.get()) {}
|
||||
|
||||
weak_unique_ptr &operator=(T *value) {
|
||||
_guarded = value ? value->getGuarded() : std::shared_ptr<enable_weak_from_this*>();
|
||||
_guarded = value ? value->getGuarded() : std::shared_ptr<enable_weak_from_this *>();
|
||||
return *this;
|
||||
}
|
||||
weak_unique_ptr &operator=(const std::unique_ptr<T> &value) {
|
||||
|
@ -80,7 +74,7 @@ public:
|
|||
|
||||
T *get() const noexcept {
|
||||
if (auto shared = _guarded.lock()) {
|
||||
return static_cast<T*>(*shared);
|
||||
return static_cast<T *>(*shared);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -95,50 +89,44 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
std::weak_ptr<enable_weak_from_this*> _guarded;
|
||||
|
||||
std::weak_ptr<enable_weak_from_this *> _guarded;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline bool operator==(const weak_unique_ptr<T> &pointer, std::nullptr_t) {
|
||||
template <typename T> inline bool operator==(const weak_unique_ptr<T> &pointer, std::nullptr_t) {
|
||||
return (pointer.get() == nullptr);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator==(std::nullptr_t, const weak_unique_ptr<T> &pointer) {
|
||||
template <typename T> inline bool operator==(std::nullptr_t, const weak_unique_ptr<T> &pointer) {
|
||||
return (pointer == nullptr);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator!=(const weak_unique_ptr<T> &pointer, std::nullptr_t) {
|
||||
template <typename T> inline bool operator!=(const weak_unique_ptr<T> &pointer, std::nullptr_t) {
|
||||
return !(pointer == nullptr);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator!=(std::nullptr_t, const weak_unique_ptr<T> &pointer) {
|
||||
template <typename T> inline bool operator!=(std::nullptr_t, const weak_unique_ptr<T> &pointer) {
|
||||
return !(pointer == nullptr);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
weak_unique_ptr<T> make_weak_unique(T *value) {
|
||||
template <typename T> weak_unique_ptr<T> make_weak_unique(T *value) {
|
||||
return weak_unique_ptr<T>(value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
weak_unique_ptr<T> make_weak_unique(const std::unique_ptr<T> &value) {
|
||||
template <typename T> weak_unique_ptr<T> make_weak_unique(const std::unique_ptr<T> &value) {
|
||||
return weak_unique_ptr<T>(value);
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
|
||||
#ifdef QT_VERSION
|
||||
template <typename Lambda>
|
||||
inline void InvokeQueued(base::enable_weak_from_this *context, Lambda &&lambda) {
|
||||
QObject proxy;
|
||||
QObject::connect(&proxy, &QObject::destroyed, QCoreApplication::instance(), [guard = base::make_weak_unique(context), lambda = std::forward<Lambda>(lambda)] {
|
||||
if (guard) {
|
||||
lambda();
|
||||
}
|
||||
}, Qt::QueuedConnection);
|
||||
template <typename Lambda> inline void InvokeQueued(base::enable_weak_from_this *context, Lambda &&lambda) {
|
||||
QObject proxy;
|
||||
QObject::connect(&proxy, &QObject::destroyed, QCoreApplication::instance(),
|
||||
[guard = base::make_weak_unique(context), lambda = std::forward<Lambda>(lambda)] {
|
||||
if (guard) {
|
||||
lambda();
|
||||
}
|
||||
},
|
||||
Qt::QueuedConnection);
|
||||
}
|
||||
#endif // QT_VERSION
|
||||
|
|
|
@ -25,8 +25,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
|
||||
#include <QByteArray>
|
||||
|
||||
#include "minizip/zip.h"
|
||||
#include "minizip/unzip.h"
|
||||
#include "minizip/zip.h"
|
||||
|
||||
#include "logs.h"
|
||||
|
||||
|
@ -35,8 +35,8 @@ namespace internal {
|
|||
|
||||
class InMemoryFile {
|
||||
public:
|
||||
InMemoryFile(const QByteArray &data = QByteArray()) : _data(data) {
|
||||
}
|
||||
InMemoryFile(const QByteArray &data = QByteArray())
|
||||
: _data(data) {}
|
||||
|
||||
zlib_filefunc_def funcs() {
|
||||
zlib_filefunc_def result;
|
||||
|
@ -74,7 +74,7 @@ private:
|
|||
return this;
|
||||
}
|
||||
|
||||
uLong read(voidpf stream, void* buf, uLong size) {
|
||||
uLong read(voidpf stream, void *buf, uLong size) {
|
||||
uLong toRead = 0;
|
||||
if (!_error) {
|
||||
if (_data.size() > int(_position)) {
|
||||
|
@ -89,7 +89,7 @@ private:
|
|||
return toRead;
|
||||
}
|
||||
|
||||
uLong write(voidpf stream, const void* buf, uLong size) {
|
||||
uLong write(voidpf stream, const void *buf, uLong size) {
|
||||
if (_data.size() < int(_position + size)) {
|
||||
_data.resize(_position + size);
|
||||
}
|
||||
|
@ -127,38 +127,37 @@ private:
|
|||
return _error;
|
||||
}
|
||||
|
||||
static voidpf Open(voidpf opaque, const char* filename, int mode) {
|
||||
return static_cast<InMemoryFile*>(opaque)->open(filename, mode);
|
||||
static voidpf Open(voidpf opaque, const char *filename, int mode) {
|
||||
return static_cast<InMemoryFile *>(opaque)->open(filename, mode);
|
||||
}
|
||||
|
||||
static uLong Read(voidpf opaque, voidpf stream, void* buf, uLong size) {
|
||||
return static_cast<InMemoryFile*>(opaque)->read(stream, buf, size);
|
||||
static uLong Read(voidpf opaque, voidpf stream, void *buf, uLong size) {
|
||||
return static_cast<InMemoryFile *>(opaque)->read(stream, buf, size);
|
||||
}
|
||||
|
||||
static uLong Write(voidpf opaque, voidpf stream, const void* buf, uLong size) {
|
||||
return static_cast<InMemoryFile*>(opaque)->write(stream, buf, size);
|
||||
static uLong Write(voidpf opaque, voidpf stream, const void *buf, uLong size) {
|
||||
return static_cast<InMemoryFile *>(opaque)->write(stream, buf, size);
|
||||
}
|
||||
|
||||
static int Close(voidpf opaque, voidpf stream) {
|
||||
return static_cast<InMemoryFile*>(opaque)->close(stream);
|
||||
return static_cast<InMemoryFile *>(opaque)->close(stream);
|
||||
}
|
||||
|
||||
static int Error(voidpf opaque, voidpf stream) {
|
||||
return static_cast<InMemoryFile*>(opaque)->error(stream);
|
||||
return static_cast<InMemoryFile *>(opaque)->error(stream);
|
||||
}
|
||||
|
||||
static long Tell(voidpf opaque, voidpf stream) {
|
||||
return static_cast<InMemoryFile*>(opaque)->tell(stream);
|
||||
return static_cast<InMemoryFile *>(opaque)->tell(stream);
|
||||
}
|
||||
|
||||
static long Seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
|
||||
return static_cast<InMemoryFile*>(opaque)->seek(stream, offset, origin);
|
||||
return static_cast<InMemoryFile *>(opaque)->seek(stream, offset, origin);
|
||||
}
|
||||
|
||||
uLong _position = 0;
|
||||
int _error = 0;
|
||||
QByteArray _data;
|
||||
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
@ -168,7 +167,8 @@ constexpr int kCaseInsensitive = 2;
|
|||
|
||||
class FileToRead {
|
||||
public:
|
||||
FileToRead(const QByteArray &content) : _data(content) {
|
||||
FileToRead(const QByteArray &content)
|
||||
: _data(content) {
|
||||
auto funcs = _data.funcs();
|
||||
if (!(_handle = unzOpen2(nullptr, &funcs))) {
|
||||
_error = -1;
|
||||
|
@ -189,26 +189,12 @@ public:
|
|||
return error();
|
||||
}
|
||||
|
||||
int getCurrentFileInfo(
|
||||
unz_file_info *pfile_info,
|
||||
char *szFileName,
|
||||
uLong fileNameBufferSize,
|
||||
void *extraField,
|
||||
uLong extraFieldBufferSize,
|
||||
char *szComment,
|
||||
uLong commentBufferSize
|
||||
) {
|
||||
int getCurrentFileInfo(unz_file_info *pfile_info, char *szFileName, uLong fileNameBufferSize, void *extraField,
|
||||
uLong extraFieldBufferSize, char *szComment, uLong commentBufferSize) {
|
||||
if (error() == UNZ_OK) {
|
||||
_error = _handle ? unzGetCurrentFileInfo(
|
||||
_handle,
|
||||
pfile_info,
|
||||
szFileName,
|
||||
fileNameBufferSize,
|
||||
extraField,
|
||||
extraFieldBufferSize,
|
||||
szComment,
|
||||
commentBufferSize
|
||||
) : -1;
|
||||
_error = _handle ? unzGetCurrentFileInfo(_handle, pfile_info, szFileName, fileNameBufferSize, extraField,
|
||||
extraFieldBufferSize, szComment, commentBufferSize) :
|
||||
-1;
|
||||
}
|
||||
return error();
|
||||
}
|
||||
|
@ -240,7 +226,7 @@ public:
|
|||
}
|
||||
|
||||
QByteArray readCurrentFileContent(int fileSizeLimit) {
|
||||
unz_file_info fileInfo = { 0 };
|
||||
unz_file_info fileInfo = {0};
|
||||
if (getCurrentFileInfo(&fileInfo, nullptr, 0, nullptr, 0, nullptr, 0) != UNZ_OK) {
|
||||
LOG(("Error: could not get current file info in a zip file."));
|
||||
return QByteArray();
|
||||
|
@ -249,7 +235,9 @@ public:
|
|||
auto size = fileInfo.uncompressed_size;
|
||||
if (size > static_cast<quint32>(fileSizeLimit)) {
|
||||
if (_error == UNZ_OK) _error = -1;
|
||||
LOG(("Error: current file is too large (should be less than %1, got %2) in a zip file.").arg(fileSizeLimit).arg(size));
|
||||
LOG(("Error: current file is too large (should be less than %1, got %2) in a zip file.")
|
||||
.arg(fileSizeLimit)
|
||||
.arg(size));
|
||||
return QByteArray();
|
||||
}
|
||||
if (openCurrentFile() != UNZ_OK) {
|
||||
|
@ -308,7 +296,6 @@ private:
|
|||
internal::InMemoryFile _data;
|
||||
unzFile _handle = nullptr;
|
||||
int _error = 0;
|
||||
|
||||
};
|
||||
|
||||
class FileToWrite {
|
||||
|
@ -320,35 +307,18 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
int openNewFile(
|
||||
const char *filename,
|
||||
const zip_fileinfo *zipfi,
|
||||
const void *extrafield_local,
|
||||
uInt size_extrafield_local,
|
||||
const void* extrafield_global,
|
||||
uInt size_extrafield_global,
|
||||
const char* comment,
|
||||
int method,
|
||||
int level
|
||||
) {
|
||||
int openNewFile(const char *filename, const zip_fileinfo *zipfi, const void *extrafield_local,
|
||||
uInt size_extrafield_local, const void *extrafield_global, uInt size_extrafield_global,
|
||||
const char *comment, int method, int level) {
|
||||
if (error() == ZIP_OK) {
|
||||
_error = _handle ? zipOpenNewFileInZip(
|
||||
_handle,
|
||||
filename,
|
||||
zipfi,
|
||||
extrafield_local,
|
||||
size_extrafield_local,
|
||||
extrafield_global,
|
||||
size_extrafield_global,
|
||||
comment,
|
||||
method,
|
||||
level
|
||||
) : -1;
|
||||
_error = _handle ? zipOpenNewFileInZip(_handle, filename, zipfi, extrafield_local, size_extrafield_local,
|
||||
extrafield_global, size_extrafield_global, comment, method, level) :
|
||||
-1;
|
||||
}
|
||||
return error();
|
||||
}
|
||||
|
||||
int writeInFile(const void* buf, unsigned len) {
|
||||
int writeInFile(const void *buf, unsigned len) {
|
||||
if (error() == ZIP_OK) {
|
||||
_error = _handle ? zipWriteInFileInZip(_handle, buf, len) : -1;
|
||||
}
|
||||
|
@ -388,7 +358,6 @@ private:
|
|||
internal::InMemoryFile _data;
|
||||
zipFile _handle = nullptr;
|
||||
int _error = 0;
|
||||
|
||||
};
|
||||
|
||||
} // namespace zlib
|
||||
|
|
|
@ -18,38 +18,43 @@ to link the code of portions of this program with the OpenSSL library.
|
|||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include <QDesktopServices>
|
||||
#include "boxes/about_box.h"
|
||||
#include <QDesktopServices>
|
||||
|
||||
#include "application.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "config.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "application.h"
|
||||
#include "platform/platform_file_utilities.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "platform/platform_file_utilities.h"
|
||||
|
||||
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)
|
||||
, _text2(this, lang(lng_about_text_2), Ui::FlatLabel::InitType::Rich, st::aboutLabel)
|
||||
, _text3(this, st::aboutLabel) {
|
||||
}
|
||||
: _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)
|
||||
, _text2(this, lang(lng_about_text_2), Ui::FlatLabel::InitType::Rich, st::aboutLabel)
|
||||
, _text3(this, st::aboutLabel) {}
|
||||
|
||||
void AboutBox::prepare() {
|
||||
constexpr auto test = std::is_convertible<const char*, QString>::value;
|
||||
constexpr auto test = std::is_convertible<const char *, QString>::value;
|
||||
setTitle([] { return str_const_toString(AppName); });
|
||||
|
||||
addButton(langFactory(lng_close), [this] { closeBox(); });
|
||||
|
||||
_text3->setRichText(lng_about_text_3(lt_faq_open, qsl("[a href=\"%1\"]").arg(telegramFaqLink()), lt_faq_close, qsl("[/a]")));
|
||||
_text3->setRichText(
|
||||
lng_about_text_3(lt_faq_open, qsl("[a href=\"%1\"]").arg(telegramFaqLink()), lt_faq_close, qsl("[/a]")));
|
||||
|
||||
_version->setClickedCallback([this] { showVersionHistory(); });
|
||||
|
||||
setDimensions(st::aboutWidth, st::aboutTextTop + _text1->height() + st::aboutSkip + _text2->height() + st::aboutSkip + _text3->height());
|
||||
setDimensions(st::aboutWidth, st::aboutTextTop + _text1->height() + st::aboutSkip + _text2->height() +
|
||||
st::aboutSkip + _text3->height());
|
||||
}
|
||||
|
||||
void AboutBox::resizeEvent(QResizeEvent *e) {
|
||||
|
@ -76,7 +81,7 @@ void AboutBox::keyPressEvent(QKeyEvent *e) {
|
|||
QString telegramFaqLink() {
|
||||
auto result = qsl("https://telegram.org/faq");
|
||||
auto language = Lang::Current().id();
|
||||
for (auto faqLanguage : { "de", "es", "it", "ko", "br" }) {
|
||||
for (auto faqLanguage : {"de", "es", "it", "ko", "br"}) {
|
||||
if (language.startsWith(QLatin1String(faqLanguage))) {
|
||||
result.append('/').append(faqLanguage);
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ class FlatLabel;
|
|||
|
||||
class AboutBox : public BoxContent {
|
||||
public:
|
||||
AboutBox(QWidget*);
|
||||
AboutBox(QWidget *);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
@ -44,7 +44,6 @@ private:
|
|||
object_ptr<Ui::FlatLabel> _text1;
|
||||
object_ptr<Ui::FlatLabel> _text2;
|
||||
object_ptr<Ui::FlatLabel> _text3;
|
||||
|
||||
};
|
||||
|
||||
QString telegramFaqLink();
|
||||
|
|
|
@ -18,25 +18,27 @@ to link the code of portions of this program with the OpenSSL library.
|
|||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include <algorithm>
|
||||
#include "boxes/abstract_box.h"
|
||||
#include <algorithm>
|
||||
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_profile.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "ui/effects/widget_fade_wrap.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_profile.h"
|
||||
#include "ui/effects/widget_fade_wrap.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
|
||||
QPointer<Ui::RoundButton> BoxContent::addButton(base::lambda<QString()> textFactory, base::lambda<void()> clickCallback) {
|
||||
QPointer<Ui::RoundButton> BoxContent::addButton(base::lambda<QString()> textFactory,
|
||||
base::lambda<void()> clickCallback) {
|
||||
return addButton(std::move(textFactory), std::move(clickCallback), st::defaultBoxButton);
|
||||
}
|
||||
|
||||
QPointer<Ui::RoundButton> BoxContent::addLeftButton(base::lambda<QString()> textFactory, base::lambda<void()> clickCallback) {
|
||||
QPointer<Ui::RoundButton> BoxContent::addLeftButton(base::lambda<QString()> textFactory,
|
||||
base::lambda<void()> clickCallback) {
|
||||
return getDelegate()->addLeftButton(std::move(textFactory), std::move(clickCallback), st::defaultBoxButton);
|
||||
}
|
||||
|
||||
|
@ -105,12 +107,13 @@ void BoxContent::onDraggingScrollDelta(int delta) {
|
|||
}
|
||||
|
||||
void BoxContent::onDraggingScrollTimer() {
|
||||
auto delta = (_draggingScrollDelta > 0) ? std::min(_draggingScrollDelta * 3 / 20 + 1, qint32(MaxScrollSpeed)) : std::max(_draggingScrollDelta * 3 / 20 - 1, -qint32(MaxScrollSpeed));
|
||||
auto delta = (_draggingScrollDelta > 0) ? std::min(_draggingScrollDelta * 3 / 20 + 1, qint32(MaxScrollSpeed)) :
|
||||
std::max(_draggingScrollDelta * 3 / 20 - 1, -qint32(MaxScrollSpeed));
|
||||
_scroll->scrollToY(_scroll->scrollTop() + delta);
|
||||
}
|
||||
|
||||
void BoxContent::updateInnerVisibleTopBottom() {
|
||||
if (auto widget = static_cast<TWidget*>(_scroll ? _scroll->widget() : nullptr)) {
|
||||
if (auto widget = static_cast<TWidget *>(_scroll ? _scroll->widget() : nullptr)) {
|
||||
auto top = _scroll->scrollTop();
|
||||
widget->setVisibleTopBottom(top, top + _scroll->height());
|
||||
}
|
||||
|
@ -210,9 +213,10 @@ void BoxContent::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
}
|
||||
|
||||
AbstractBox::AbstractBox(QWidget *parent, Window::Controller *controller, object_ptr<BoxContent> content) : LayerWidget(parent)
|
||||
, _controller(controller)
|
||||
, _content(std::move(content)) {
|
||||
AbstractBox::AbstractBox(QWidget *parent, Window::Controller *controller, object_ptr<BoxContent> content)
|
||||
: LayerWidget(parent)
|
||||
, _controller(controller)
|
||||
, _content(std::move(content)) {
|
||||
subscribe(Lang::Current().updated(), [this] { refreshLang(); });
|
||||
_content->setParent(this);
|
||||
_content->setDelegate(this);
|
||||
|
@ -263,7 +267,9 @@ void AbstractBox::paintEvent(QPaintEvent *e) {
|
|||
void AbstractBox::paintAdditionalTitle(Painter &p) {
|
||||
p.setFont(st::boxLayerTitleAdditionalFont);
|
||||
p.setPen(st::boxTitleAdditionalFg);
|
||||
p.drawTextLeft(_titleLeft + (_title ? _title->width() : 0) + st::boxLayerTitleAdditionalSkip, _titleTop + st::boxTitleFont->ascent - st::boxLayerTitleAdditionalFont->ascent, width(), _additionalTitle);
|
||||
p.drawTextLeft(_titleLeft + (_title ? _title->width() : 0) + st::boxLayerTitleAdditionalSkip,
|
||||
_titleTop + st::boxTitleFont->ascent - st::boxLayerTitleAdditionalFont->ascent, width(),
|
||||
_additionalTitle);
|
||||
}
|
||||
|
||||
void AbstractBox::parentResized() {
|
||||
|
@ -349,7 +355,8 @@ void AbstractBox::clearButtons() {
|
|||
_leftButton.destroy();
|
||||
}
|
||||
|
||||
QPointer<Ui::RoundButton> AbstractBox::addButton(base::lambda<QString()> textFactory, base::lambda<void()> clickCallback, const style::RoundButton &st) {
|
||||
QPointer<Ui::RoundButton> AbstractBox::addButton(base::lambda<QString()> textFactory,
|
||||
base::lambda<void()> clickCallback, const style::RoundButton &st) {
|
||||
_buttons.push_back(object_ptr<Ui::RoundButton>(this, std::move(textFactory), st));
|
||||
auto result = QPointer<Ui::RoundButton>(_buttons.back());
|
||||
result->setClickedCallback(std::move(clickCallback));
|
||||
|
@ -358,7 +365,8 @@ QPointer<Ui::RoundButton> AbstractBox::addButton(base::lambda<QString()> textFac
|
|||
return result;
|
||||
}
|
||||
|
||||
QPointer<Ui::RoundButton> AbstractBox::addLeftButton(base::lambda<QString()> textFactory, base::lambda<void()> clickCallback, const style::RoundButton &st) {
|
||||
QPointer<Ui::RoundButton> AbstractBox::addLeftButton(base::lambda<QString()> textFactory,
|
||||
base::lambda<void()> clickCallback, const style::RoundButton &st) {
|
||||
_leftButton = object_ptr<Ui::RoundButton>(this, std::move(textFactory), st);
|
||||
auto result = QPointer<Ui::RoundButton>(_leftButton);
|
||||
result->setClickedCallback(std::move(clickCallback));
|
||||
|
@ -379,7 +387,8 @@ void AbstractBox::setDimensions(int newWidth, int maxHeight) {
|
|||
auto newGeometry = geometry();
|
||||
auto parentHeight = parentWidget()->height();
|
||||
if (newGeometry.top() + newGeometry.height() + st::boxVerticalMargin > parentHeight) {
|
||||
auto newTop = std::max(parentHeight - int(st::boxVerticalMargin) - newGeometry.height(), (parentHeight - newGeometry.height()) / 2);
|
||||
auto newTop = std::max(parentHeight - int(st::boxVerticalMargin) - newGeometry.height(),
|
||||
(parentHeight - newGeometry.height()) / 2);
|
||||
if (newTop != newGeometry.top()) {
|
||||
move(newGeometry.left(), newTop);
|
||||
}
|
||||
|
@ -422,11 +431,11 @@ void AbstractBox::keyPressEvent(QKeyEvent *e) {
|
|||
}
|
||||
}
|
||||
|
||||
BoxLayerTitleShadow::BoxLayerTitleShadow(QWidget *parent) : Ui::PlainShadow(parent, st::boxLayerTitleShadow) {
|
||||
}
|
||||
BoxLayerTitleShadow::BoxLayerTitleShadow(QWidget *parent)
|
||||
: Ui::PlainShadow(parent, st::boxLayerTitleShadow) {}
|
||||
|
||||
BoxContentDivider::BoxContentDivider(QWidget *parent) : TWidget(parent) {
|
||||
}
|
||||
BoxContentDivider::BoxContentDivider(QWidget *parent)
|
||||
: TWidget(parent) {}
|
||||
|
||||
int BoxContentDivider::resizeGetHeight(int newWidth) {
|
||||
return st::rightsDividerHeight;
|
||||
|
@ -437,6 +446,7 @@ void BoxContentDivider::paintEvent(QPaintEvent *e) {
|
|||
p.fillRect(e->rect(), st::contactsAboutBg);
|
||||
auto dividerFillTop = myrtlrect(0, 0, width(), st::profileDividerTop.height());
|
||||
st::profileDividerTop.fill(p, dividerFillTop);
|
||||
auto dividerFillBottom = myrtlrect(0, height() - st::profileDividerBottom.height(), width(), st::profileDividerBottom.height());
|
||||
auto dividerFillBottom =
|
||||
myrtlrect(0, height() - st::profileDividerBottom.height(), width(), st::profileDividerBottom.height());
|
||||
st::profileDividerBottom.fill(p, dividerFillBottom);
|
||||
}
|
||||
|
|
|
@ -22,18 +22,17 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
|
||||
#include "base/lambda.h"
|
||||
#include "base/observer.h"
|
||||
#include "ui/text/text_entity.h"
|
||||
#include "ui/widgets/shadow.h"
|
||||
#include "ui/twidget.h"
|
||||
#include "layerwidget.h"
|
||||
#include "ui/text/text_entity.h"
|
||||
#include "ui/twidget.h"
|
||||
#include "ui/widgets/shadow.h"
|
||||
|
||||
namespace Ui {
|
||||
class RoundButton;
|
||||
class IconButton;
|
||||
class ScrollArea;
|
||||
class FlatLabel;
|
||||
template <typename Widget>
|
||||
class WidgetFadeWrap;
|
||||
template <typename Widget> class WidgetFadeWrap;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Window {
|
||||
|
@ -51,15 +50,17 @@ public:
|
|||
virtual void setAdditionalTitle(base::lambda<QString()> additionalFactory) = 0;
|
||||
|
||||
virtual void clearButtons() = 0;
|
||||
virtual QPointer<Ui::RoundButton> addButton(base::lambda<QString()> textFactory, base::lambda<void()> clickCallback, const style::RoundButton &st) = 0;
|
||||
virtual QPointer<Ui::RoundButton> addLeftButton(base::lambda<QString()> textFactory, base::lambda<void()> clickCallback, const style::RoundButton &st) = 0;
|
||||
virtual QPointer<Ui::RoundButton> addButton(base::lambda<QString()> textFactory, base::lambda<void()> clickCallback,
|
||||
const style::RoundButton &st) = 0;
|
||||
virtual QPointer<Ui::RoundButton> addLeftButton(base::lambda<QString()> textFactory,
|
||||
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 {
|
||||
|
@ -79,7 +80,7 @@ public:
|
|||
|
||||
void setTitle(base::lambda<QString()> titleFactory) {
|
||||
if (titleFactory) {
|
||||
getDelegate()->setTitle([titleFactory] { return TextWithEntities { titleFactory(), EntitiesInText() }; });
|
||||
getDelegate()->setTitle([titleFactory] { return TextWithEntities{titleFactory(), EntitiesInText()}; });
|
||||
} else {
|
||||
getDelegate()->setTitle(base::lambda<TextWithEntities()>());
|
||||
}
|
||||
|
@ -96,7 +97,8 @@ public:
|
|||
}
|
||||
QPointer<Ui::RoundButton> addButton(base::lambda<QString()> textFactory, base::lambda<void()> clickCallback);
|
||||
QPointer<Ui::RoundButton> addLeftButton(base::lambda<QString()> textFactory, base::lambda<void()> clickCallback);
|
||||
QPointer<Ui::RoundButton> addButton(base::lambda<QString()> textFactory, base::lambda<void()> clickCallback, const style::RoundButton &st) {
|
||||
QPointer<Ui::RoundButton> addButton(base::lambda<QString()> textFactory, base::lambda<void()> clickCallback,
|
||||
const style::RoundButton &st) {
|
||||
return getDelegate()->addButton(std::move(textFactory), std::move(clickCallback), st);
|
||||
}
|
||||
void updateButtonsGeometry() {
|
||||
|
@ -152,16 +154,14 @@ protected:
|
|||
return result;
|
||||
}
|
||||
|
||||
template <typename Widget>
|
||||
QPointer<Widget> setInnerWidget(object_ptr<Widget> inner, int topSkip = 0) {
|
||||
template <typename Widget> QPointer<Widget> setInnerWidget(object_ptr<Widget> inner, int topSkip = 0) {
|
||||
auto result = QPointer<Widget>(inner.data());
|
||||
setInnerTopSkip(topSkip);
|
||||
setInner(std::move(inner));
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Widget>
|
||||
object_ptr<Widget> takeInnerWidget() {
|
||||
template <typename Widget> object_ptr<Widget> takeInnerWidget() {
|
||||
return static_object_cast<Widget>(doTakeInnerWidget());
|
||||
}
|
||||
|
||||
|
@ -196,13 +196,12 @@ private:
|
|||
bool _preparing = false;
|
||||
bool _noContentMargin = false;
|
||||
int _innerTopSkip = 0;
|
||||
object_ptr<Ui::ScrollArea> _scroll = { nullptr };
|
||||
object_ptr<Ui::WidgetFadeWrap<BoxLayerTitleShadow>> _topShadow = { nullptr };
|
||||
object_ptr<Ui::WidgetFadeWrap<BoxLayerTitleShadow>> _bottomShadow = { nullptr };
|
||||
object_ptr<Ui::ScrollArea> _scroll = {nullptr};
|
||||
object_ptr<Ui::WidgetFadeWrap<BoxLayerTitleShadow>> _topShadow = {nullptr};
|
||||
object_ptr<Ui::WidgetFadeWrap<BoxLayerTitleShadow>> _bottomShadow = {nullptr};
|
||||
|
||||
object_ptr<QTimer> _draggingScrollTimer = { nullptr };
|
||||
object_ptr<QTimer> _draggingScrollTimer = {nullptr};
|
||||
int _draggingScrollDelta = 0;
|
||||
|
||||
};
|
||||
|
||||
class AbstractBox : public LayerWidget, public BoxContentDelegate, protected base::Subscriber {
|
||||
|
@ -219,8 +218,10 @@ public:
|
|||
void setAdditionalTitle(base::lambda<QString()> additionalFactory) override;
|
||||
|
||||
void clearButtons() override;
|
||||
QPointer<Ui::RoundButton> addButton(base::lambda<QString()> textFactory, base::lambda<void()> clickCallback, const style::RoundButton &st) override;
|
||||
QPointer<Ui::RoundButton> addLeftButton(base::lambda<QString()> textFactory, base::lambda<void()> clickCallback, const style::RoundButton &st) override;
|
||||
QPointer<Ui::RoundButton> addButton(base::lambda<QString()> textFactory, base::lambda<void()> clickCallback,
|
||||
const style::RoundButton &st) override;
|
||||
QPointer<Ui::RoundButton> addLeftButton(base::lambda<QString()> textFactory, base::lambda<void()> clickCallback,
|
||||
const style::RoundButton &st) override;
|
||||
void updateButtonsPositions() override;
|
||||
|
||||
void setDimensions(int newWidth, int maxHeight) override;
|
||||
|
@ -274,7 +275,7 @@ private:
|
|||
int _maxContentHeight = 0;
|
||||
object_ptr<BoxContent> _content;
|
||||
|
||||
object_ptr<Ui::FlatLabel> _title = { nullptr };
|
||||
object_ptr<Ui::FlatLabel> _title = {nullptr};
|
||||
base::lambda<TextWithEntities()> _titleFactory;
|
||||
QString _additionalTitle;
|
||||
base::lambda<QString()> _additionalTitleFactory;
|
||||
|
@ -283,14 +284,12 @@ private:
|
|||
bool _layerType = false;
|
||||
|
||||
std::vector<object_ptr<Ui::RoundButton>> _buttons;
|
||||
object_ptr<Ui::RoundButton> _leftButton = { nullptr };
|
||||
|
||||
object_ptr<Ui::RoundButton> _leftButton = {nullptr};
|
||||
};
|
||||
|
||||
class BoxLayerTitleShadow : public Ui::PlainShadow {
|
||||
public:
|
||||
BoxLayerTitleShadow(QWidget *parent);
|
||||
|
||||
};
|
||||
|
||||
class BoxContentDivider : public TWidget {
|
||||
|
@ -300,7 +299,6 @@ public:
|
|||
protected:
|
||||
int resizeGetHeight(int newWidth) override;
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
};
|
||||
|
||||
enum CreatingGroupType {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -33,10 +33,8 @@ class PhoneInput;
|
|||
class InputArea;
|
||||
class UsernameInput;
|
||||
class Checkbox;
|
||||
template <typename Enum>
|
||||
class RadioenumGroup;
|
||||
template <typename Enum>
|
||||
class Radioenum;
|
||||
template <typename Enum> class RadioenumGroup;
|
||||
template <typename Enum> class Radioenum;
|
||||
class LinkButton;
|
||||
class NewAvatarButton;
|
||||
} // namespace Ui
|
||||
|
@ -52,8 +50,8 @@ class AddContactBox : public BoxContent, public RPCSender {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AddContactBox(QWidget*, QString fname = QString(), QString lname = QString(), QString phone = QString());
|
||||
AddContactBox(QWidget*, UserData *user);
|
||||
AddContactBox(QWidget *, QString fname = QString(), QString lname = QString(), QString phone = QString());
|
||||
AddContactBox(QWidget *, UserData *user);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
@ -88,14 +86,13 @@ private:
|
|||
|
||||
mtpRequestId _addRequest = 0;
|
||||
QString _sentName;
|
||||
|
||||
};
|
||||
|
||||
class GroupInfoBox : public BoxContent, private MTP::Sender {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GroupInfoBox(QWidget*, CreatingGroupType creating, bool fromTypeChoose);
|
||||
GroupInfoBox(QWidget *, CreatingGroupType creating, bool fromTypeChoose);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
@ -116,7 +113,8 @@ private slots:
|
|||
private:
|
||||
void setupPhotoButton();
|
||||
void createChannel(const QString &title, const QString &description);
|
||||
void createGroup(not_null<PeerListBox*> selectUsersBox, const QString &title, const std::vector<not_null<PeerData*>> &users);
|
||||
void createGroup(not_null<PeerListBox *> selectUsersBox, const QString &title,
|
||||
const std::vector<not_null<PeerData *>> &users);
|
||||
|
||||
void updateMaxHeight();
|
||||
void updateSelected(const QPoint &cursorGlobalPosition);
|
||||
|
@ -126,21 +124,20 @@ private:
|
|||
|
||||
object_ptr<Ui::NewAvatarButton> _photo;
|
||||
object_ptr<Ui::InputField> _title;
|
||||
object_ptr<Ui::InputArea> _description = { nullptr };
|
||||
object_ptr<Ui::InputArea> _description = {nullptr};
|
||||
|
||||
QImage _photoImage;
|
||||
|
||||
// group / channel creation
|
||||
mtpRequestId _creationRequestId = 0;
|
||||
ChannelData *_createdChannel = nullptr;
|
||||
|
||||
};
|
||||
|
||||
class SetupChannelBox : public BoxContent, public RPCSender {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SetupChannelBox(QWidget*, ChannelData *channel, bool existing = false);
|
||||
SetupChannelBox(QWidget *, ChannelData *channel, bool existing = false);
|
||||
|
||||
void setInnerFocus() override;
|
||||
|
||||
|
@ -199,14 +196,13 @@ private:
|
|||
QString _sentUsername, _checkUsername, _errorText, _goodText;
|
||||
|
||||
QTimer _checkTimer;
|
||||
|
||||
};
|
||||
|
||||
class EditNameTitleBox : public BoxContent, public RPCSender {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
EditNameTitleBox(QWidget*, not_null<PeerData*> peer);
|
||||
EditNameTitleBox(QWidget *, not_null<PeerData *> peer);
|
||||
|
||||
protected:
|
||||
void setInnerFocus() override;
|
||||
|
@ -225,7 +221,7 @@ private:
|
|||
void onSaveChatDone(const MTPUpdates &updates);
|
||||
bool onSaveChatFail(const RPCError &e);
|
||||
|
||||
not_null<PeerData*> _peer;
|
||||
not_null<PeerData *> _peer;
|
||||
|
||||
object_ptr<Ui::InputField> _first;
|
||||
object_ptr<Ui::InputField> _last;
|
||||
|
@ -234,12 +230,11 @@ private:
|
|||
|
||||
mtpRequestId _requestId = 0;
|
||||
QString _sentName;
|
||||
|
||||
};
|
||||
|
||||
class EditBioBox : public BoxContent, private MTP::Sender {
|
||||
public:
|
||||
EditBioBox(QWidget*, not_null<UserData*> self);
|
||||
EditBioBox(QWidget *, not_null<UserData *> self);
|
||||
|
||||
protected:
|
||||
void setInnerFocus() override;
|
||||
|
@ -253,21 +248,20 @@ private:
|
|||
void save();
|
||||
|
||||
style::InputField _dynamicFieldStyle;
|
||||
not_null<UserData*> _self;
|
||||
not_null<UserData *> _self;
|
||||
|
||||
object_ptr<Ui::InputArea> _bio;
|
||||
object_ptr<Ui::FlatLabel> _countdown;
|
||||
object_ptr<Ui::FlatLabel> _about;
|
||||
mtpRequestId _requestId = 0;
|
||||
QString _sentBio;
|
||||
|
||||
};
|
||||
|
||||
class EditChannelBox : public BoxContent, public RPCSender {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
EditChannelBox(QWidget*, not_null<ChannelData*> channel);
|
||||
EditChannelBox(QWidget *, not_null<ChannelData *> channel);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
@ -301,7 +295,7 @@ private:
|
|||
void saveSign();
|
||||
void saveInvites();
|
||||
|
||||
not_null<ChannelData*> _channel;
|
||||
not_null<ChannelData *> _channel;
|
||||
|
||||
object_ptr<Ui::InputField> _title;
|
||||
object_ptr<Ui::InputArea> _description;
|
||||
|
@ -323,12 +317,11 @@ private:
|
|||
mtpRequestId _saveInvitesRequestId = 0;
|
||||
|
||||
QString _sentTitle, _sentDescription;
|
||||
|
||||
};
|
||||
|
||||
class RevokePublicLinkBox : public BoxContent, public RPCSender {
|
||||
public:
|
||||
RevokePublicLinkBox(QWidget*, base::lambda<void()> revokeCallback);
|
||||
RevokePublicLinkBox(QWidget *, base::lambda<void()> revokeCallback);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
@ -343,5 +336,4 @@ private:
|
|||
|
||||
int _innerTop = 0;
|
||||
base::lambda<void()> _revokeCallback;
|
||||
|
||||
};
|
||||
|
|
|
@ -20,31 +20,36 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#include "boxes/autolock_box.h"
|
||||
|
||||
#include "lang/lang_keys.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "mainwindow.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "facades.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwindow.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
void AutoLockBox::prepare() {
|
||||
setTitle(langFactory(lng_passcode_autolock));
|
||||
|
||||
addButton(langFactory(lng_box_ok), [this] { closeBox(); });
|
||||
|
||||
auto options = { 60, 300, 3600, 18000 };
|
||||
auto options = {60, 300, 3600, 18000};
|
||||
|
||||
auto group = std::make_shared<Ui::RadiobuttonGroup>(Global::AutoLock());
|
||||
auto y = st::boxOptionListPadding.top() + st::langsButton.margin.top();
|
||||
auto count = int(options.size());
|
||||
_options.reserve(count);
|
||||
for (auto seconds : options) {
|
||||
_options.emplace_back(this, group, seconds, (seconds % 3600) ? lng_passcode_autolock_minutes(lt_count, seconds / 60) : lng_passcode_autolock_hours(lt_count, seconds / 3600), st::langsButton);
|
||||
_options.emplace_back(this, group, seconds,
|
||||
(seconds % 3600) ? lng_passcode_autolock_minutes(lt_count, seconds / 60) :
|
||||
lng_passcode_autolock_hours(lt_count, seconds / 3600),
|
||||
st::langsButton);
|
||||
_options.back()->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), y);
|
||||
y += _options.back()->heightNoMargins() + st::boxOptionListSkip;
|
||||
}
|
||||
group->setChangedCallback([this](int value) { durationChanged(value); });
|
||||
|
||||
setDimensions(st::langsWidth, st::boxOptionListPadding.top() + count * _options.back()->heightNoMargins() + (count - 1) * st::boxOptionListSkip + st::boxOptionListPadding.bottom() + st::boxPadding.bottom());
|
||||
setDimensions(st::langsWidth, st::boxOptionListPadding.top() + count * _options.back()->heightNoMargins() +
|
||||
(count - 1) * st::boxOptionListSkip + st::boxOptionListPadding.bottom() +
|
||||
st::boxPadding.bottom());
|
||||
}
|
||||
|
||||
void AutoLockBox::durationChanged(int seconds) {
|
||||
|
|
|
@ -30,8 +30,7 @@ class AutoLockBox : public BoxContent {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AutoLockBox(QWidget*) {
|
||||
}
|
||||
AutoLockBox(QWidget*) {}
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
@ -40,5 +39,4 @@ private:
|
|||
void durationChanged(int seconds);
|
||||
|
||||
std::vector<object_ptr<Ui::Radiobutton>> _options;
|
||||
|
||||
};
|
||||
|
|
|
@ -20,14 +20,14 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#include "boxes/background_box.h"
|
||||
|
||||
#include "auth_session.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
#include "window/themes/window_theme.h"
|
||||
#include "styles/style_overview.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_overview.h"
|
||||
#include "ui/effects/round_checkbox.h"
|
||||
#include "auth_session.h"
|
||||
#include "window/themes/window_theme.h"
|
||||
|
||||
class BackgroundBox::Inner : public TWidget, public RPCSender, private base::Subscriber {
|
||||
public:
|
||||
|
@ -56,11 +56,9 @@ private:
|
|||
int _over = -1;
|
||||
int _overDown = -1;
|
||||
std::unique_ptr<Ui::RoundCheckbox> _check; // this is not a widget
|
||||
|
||||
};
|
||||
|
||||
BackgroundBox::BackgroundBox(QWidget*) {
|
||||
}
|
||||
BackgroundBox::BackgroundBox(QWidget *) {}
|
||||
|
||||
void BackgroundBox::prepare() {
|
||||
setTitle(langFactory(lng_backgrounds_header));
|
||||
|
@ -84,11 +82,13 @@ void BackgroundBox::backgroundChosen(int index) {
|
|||
closeBox();
|
||||
}
|
||||
|
||||
BackgroundBox::Inner::Inner(QWidget *parent) : TWidget(parent)
|
||||
, _check(std::make_unique<Ui::RoundCheckbox>(st::overviewCheck, [this] { update(); })) {
|
||||
BackgroundBox::Inner::Inner(QWidget *parent)
|
||||
: TWidget(parent)
|
||||
, _check(std::make_unique<Ui::RoundCheckbox>(st::overviewCheck, [this] { update(); })) {
|
||||
_check->setChecked(true, Ui::RoundCheckbox::SetStyle::Fast);
|
||||
if (App::cServerBackgrounds().isEmpty()) {
|
||||
resize(BackgroundsInRow * (st::backgroundSize.width() + st::backgroundPadding) + st::backgroundPadding, 2 * (st::backgroundSize.height() + st::backgroundPadding) + st::backgroundPadding);
|
||||
resize(BackgroundsInRow * (st::backgroundSize.width() + st::backgroundPadding) + st::backgroundPadding,
|
||||
2 * (st::backgroundSize.height() + st::backgroundPadding) + st::backgroundPadding);
|
||||
MTP::send(MTPaccount_GetWallPapers(), rpcDone(&Inner::gotWallpapers));
|
||||
} else {
|
||||
updateWallpapers();
|
||||
|
@ -136,7 +136,8 @@ void BackgroundBox::Inner::gotWallpapers(const MTPVector<MTPWallPaper> &result)
|
|||
}
|
||||
if (!size || !w || !h) continue;
|
||||
|
||||
qint32 newThumbLevel = qAbs((st::backgroundSize.width() * cIntRetinaFactor()) - w), newFullLevel = qAbs(2560 - w);
|
||||
qint32 newThumbLevel = qAbs((st::backgroundSize.width() * cIntRetinaFactor()) - w),
|
||||
newFullLevel = qAbs(2560 - w);
|
||||
if (thumbLevel < 0 || newThumbLevel < thumbLevel) {
|
||||
thumbLevel = newThumbLevel;
|
||||
thumb = &(*j);
|
||||
|
@ -147,7 +148,8 @@ void BackgroundBox::Inner::gotWallpapers(const MTPVector<MTPWallPaper> &result)
|
|||
}
|
||||
}
|
||||
if (thumb && full && full->type() != mtpc_photoSizeEmpty) {
|
||||
wallpapers.push_back(App::WallPaper(d.vid.v ? d.vid.v : INT_MAX, App::image(*thumb), App::image(*full)));
|
||||
wallpapers.push_back(
|
||||
App::WallPaper(d.vid.v ? d.vid.v : INT_MAX, App::image(*thumb), App::image(*full)));
|
||||
}
|
||||
} break;
|
||||
|
||||
|
@ -166,7 +168,8 @@ void BackgroundBox::Inner::updateWallpapers() {
|
|||
_rows = _bgCount / BackgroundsInRow;
|
||||
if (_bgCount % BackgroundsInRow) ++_rows;
|
||||
|
||||
resize(BackgroundsInRow * (st::backgroundSize.width() + st::backgroundPadding) + st::backgroundPadding, _rows * (st::backgroundSize.height() + st::backgroundPadding) + st::backgroundPadding);
|
||||
resize(BackgroundsInRow * (st::backgroundSize.width() + st::backgroundPadding) + st::backgroundPadding,
|
||||
_rows * (st::backgroundSize.height() + st::backgroundPadding) + st::backgroundPadding);
|
||||
for (int i = 0; i < BackgroundsInRow * 3; ++i) {
|
||||
if (i >= _bgCount) break;
|
||||
|
||||
|
@ -211,10 +214,14 @@ void BackgroundBox::Inner::paintEvent(QPaintEvent *e) {
|
|||
void BackgroundBox::Inner::mouseMoveEvent(QMouseEvent *e) {
|
||||
int x = e->pos().x(), y = e->pos().y();
|
||||
int row = int((y - st::backgroundPadding) / (st::backgroundSize.height() + st::backgroundPadding));
|
||||
if (y - row * (st::backgroundSize.height() + st::backgroundPadding) > st::backgroundPadding + st::backgroundSize.height()) row = _rows + 1;
|
||||
if (y - row * (st::backgroundSize.height() + st::backgroundPadding) >
|
||||
st::backgroundPadding + st::backgroundSize.height())
|
||||
row = _rows + 1;
|
||||
|
||||
int col = int((x - st::backgroundPadding) / (st::backgroundSize.width() + st::backgroundPadding));
|
||||
if (x - col * (st::backgroundSize.width() + st::backgroundPadding) > st::backgroundPadding + st::backgroundSize.width()) row = _rows + 1;
|
||||
if (x - col * (st::backgroundSize.width() + st::backgroundPadding) >
|
||||
st::backgroundPadding + st::backgroundSize.width())
|
||||
row = _rows + 1;
|
||||
|
||||
int newOver = row * BackgroundsInRow + col;
|
||||
if (newOver >= _bgCount) newOver = -1;
|
||||
|
|
|
@ -38,5 +38,4 @@ private:
|
|||
|
||||
class Inner;
|
||||
QPointer<Inner> _inner;
|
||||
|
||||
};
|
||||
|
|
|
@ -20,11 +20,11 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#include "boxes/calendar_box.h"
|
||||
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_dialogs.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -92,10 +92,10 @@ private:
|
|||
int _daysCount = 0;
|
||||
int _daysShift = 0;
|
||||
int _rowsCount = 0;
|
||||
|
||||
};
|
||||
|
||||
CalendarBox::Context::Context(QDate month, QDate highlighted) : _highlighted(highlighted) {
|
||||
CalendarBox::Context::Context(QDate month, QDate highlighted)
|
||||
: _highlighted(highlighted) {
|
||||
showMonth(month);
|
||||
}
|
||||
|
||||
|
@ -176,7 +176,8 @@ QDate CalendarBox::Context::dateFromIndex(int index) const {
|
|||
}
|
||||
index += QDate(year, month, 1).daysInMonth();
|
||||
}
|
||||
for (auto maxIndex = QDate(year, month, 1).daysInMonth(); index >= maxIndex; maxIndex = QDate(year, month, 1).daysInMonth()) {
|
||||
for (auto maxIndex = QDate(year, month, 1).daysInMonth(); index >= maxIndex;
|
||||
maxIndex = QDate(year, month, 1).daysInMonth()) {
|
||||
index -= maxIndex;
|
||||
if (month++ == kMonthsCount) {
|
||||
month -= kMonthsCount;
|
||||
|
@ -236,11 +237,11 @@ private:
|
|||
static constexpr auto kEmptySelection = -kDaysInWeek;
|
||||
int _selected = kEmptySelection;
|
||||
int _pressed = kEmptySelection;
|
||||
|
||||
};
|
||||
|
||||
CalendarBox::Inner::Inner(QWidget *parent, Context *context) : TWidget(parent)
|
||||
, _context(context) {
|
||||
CalendarBox::Inner::Inner(QWidget *parent, Context *context)
|
||||
: TWidget(parent)
|
||||
, _context(context) {
|
||||
setMouseTracking(true);
|
||||
subscribe(context->month(), [this](QDate month) { monthChanged(month); });
|
||||
}
|
||||
|
@ -295,11 +296,11 @@ void CalendarBox::Inner::paintRows(Painter &p, QRect clip) {
|
|||
auto y = rowsTop();
|
||||
auto index = -_context->daysShift();
|
||||
auto highlightedIndex = _context->highlightedIndex();
|
||||
for (auto row = 0, rowsCount = _context->rowsCount(), daysCount = _context->daysCount()
|
||||
; row != rowsCount
|
||||
; ++row, y += st::calendarCellSize.height()) {
|
||||
for (auto row = 0, rowsCount = _context->rowsCount(), daysCount = _context->daysCount(); row != rowsCount;
|
||||
++row, y += st::calendarCellSize.height()) {
|
||||
auto x = rowsLeft();
|
||||
if (!myrtlrect(x, y, st::calendarCellSize.width() * kDaysInWeek, st::calendarCellSize.height()).intersects(clip)) {
|
||||
if (!myrtlrect(x, y, st::calendarCellSize.width() * kDaysInWeek, st::calendarCellSize.height())
|
||||
.intersects(clip)) {
|
||||
index += kDaysInWeek;
|
||||
continue;
|
||||
}
|
||||
|
@ -364,14 +365,20 @@ void CalendarBox::Inner::mousePressEvent(QMouseEvent *e) {
|
|||
|
||||
auto row = index / kDaysInWeek;
|
||||
auto col = index % kDaysInWeek;
|
||||
auto cell = QRect(rowsLeft() + col * st::calendarCellSize.width(), rowsTop() + row * st::calendarCellSize.height(), st::calendarCellSize.width(), st::calendarCellSize.height());
|
||||
auto cell =
|
||||
QRect(rowsLeft() + col * st::calendarCellSize.width(), rowsTop() + row * st::calendarCellSize.height(),
|
||||
st::calendarCellSize.width(), st::calendarCellSize.height());
|
||||
auto it = _ripples.find(_selected);
|
||||
if (it == _ripples.cend()) {
|
||||
auto mask = Ui::RippleAnimation::ellipseMask(QSize(st::calendarCellInner, st::calendarCellInner));
|
||||
auto update = [this, cell] { rtlupdate(cell); };
|
||||
it = _ripples.emplace(_selected, std::make_unique<Ui::RippleAnimation>(st::defaultRippleAnimation, std::move(mask), std::move(update))).first;
|
||||
it = _ripples
|
||||
.emplace(_selected, std::make_unique<Ui::RippleAnimation>(st::defaultRippleAnimation,
|
||||
std::move(mask), std::move(update)))
|
||||
.first;
|
||||
}
|
||||
auto ripplePosition = QPoint(cell.x() + (st::calendarCellSize.width() - st::calendarCellInner) / 2, cell.y() + (st::calendarCellSize.height() - st::calendarCellInner) / 2);
|
||||
auto ripplePosition = QPoint(cell.x() + (st::calendarCellSize.width() - st::calendarCellInner) / 2,
|
||||
cell.y() + (st::calendarCellSize.height() - st::calendarCellInner) / 2);
|
||||
it->second->add(e->pos() - ripplePosition);
|
||||
}
|
||||
}
|
||||
|
@ -400,7 +407,9 @@ CalendarBox::Inner::~Inner() = default;
|
|||
|
||||
class CalendarBox::Title : public TWidget, private base::Subscriber {
|
||||
public:
|
||||
Title(QWidget *parent, Context *context) : TWidget(parent), _context(context) {
|
||||
Title(QWidget *parent, Context *context)
|
||||
: TWidget(parent)
|
||||
, _context(context) {
|
||||
subscribe(_context->month(), [this](QDate date) { monthChanged(date); });
|
||||
}
|
||||
|
||||
|
@ -414,7 +423,6 @@ private:
|
|||
|
||||
QString _text;
|
||||
int _textWidth = 0;
|
||||
|
||||
};
|
||||
|
||||
void CalendarBox::Title::monthChanged(QDate month) {
|
||||
|
@ -428,17 +436,17 @@ void CalendarBox::Title::paintEvent(QPaintEvent *e) {
|
|||
|
||||
p.setFont(st::calendarTitleFont);
|
||||
p.setPen(st::boxTitleFg);
|
||||
p.drawTextLeft((width() - _textWidth) / 2, (height() - st::calendarTitleFont->height) / 2, width(), _text, _textWidth);
|
||||
p.drawTextLeft((width() - _textWidth) / 2, (height() - st::calendarTitleFont->height) / 2, width(), _text,
|
||||
_textWidth);
|
||||
}
|
||||
|
||||
CalendarBox::CalendarBox(QWidget*, QDate month, QDate highlighted, base::lambda<void(QDate date)> callback)
|
||||
: _context(std::make_unique<Context>(month, highlighted))
|
||||
, _inner(this, _context.get())
|
||||
, _title(this, _context.get())
|
||||
, _previous(this, st::calendarPrevious)
|
||||
, _next(this, st::calendarNext)
|
||||
, _callback(std::move(callback)) {
|
||||
}
|
||||
CalendarBox::CalendarBox(QWidget *, QDate month, QDate highlighted, base::lambda<void(QDate date)> callback)
|
||||
: _context(std::make_unique<Context>(month, highlighted))
|
||||
, _inner(this, _context.get())
|
||||
, _title(this, _context.get())
|
||||
, _previous(this, st::calendarPrevious)
|
||||
, _next(this, st::calendarNext)
|
||||
, _callback(std::move(callback)) {}
|
||||
|
||||
void CalendarBox::setMinDate(QDate date) {
|
||||
_context->setMinDate(date);
|
||||
|
@ -460,7 +468,7 @@ void CalendarBox::prepare() {
|
|||
}
|
||||
});
|
||||
|
||||
// _inner = setInnerWidget(object_ptr<Inner>(this, _context.get()), st::calendarScroll, st::calendarTitleHeight);
|
||||
// _inner = setInnerWidget(object_ptr<Inner>(this, _context.get()), st::calendarScroll, st::calendarTitleHeight);
|
||||
_inner->setDateChosenCallback(std::move(_callback));
|
||||
|
||||
addButton(langFactory(lng_close), [this] { closeBox(); });
|
||||
|
@ -493,7 +501,8 @@ void CalendarBox::monthChanged(QDate month) {
|
|||
void CalendarBox::resizeEvent(QResizeEvent *e) {
|
||||
_previous->moveToLeft(0, 0);
|
||||
_next->moveToRight(0, 0);
|
||||
_title->setGeometryToLeft(_previous->width(), 0, width() - _previous->width() - _next->width(), st::calendarTitleHeight);
|
||||
_title->setGeometryToLeft(_previous->width(), 0, width() - _previous->width() - _next->width(),
|
||||
st::calendarTitleHeight);
|
||||
_inner->setGeometryToLeft(0, st::calendarTitleHeight, width(), height() - st::calendarTitleHeight);
|
||||
BoxContent::resizeEvent(e);
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ class IconButton;
|
|||
|
||||
class CalendarBox : public BoxContent {
|
||||
public:
|
||||
CalendarBox(QWidget*, QDate month, QDate highlighted, base::lambda<void(QDate date)> callback);
|
||||
CalendarBox(QWidget *, QDate month, QDate highlighted, base::lambda<void(QDate date)> callback);
|
||||
|
||||
void setMinDate(QDate date);
|
||||
void setMaxDate(QDate date);
|
||||
|
@ -58,5 +58,4 @@ private:
|
|||
object_ptr<Ui::IconButton> _next;
|
||||
|
||||
base::lambda<void(QDate date)> _callback;
|
||||
|
||||
};
|
||||
|
|
|
@ -18,22 +18,23 @@ to link the code of portions of this program with the OpenSSL library.
|
|||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "base/lambda_guard.h"
|
||||
#include "boxes/change_phone_box.h"
|
||||
#include "app.h" // For formatPhone
|
||||
#include "base/lambda_guard.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "boxes/confirm_phone_box.h"
|
||||
#include "facades.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/effects/widget_fade_wrap.h"
|
||||
#include "boxes/confirm_phone_box.h"
|
||||
#include "ui/toast/toast.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "facades.h"
|
||||
#include "app.h" // For formatPhone
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
|
||||
namespace {
|
||||
|
||||
void createErrorLabel(QWidget *parent, object_ptr<Ui::WidgetFadeWrap<Ui::FlatLabel>> &label, const QString &text, int x, int y) {
|
||||
void createErrorLabel(QWidget *parent, object_ptr<Ui::WidgetFadeWrap<Ui::FlatLabel>> &label, const QString &text, int x,
|
||||
int y) {
|
||||
if (label) {
|
||||
auto errorFadeOut = std::move(label);
|
||||
errorFadeOut->setUpdateCallback([label = errorFadeOut.data()] {
|
||||
|
@ -44,7 +45,8 @@ void createErrorLabel(QWidget *parent, object_ptr<Ui::WidgetFadeWrap<Ui::FlatLab
|
|||
errorFadeOut->hideAnimated();
|
||||
}
|
||||
if (!text.isEmpty()) {
|
||||
label.create(parent, object_ptr<Ui::FlatLabel>(parent, text, Ui::FlatLabel::InitType::Simple, st::changePhoneError));
|
||||
label.create(parent,
|
||||
object_ptr<Ui::FlatLabel>(parent, text, Ui::FlatLabel::InitType::Simple, st::changePhoneError));
|
||||
label->hideFast();
|
||||
label->moveToLeft(x, y);
|
||||
label->showAnimated();
|
||||
|
@ -55,8 +57,7 @@ void createErrorLabel(QWidget *parent, object_ptr<Ui::WidgetFadeWrap<Ui::FlatLab
|
|||
|
||||
class ChangePhoneBox::EnterPhone : public BoxContent {
|
||||
public:
|
||||
EnterPhone(QWidget*) {
|
||||
}
|
||||
EnterPhone(QWidget *) {}
|
||||
|
||||
void setInnerFocus() override {
|
||||
_phone->setFocusFast();
|
||||
|
@ -74,15 +75,14 @@ private:
|
|||
showError(QString());
|
||||
}
|
||||
|
||||
object_ptr<Ui::PhoneInput> _phone = { nullptr };
|
||||
object_ptr<Ui::WidgetFadeWrap<Ui::FlatLabel>> _error = { nullptr };
|
||||
object_ptr<Ui::PhoneInput> _phone = {nullptr};
|
||||
object_ptr<Ui::WidgetFadeWrap<Ui::FlatLabel>> _error = {nullptr};
|
||||
mtpRequestId _requestId = 0;
|
||||
|
||||
};
|
||||
|
||||
class ChangePhoneBox::EnterCode : public BoxContent {
|
||||
public:
|
||||
EnterCode(QWidget*, const QString &phone, const QString &hash, int codeLength, int callTimeout);
|
||||
EnterCode(QWidget *, const QString &phone, const QString &hash, int codeLength, int callTimeout);
|
||||
|
||||
void setInnerFocus() override {
|
||||
_code->setFocusFast();
|
||||
|
@ -106,12 +106,11 @@ private:
|
|||
QString _hash;
|
||||
int _codeLength = 0;
|
||||
int _callTimeout = 0;
|
||||
object_ptr<SentCodeField> _code = { nullptr };
|
||||
object_ptr<Ui::WidgetFadeWrap<Ui::FlatLabel>> _error = { nullptr };
|
||||
object_ptr<Ui::FlatLabel> _callLabel = { nullptr };
|
||||
object_ptr<SentCodeField> _code = {nullptr};
|
||||
object_ptr<Ui::WidgetFadeWrap<Ui::FlatLabel>> _error = {nullptr};
|
||||
object_ptr<Ui::FlatLabel> _callLabel = {nullptr};
|
||||
mtpRequestId _requestId = 0;
|
||||
SentCodeCall _call;
|
||||
|
||||
};
|
||||
|
||||
void ChangePhoneBox::EnterPhone::prepare() {
|
||||
|
@ -124,7 +123,8 @@ void ChangePhoneBox::EnterPhone::prepare() {
|
|||
_phone->moveToLeft(st::boxPadding.left(), st::boxLittleSkip);
|
||||
connect(_phone, &Ui::PhoneInput::submitted, this, [this] { submit(); });
|
||||
|
||||
auto description = object_ptr<Ui::FlatLabel>(this, lang(lng_change_phone_new_description), Ui::FlatLabel::InitType::Simple, st::changePhoneLabel);
|
||||
auto description = object_ptr<Ui::FlatLabel>(this, lang(lng_change_phone_new_description),
|
||||
Ui::FlatLabel::InitType::Simple, st::changePhoneLabel);
|
||||
auto errorSkip = st::boxLittleSkip + st::changePhoneError.style.font->height;
|
||||
description->moveToLeft(st::boxPadding.left(), _phone->y() + _phone->height() + errorSkip + st::boxLittleSkip);
|
||||
|
||||
|
@ -141,11 +141,12 @@ void ChangePhoneBox::EnterPhone::submit() {
|
|||
hideError();
|
||||
|
||||
auto phoneNumber = _phone->getLastText().trimmed();
|
||||
_requestId = MTP::send(MTPaccount_SendChangePhoneCode(MTP_flags(0), MTP_string(phoneNumber), MTP_bool(false)), rpcDone(base::lambda_guarded(this, [this, phoneNumber](const MTPauth_SentCode &result) {
|
||||
return sendPhoneDone(phoneNumber, result);
|
||||
})), rpcFail(base::lambda_guarded(this, [this, phoneNumber](const RPCError &error) {
|
||||
return sendPhoneFail(phoneNumber, error);
|
||||
})));
|
||||
_requestId = MTP::send(
|
||||
MTPaccount_SendChangePhoneCode(MTP_flags(0), MTP_string(phoneNumber), MTP_bool(false)),
|
||||
rpcDone(base::lambda_guarded(
|
||||
this, [this, phoneNumber](const MTPauth_SentCode &result) { return sendPhoneDone(phoneNumber, result); })),
|
||||
rpcFail(base::lambda_guarded(
|
||||
this, [this, phoneNumber](const RPCError &error) { return sendPhoneFail(phoneNumber, error); })));
|
||||
}
|
||||
|
||||
void ChangePhoneBox::EnterPhone::sendPhoneDone(const QString &phoneNumber, const MTPauth_SentCode &result) {
|
||||
|
@ -199,19 +200,21 @@ void ChangePhoneBox::EnterPhone::showError(const QString &text) {
|
|||
}
|
||||
}
|
||||
|
||||
ChangePhoneBox::EnterCode::EnterCode(QWidget*, const QString &phone, const QString &hash, int codeLength, int callTimeout)
|
||||
: _phone(phone)
|
||||
, _hash(hash)
|
||||
, _codeLength(codeLength)
|
||||
, _callTimeout(callTimeout)
|
||||
, _call(this, [this] { sendCall(); }, [this] { updateCall(); }) {
|
||||
}
|
||||
ChangePhoneBox::EnterCode::EnterCode(QWidget *, const QString &phone, const QString &hash, int codeLength,
|
||||
int callTimeout)
|
||||
: _phone(phone)
|
||||
, _hash(hash)
|
||||
, _codeLength(codeLength)
|
||||
, _callTimeout(callTimeout)
|
||||
, _call(this, [this] { sendCall(); }, [this] { updateCall(); }) {}
|
||||
|
||||
void ChangePhoneBox::EnterCode::prepare() {
|
||||
setTitle(langFactory(lng_change_phone_title));
|
||||
|
||||
auto descriptionText = lng_change_phone_code_description(lt_phone, textcmdStartSemibold() + App::formatPhone(_phone) + textcmdStopSemibold());
|
||||
auto description = object_ptr<Ui::FlatLabel>(this, descriptionText, Ui::FlatLabel::InitType::Rich, st::changePhoneLabel);
|
||||
auto descriptionText = lng_change_phone_code_description(
|
||||
lt_phone, textcmdStartSemibold() + App::formatPhone(_phone) + textcmdStopSemibold());
|
||||
auto description =
|
||||
object_ptr<Ui::FlatLabel>(this, descriptionText, Ui::FlatLabel::InitType::Rich, st::changePhoneLabel);
|
||||
description->moveToLeft(st::boxPadding.left(), 0);
|
||||
|
||||
auto phoneValue = QString();
|
||||
|
@ -226,7 +229,7 @@ void ChangePhoneBox::EnterCode::prepare() {
|
|||
setDimensions(st::boxWidth, countHeight());
|
||||
|
||||
if (_callTimeout > 0) {
|
||||
_call.setStatus({ SentCodeCall::State::Waiting, _callTimeout });
|
||||
_call.setStatus({SentCodeCall::State::Waiting, _callTimeout});
|
||||
updateCall();
|
||||
}
|
||||
|
||||
|
@ -246,21 +249,21 @@ void ChangePhoneBox::EnterCode::submit() {
|
|||
hideError();
|
||||
|
||||
auto code = _code->getLastText().trimmed();
|
||||
_requestId = MTP::send(MTPaccount_ChangePhone(MTP_string(_phone), MTP_string(_hash), MTP_string(code)), rpcDone([weak = weak(this)](const MTPUser &result) {
|
||||
App::feedUser(result);
|
||||
if (weak) {
|
||||
Ui::hideLayer();
|
||||
}
|
||||
Ui::Toast::Show(lang(lng_change_phone_success));
|
||||
}), rpcFail(base::lambda_guarded(this, [this](const RPCError &error) {
|
||||
return sendCodeFail(error);
|
||||
})));
|
||||
_requestId =
|
||||
MTP::send(MTPaccount_ChangePhone(MTP_string(_phone), MTP_string(_hash), MTP_string(code)),
|
||||
rpcDone([weak = weak(this)](const MTPUser &result) {
|
||||
App::feedUser(result);
|
||||
if (weak) {
|
||||
Ui::hideLayer();
|
||||
}
|
||||
Ui::Toast::Show(lang(lng_change_phone_success));
|
||||
}),
|
||||
rpcFail(base::lambda_guarded(this, [this](const RPCError &error) { return sendCodeFail(error); })));
|
||||
}
|
||||
|
||||
void ChangePhoneBox::EnterCode::sendCall() {
|
||||
MTP::send(MTPauth_ResendCode(MTP_string(_phone), MTP_string(_hash)), rpcDone(base::lambda_guarded(this, [this] {
|
||||
_call.callDone();
|
||||
})));
|
||||
MTP::send(MTPauth_ResendCode(MTP_string(_phone), MTP_string(_hash)),
|
||||
rpcDone(base::lambda_guarded(this, [this] { _call.callDone(); })));
|
||||
}
|
||||
|
||||
void ChangePhoneBox::EnterCode::updateCall() {
|
||||
|
@ -305,16 +308,12 @@ bool ChangePhoneBox::EnterCode::sendCodeFail(const RPCError &error) {
|
|||
|
||||
void ChangePhoneBox::prepare() {
|
||||
setTitle(langFactory(lng_change_phone_title));
|
||||
addButton(langFactory(lng_change_phone_button), [] {
|
||||
Ui::show(Box<ConfirmBox>(lang(lng_change_phone_warning), [] {
|
||||
Ui::show(Box<EnterPhone>());
|
||||
}));
|
||||
});
|
||||
addButton(langFactory(lng_cancel), [this] {
|
||||
closeBox();
|
||||
});
|
||||
addButton(langFactory(lng_change_phone_button),
|
||||
[] { Ui::show(Box<ConfirmBox>(lang(lng_change_phone_warning), [] { Ui::show(Box<EnterPhone>()); })); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
auto label = object_ptr<Ui::FlatLabel>(this, lang(lng_change_phone_description), Ui::FlatLabel::InitType::Rich, st::changePhoneDescription);
|
||||
auto label = object_ptr<Ui::FlatLabel>(this, lang(lng_change_phone_description), Ui::FlatLabel::InitType::Rich,
|
||||
st::changePhoneDescription);
|
||||
label->moveToLeft((st::boxWideWidth - label->width()) / 2, st::changePhoneDescriptionTop);
|
||||
|
||||
setDimensions(st::boxWideWidth, label->bottomNoMargins() + st::boxLittleSkip);
|
||||
|
|
|
@ -24,8 +24,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
|
||||
class ChangePhoneBox : public BoxContent {
|
||||
public:
|
||||
ChangePhoneBox(QWidget*) {
|
||||
}
|
||||
ChangePhoneBox(QWidget *) {}
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
@ -35,6 +34,4 @@ protected:
|
|||
private:
|
||||
class EnterPhone;
|
||||
class EnterCode;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -20,85 +20,93 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#include "boxes/confirm_box.h"
|
||||
|
||||
#include "styles/style_boxes.h"
|
||||
#include "apiwrap.h"
|
||||
#include "application.h"
|
||||
#include "auth_session.h"
|
||||
#include "core/click_handler_types.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
#include "apiwrap.h"
|
||||
#include "application.h"
|
||||
#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 "storage/localstorage.h"
|
||||
#include "auth_session.h"
|
||||
#include "observer_peer.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "ui/toast/toast.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
|
||||
TextParseOptions _confirmBoxTextOptions = {
|
||||
TextParseLinks | TextParseMultiline | TextParseRichText, // flags
|
||||
0, // maxw
|
||||
0, // maxh
|
||||
Qt::LayoutDirectionAuto, // dir
|
||||
TextParseLinks | TextParseMultiline | TextParseRichText, // flags
|
||||
0, // maxw
|
||||
0, // maxh
|
||||
Qt::LayoutDirectionAuto, // dir
|
||||
};
|
||||
|
||||
ConfirmBox::ConfirmBox(QWidget*, const QString &text, base::lambda_once<void()> confirmedCallback, base::lambda_once<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)) {
|
||||
ConfirmBox::ConfirmBox(QWidget *, const QString &text, base::lambda_once<void()> confirmedCallback,
|
||||
base::lambda_once<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(QWidget*, const QString &text, const QString &confirmText, base::lambda_once<void()> confirmedCallback, base::lambda_once<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)) {
|
||||
ConfirmBox::ConfirmBox(QWidget *, const QString &text, const QString &confirmText,
|
||||
base::lambda_once<void()> confirmedCallback, base::lambda_once<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_once<void()> confirmedCallback, base::lambda_once<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)) {
|
||||
ConfirmBox::ConfirmBox(QWidget *, const QString &text, const QString &confirmText,
|
||||
const style::RoundButton &confirmStyle, base::lambda_once<void()> confirmedCallback,
|
||||
base::lambda_once<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_once<void()> confirmedCallback, base::lambda_once<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)) {
|
||||
ConfirmBox::ConfirmBox(QWidget *, const QString &text, const QString &confirmText, const QString &cancelText,
|
||||
base::lambda_once<void()> confirmedCallback, base::lambda_once<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_once<void()> confirmedCallback, base::lambda_once<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)) {
|
||||
ConfirmBox::ConfirmBox(QWidget *, const QString &text, const QString &confirmText,
|
||||
const style::RoundButton &confirmStyle, const QString &cancelText,
|
||||
base::lambda_once<void()> confirmedCallback, base::lambda_once<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<void()> closedCallback)
|
||||
: _confirmText(doneText)
|
||||
, _confirmStyle(st::defaultBoxButton)
|
||||
, _informative(true)
|
||||
, _text(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right())
|
||||
, _confirmedCallback(generateInformCallback(closedCallback))
|
||||
, _cancelledCallback(generateInformCallback(closedCallback)) {
|
||||
ConfirmBox::ConfirmBox(const InformBoxTag &, const QString &text, const QString &doneText,
|
||||
base::lambda<void()> closedCallback)
|
||||
: _confirmText(doneText)
|
||||
, _confirmStyle(st::defaultBoxButton)
|
||||
, _informative(true)
|
||||
, _text(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right())
|
||||
, _confirmedCallback(generateInformCallback(closedCallback))
|
||||
, _cancelledCallback(generateInformCallback(closedCallback)) {
|
||||
init(text);
|
||||
}
|
||||
|
||||
|
@ -118,7 +126,11 @@ void ConfirmBox::init(const QString &text) {
|
|||
void ConfirmBox::prepare() {
|
||||
addButton([this] { return _confirmText; }, [this] { confirmed(); }, _confirmStyle);
|
||||
if (!_informative) {
|
||||
addButton([this] { return _cancelText; }, [this] { _cancelled = true; closeBox(); });
|
||||
addButton([this] { return _cancelText; },
|
||||
[this] {
|
||||
_cancelled = true;
|
||||
closeBox();
|
||||
});
|
||||
}
|
||||
subscribe(boxClosing, [this] {
|
||||
if (!_confirmed && (!_strictCancel || _cancelled) && _cancelledCallback) {
|
||||
|
@ -210,16 +222,17 @@ void ConfirmBox::paintEvent(QPaintEvent *e) {
|
|||
_text.drawLeftElided(p, st::boxPadding.left(), st::boxPadding.top(), _textWidth, width(), 16, style::al_left);
|
||||
}
|
||||
|
||||
InformBox::InformBox(QWidget*, const QString &text, base::lambda<void()> closedCallback) : ConfirmBox(ConfirmBox::InformBoxTag(), text, lang(lng_box_ok), std::move(closedCallback)) {
|
||||
}
|
||||
InformBox::InformBox(QWidget *, const QString &text, base::lambda<void()> closedCallback)
|
||||
: ConfirmBox(ConfirmBox::InformBoxTag(), text, lang(lng_box_ok), std::move(closedCallback)) {}
|
||||
|
||||
InformBox::InformBox(QWidget*, const QString &text, const QString &doneText, base::lambda<void()> closedCallback) : ConfirmBox(ConfirmBox::InformBoxTag(), text, doneText, std::move(closedCallback)) {
|
||||
}
|
||||
InformBox::InformBox(QWidget *, const QString &text, const QString &doneText, base::lambda<void()> closedCallback)
|
||||
: ConfirmBox(ConfirmBox::InformBoxTag(), text, doneText, std::move(closedCallback)) {}
|
||||
|
||||
MaxInviteBox::MaxInviteBox(QWidget*, not_null<ChannelData*> channel) : BoxContent()
|
||||
, _channel(channel)
|
||||
, _text(st::boxLabelStyle, lng_participant_invite_sorry(lt_count, Global::ChatSizeMax()), _confirmBoxTextOptions, st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()) {
|
||||
}
|
||||
MaxInviteBox::MaxInviteBox(QWidget *, not_null<ChannelData *> channel)
|
||||
: BoxContent()
|
||||
, _channel(channel)
|
||||
, _text(st::boxLabelStyle, lng_participant_invite_sorry(lt_count, Global::ChatSizeMax()), _confirmBoxTextOptions,
|
||||
st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()) {}
|
||||
|
||||
void MaxInviteBox::prepare() {
|
||||
setMouseTracking(true);
|
||||
|
@ -228,13 +241,15 @@ void MaxInviteBox::prepare() {
|
|||
|
||||
_textWidth = st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right();
|
||||
_textHeight = std::min(_text.countHeight(_textWidth), 16 * st::boxLabelStyle.lineHeight);
|
||||
setDimensions(st::boxWidth, st::boxPadding.top() + _textHeight + st::boxTextFont->height + st::boxTextFont->height * 2 + st::newGroupLinkPadding.bottom());
|
||||
setDimensions(st::boxWidth, st::boxPadding.top() + _textHeight + st::boxTextFont->height +
|
||||
st::boxTextFont->height * 2 + st::newGroupLinkPadding.bottom());
|
||||
|
||||
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(Notify::PeerUpdate::Flag::InviteLinkChanged, [this](const Notify::PeerUpdate &update) {
|
||||
if (update.peer == _channel) {
|
||||
rtlupdate(_invitationLink);
|
||||
}
|
||||
}));
|
||||
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(Notify::PeerUpdate::Flag::InviteLinkChanged,
|
||||
[this](const Notify::PeerUpdate &update) {
|
||||
if (update.peer == _channel) {
|
||||
rtlupdate(_invitationLink);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
void MaxInviteBox::mouseMoveEvent(QMouseEvent *e) {
|
||||
|
@ -287,14 +302,14 @@ void MaxInviteBox::paintEvent(QPaintEvent *e) {
|
|||
|
||||
void MaxInviteBox::resizeEvent(QResizeEvent *e) {
|
||||
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);
|
||||
_invitationLink = myrtlrect(st::boxPadding.left(), st::boxPadding.top() + _textHeight + st::boxTextFont->height,
|
||||
width() - st::boxPadding.left() - st::boxPadding.right(), 2 * st::boxTextFont->height);
|
||||
}
|
||||
|
||||
ConvertToSupergroupBox::ConvertToSupergroupBox(QWidget*, ChatData *chat)
|
||||
: _chat(chat)
|
||||
, _text(100)
|
||||
, _note(100) {
|
||||
}
|
||||
ConvertToSupergroupBox::ConvertToSupergroupBox(QWidget *, ChatData *chat)
|
||||
: _chat(chat)
|
||||
, _text(100)
|
||||
, _note(100) {}
|
||||
|
||||
void ConvertToSupergroupBox::prepare() {
|
||||
QStringList text;
|
||||
|
@ -309,14 +324,18 @@ void ConvertToSupergroupBox::prepare() {
|
|||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
_text.setText(st::boxLabelStyle, text.join('\n'), _confirmBoxTextOptions);
|
||||
_note.setText(st::boxLabelStyle, lng_profile_convert_warning(lt_bold_start, textcmdStartSemibold(), lt_bold_end, textcmdStopSemibold()), _confirmBoxTextOptions);
|
||||
_note.setText(
|
||||
st::boxLabelStyle,
|
||||
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);
|
||||
setDimensions(st::boxWideWidth, _textHeight + st::boxPadding.bottom() + _note.countHeight(_textWidth));
|
||||
}
|
||||
|
||||
void ConvertToSupergroupBox::convertToSupergroup() {
|
||||
MTP::send(MTPmessages_MigrateChat(_chat->inputChat), rpcDone(&ConvertToSupergroupBox::convertDone), rpcFail(&ConvertToSupergroupBox::convertFail));
|
||||
MTP::send(MTPmessages_MigrateChat(_chat->inputChat), rpcDone(&ConvertToSupergroupBox::convertDone),
|
||||
rpcFail(&ConvertToSupergroupBox::convertFail));
|
||||
}
|
||||
|
||||
void ConvertToSupergroupBox::convertDone(const MTPUpdates &updates) {
|
||||
|
@ -336,7 +355,9 @@ void ConvertToSupergroupBox::convertDone(const MTPUpdates &updates) {
|
|||
switch (updates.type()) {
|
||||
case mtpc_updates: handleChats(updates.c_updates().vchats); break;
|
||||
case mtpc_updatesCombined: handleChats(updates.c_updatesCombined().vchats); break;
|
||||
default: LOG(("API Error: unexpected update cons %1 (ConvertToSupergroupBox::convertDone)").arg(updates.type())); break;
|
||||
default:
|
||||
LOG(("API Error: unexpected update cons %1 (ConvertToSupergroupBox::convertDone)").arg(updates.type()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -365,18 +386,18 @@ void ConvertToSupergroupBox::paintEvent(QPaintEvent *e) {
|
|||
_note.drawLeft(p, st::boxPadding.left(), _textHeight + st::boxPadding.bottom(), _textWidth, width());
|
||||
}
|
||||
|
||||
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) {
|
||||
}
|
||||
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) {}
|
||||
|
||||
void PinMessageBox::prepare() {
|
||||
addButton(langFactory(lng_pinned_pin), [this] { pinMessage(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
setDimensions(st::boxWidth, st::boxPadding.top() + _text->height() + st::boxMediumSkip + _notify->heightNoMargins() + st::boxPadding.bottom());
|
||||
setDimensions(st::boxWidth, st::boxPadding.top() + _text->height() + st::boxMediumSkip +
|
||||
_notify->heightNoMargins() + st::boxPadding.bottom());
|
||||
}
|
||||
|
||||
void PinMessageBox::resizeEvent(QResizeEvent *e) {
|
||||
|
@ -400,7 +421,8 @@ void PinMessageBox::pinMessage() {
|
|||
if (!_notify->checked()) {
|
||||
flags |= MTPchannels_UpdatePinnedMessage::Flag::f_silent;
|
||||
}
|
||||
_requestId = MTP::send(MTPchannels_UpdatePinnedMessage(MTP_flags(flags), _channel->inputChannel, MTP_int(_msgId)), rpcDone(&PinMessageBox::pinDone), rpcFail(&PinMessageBox::pinFail));
|
||||
_requestId = MTP::send(MTPchannels_UpdatePinnedMessage(MTP_flags(flags), _channel->inputChannel, MTP_int(_msgId)),
|
||||
rpcDone(&PinMessageBox::pinDone), rpcFail(&PinMessageBox::pinFail));
|
||||
}
|
||||
|
||||
void PinMessageBox::pinDone(const MTPUpdates &updates) {
|
||||
|
@ -416,7 +438,8 @@ bool PinMessageBox::pinFail(const RPCError &error) {
|
|||
return true;
|
||||
}
|
||||
|
||||
DeleteMessagesBox::DeleteMessagesBox(QWidget*, HistoryItem *item, bool suggestModerateActions) : _singleItem(true) {
|
||||
DeleteMessagesBox::DeleteMessagesBox(QWidget *, HistoryItem *item, bool suggestModerateActions)
|
||||
: _singleItem(true) {
|
||||
_ids.push_back(item->fullId());
|
||||
if (suggestModerateActions) {
|
||||
_moderateBan = item->suggestBanReport();
|
||||
|
@ -428,13 +451,11 @@ DeleteMessagesBox::DeleteMessagesBox(QWidget*, HistoryItem *item, bool suggestMo
|
|||
}
|
||||
}
|
||||
|
||||
DeleteMessagesBox::DeleteMessagesBox(QWidget*, const SelectedItemSet &selected) {
|
||||
DeleteMessagesBox::DeleteMessagesBox(QWidget *, const SelectedItemSet &selected) {
|
||||
auto count = selected.size();
|
||||
Assert(count > 0);
|
||||
_ids.reserve(count);
|
||||
for_const (auto item, selected) {
|
||||
_ids.push_back(item->fullId());
|
||||
}
|
||||
for_const (auto item, selected) { _ids.push_back(item->fullId()); }
|
||||
}
|
||||
|
||||
void DeleteMessagesBox::prepare() {
|
||||
|
@ -453,8 +474,8 @@ void DeleteMessagesBox::prepare() {
|
|||
text = _singleItem ? lang(lng_selected_delete_sure_this) : lng_selected_delete_sure(lt_count, _ids.size());
|
||||
auto canDeleteAllForEveryone = true;
|
||||
auto now = ::date(unixtime());
|
||||
auto deleteForUser = (UserData*)nullptr;
|
||||
auto peer = (PeerData*)nullptr;
|
||||
auto deleteForUser = (UserData *)nullptr;
|
||||
auto peer = (PeerData *)nullptr;
|
||||
auto forEveryoneText = lang(lng_delete_for_everyone_check);
|
||||
for_const (auto fullId, _ids) {
|
||||
if (auto item = App::histItemById(fullId)) {
|
||||
|
@ -542,10 +563,12 @@ void DeleteMessagesBox::deleteAndClear() {
|
|||
|
||||
if (_moderateFrom) {
|
||||
if (_banUser && _banUser->checked()) {
|
||||
Auth().api().kickParticipant(_moderateInChannel, _moderateFrom, MTP_channelBannedRights(MTP_flags(0), MTP_int(0)));
|
||||
Auth().api().kickParticipant(_moderateInChannel, _moderateFrom,
|
||||
MTP_channelBannedRights(MTP_flags(0), MTP_int(0)));
|
||||
}
|
||||
if (_reportSpam->checked()) {
|
||||
MTP::send(MTPchannels_ReportSpam(_moderateInChannel->inputChannel, _moderateFrom->inputUser, MTP_vector<MTPint>(1, MTP_int(_ids[0].msg))));
|
||||
MTP::send(MTPchannels_ReportSpam(_moderateInChannel->inputChannel, _moderateFrom->inputUser,
|
||||
MTP_vector<MTPint>(1, MTP_int(_ids[0].msg))));
|
||||
}
|
||||
if (_deleteAll && _deleteAll->checked()) {
|
||||
App::main()->deleteAllFromUser(_moderateInChannel, _moderateFrom);
|
||||
|
@ -556,7 +579,7 @@ void DeleteMessagesBox::deleteAndClear() {
|
|||
App::main()->clearSelectedItems();
|
||||
}
|
||||
|
||||
QMap<PeerData*, QVector<MTPint>> idsByPeer;
|
||||
QMap<PeerData *, QVector<MTPint>> idsByPeer;
|
||||
for_const (auto fullId, _ids) {
|
||||
if (auto item = App::histItemById(fullId)) {
|
||||
auto history = item->history();
|
||||
|
@ -579,10 +602,11 @@ void DeleteMessagesBox::deleteAndClear() {
|
|||
Ui::hideLayer();
|
||||
}
|
||||
|
||||
ConfirmInviteBox::ConfirmInviteBox(QWidget*, const QString &title, bool isChannel, const MTPChatPhoto &photo, int count, const QVector<UserData*> &participants)
|
||||
: _title(this, st::confirmInviteTitle)
|
||||
, _status(this, st::confirmInviteStatus)
|
||||
, _participants(participants) {
|
||||
ConfirmInviteBox::ConfirmInviteBox(QWidget *, const QString &title, bool isChannel, const MTPChatPhoto &photo,
|
||||
int count, const QVector<UserData *> &participants)
|
||||
: _title(this, st::confirmInviteTitle)
|
||||
, _status(this, st::confirmInviteStatus)
|
||||
, _participants(participants) {
|
||||
_title->setText(title);
|
||||
QString status;
|
||||
if (_participants.isEmpty() || _participants.size() >= count) {
|
||||
|
@ -655,15 +679,18 @@ void ConfirmInviteBox::paintEvent(QPaintEvent *e) {
|
|||
Painter p(this);
|
||||
|
||||
if (_photo) {
|
||||
p.drawPixmap((width() - st::confirmInvitePhotoSize) / 2, st::confirmInvitePhotoTop, _photo->pixCircled(st::confirmInvitePhotoSize, st::confirmInvitePhotoSize));
|
||||
p.drawPixmap((width() - st::confirmInvitePhotoSize) / 2, st::confirmInvitePhotoTop,
|
||||
_photo->pixCircled(st::confirmInvitePhotoSize, st::confirmInvitePhotoSize));
|
||||
} else {
|
||||
_photoEmpty.paint(p, (width() - st::confirmInvitePhotoSize) / 2, st::confirmInvitePhotoTop, width(), st::confirmInvitePhotoSize);
|
||||
_photoEmpty.paint(p, (width() - st::confirmInvitePhotoSize) / 2, st::confirmInvitePhotoTop, width(),
|
||||
st::confirmInvitePhotoSize);
|
||||
}
|
||||
|
||||
int sumWidth = _participants.size() * _userWidth;
|
||||
int left = (width() - sumWidth) / 2;
|
||||
for_const (auto user, _participants) {
|
||||
user->paintUserpicLeft(p, left + (_userWidth - st::confirmInviteUserPhotoSize) / 2, st::confirmInviteUserPhotoTop, width(), st::confirmInviteUserPhotoSize);
|
||||
user->paintUserpicLeft(p, left + (_userWidth - st::confirmInviteUserPhotoSize) / 2,
|
||||
st::confirmInviteUserPhotoTop, width(), st::confirmInviteUserPhotoSize);
|
||||
left += _userWidth;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,11 +31,21 @@ class FlatLabel;
|
|||
class InformBox;
|
||||
class ConfirmBox : public BoxContent, public ClickHandlerHost {
|
||||
public:
|
||||
ConfirmBox(QWidget*, const QString &text, base::lambda_once<void()> confirmedCallback = base::lambda_once<void()>(), base::lambda_once<void()> cancelledCallback = base::lambda_once<void()>());
|
||||
ConfirmBox(QWidget*, const QString &text, const QString &confirmText, base::lambda_once<void()> confirmedCallback = base::lambda_once<void()>(), base::lambda_once<void()> cancelledCallback = base::lambda_once<void()>());
|
||||
ConfirmBox(QWidget*, const QString &text, const QString &confirmText, const style::RoundButton &confirmStyle, base::lambda_once<void()> confirmedCallback = base::lambda_once<void()>(), base::lambda_once<void()> cancelledCallback = base::lambda_once<void()>());
|
||||
ConfirmBox(QWidget*, const QString &text, const QString &confirmText, const QString &cancelText, base::lambda_once<void()> confirmedCallback = base::lambda_once<void()>(), base::lambda_once<void()> cancelledCallback = base::lambda_once<void()>());
|
||||
ConfirmBox(QWidget*, const QString &text, const QString &confirmText, const style::RoundButton &confirmStyle, const QString &cancelText, base::lambda_once<void()> confirmedCallback = base::lambda_once<void()>(), base::lambda_once<void()> cancelledCallback = base::lambda_once<void()>());
|
||||
ConfirmBox(QWidget *, const QString &text,
|
||||
base::lambda_once<void()> confirmedCallback = base::lambda_once<void()>(),
|
||||
base::lambda_once<void()> cancelledCallback = base::lambda_once<void()>());
|
||||
ConfirmBox(QWidget *, const QString &text, const QString &confirmText,
|
||||
base::lambda_once<void()> confirmedCallback = base::lambda_once<void()>(),
|
||||
base::lambda_once<void()> cancelledCallback = base::lambda_once<void()>());
|
||||
ConfirmBox(QWidget *, const QString &text, const QString &confirmText, const style::RoundButton &confirmStyle,
|
||||
base::lambda_once<void()> confirmedCallback = base::lambda_once<void()>(),
|
||||
base::lambda_once<void()> cancelledCallback = base::lambda_once<void()>());
|
||||
ConfirmBox(QWidget *, const QString &text, const QString &confirmText, const QString &cancelText,
|
||||
base::lambda_once<void()> confirmedCallback = base::lambda_once<void()>(),
|
||||
base::lambda_once<void()> cancelledCallback = base::lambda_once<void()>());
|
||||
ConfirmBox(QWidget *, const QString &text, const QString &confirmText, const style::RoundButton &confirmStyle,
|
||||
const QString &cancelText, base::lambda_once<void()> confirmedCallback = base::lambda_once<void()>(),
|
||||
base::lambda_once<void()> cancelledCallback = base::lambda_once<void()>());
|
||||
|
||||
void updateLink();
|
||||
|
||||
|
@ -59,8 +69,7 @@ protected:
|
|||
void leaveEventHook(QEvent *e) override;
|
||||
|
||||
private:
|
||||
struct InformBoxTag {
|
||||
};
|
||||
struct InformBoxTag {};
|
||||
ConfirmBox(const InformBoxTag &, const QString &text, const QString &doneText, base::lambda<void()> closedCallback);
|
||||
base::lambda_once<void()> generateInformCallback(base::lambda<void()> closedCallback);
|
||||
friend class InformBox;
|
||||
|
@ -87,19 +96,18 @@ private:
|
|||
bool _strictCancel = false;
|
||||
base::lambda_once<void()> _confirmedCallback;
|
||||
base::lambda_once<void()> _cancelledCallback;
|
||||
|
||||
};
|
||||
|
||||
class InformBox : public ConfirmBox {
|
||||
public:
|
||||
InformBox(QWidget*, const QString &text, base::lambda<void()> closedCallback = base::lambda<void()>());
|
||||
InformBox(QWidget*, const QString &text, const QString &doneText, base::lambda<void()> closedCallback = base::lambda<void()>());
|
||||
|
||||
InformBox(QWidget *, const QString &text, base::lambda<void()> closedCallback = base::lambda<void()>());
|
||||
InformBox(QWidget *, const QString &text, const QString &doneText,
|
||||
base::lambda<void()> closedCallback = base::lambda<void()>());
|
||||
};
|
||||
|
||||
class MaxInviteBox : public BoxContent {
|
||||
public:
|
||||
MaxInviteBox(QWidget*, not_null<ChannelData*> channel);
|
||||
MaxInviteBox(QWidget *, not_null<ChannelData *> channel);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
@ -113,7 +121,7 @@ protected:
|
|||
private:
|
||||
void updateSelected(const QPoint &cursorGlobalPosition);
|
||||
|
||||
not_null<ChannelData*> _channel;
|
||||
not_null<ChannelData *> _channel;
|
||||
|
||||
Text _text;
|
||||
qint32 _textWidth, _textHeight;
|
||||
|
@ -122,12 +130,11 @@ private:
|
|||
bool _linkOver = false;
|
||||
|
||||
QPoint _lastMousePos;
|
||||
|
||||
};
|
||||
|
||||
class ConvertToSupergroupBox : public BoxContent, public RPCSender {
|
||||
public:
|
||||
ConvertToSupergroupBox(QWidget*, ChatData *chat);
|
||||
ConvertToSupergroupBox(QWidget *, ChatData *chat);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
@ -143,12 +150,11 @@ private:
|
|||
ChatData *_chat;
|
||||
Text _text, _note;
|
||||
qint32 _textWidth, _textHeight;
|
||||
|
||||
};
|
||||
|
||||
class PinMessageBox : public BoxContent, public RPCSender {
|
||||
public:
|
||||
PinMessageBox(QWidget*, ChannelData *channel, MsgId msgId);
|
||||
PinMessageBox(QWidget *, ChannelData *channel, MsgId msgId);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
@ -168,13 +174,12 @@ private:
|
|||
object_ptr<Ui::Checkbox> _notify;
|
||||
|
||||
mtpRequestId _requestId = 0;
|
||||
|
||||
};
|
||||
|
||||
class DeleteMessagesBox : public BoxContent, public RPCSender {
|
||||
public:
|
||||
DeleteMessagesBox(QWidget*, HistoryItem *item, bool suggestModerateActions);
|
||||
DeleteMessagesBox(QWidget*, const SelectedItemSet &selected);
|
||||
DeleteMessagesBox(QWidget *, HistoryItem *item, bool suggestModerateActions);
|
||||
DeleteMessagesBox(QWidget *, const SelectedItemSet &selected);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
@ -192,17 +197,17 @@ private:
|
|||
bool _moderateBan = false;
|
||||
bool _moderateDeleteAll = false;
|
||||
|
||||
object_ptr<Ui::FlatLabel> _text = { nullptr };
|
||||
object_ptr<Ui::Checkbox> _forEveryone = { nullptr };
|
||||
object_ptr<Ui::Checkbox> _banUser = { nullptr };
|
||||
object_ptr<Ui::Checkbox> _reportSpam = { nullptr };
|
||||
object_ptr<Ui::Checkbox> _deleteAll = { nullptr };
|
||||
|
||||
object_ptr<Ui::FlatLabel> _text = {nullptr};
|
||||
object_ptr<Ui::Checkbox> _forEveryone = {nullptr};
|
||||
object_ptr<Ui::Checkbox> _banUser = {nullptr};
|
||||
object_ptr<Ui::Checkbox> _reportSpam = {nullptr};
|
||||
object_ptr<Ui::Checkbox> _deleteAll = {nullptr};
|
||||
};
|
||||
|
||||
class ConfirmInviteBox : public BoxContent, public RPCSender {
|
||||
public:
|
||||
ConfirmInviteBox(QWidget*, const QString &title, bool isChannel, const MTPChatPhoto &photo, int count, const QVector<UserData*> &participants);
|
||||
ConfirmInviteBox(QWidget *, const QString &title, bool isChannel, const MTPChatPhoto &photo, int count,
|
||||
const QVector<UserData *> &participants);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
@ -215,8 +220,7 @@ private:
|
|||
object_ptr<Ui::FlatLabel> _status;
|
||||
ImagePtr _photo;
|
||||
EmptyUserpic _photoEmpty;
|
||||
QVector<UserData*> _participants;
|
||||
QVector<UserData *> _participants;
|
||||
|
||||
int _userWidth = 0;
|
||||
|
||||
};
|
||||
|
|
|
@ -20,17 +20,17 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#include "boxes/confirm_phone_box.h"
|
||||
|
||||
#include "styles/style_boxes.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwidget.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "mainwidget.h"
|
||||
#include "lang/lang_keys.h"
|
||||
|
||||
namespace {
|
||||
|
||||
object_ptr<ConfirmPhoneBox> CurrentConfirmPhoneBox = { nullptr };
|
||||
object_ptr<ConfirmPhoneBox> CurrentConfirmPhoneBox = {nullptr};
|
||||
|
||||
} // namespace
|
||||
|
||||
|
@ -90,9 +90,9 @@ void SentCodeField::fix() {
|
|||
}
|
||||
|
||||
SentCodeCall::SentCodeCall(QObject *parent, base::lambda_once<void()> callCallback, base::lambda<void()> updateCallback)
|
||||
: _timer(parent)
|
||||
, _call(std::move(callCallback))
|
||||
, _update(std::move(updateCallback)) {
|
||||
: _timer(parent)
|
||||
, _call(std::move(callCallback))
|
||||
, _update(std::move(updateCallback)) {
|
||||
_timer->connect(_timer, &QTimer::timeout, [this] {
|
||||
if (_status.state == State::Waiting) {
|
||||
if (--_status.timeout <= 0) {
|
||||
|
@ -120,9 +120,13 @@ QString SentCodeCall::getText() const {
|
|||
switch (_status.state) {
|
||||
case State::Waiting: {
|
||||
if (_status.timeout >= 3600) {
|
||||
return lng_code_call(lt_minutes, qsl("%1:%2").arg(_status.timeout / 3600).arg((_status.timeout / 60) % 60, 2, 10, QChar('0')), lt_seconds, qsl("%1").arg(_status.timeout % 60, 2, 10, QChar('0')));
|
||||
return lng_code_call(
|
||||
lt_minutes,
|
||||
qsl("%1:%2").arg(_status.timeout / 3600).arg((_status.timeout / 60) % 60, 2, 10, QChar('0')),
|
||||
lt_seconds, qsl("%1").arg(_status.timeout % 60, 2, 10, QChar('0')));
|
||||
}
|
||||
return lng_code_call(lt_minutes, QString::number(_status.timeout / 60), lt_seconds, qsl("%1").arg(_status.timeout % 60, 2, 10, QChar('0')));
|
||||
return lng_code_call(lt_minutes, QString::number(_status.timeout / 60), lt_seconds,
|
||||
qsl("%1").arg(_status.timeout % 60, 2, 10, QChar('0')));
|
||||
} break;
|
||||
case State::Calling: return lang(lng_code_calling);
|
||||
case State::Called: return lang(lng_code_called);
|
||||
|
@ -140,11 +144,10 @@ void ConfirmPhoneBox::start(const QString &phone, const QString &hash) {
|
|||
CurrentConfirmPhoneBox->checkPhoneAndHash();
|
||||
}
|
||||
|
||||
ConfirmPhoneBox::ConfirmPhoneBox(QWidget*, const QString &phone, const QString &hash)
|
||||
: _phone(phone)
|
||||
, _hash(hash)
|
||||
, _call(this, [this] { sendCall(); }, [this] { update(); }) {
|
||||
}
|
||||
ConfirmPhoneBox::ConfirmPhoneBox(QWidget *, const QString &phone, const QString &hash)
|
||||
: _phone(phone)
|
||||
, _hash(hash)
|
||||
, _call(this, [this] { sendCall(); }, [this] { update(); }) {}
|
||||
|
||||
void ConfirmPhoneBox::sendCall() {
|
||||
MTP::send(MTPauth_ResendCode(MTP_string(_phone), MTP_string(_phoneHash)), rpcDone(&ConfirmPhoneBox::callDone));
|
||||
|
@ -154,7 +157,8 @@ void ConfirmPhoneBox::checkPhoneAndHash() {
|
|||
if (_sendCodeRequestId) {
|
||||
return;
|
||||
}
|
||||
_sendCodeRequestId = MTP::send(MTPaccount_SendConfirmPhoneCode(MTP_flags(0), MTP_string(_hash), MTPBool()), rpcDone(&ConfirmPhoneBox::sendCodeDone), rpcFail(&ConfirmPhoneBox::sendCodeFail));
|
||||
_sendCodeRequestId = MTP::send(MTPaccount_SendConfirmPhoneCode(MTP_flags(0), MTP_string(_hash), MTPBool()),
|
||||
rpcDone(&ConfirmPhoneBox::sendCodeDone), rpcFail(&ConfirmPhoneBox::sendCodeFail));
|
||||
}
|
||||
|
||||
void ConfirmPhoneBox::sendCodeDone(const MTPauth_SentCode &result) {
|
||||
|
@ -170,7 +174,7 @@ void ConfirmPhoneBox::sendCodeDone(const MTPauth_SentCode &result) {
|
|||
}
|
||||
_phoneHash = qs(resultInner.vphone_code_hash);
|
||||
if (resultInner.has_next_type() && resultInner.vnext_type.type() == mtpc_auth_codeTypeCall) {
|
||||
_call.setStatus({ SentCodeCall::State::Waiting, resultInner.has_timeout() ? resultInner.vtimeout.v : 60 });
|
||||
_call.setStatus({SentCodeCall::State::Waiting, resultInner.has_timeout() ? resultInner.vtimeout.v : 60});
|
||||
}
|
||||
launch();
|
||||
}
|
||||
|
@ -219,7 +223,8 @@ void ConfirmPhoneBox::prepare() {
|
|||
addButton(langFactory(lng_confirm_phone_send), [this] { onSendCode(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
setDimensions(st::boxWidth, st::usernamePadding.top() + _code->height() + st::usernameSkip + _about->height() + st::usernameSkip);
|
||||
setDimensions(st::boxWidth,
|
||||
st::usernamePadding.top() + _code->height() + st::usernameSkip + _about->height() + st::usernameSkip);
|
||||
|
||||
connect(_code, SIGNAL(submitted(bool)), this, SLOT(onSendCode()));
|
||||
|
||||
|
@ -245,7 +250,8 @@ void ConfirmPhoneBox::onSendCode() {
|
|||
|
||||
showError(QString());
|
||||
|
||||
_sendCodeRequestId = MTP::send(MTPaccount_ConfirmPhone(MTP_string(_phoneHash), MTP_string(_code->getLastText())), rpcDone(&ConfirmPhoneBox::confirmDone), rpcFail(&ConfirmPhoneBox::confirmFail));
|
||||
_sendCodeRequestId = MTP::send(MTPaccount_ConfirmPhone(MTP_string(_phoneHash), MTP_string(_code->getLastText())),
|
||||
rpcDone(&ConfirmPhoneBox::confirmDone), rpcFail(&ConfirmPhoneBox::confirmFail));
|
||||
}
|
||||
|
||||
void ConfirmPhoneBox::confirmDone(const MTPBool &result) {
|
||||
|
|
|
@ -30,7 +30,10 @@ class FlatLabel;
|
|||
|
||||
class SentCodeField : public Ui::InputField {
|
||||
public:
|
||||
SentCodeField(QWidget *parent, const style::InputField &st, base::lambda<QString()> placeholderFactory = base::lambda<QString()>(), const QString &val = QString()) : Ui::InputField(parent, st, std::move(placeholderFactory), val) {
|
||||
SentCodeField(QWidget *parent, const style::InputField &st,
|
||||
base::lambda<QString()> placeholderFactory = base::lambda<QString()>(),
|
||||
const QString &val = QString())
|
||||
: Ui::InputField(parent, st, std::move(placeholderFactory), val) {
|
||||
connect(this, &Ui::InputField::changed, [this] { fix(); });
|
||||
}
|
||||
|
||||
|
@ -51,7 +54,6 @@ private:
|
|||
int _autoSubmitLength = 0;
|
||||
base::lambda<void()> _submitCallback;
|
||||
base::lambda<void()> _changedCallback;
|
||||
|
||||
};
|
||||
|
||||
class SentCodeCall {
|
||||
|
@ -65,10 +67,10 @@ public:
|
|||
Disabled,
|
||||
};
|
||||
struct Status {
|
||||
Status() {
|
||||
}
|
||||
Status(State state, int timeout) : state(state), timeout(timeout) {
|
||||
}
|
||||
Status() {}
|
||||
Status(State state, int timeout)
|
||||
: state(state)
|
||||
, timeout(timeout) {}
|
||||
|
||||
State state = State::Disabled;
|
||||
int timeout = 0;
|
||||
|
@ -91,7 +93,6 @@ private:
|
|||
object_ptr<QTimer> _timer;
|
||||
base::lambda_once<void()> _call;
|
||||
base::lambda<void()> _update;
|
||||
|
||||
};
|
||||
|
||||
class ConfirmPhoneBox : public BoxContent, public RPCSender {
|
||||
|
@ -113,7 +114,7 @@ protected:
|
|||
void resizeEvent(QResizeEvent *e) override;
|
||||
|
||||
private:
|
||||
ConfirmPhoneBox(QWidget*, const QString &phone, const QString &hash);
|
||||
ConfirmPhoneBox(QWidget *, const QString &phone, const QString &hash);
|
||||
friend class object_ptr<ConfirmPhoneBox>;
|
||||
|
||||
void sendCall();
|
||||
|
@ -146,10 +147,9 @@ private:
|
|||
|
||||
mtpRequestId _checkCodeRequestId = 0;
|
||||
|
||||
object_ptr<Ui::FlatLabel> _about = { nullptr };
|
||||
object_ptr<SentCodeField> _code = { nullptr };
|
||||
object_ptr<Ui::FlatLabel> _about = {nullptr};
|
||||
object_ptr<SentCodeField> _code = {nullptr};
|
||||
|
||||
QString _error;
|
||||
SentCodeCall _call;
|
||||
|
||||
};
|
||||
|
|
|
@ -21,52 +21,58 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
#include "boxes/connection_box.h"
|
||||
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "history/history_location_manager.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "history/history_location_manager.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
|
||||
void ConnectionBox::ShowApplyProxyConfirmation(const QMap<QString, QString> &fields) {
|
||||
auto server = fields.value(qsl("server"));
|
||||
auto port = fields.value(qsl("port")).toInt();
|
||||
if (!server.isEmpty() && port != 0) {
|
||||
auto weakBox = std::make_shared<QPointer<ConfirmBox>>(nullptr);
|
||||
auto box = Ui::show(Box<ConfirmBox>(lng_sure_enable_socks(lt_server, server, lt_port, QString::number(port)), lang(lng_sure_enable), [fields, weakBox] {
|
||||
auto p = ProxyData();
|
||||
p.host = fields.value(qsl("server"));
|
||||
p.user = fields.value(qsl("user"));
|
||||
p.password = fields.value(qsl("pass"));
|
||||
p.port = fields.value(qsl("port")).toInt();
|
||||
Global::SetConnectionType(dbictTcpProxy);
|
||||
Global::SetLastProxyType(dbictTcpProxy);
|
||||
Global::SetConnectionProxy(p);
|
||||
Local::writeSettings();
|
||||
Global::RefConnectionTypeChanged().notify();
|
||||
MTP::restart();
|
||||
reinitLocationManager();
|
||||
reinitWebLoadManager();
|
||||
if (*weakBox) (*weakBox)->closeBox();
|
||||
}), KeepOtherLayers);
|
||||
auto box = Ui::show(Box<ConfirmBox>(lng_sure_enable_socks(lt_server, server, lt_port, QString::number(port)),
|
||||
lang(lng_sure_enable),
|
||||
[fields, weakBox] {
|
||||
auto p = ProxyData();
|
||||
p.host = fields.value(qsl("server"));
|
||||
p.user = fields.value(qsl("user"));
|
||||
p.password = fields.value(qsl("pass"));
|
||||
p.port = fields.value(qsl("port")).toInt();
|
||||
Global::SetConnectionType(dbictTcpProxy);
|
||||
Global::SetLastProxyType(dbictTcpProxy);
|
||||
Global::SetConnectionProxy(p);
|
||||
Local::writeSettings();
|
||||
Global::RefConnectionTypeChanged().notify();
|
||||
MTP::restart();
|
||||
reinitLocationManager();
|
||||
reinitWebLoadManager();
|
||||
if (*weakBox) (*weakBox)->closeBox();
|
||||
}),
|
||||
KeepOtherLayers);
|
||||
*weakBox = box;
|
||||
}
|
||||
}
|
||||
|
||||
ConnectionBox::ConnectionBox(QWidget *parent)
|
||||
: _hostInput(this, st::connectionHostInputField, langFactory(lng_connection_host_ph), Global::ConnectionProxy().host)
|
||||
, _portInput(this, st::connectionPortInputField, langFactory(lng_connection_port_ph), QString::number(Global::ConnectionProxy().port))
|
||||
, _userInput(this, st::connectionUserInputField, langFactory(lng_connection_user_ph), Global::ConnectionProxy().user)
|
||||
, _passwordInput(this, st::connectionPasswordInputField, langFactory(lng_connection_password_ph), Global::ConnectionProxy().password)
|
||||
, _typeGroup(std::make_shared<Ui::RadioenumGroup<DBIConnectionType>>(Global::ConnectionType()))
|
||||
, _autoRadio(this, _typeGroup, dbictAuto, lang(lng_connection_auto_rb), st::defaultBoxCheckbox)
|
||||
, _httpProxyRadio(this, _typeGroup, dbictHttpProxy, lang(lng_connection_http_proxy_rb), st::defaultBoxCheckbox)
|
||||
, _tcpProxyRadio(this, _typeGroup, dbictTcpProxy, lang(lng_connection_tcp_proxy_rb), st::defaultBoxCheckbox)
|
||||
, _tryIPv6(this, lang(lng_connection_try_ipv6), Global::TryIPv6(), st::defaultBoxCheckbox) {
|
||||
}
|
||||
: _hostInput(this, st::connectionHostInputField, langFactory(lng_connection_host_ph),
|
||||
Global::ConnectionProxy().host)
|
||||
, _portInput(this, st::connectionPortInputField, langFactory(lng_connection_port_ph),
|
||||
QString::number(Global::ConnectionProxy().port))
|
||||
, _userInput(this, st::connectionUserInputField, langFactory(lng_connection_user_ph),
|
||||
Global::ConnectionProxy().user)
|
||||
, _passwordInput(this, st::connectionPasswordInputField, langFactory(lng_connection_password_ph),
|
||||
Global::ConnectionProxy().password)
|
||||
, _typeGroup(std::make_shared<Ui::RadioenumGroup<DBIConnectionType>>(Global::ConnectionType()))
|
||||
, _autoRadio(this, _typeGroup, dbictAuto, lang(lng_connection_auto_rb), st::defaultBoxCheckbox)
|
||||
, _httpProxyRadio(this, _typeGroup, dbictHttpProxy, lang(lng_connection_http_proxy_rb), st::defaultBoxCheckbox)
|
||||
, _tcpProxyRadio(this, _typeGroup, dbictTcpProxy, lang(lng_connection_tcp_proxy_rb), st::defaultBoxCheckbox)
|
||||
, _tryIPv6(this, lang(lng_connection_try_ipv6), Global::TryIPv6(), st::defaultBoxCheckbox) {}
|
||||
|
||||
void ConnectionBox::prepare() {
|
||||
setTitle(langFactory(lng_connection_header));
|
||||
|
@ -93,7 +99,10 @@ bool ConnectionBox::badProxyValue() const {
|
|||
}
|
||||
|
||||
void ConnectionBox::updateControlsVisibility() {
|
||||
auto newHeight = st::boxOptionListPadding.top() + _autoRadio->heightNoMargins() + st::boxOptionListSkip + _httpProxyRadio->heightNoMargins() + st::boxOptionListSkip + _tcpProxyRadio->heightNoMargins() + st::boxOptionListSkip + st::connectionIPv6Skip + _tryIPv6->heightNoMargins() + st::defaultCheckbox.margin.bottom() + st::boxOptionListPadding.bottom() + st::boxPadding.bottom();
|
||||
auto newHeight = st::boxOptionListPadding.top() + _autoRadio->heightNoMargins() + st::boxOptionListSkip +
|
||||
_httpProxyRadio->heightNoMargins() + st::boxOptionListSkip + _tcpProxyRadio->heightNoMargins() +
|
||||
st::boxOptionListSkip + st::connectionIPv6Skip + _tryIPv6->heightNoMargins() +
|
||||
st::defaultCheckbox.margin.bottom() + st::boxOptionListPadding.bottom() + st::boxPadding.bottom();
|
||||
if (_typeGroup->value() == dbictAuto && badProxyValue()) {
|
||||
_hostInput->hide();
|
||||
_portInput->hide();
|
||||
|
@ -127,31 +136,42 @@ void ConnectionBox::resizeEvent(QResizeEvent *e) {
|
|||
|
||||
void ConnectionBox::updateControlsPosition() {
|
||||
auto type = _typeGroup->value();
|
||||
_autoRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _autoRadio->getMargins().top() + st::boxOptionListPadding.top());
|
||||
_httpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _autoRadio->bottomNoMargins() + st::boxOptionListSkip);
|
||||
_autoRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(),
|
||||
_autoRadio->getMargins().top() + st::boxOptionListPadding.top());
|
||||
_httpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(),
|
||||
_autoRadio->bottomNoMargins() + st::boxOptionListSkip);
|
||||
|
||||
auto inputy = 0;
|
||||
auto fieldsVisible = (type != dbictAuto) || (!badProxyValue() && Global::LastProxyType() != dbictAuto);
|
||||
auto fieldsBelowHttp = fieldsVisible && (type == dbictHttpProxy || (type == dbictAuto && Global::LastProxyType() == dbictHttpProxy));
|
||||
auto fieldsBelowTcp = fieldsVisible && (type == dbictTcpProxy || (type == dbictAuto && Global::LastProxyType() == dbictTcpProxy));
|
||||
auto fieldsBelowHttp =
|
||||
fieldsVisible && (type == dbictHttpProxy || (type == dbictAuto && Global::LastProxyType() == dbictHttpProxy));
|
||||
auto fieldsBelowTcp =
|
||||
fieldsVisible && (type == dbictTcpProxy || (type == dbictAuto && Global::LastProxyType() == dbictTcpProxy));
|
||||
if (fieldsBelowHttp) {
|
||||
inputy = _httpProxyRadio->bottomNoMargins() + st::boxOptionInputSkip;
|
||||
_tcpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), inputy + st::boxOptionInputSkip + 2 * _hostInput->height() + st::boxOptionListSkip);
|
||||
_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::boxOptionListSkip);
|
||||
_tcpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(),
|
||||
_httpProxyRadio->bottomNoMargins() + st::boxOptionListSkip);
|
||||
if (fieldsBelowTcp) {
|
||||
inputy = _tcpProxyRadio->bottomNoMargins() + st::boxOptionInputSkip;
|
||||
}
|
||||
}
|
||||
|
||||
if (inputy) {
|
||||
_hostInput->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left() + st::defaultCheck.diameter + st::defaultBoxCheckbox.textPosition.x() - st::defaultInputField.textMargins.left(), inputy);
|
||||
_hostInput->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left() + st::defaultCheck.diameter +
|
||||
st::defaultBoxCheckbox.textPosition.x() - st::defaultInputField.textMargins.left(),
|
||||
inputy);
|
||||
_portInput->moveToRight(st::boxPadding.right(), inputy);
|
||||
_userInput->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left() + st::defaultCheck.diameter + st::defaultBoxCheckbox.textPosition.x() - st::defaultInputField.textMargins.left(), _hostInput->y() + _hostInput->height() + st::boxOptionInputSkip);
|
||||
_userInput->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left() + st::defaultCheck.diameter +
|
||||
st::defaultBoxCheckbox.textPosition.x() - st::defaultInputField.textMargins.left(),
|
||||
_hostInput->y() + _hostInput->height() + st::boxOptionInputSkip);
|
||||
_passwordInput->moveToRight(st::boxPadding.right(), _userInput->y());
|
||||
}
|
||||
|
||||
auto tryipv6y = (fieldsBelowTcp ? _userInput->bottomNoMargins() : _tcpProxyRadio->bottomNoMargins()) + st::boxOptionListSkip + st::connectionIPv6Skip;
|
||||
auto tryipv6y = (fieldsBelowTcp ? _userInput->bottomNoMargins() : _tcpProxyRadio->bottomNoMargins()) +
|
||||
st::boxOptionListSkip + st::connectionIPv6Skip;
|
||||
_tryIPv6->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), tryipv6y);
|
||||
}
|
||||
|
||||
|
@ -162,7 +182,8 @@ void ConnectionBox::typeChanged(DBIConnectionType type) {
|
|||
updateControlsVisibility();
|
||||
if (type != dbictAuto) {
|
||||
Global::SetLastProxyType(type);
|
||||
if (!_hostInput->hasFocus() && !_portInput->hasFocus() && !_userInput->hasFocus() && !_passwordInput->hasFocus()) {
|
||||
if (!_hostInput->hasFocus() && !_portInput->hasFocus() && !_userInput->hasFocus() &&
|
||||
!_passwordInput->hasFocus()) {
|
||||
_hostInput->setFocusFast();
|
||||
}
|
||||
if ((type == dbictHttpProxy) && !_portInput->getLastText().toInt()) {
|
||||
|
@ -257,21 +278,24 @@ void ConnectionBox::onSave() {
|
|||
}
|
||||
|
||||
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(st::boxTitleHeight + 2 * (st::defaultCheck.diameter + st::setLittleSkip)) {
|
||||
}
|
||||
: _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(st::boxTitleHeight + 2 * (st::defaultCheck.diameter + st::setLittleSkip)) {}
|
||||
|
||||
void AutoDownloadBox::prepare() {
|
||||
addButton(langFactory(lng_connection_save), [this] { onSave(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
setDimensions(st::boxWidth, 3 * _sectionHeight - st::autoDownloadTopDelta + st::setLittleSkip + _gifPlay->heightNoMargins() + st::setLittleSkip);
|
||||
setDimensions(st::boxWidth, 3 * _sectionHeight - st::autoDownloadTopDelta + st::setLittleSkip +
|
||||
_gifPlay->heightNoMargins() + st::setLittleSkip);
|
||||
}
|
||||
|
||||
void AutoDownloadBox::paintEvent(QPaintEvent *e) {
|
||||
|
@ -281,9 +305,12 @@ void AutoDownloadBox::paintEvent(QPaintEvent *e) {
|
|||
|
||||
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));
|
||||
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) {
|
||||
|
@ -303,7 +330,8 @@ void AutoDownloadBox::resizeEvent(QResizeEvent *e) {
|
|||
|
||||
void AutoDownloadBox::onSave() {
|
||||
bool changed = false;
|
||||
qint32 autoDownloadPhoto = (_photoPrivate->checked() ? 0 : dbiadNoPrivate) | (_photoGroups->checked() ? 0 : dbiadNoGroups);
|
||||
qint32 autoDownloadPhoto =
|
||||
(_photoPrivate->checked() ? 0 : dbiadNoPrivate) | (_photoGroups->checked() ? 0 : dbiadNoGroups);
|
||||
if (cAutoDownloadPhoto() != autoDownloadPhoto) {
|
||||
bool enabledPrivate = ((cAutoDownloadPhoto() & dbiadNoPrivate) && !(autoDownloadPhoto & dbiadNoPrivate));
|
||||
bool enabledGroups = ((cAutoDownloadPhoto() & dbiadNoGroups) && !(autoDownloadPhoto & dbiadNoGroups));
|
||||
|
@ -316,7 +344,8 @@ void AutoDownloadBox::onSave() {
|
|||
}
|
||||
changed = true;
|
||||
}
|
||||
qint32 autoDownloadAudio = (_audioPrivate->checked() ? 0 : dbiadNoPrivate) | (_audioGroups->checked() ? 0 : dbiadNoGroups);
|
||||
qint32 autoDownloadAudio =
|
||||
(_audioPrivate->checked() ? 0 : dbiadNoPrivate) | (_audioGroups->checked() ? 0 : dbiadNoGroups);
|
||||
if (cAutoDownloadAudio() != autoDownloadAudio) {
|
||||
bool enabledPrivate = ((cAutoDownloadAudio() & dbiadNoPrivate) && !(autoDownloadAudio & dbiadNoPrivate));
|
||||
bool enabledGroups = ((cAutoDownloadAudio() & dbiadNoGroups) && !(autoDownloadAudio & dbiadNoGroups));
|
||||
|
@ -330,7 +359,8 @@ void AutoDownloadBox::onSave() {
|
|||
}
|
||||
changed = true;
|
||||
}
|
||||
qint32 autoDownloadGif = (_gifPrivate->checked() ? 0 : dbiadNoPrivate) | (_gifGroups->checked() ? 0 : dbiadNoGroups);
|
||||
qint32 autoDownloadGif =
|
||||
(_gifPrivate->checked() ? 0 : dbiadNoPrivate) | (_gifGroups->checked() ? 0 : dbiadNoGroups);
|
||||
if (cAutoDownloadGif() != autoDownloadGif) {
|
||||
bool enabledPrivate = ((cAutoDownloadGif() & dbiadNoPrivate) && !(autoDownloadGif & dbiadNoPrivate));
|
||||
bool enabledGroups = ((cAutoDownloadGif() & dbiadNoGroups) && !(autoDownloadGif & dbiadNoGroups));
|
||||
|
|
|
@ -27,10 +27,8 @@ class InputField;
|
|||
class PortInput;
|
||||
class PasswordInput;
|
||||
class Checkbox;
|
||||
template <typename Enum>
|
||||
class RadioenumGroup;
|
||||
template <typename Enum>
|
||||
class Radioenum;
|
||||
template <typename Enum> class RadioenumGroup;
|
||||
template <typename Enum> class Radioenum;
|
||||
} // namespace Ui
|
||||
|
||||
class ConnectionBox : public BoxContent {
|
||||
|
@ -67,7 +65,6 @@ private:
|
|||
object_ptr<Ui::Radioenum<DBIConnectionType>> _httpProxyRadio;
|
||||
object_ptr<Ui::Radioenum<DBIConnectionType>> _tcpProxyRadio;
|
||||
object_ptr<Ui::Checkbox> _tryIPv6;
|
||||
|
||||
};
|
||||
|
||||
class AutoDownloadBox : public BoxContent {
|
||||
|
@ -95,5 +92,4 @@ private:
|
|||
object_ptr<Ui::Checkbox> _gifPlay;
|
||||
|
||||
int _sectionHeight = 0;
|
||||
|
||||
};
|
||||
|
|
|
@ -20,24 +20,23 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#include "boxes/download_path_box.h"
|
||||
|
||||
#include "lang/lang_keys.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "core/file_utilities.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "platform/platform_specific.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "facades.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "platform/platform_specific.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
|
||||
DownloadPathBox::DownloadPathBox(QWidget *parent)
|
||||
: _path(Global::DownloadPath())
|
||||
, _pathBookmark(Global::DownloadPathBookmark())
|
||||
, _group(std::make_shared<Ui::RadioenumGroup<Directory>>(typeFromPath(_path)))
|
||||
, _default(this, _group, Directory::Downloads, lang(lng_download_path_default_radio), st::defaultBoxCheckbox)
|
||||
, _temp(this, _group, Directory::Temp, lang(lng_download_path_temp_radio), st::defaultBoxCheckbox)
|
||||
, _dir(this, _group, Directory::Custom, lang(lng_download_path_dir_radio), st::defaultBoxCheckbox)
|
||||
, _pathLink(this, QString(), st::boxLinkButton) {
|
||||
}
|
||||
: _path(Global::DownloadPath())
|
||||
, _pathBookmark(Global::DownloadPathBookmark())
|
||||
, _group(std::make_shared<Ui::RadioenumGroup<Directory>>(typeFromPath(_path)))
|
||||
, _default(this, _group, Directory::Downloads, lang(lng_download_path_default_radio), st::defaultBoxCheckbox)
|
||||
, _temp(this, _group, Directory::Temp, lang(lng_download_path_temp_radio), st::defaultBoxCheckbox)
|
||||
, _dir(this, _group, Directory::Custom, lang(lng_download_path_dir_radio), st::defaultBoxCheckbox)
|
||||
, _pathLink(this, QString(), st::boxLinkButton) {}
|
||||
|
||||
void DownloadPathBox::prepare() {
|
||||
addButton(langFactory(lng_connection_save), [this] { save(); });
|
||||
|
@ -58,7 +57,8 @@ void DownloadPathBox::updateControlsVisibility() {
|
|||
auto custom = (_group->value() == Directory::Custom);
|
||||
_pathLink->setVisible(custom);
|
||||
|
||||
auto newHeight = st::boxOptionListPadding.top() + _default->getMargins().top() + _default->heightNoMargins() + st::boxOptionListSkip + _temp->heightNoMargins() + st::boxOptionListSkip + _dir->heightNoMargins();
|
||||
auto newHeight = st::boxOptionListPadding.top() + _default->getMargins().top() + _default->heightNoMargins() +
|
||||
st::boxOptionListSkip + _temp->heightNoMargins() + st::boxOptionListSkip + _dir->heightNoMargins();
|
||||
if (custom) {
|
||||
newHeight += st::downloadPathSkip + _pathLink->height();
|
||||
}
|
||||
|
@ -70,10 +70,14 @@ void DownloadPathBox::updateControlsVisibility() {
|
|||
void DownloadPathBox::resizeEvent(QResizeEvent *e) {
|
||||
BoxContent::resizeEvent(e);
|
||||
|
||||
_default->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), st::boxOptionListPadding.top() + _default->getMargins().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::defaultCheck.diameter + st::defaultBoxCheckbox.textPosition.x();
|
||||
_default->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(),
|
||||
st::boxOptionListPadding.top() + _default->getMargins().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::defaultCheck.diameter +
|
||||
st::defaultBoxCheckbox.textPosition.x();
|
||||
auto inputy = _dir->bottomNoMargins() + st::downloadPathSkip;
|
||||
|
||||
_pathLink->moveToLeft(inputx, inputy);
|
||||
|
@ -99,18 +103,20 @@ void DownloadPathBox::radioChanged(Directory value) {
|
|||
void DownloadPathBox::onEditPath() {
|
||||
auto initialPath = [] {
|
||||
if (!Global::DownloadPath().isEmpty() && Global::DownloadPath() != qstr("tmp")) {
|
||||
return Global::DownloadPath().left(Global::DownloadPath().size() - (Global::DownloadPath().endsWith('/') ? 1 : 0));
|
||||
return Global::DownloadPath().left(Global::DownloadPath().size() -
|
||||
(Global::DownloadPath().endsWith('/') ? 1 : 0));
|
||||
}
|
||||
return QString();
|
||||
};
|
||||
FileDialog::GetFolder(lang(lng_download_path_choose), initialPath(), base::lambda_guarded(this, [this](const QString &result) {
|
||||
if (!result.isEmpty()) {
|
||||
_path = result + '/';
|
||||
_pathBookmark = psDownloadPathBookmark(_path);
|
||||
setPathText(QDir::toNativeSeparators(_path));
|
||||
_group->setValue(Directory::Custom);
|
||||
}
|
||||
}));
|
||||
FileDialog::GetFolder(lang(lng_download_path_choose), initialPath(),
|
||||
base::lambda_guarded(this, [this](const QString &result) {
|
||||
if (!result.isEmpty()) {
|
||||
_path = result + '/';
|
||||
_pathBookmark = psDownloadPathBookmark(_path);
|
||||
setPathText(QDir::toNativeSeparators(_path));
|
||||
_group->setValue(Directory::Custom);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
void DownloadPathBox::save() {
|
||||
|
@ -133,6 +139,7 @@ void DownloadPathBox::save() {
|
|||
}
|
||||
|
||||
void DownloadPathBox::setPathText(const QString &text) {
|
||||
auto availw = st::boxWideWidth - st::boxPadding.left() - st::defaultCheck.diameter - st::defaultBoxCheckbox.textPosition.x() - st::boxPadding.right();
|
||||
auto availw = st::boxWideWidth - st::boxPadding.left() - st::defaultCheck.diameter -
|
||||
st::defaultBoxCheckbox.textPosition.x() - st::boxPadding.right();
|
||||
_pathLink->setText(st::boxTextFont->elided(text, availw));
|
||||
}
|
||||
|
|
|
@ -20,14 +20,12 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "boxes/abstract_box.h"
|
||||
#include "base/observer.h"
|
||||
#include "boxes/abstract_box.h"
|
||||
|
||||
namespace Ui {
|
||||
template <typename Enum>
|
||||
class RadioenumGroup;
|
||||
template <typename Enum>
|
||||
class Radioenum;
|
||||
template <typename Enum> class RadioenumGroup;
|
||||
template <typename Enum> class Radioenum;
|
||||
class LinkButton;
|
||||
} // namespace Ui
|
||||
|
||||
|
@ -73,5 +71,4 @@ private:
|
|||
object_ptr<Ui::Radioenum<Directory>> _temp;
|
||||
object_ptr<Ui::Radioenum<Directory>> _dir;
|
||||
object_ptr<Ui::LinkButton> _pathLink;
|
||||
|
||||
};
|
||||
|
|
|
@ -20,12 +20,12 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#include "boxes/edit_color_box.h"
|
||||
|
||||
#include "app.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "ui/widgets/shadow.h"
|
||||
#include "styles/style_mediaview.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "app.h"
|
||||
#include "ui/widgets/shadow.h"
|
||||
|
||||
class EditColorBox::Picker : public TWidget {
|
||||
public:
|
||||
|
@ -70,7 +70,6 @@ private:
|
|||
|
||||
bool _choosing = false;
|
||||
base::Observable<void> _changed;
|
||||
|
||||
};
|
||||
|
||||
QCursor EditColorBox::Picker::generateCursor() {
|
||||
|
@ -97,7 +96,8 @@ QCursor EditColorBox::Picker::generateCursor() {
|
|||
return QCursor(QPixmap::fromImage(cursor));
|
||||
}
|
||||
|
||||
EditColorBox::Picker::Picker(QWidget *parent, QColor color) : TWidget(parent) {
|
||||
EditColorBox::Picker::Picker(QWidget *parent, QColor color)
|
||||
: TWidget(parent) {
|
||||
setCursor(generateCursor());
|
||||
|
||||
auto size = QSize(st::colorPickerSize, st::colorPickerSize);
|
||||
|
@ -128,7 +128,8 @@ void EditColorBox::Picker::paintEvent(QPaintEvent *e) {
|
|||
auto y = anim::interpolate(0, height() - 1, _y);
|
||||
PainterHighQualityEnabler hq(p);
|
||||
|
||||
p.drawEllipse(QRect(x - st::colorPickerMarkRadius, y - st::colorPickerMarkRadius, 2 * st::colorPickerMarkRadius, 2 * st::colorPickerMarkRadius));
|
||||
p.drawEllipse(QRect(x - st::colorPickerMarkRadius, y - st::colorPickerMarkRadius, 2 * st::colorPickerMarkRadius,
|
||||
2 * st::colorPickerMarkRadius));
|
||||
}
|
||||
|
||||
void EditColorBox::Picker::mousePressEvent(QMouseEvent *e) {
|
||||
|
@ -151,7 +152,7 @@ void EditColorBox::Picker::preparePalette() {
|
|||
_paletteInvalidated = false;
|
||||
|
||||
auto size = _palette.width();
|
||||
auto ints = reinterpret_cast<quint32*>(_palette.bits());
|
||||
auto ints = reinterpret_cast<quint32 *>(_palette.bits());
|
||||
auto intsAddPerLine = (_palette.bytesPerLine() - size * sizeof(quint32)) / sizeof(quint32);
|
||||
|
||||
constexpr auto Large = 1024 * 1024;
|
||||
|
@ -280,15 +281,15 @@ private:
|
|||
|
||||
bool _choosing = false;
|
||||
base::Observable<void> _changed;
|
||||
|
||||
};
|
||||
|
||||
EditColorBox::Slider::Slider(QWidget *parent, Direction direction, Type type, QColor color) : TWidget(parent)
|
||||
, _direction(direction)
|
||||
, _type(type)
|
||||
, _color(color.red(), color.green(), color.blue())
|
||||
, _value(valueFromColor(color))
|
||||
, _transparent((_type == Type::Hue) ? QBrush() : style::transparentPlaceholderBrush()) {
|
||||
EditColorBox::Slider::Slider(QWidget *parent, Direction direction, Type type, QColor color)
|
||||
: TWidget(parent)
|
||||
, _direction(direction)
|
||||
, _type(type)
|
||||
, _color(color.red(), color.green(), color.blue())
|
||||
, _value(valueFromColor(color))
|
||||
, _transparent((_type == Type::Hue) ? QBrush() : style::transparentPlaceholderBrush()) {
|
||||
prepareMinSize();
|
||||
}
|
||||
|
||||
|
@ -299,7 +300,8 @@ void EditColorBox::Slider::prepareMinSize() {
|
|||
|
||||
void EditColorBox::Slider::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
auto to = rect().marginsRemoved(QMargins(st::colorSliderSkip, st::colorSliderSkip, st::colorSliderSkip, st::colorSliderSkip));
|
||||
auto to = rect().marginsRemoved(
|
||||
QMargins(st::colorSliderSkip, st::colorSliderSkip, st::colorSliderSkip, st::colorSliderSkip));
|
||||
Ui::Shadow::paint(p, to, width(), st::defaultRoundShadow);
|
||||
if (_type == Type::Opacity) {
|
||||
p.fillRect(to, _transparent);
|
||||
|
@ -308,11 +310,13 @@ void EditColorBox::Slider::paintEvent(QPaintEvent *e) {
|
|||
if (isHorizontal()) {
|
||||
auto x = st::colorSliderSkip + std::round(_value * to.width());
|
||||
st::colorSliderArrowTop.paint(p, x - st::colorSliderArrowTop.width() / 2, 0, width());
|
||||
st::colorSliderArrowBottom.paint(p, x - st::colorSliderArrowBottom.width() / 2, height() - st::colorSliderArrowBottom.height(), width());
|
||||
st::colorSliderArrowBottom.paint(p, x - st::colorSliderArrowBottom.width() / 2,
|
||||
height() - st::colorSliderArrowBottom.height(), width());
|
||||
} else {
|
||||
auto y = st::colorSliderSkip + std::round(_value * to.height());
|
||||
st::colorSliderArrowLeft.paint(p, 0, y - st::colorSliderArrowLeft.height() / 2, width());
|
||||
st::colorSliderArrowRight.paint(p, width() - st::colorSliderArrowRight.width(), y - st::colorSliderArrowRight.height() / 2, width());
|
||||
st::colorSliderArrowRight.paint(p, width() - st::colorSliderArrowRight.width(),
|
||||
y - st::colorSliderArrowRight.height() / 2, width());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -340,7 +344,7 @@ void EditColorBox::Slider::generatePixmap() {
|
|||
auto size = (isHorizontal() ? width() : height()) * cIntRetinaFactor();
|
||||
auto image = QImage(size, cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
|
||||
image.setDevicePixelRatio(cRetinaFactor());
|
||||
auto ints = reinterpret_cast<quint32*>(image.bits());
|
||||
auto ints = reinterpret_cast<quint32 *>(image.bits());
|
||||
auto intsPerLine = image.bytesPerLine() / sizeof(quint32);
|
||||
auto intsPerLineAdded = intsPerLine - size;
|
||||
|
||||
|
@ -441,7 +445,8 @@ void EditColorBox::Slider::updateCurrentPoint(QPoint localPosition) {
|
|||
|
||||
class EditColorBox::Field : public Ui::MaskedInputField {
|
||||
public:
|
||||
Field(QWidget *parent, const style::InputField &st, const QString &placeholder, int limit, const QString &units = QString());
|
||||
Field(QWidget *parent, const style::InputField &st, const QString &placeholder, int limit,
|
||||
const QString &units = QString());
|
||||
|
||||
int value() const {
|
||||
return getLastText().toInt();
|
||||
|
@ -468,15 +473,15 @@ private:
|
|||
int _limit = 0;
|
||||
int _digitLimit = 1;
|
||||
int _wheelDelta = 0;
|
||||
|
||||
};
|
||||
|
||||
EditColorBox::Field::Field(QWidget *parent, const style::InputField &st, const QString &placeholder, int limit, const QString &units) : Ui::MaskedInputField(parent, st)
|
||||
, _placeholder(placeholder)
|
||||
, _units(units)
|
||||
, _limit(limit)
|
||||
, _digitLimit(QString::number(_limit).size()) {
|
||||
}
|
||||
EditColorBox::Field::Field(QWidget *parent, const style::InputField &st, const QString &placeholder, int limit,
|
||||
const QString &units)
|
||||
: Ui::MaskedInputField(parent, st)
|
||||
, _placeholder(placeholder)
|
||||
, _units(units)
|
||||
, _limit(limit)
|
||||
, _digitLimit(QString::number(_limit).size()) {}
|
||||
|
||||
void EditColorBox::Field::correctValue(const QString &was, int wasCursor, QString &now, int &nowCursor) {
|
||||
QString newText;
|
||||
|
@ -518,7 +523,8 @@ void EditColorBox::Field::correctValue(const QString &was, int wasCursor, QStrin
|
|||
void EditColorBox::Field::paintAdditionalPlaceholder(Painter &p, TimeMs ms) {
|
||||
p.setFont(_st.font);
|
||||
p.setPen(_st.placeholderFg);
|
||||
auto inner = QRect(_st.textMargins.right(), _st.textMargins.top(), width() - 2 * _st.textMargins.right(), height() - _st.textMargins.top() - _st.textMargins.bottom());
|
||||
auto inner = QRect(_st.textMargins.right(), _st.textMargins.top(), width() - 2 * _st.textMargins.right(),
|
||||
height() - _st.textMargins.top() - _st.textMargins.bottom());
|
||||
p.drawText(inner, _placeholder, style::al_topleft);
|
||||
if (!_units.isEmpty()) {
|
||||
p.drawText(inner, _units, style::al_topright);
|
||||
|
@ -580,11 +586,10 @@ public:
|
|||
protected:
|
||||
void correctValue(const QString &was, int wasCursor, QString &now, int &nowCursor) override;
|
||||
void paintAdditionalPlaceholder(Painter &p, TimeMs ms) override;
|
||||
|
||||
};
|
||||
|
||||
EditColorBox::ResultField::ResultField(QWidget *parent, const style::InputField &st) : Ui::MaskedInputField(parent, st) {
|
||||
}
|
||||
EditColorBox::ResultField::ResultField(QWidget *parent, const style::InputField &st)
|
||||
: Ui::MaskedInputField(parent, st) {}
|
||||
|
||||
void EditColorBox::ResultField::correctValue(const QString &was, int wasCursor, QString &now, int &nowCursor) {
|
||||
QString newText;
|
||||
|
@ -623,25 +628,27 @@ void EditColorBox::ResultField::correctValue(const QString &was, int wasCursor,
|
|||
void EditColorBox::ResultField::paintAdditionalPlaceholder(Painter &p, TimeMs ms) {
|
||||
p.setFont(_st.font);
|
||||
p.setPen(_st.placeholderFg);
|
||||
p.drawText(QRect(_st.textMargins.right(), _st.textMargins.top(), width(), height() - _st.textMargins.top() - _st.textMargins.bottom()), "#", style::al_topleft);
|
||||
p.drawText(QRect(_st.textMargins.right(), _st.textMargins.top(), width(),
|
||||
height() - _st.textMargins.top() - _st.textMargins.bottom()),
|
||||
"#", style::al_topleft);
|
||||
}
|
||||
|
||||
EditColorBox::EditColorBox(QWidget*, const QString &title, QColor current) : BoxContent()
|
||||
, _title(title)
|
||||
, _picker(this, current)
|
||||
, _hueSlider(this, Slider::Direction::Vertical, Slider::Type::Hue, current)
|
||||
, _opacitySlider(this, Slider::Direction::Horizontal, Slider::Type::Opacity, current)
|
||||
, _hueField(this, st::colorValueInput, "H", 360, QString() + QChar(176)) // degree character
|
||||
, _saturationField(this, st::colorValueInput, "S", 100, "%")
|
||||
, _brightnessField(this, st::colorValueInput, "B", 100, "%")
|
||||
, _redField(this, st::colorValueInput, "R", 255)
|
||||
, _greenField(this, st::colorValueInput, "G", 255)
|
||||
, _blueField(this, st::colorValueInput, "B", 255)
|
||||
, _result(this, st::colorResultInput)
|
||||
, _transparent(style::transparentPlaceholderBrush())
|
||||
, _current(current)
|
||||
, _new(current) {
|
||||
}
|
||||
EditColorBox::EditColorBox(QWidget *, const QString &title, QColor current)
|
||||
: BoxContent()
|
||||
, _title(title)
|
||||
, _picker(this, current)
|
||||
, _hueSlider(this, Slider::Direction::Vertical, Slider::Type::Hue, current)
|
||||
, _opacitySlider(this, Slider::Direction::Horizontal, Slider::Type::Opacity, current)
|
||||
, _hueField(this, st::colorValueInput, "H", 360, QString() + QChar(176)) // degree character
|
||||
, _saturationField(this, st::colorValueInput, "S", 100, "%")
|
||||
, _brightnessField(this, st::colorValueInput, "B", 100, "%")
|
||||
, _redField(this, st::colorValueInput, "R", 255)
|
||||
, _greenField(this, st::colorValueInput, "G", 255)
|
||||
, _blueField(this, st::colorValueInput, "B", 255)
|
||||
, _result(this, st::colorResultInput)
|
||||
, _transparent(style::transparentPlaceholderBrush())
|
||||
, _current(current)
|
||||
, _new(current) {}
|
||||
|
||||
void EditColorBox::prepare() {
|
||||
setTitle([this] { return _title; });
|
||||
|
@ -665,7 +672,8 @@ void EditColorBox::prepare() {
|
|||
addButton(langFactory(lng_settings_save), [this] { saveColor(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
auto height = st::colorEditSkip + st::colorPickerSize + st::colorEditSkip + st::colorSliderWidth + st::colorEditSkip;
|
||||
auto height =
|
||||
st::colorEditSkip + st::colorPickerSize + st::colorEditSkip + st::colorSliderWidth + st::colorEditSkip;
|
||||
setDimensions(st::colorEditWidth, height);
|
||||
|
||||
subscribe(_picker->changed(), [this] { updateFromControls(); });
|
||||
|
@ -708,15 +716,8 @@ void EditColorBox::onFieldChanged() {
|
|||
}
|
||||
|
||||
void EditColorBox::onFieldSubmitted() {
|
||||
Ui::MaskedInputField *fields[] = {
|
||||
_hueField,
|
||||
_saturationField,
|
||||
_brightnessField,
|
||||
_redField,
|
||||
_greenField,
|
||||
_blueField,
|
||||
_result
|
||||
};
|
||||
Ui::MaskedInputField *fields[] = {_hueField, _saturationField, _brightnessField, _redField,
|
||||
_greenField, _blueField, _result};
|
||||
for (auto i = 0, count = int(base::array_size(fields)); i + 1 != count; ++i) {
|
||||
if (fields[i]->hasFocus()) {
|
||||
fields[i + 1]->setFocus();
|
||||
|
@ -776,23 +777,33 @@ void EditColorBox::updateResultField() {
|
|||
}
|
||||
|
||||
void EditColorBox::resizeEvent(QResizeEvent *e) {
|
||||
auto fullwidth = _picker->width() + 2 * (st::colorEditSkip - st::colorSliderSkip) + _hueSlider->width() + st::colorSampleSize.width();
|
||||
auto fullwidth = _picker->width() + 2 * (st::colorEditSkip - st::colorSliderSkip) + _hueSlider->width() +
|
||||
st::colorSampleSize.width();
|
||||
auto left = (width() - fullwidth) / 2;
|
||||
_picker->moveToLeft(left, st::colorEditSkip);
|
||||
_hueSlider->setGeometryToLeft(_picker->x() + _picker->width() + st::colorEditSkip - st::colorSliderSkip, st::colorEditSkip - st::colorSliderSkip, _hueSlider->width(), st::colorPickerSize + 2 * st::colorSliderSkip);
|
||||
_opacitySlider->setGeometryToLeft(_picker->x() - st::colorSliderSkip, _picker->y() + _picker->height() + st::colorEditSkip - st::colorSliderSkip, _picker->width() + 2 * st::colorSliderSkip, _opacitySlider->height());
|
||||
_hueSlider->setGeometryToLeft(_picker->x() + _picker->width() + st::colorEditSkip - st::colorSliderSkip,
|
||||
st::colorEditSkip - st::colorSliderSkip, _hueSlider->width(),
|
||||
st::colorPickerSize + 2 * st::colorSliderSkip);
|
||||
_opacitySlider->setGeometryToLeft(_picker->x() - st::colorSliderSkip,
|
||||
_picker->y() + _picker->height() + st::colorEditSkip - st::colorSliderSkip,
|
||||
_picker->width() + 2 * st::colorSliderSkip, _opacitySlider->height());
|
||||
auto fieldLeft = _hueSlider->x() + _hueSlider->width() - st::colorSliderSkip + st::colorEditSkip;
|
||||
auto fieldWidth = st::colorSampleSize.width();
|
||||
auto fieldHeight = _hueField->height();
|
||||
_newRect = QRect(fieldLeft, st::colorEditSkip, fieldWidth, st::colorSampleSize.height());
|
||||
_currentRect = _newRect.translated(0, st::colorSampleSize.height());
|
||||
_hueField->setGeometryToLeft(fieldLeft, _currentRect.y() + _currentRect.height() + st::colorFieldSkip, fieldWidth, fieldHeight);
|
||||
_hueField->setGeometryToLeft(fieldLeft, _currentRect.y() + _currentRect.height() + st::colorFieldSkip, fieldWidth,
|
||||
fieldHeight);
|
||||
_saturationField->setGeometryToLeft(fieldLeft, _hueField->y() + _hueField->height(), fieldWidth, fieldHeight);
|
||||
_brightnessField->setGeometryToLeft(fieldLeft, _saturationField->y() + _saturationField->height(), fieldWidth, fieldHeight);
|
||||
_redField->setGeometryToLeft(fieldLeft, _brightnessField->y() + _brightnessField->height() + st::colorFieldSkip, fieldWidth, fieldHeight);
|
||||
_brightnessField->setGeometryToLeft(fieldLeft, _saturationField->y() + _saturationField->height(), fieldWidth,
|
||||
fieldHeight);
|
||||
_redField->setGeometryToLeft(fieldLeft, _brightnessField->y() + _brightnessField->height() + st::colorFieldSkip,
|
||||
fieldWidth, fieldHeight);
|
||||
_greenField->setGeometryToLeft(fieldLeft, _redField->y() + _redField->height(), fieldWidth, fieldHeight);
|
||||
_blueField->setGeometryToLeft(fieldLeft, _greenField->y() + _greenField->height(), fieldWidth, fieldHeight);
|
||||
_result->setGeometryToLeft(fieldLeft - (st::colorEditSkip + st::colorSliderWidth), _opacitySlider->y() + _opacitySlider->height() - st::colorSliderSkip - _result->height(), fieldWidth + (st::colorEditSkip + st::colorSliderWidth), fieldHeight);
|
||||
_result->setGeometryToLeft(fieldLeft - (st::colorEditSkip + st::colorSliderWidth),
|
||||
_opacitySlider->y() + _opacitySlider->height() - st::colorSliderSkip - _result->height(),
|
||||
fieldWidth + (st::colorEditSkip + st::colorSliderWidth), fieldHeight);
|
||||
}
|
||||
|
||||
void EditColorBox::paintEvent(QPaintEvent *e) {
|
||||
|
@ -801,7 +812,8 @@ void EditColorBox::paintEvent(QPaintEvent *e) {
|
|||
Painter p(this);
|
||||
Ui::Shadow::paint(p, _picker->geometry(), width(), st::defaultRoundShadow);
|
||||
|
||||
Ui::Shadow::paint(p, QRect(_newRect.x(), _newRect.y(), _newRect.width(), _newRect.height() + _currentRect.height()), width(), st::defaultRoundShadow);
|
||||
Ui::Shadow::paint(p, QRect(_newRect.x(), _newRect.y(), _newRect.width(), _newRect.height() + _currentRect.height()),
|
||||
width(), st::defaultRoundShadow);
|
||||
if (_new.alphaF() < 1.) {
|
||||
p.fillRect(myrtlrect(_newRect), _transparent);
|
||||
}
|
||||
|
@ -870,9 +882,7 @@ void EditColorBox::updateFromResultField() {
|
|||
}
|
||||
return code - '0';
|
||||
};
|
||||
auto fromChars = [fromHex](QChar a, QChar b) {
|
||||
return fromHex(a) * 0x10 + fromHex(b);
|
||||
};
|
||||
auto fromChars = [fromHex](QChar a, QChar b) { return fromHex(a) * 0x10 + fromHex(b); };
|
||||
auto red = fromChars(text[0], text[1]);
|
||||
auto green = fromChars(text[2], text[3]);
|
||||
auto blue = fromChars(text[4], text[5]);
|
||||
|
|
|
@ -26,7 +26,7 @@ class EditColorBox : public BoxContent {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
EditColorBox(QWidget*, const QString &title, QColor current = QColor(255, 255, 255));
|
||||
EditColorBox(QWidget *, const QString &title, QColor current = QColor(255, 255, 255));
|
||||
|
||||
void setSaveCallback(base::lambda<void(QColor)> callback) {
|
||||
_saveCallback = std::move(callback);
|
||||
|
@ -105,5 +105,4 @@ private:
|
|||
|
||||
base::lambda<void(QColor)> _saveCallback;
|
||||
base::lambda<void()> _cancelCallback;
|
||||
|
||||
};
|
||||
|
|
|
@ -20,15 +20,15 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#include "boxes/edit_participant_box.h"
|
||||
|
||||
#include "lang/lang_keys.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "ui/special_buttons.h"
|
||||
#include "app.h" // For App::peerName
|
||||
#include "boxes/calendar_box.h"
|
||||
#include "facades.h"
|
||||
#include "app.h" // For App::peerName
|
||||
#include "lang/lang_keys.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "ui/special_buttons.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -77,12 +77,11 @@ void ApplyDependencies(CheckboxesMap &checkboxes, DependenciesMap &dependencies,
|
|||
|
||||
class EditParticipantBox::Inner : public TWidget {
|
||||
public:
|
||||
Inner(QWidget *parent, not_null<ChannelData*> channel, not_null<UserData*> user, bool hasAdminRights);
|
||||
Inner(QWidget *parent, not_null<ChannelData *> channel, not_null<UserData *> user, bool hasAdminRights);
|
||||
|
||||
template <typename Widget>
|
||||
QPointer<Widget> addControl(object_ptr<Widget> widget, QMargins margin) {
|
||||
template <typename Widget> QPointer<Widget> addControl(object_ptr<Widget> widget, QMargins margin) {
|
||||
doAddControl(std::move(widget), margin);
|
||||
return static_cast<Widget*>(_rows.back().widget.data());
|
||||
return static_cast<Widget *>(_rows.back().widget.data());
|
||||
}
|
||||
|
||||
void removeControl(QPointer<TWidget> widget);
|
||||
|
@ -94,8 +93,8 @@ protected:
|
|||
private:
|
||||
void doAddControl(object_ptr<TWidget> widget, QMargins margin);
|
||||
|
||||
not_null<ChannelData*> _channel;
|
||||
not_null<UserData*> _user;
|
||||
not_null<ChannelData *> _channel;
|
||||
not_null<UserData *> _user;
|
||||
object_ptr<Ui::PeerAvatarButton> _userPhoto;
|
||||
Text _userName;
|
||||
bool _hasAdminRights = false;
|
||||
|
@ -104,22 +103,21 @@ private:
|
|||
QMargins margin;
|
||||
};
|
||||
std::vector<Control> _rows;
|
||||
|
||||
};
|
||||
|
||||
EditParticipantBox::Inner::Inner(QWidget *parent, not_null<ChannelData*> channel, not_null<UserData*> user, bool hasAdminRights) : TWidget(parent)
|
||||
, _channel(channel)
|
||||
, _user(user)
|
||||
, _userPhoto(this, _user, st::rightsPhotoButton)
|
||||
, _hasAdminRights(hasAdminRights) {
|
||||
EditParticipantBox::Inner::Inner(QWidget *parent, not_null<ChannelData *> channel, not_null<UserData *> user,
|
||||
bool hasAdminRights)
|
||||
: TWidget(parent)
|
||||
, _channel(channel)
|
||||
, _user(user)
|
||||
, _userPhoto(this, _user, st::rightsPhotoButton)
|
||||
, _hasAdminRights(hasAdminRights) {
|
||||
_userName.setText(st::rightsNameStyle, App::peerName(_user), _textNameOptions);
|
||||
_userPhoto->setClickedCallback([this] { Ui::showPeerProfile(_user); });
|
||||
}
|
||||
|
||||
void EditParticipantBox::Inner::removeControl(QPointer<TWidget> widget) {
|
||||
auto row = std::find_if(_rows.begin(), _rows.end(), [widget](auto &&row) {
|
||||
return (row.widget == widget);
|
||||
});
|
||||
auto row = std::find_if(_rows.begin(), _rows.end(), [widget](auto &&row) { return (row.widget == widget); });
|
||||
Assert(row != _rows.end());
|
||||
row->widget.destroy();
|
||||
_rows.erase(row);
|
||||
|
@ -127,7 +125,7 @@ void EditParticipantBox::Inner::removeControl(QPointer<TWidget> widget) {
|
|||
|
||||
void EditParticipantBox::Inner::doAddControl(object_ptr<TWidget> widget, QMargins margin) {
|
||||
widget->setParent(this);
|
||||
_rows.push_back({ std::move(widget), margin });
|
||||
_rows.push_back({std::move(widget), margin});
|
||||
_rows.back().widget->show();
|
||||
}
|
||||
|
||||
|
@ -165,18 +163,18 @@ void EditParticipantBox::Inner::paintEvent(QPaintEvent *e) {
|
|||
p.drawTextLeft(namex, st::rightsPhotoMargin.top() + st::rightsStatusTop, width(), statusText());
|
||||
}
|
||||
|
||||
EditParticipantBox::EditParticipantBox(QWidget*, not_null<ChannelData*> channel, not_null<UserData*> user, bool hasAdminRights) : BoxContent()
|
||||
, _channel(channel)
|
||||
, _user(user)
|
||||
, _hasAdminRights(hasAdminRights) {
|
||||
}
|
||||
EditParticipantBox::EditParticipantBox(QWidget *, not_null<ChannelData *> channel, not_null<UserData *> user,
|
||||
bool hasAdminRights)
|
||||
: BoxContent()
|
||||
, _channel(channel)
|
||||
, _user(user)
|
||||
, _hasAdminRights(hasAdminRights) {}
|
||||
|
||||
void EditParticipantBox::prepare() {
|
||||
_inner = setInnerWidget(object_ptr<Inner>(this, _channel, _user, hasAdminRights()));
|
||||
}
|
||||
|
||||
template <typename Widget>
|
||||
QPointer<Widget> EditParticipantBox::addControl(object_ptr<Widget> widget, QMargins margin) {
|
||||
template <typename Widget> QPointer<Widget> EditParticipantBox::addControl(object_ptr<Widget> widget, QMargins margin) {
|
||||
Expects(_inner != nullptr);
|
||||
return _inner->addControl(std::move(widget), margin);
|
||||
}
|
||||
|
@ -191,8 +189,10 @@ void EditParticipantBox::resizeToContent() {
|
|||
setDimensions(_inner->width(), std::min(_inner->height(), st::boxMaxListHeight));
|
||||
}
|
||||
|
||||
EditAdminBox::EditAdminBox(QWidget*, not_null<ChannelData*> channel, not_null<UserData*> user, const MTPChannelAdminRights &rights) : EditParticipantBox(nullptr, channel, user, (rights.c_channelAdminRights().vflags.v != 0))
|
||||
, _oldRights(rights) {
|
||||
EditAdminBox::EditAdminBox(QWidget *, not_null<ChannelData *> channel, not_null<UserData *> user,
|
||||
const MTPChannelAdminRights &rights)
|
||||
: EditParticipantBox(nullptr, channel, user, (rights.c_channelAdminRights().vflags.v != 0))
|
||||
, _oldRights(rights) {
|
||||
auto dependency = [this](Flag dependent, Flag dependency) {
|
||||
_dependencies.push_back(std::make_pair(dependent, dependency));
|
||||
};
|
||||
|
@ -200,10 +200,12 @@ EditAdminBox::EditAdminBox(QWidget*, not_null<ChannelData*> channel, not_null<Us
|
|||
dependency(Flag::f_invite_users, Flag::f_invite_link);
|
||||
}
|
||||
|
||||
MTPChannelAdminRights EditAdminBox::DefaultRights(not_null<ChannelData*> channel) {
|
||||
auto defaultRights = channel->isMegagroup()
|
||||
? (Flag::f_change_info | Flag::f_delete_messages | Flag::f_ban_users | Flag::f_invite_users | Flag::f_invite_link | Flag::f_pin_messages)
|
||||
: (Flag::f_change_info | Flag::f_post_messages | Flag::f_edit_messages | Flag::f_delete_messages | Flag::f_invite_users | Flag::f_invite_link);
|
||||
MTPChannelAdminRights EditAdminBox::DefaultRights(not_null<ChannelData *> channel) {
|
||||
auto defaultRights = channel->isMegagroup() ?
|
||||
(Flag::f_change_info | Flag::f_delete_messages | Flag::f_ban_users | Flag::f_invite_users |
|
||||
Flag::f_invite_link | Flag::f_pin_messages) :
|
||||
(Flag::f_change_info | Flag::f_post_messages | Flag::f_edit_messages |
|
||||
Flag::f_delete_messages | Flag::f_invite_users | Flag::f_invite_link);
|
||||
return MTP_channelAdminRights(MTP_flags(defaultRights));
|
||||
}
|
||||
|
||||
|
@ -214,12 +216,15 @@ void EditAdminBox::prepare() {
|
|||
setTitle(langFactory(hadRights ? lng_rights_edit_admin : lng_channel_add_admin));
|
||||
|
||||
addControl(object_ptr<BoxContentDivider>(this), QMargins());
|
||||
addControl(object_ptr<Ui::FlatLabel>(this, lang(lng_rights_edit_admin_header), Ui::FlatLabel::InitType::Simple, st::rightsHeaderLabel), st::rightsHeaderMargin);
|
||||
addControl(object_ptr<Ui::FlatLabel>(this, lang(lng_rights_edit_admin_header), Ui::FlatLabel::InitType::Simple,
|
||||
st::rightsHeaderLabel),
|
||||
st::rightsHeaderMargin);
|
||||
|
||||
auto prepareRights = (hadRights ? _oldRights : DefaultRights(channel()));
|
||||
auto addCheckbox = [this, &prepareRights](Flags flags, const QString &text) {
|
||||
auto checked = (prepareRights.c_channelAdminRights().vflags.v & flags) != 0;
|
||||
auto control = addControl(object_ptr<Ui::Checkbox>(this, text, checked, st::rightsCheckbox, st::rightsToggle), st::rightsToggleMargin);
|
||||
auto control = addControl(object_ptr<Ui::Checkbox>(this, text, checked, st::rightsCheckbox, st::rightsToggle),
|
||||
st::rightsToggleMargin);
|
||||
subscribe(control->checkedChanged, [this, control](bool checked) {
|
||||
InvokeQueued(this, [this, control] { applyDependencies(control); });
|
||||
});
|
||||
|
@ -237,7 +242,8 @@ void EditAdminBox::prepare() {
|
|||
addCheckbox(Flag::f_change_info, lang(lng_rights_group_info));
|
||||
addCheckbox(Flag::f_delete_messages, lang(lng_rights_group_delete));
|
||||
addCheckbox(Flag::f_ban_users, lang(lng_rights_group_ban));
|
||||
addCheckbox(Flag::f_invite_users | Flag::f_invite_link, lang(channel()->anyoneCanAddMembers() ? lng_rights_group_invite_link : lng_rights_group_invite));
|
||||
addCheckbox(Flag::f_invite_users | Flag::f_invite_link,
|
||||
lang(channel()->anyoneCanAddMembers() ? lng_rights_group_invite_link : lng_rights_group_invite));
|
||||
addCheckbox(Flag::f_pin_messages, lang(lng_rights_group_pin));
|
||||
addCheckbox(Flag::f_add_admins, lang(lng_rights_add_admins));
|
||||
} else {
|
||||
|
@ -253,9 +259,7 @@ void EditAdminBox::prepare() {
|
|||
if (addAdmins != _checkboxes.end()) {
|
||||
_aboutAddAdmins = addControl(object_ptr<Ui::FlatLabel>(this, st::boxLabel), st::rightsAboutMargin);
|
||||
Assert(addAdmins != _checkboxes.end());
|
||||
subscribe(addAdmins->second->checkedChanged, [this](bool checked) {
|
||||
refreshAboutAddAdminsText();
|
||||
});
|
||||
subscribe(addAdmins->second->checkedChanged, [this](bool checked) { refreshAboutAddAdminsText(); });
|
||||
refreshAboutAddAdminsText();
|
||||
}
|
||||
|
||||
|
@ -310,8 +314,10 @@ void EditAdminBox::refreshAboutAddAdminsText() {
|
|||
resizeToContent();
|
||||
}
|
||||
|
||||
EditRestrictedBox::EditRestrictedBox(QWidget*, not_null<ChannelData*> channel, not_null<UserData*> user, bool hasAdminRights, const MTPChannelBannedRights &rights) : EditParticipantBox(nullptr, channel, user, hasAdminRights)
|
||||
, _oldRights(rights) {
|
||||
EditRestrictedBox::EditRestrictedBox(QWidget *, not_null<ChannelData *> channel, not_null<UserData *> user,
|
||||
bool hasAdminRights, const MTPChannelBannedRights &rights)
|
||||
: EditParticipantBox(nullptr, channel, user, hasAdminRights)
|
||||
, _oldRights(rights) {
|
||||
auto dependency = [this](Flag dependent, Flag dependency) {
|
||||
_dependencies.push_back(std::make_pair(dependent, dependency));
|
||||
};
|
||||
|
@ -333,14 +339,17 @@ void EditRestrictedBox::prepare() {
|
|||
setTitle(langFactory(lng_rights_user_restrictions));
|
||||
|
||||
addControl(object_ptr<BoxContentDivider>(this), QMargins());
|
||||
addControl(object_ptr<Ui::FlatLabel>(this, lang(lng_rights_user_restrictions_header), Ui::FlatLabel::InitType::Simple, st::rightsHeaderLabel), st::rightsHeaderMargin);
|
||||
addControl(object_ptr<Ui::FlatLabel>(this, lang(lng_rights_user_restrictions_header),
|
||||
Ui::FlatLabel::InitType::Simple, st::rightsHeaderLabel),
|
||||
st::rightsHeaderMargin);
|
||||
|
||||
auto prepareRights = (_oldRights.c_channelBannedRights().vflags.v ? _oldRights : DefaultRights(channel()));
|
||||
_until = prepareRights.c_channelBannedRights().vuntil_date.v;
|
||||
|
||||
auto addCheckbox = [this, &prepareRights](Flags flags, const QString &text) {
|
||||
auto checked = (prepareRights.c_channelBannedRights().vflags.v & flags) == 0;
|
||||
auto control = addControl(object_ptr<Ui::Checkbox>(this, text, checked, st::rightsCheckbox, st::rightsToggle), st::rightsToggleMargin);
|
||||
auto control = addControl(object_ptr<Ui::Checkbox>(this, text, checked, st::rightsCheckbox, st::rightsToggle),
|
||||
st::rightsToggleMargin);
|
||||
subscribe(control->checkedChanged, [this, control](bool checked) {
|
||||
InvokeQueued(this, [this, control] { applyDependencies(control); });
|
||||
});
|
||||
|
@ -352,14 +361,17 @@ void EditRestrictedBox::prepare() {
|
|||
addCheckbox(Flag::f_view_messages, lang(lng_rights_chat_read));
|
||||
addCheckbox(Flag::f_send_messages, lang(lng_rights_chat_send_text));
|
||||
addCheckbox(Flag::f_send_media, lang(lng_rights_chat_send_media));
|
||||
addCheckbox(Flag::f_send_stickers | Flag::f_send_gifs | Flag::f_send_games | Flag::f_send_inline, lang(lng_rights_chat_send_stickers));
|
||||
addCheckbox(Flag::f_send_stickers | Flag::f_send_gifs | Flag::f_send_games | Flag::f_send_inline,
|
||||
lang(lng_rights_chat_send_stickers));
|
||||
addCheckbox(Flag::f_embed_links, lang(lng_rights_chat_send_links));
|
||||
|
||||
addControl(object_ptr<BoxContentDivider>(this), st::rightsUntilMargin);
|
||||
addControl(object_ptr<Ui::FlatLabel>(this, lang(lng_rights_chat_banned_until_header), Ui::FlatLabel::InitType::Simple, st::rightsHeaderLabel), st::rightsHeaderMargin);
|
||||
addControl(object_ptr<Ui::FlatLabel>(this, lang(lng_rights_chat_banned_until_header),
|
||||
Ui::FlatLabel::InitType::Simple, st::rightsHeaderLabel),
|
||||
st::rightsHeaderMargin);
|
||||
setRestrictUntil(_until);
|
||||
|
||||
//addControl(object_ptr<Ui::LinkButton>(this, lang(lng_rights_chat_banned_block), st::boxLinkButton));
|
||||
// addControl(object_ptr<Ui::LinkButton>(this, lang(lng_rights_chat_banned_block), st::boxLinkButton));
|
||||
|
||||
if (canSave()) {
|
||||
addButton(langFactory(lng_settings_save), [this] {
|
||||
|
@ -393,8 +405,9 @@ void EditRestrictedBox::applyDependencies(QPointer<Ui::Checkbox> changed) {
|
|||
ApplyDependencies(_checkboxes, _dependencies, changed);
|
||||
}
|
||||
|
||||
MTPChannelBannedRights EditRestrictedBox::DefaultRights(not_null<ChannelData*> channel) {
|
||||
auto defaultRights = Flag::f_send_messages | Flag::f_send_media | Flag::f_embed_links | Flag::f_send_stickers | Flag::f_send_gifs | Flag::f_send_games | Flag::f_send_inline;
|
||||
MTPChannelBannedRights EditRestrictedBox::DefaultRights(not_null<ChannelData *> channel) {
|
||||
auto defaultRights = Flag::f_send_messages | Flag::f_send_media | Flag::f_embed_links | Flag::f_send_stickers |
|
||||
Flag::f_send_gifs | Flag::f_send_games | Flag::f_send_inline;
|
||||
return MTP_channelBannedRights(MTP_flags(defaultRights), MTP_int(0));
|
||||
}
|
||||
|
||||
|
@ -402,7 +415,10 @@ void EditRestrictedBox::showRestrictUntil() {
|
|||
auto tomorrow = QDate::currentDate().addDays(1);
|
||||
auto highlighted = isUntilForever() ? tomorrow : date(getRealUntilValue()).date();
|
||||
auto month = highlighted;
|
||||
_restrictUntilBox = Ui::show(Box<CalendarBox>(month, highlighted, [this](const QDate &date) { setRestrictUntil(static_cast<int>(QDateTime(date).toTime_t())); }), KeepOtherLayers);
|
||||
_restrictUntilBox = Ui::show(
|
||||
Box<CalendarBox>(month, highlighted,
|
||||
[this](const QDate &date) { setRestrictUntil(static_cast<int>(QDateTime(date).toTime_t())); }),
|
||||
KeepOtherLayers);
|
||||
_restrictUntilBox->setMaxDate(QDate::currentDate().addDays(kMaxRestrictDelayDays));
|
||||
_restrictUntilBox->setMinDate(tomorrow);
|
||||
_restrictUntilBox->addLeftButton(langFactory(lng_rights_chat_banned_forever), [this] { setRestrictUntil(0); });
|
||||
|
@ -442,7 +458,9 @@ void EditRestrictedBox::createUntilVariants() {
|
|||
if (!canSave() && _untilGroup->value() != value) {
|
||||
return;
|
||||
}
|
||||
_untilVariants.push_back(addControl(object_ptr<Ui::Radiobutton>(this, _untilGroup, value, text, st::defaultBoxCheckbox), st::rightsToggleMargin));
|
||||
_untilVariants.push_back(
|
||||
addControl(object_ptr<Ui::Radiobutton>(this, _untilGroup, value, text, st::defaultBoxCheckbox),
|
||||
st::rightsToggleMargin));
|
||||
if (!canSave()) {
|
||||
_untilVariants.back()->setDisabled(true);
|
||||
}
|
||||
|
|
|
@ -34,22 +34,21 @@ class CalendarBox;
|
|||
|
||||
class EditParticipantBox : public BoxContent {
|
||||
public:
|
||||
EditParticipantBox(QWidget*, not_null<ChannelData*> channel, not_null<UserData*> user, bool hasAdminRights);
|
||||
EditParticipantBox(QWidget *, not_null<ChannelData *> channel, not_null<UserData *> user, bool hasAdminRights);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
||||
void resizeToContent();
|
||||
|
||||
not_null<UserData*> user() const {
|
||||
not_null<UserData *> user() const {
|
||||
return _user;
|
||||
}
|
||||
not_null<ChannelData*> channel() const {
|
||||
not_null<ChannelData *> channel() const {
|
||||
return _channel;
|
||||
}
|
||||
|
||||
template <typename Widget>
|
||||
QPointer<Widget> addControl(object_ptr<Widget> widget, QMargins margin);
|
||||
template <typename Widget> QPointer<Widget> addControl(object_ptr<Widget> widget, QMargins margin);
|
||||
|
||||
void removeControl(QPointer<TWidget> widget);
|
||||
|
||||
|
@ -58,18 +57,18 @@ protected:
|
|||
}
|
||||
|
||||
private:
|
||||
not_null<ChannelData*> _channel;
|
||||
not_null<UserData*> _user;
|
||||
not_null<ChannelData *> _channel;
|
||||
not_null<UserData *> _user;
|
||||
bool _hasAdminRights = false;
|
||||
|
||||
class Inner;
|
||||
QPointer<Inner> _inner;
|
||||
|
||||
};
|
||||
|
||||
class EditAdminBox : public EditParticipantBox {
|
||||
public:
|
||||
EditAdminBox(QWidget*, not_null<ChannelData*> channel, not_null<UserData*> user, const MTPChannelAdminRights &rights);
|
||||
EditAdminBox(QWidget *, not_null<ChannelData *> channel, not_null<UserData *> user,
|
||||
const MTPChannelAdminRights &rights);
|
||||
|
||||
void setSaveCallback(base::lambda<void(MTPChannelAdminRights, MTPChannelAdminRights)> callback) {
|
||||
_saveCallback = std::move(callback);
|
||||
|
@ -82,7 +81,7 @@ private:
|
|||
using Flag = MTPDchannelAdminRights::Flag;
|
||||
using Flags = MTPDchannelAdminRights::Flags;
|
||||
|
||||
static MTPChannelAdminRights DefaultRights(not_null<ChannelData*> channel);
|
||||
static MTPChannelAdminRights DefaultRights(not_null<ChannelData *> channel);
|
||||
|
||||
bool canSave() const {
|
||||
return !!_saveCallback;
|
||||
|
@ -96,7 +95,6 @@ private:
|
|||
|
||||
std::map<Flags, QPointer<Ui::Checkbox>> _checkboxes;
|
||||
QPointer<Ui::FlatLabel> _aboutAddAdmins;
|
||||
|
||||
};
|
||||
|
||||
// Restricted box works with flags in the opposite way.
|
||||
|
@ -104,7 +102,8 @@ private:
|
|||
|
||||
class EditRestrictedBox : public EditParticipantBox {
|
||||
public:
|
||||
EditRestrictedBox(QWidget*, not_null<ChannelData*> channel, not_null<UserData*> user, bool hasAdminRights, const MTPChannelBannedRights &rights);
|
||||
EditRestrictedBox(QWidget *, not_null<ChannelData *> channel, not_null<UserData *> user, bool hasAdminRights,
|
||||
const MTPChannelBannedRights &rights);
|
||||
|
||||
void setSaveCallback(base::lambda<void(MTPChannelBannedRights, MTPChannelBannedRights)> callback) {
|
||||
_saveCallback = std::move(callback);
|
||||
|
@ -117,7 +116,7 @@ private:
|
|||
using Flag = MTPDchannelBannedRights::Flag;
|
||||
using Flags = MTPDchannelBannedRights::Flags;
|
||||
|
||||
static MTPChannelBannedRights DefaultRights(not_null<ChannelData*> channel);
|
||||
static MTPChannelBannedRights DefaultRights(not_null<ChannelData *> channel);
|
||||
|
||||
bool canSave() const {
|
||||
return !!_saveCallback;
|
||||
|
@ -147,5 +146,4 @@ private:
|
|||
static constexpr auto kUntilOneDay = -1;
|
||||
static constexpr auto kUntilOneWeek = -2;
|
||||
static constexpr auto kUntilCustom = -3;
|
||||
|
||||
};
|
||||
|
|
|
@ -18,52 +18,52 @@ to link the code of portions of this program with the OpenSSL library.
|
|||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "base/lambda_guard.h"
|
||||
#include "boxes/edit_privacy_box.h"
|
||||
#include "base/lambda_guard.h"
|
||||
|
||||
#include "apiwrap.h"
|
||||
#include "app.h" // For App::user, App::feedUsers
|
||||
#include "auth_session.h"
|
||||
#include "boxes/peer_list_controllers.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "ui/effects/widget_slide_wrap.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/effects/widget_slide_wrap.h"
|
||||
#include "boxes/peer_list_controllers.h"
|
||||
#include "apiwrap.h"
|
||||
#include "auth_session.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "app.h" // For App::user, App::feedUsers
|
||||
|
||||
namespace {
|
||||
|
||||
class PrivacyExceptionsBoxController : public ChatsListBoxController {
|
||||
public:
|
||||
PrivacyExceptionsBoxController(base::lambda<QString()> titleFactory, const std::vector<not_null<UserData*>> &selected);
|
||||
void rowClicked(not_null<PeerListRow*> row) override;
|
||||
PrivacyExceptionsBoxController(base::lambda<QString()> titleFactory,
|
||||
const std::vector<not_null<UserData *>> &selected);
|
||||
void rowClicked(not_null<PeerListRow *> row) override;
|
||||
|
||||
std::vector<not_null<UserData*>> getResult() const;
|
||||
std::vector<not_null<UserData *>> getResult() const;
|
||||
|
||||
protected:
|
||||
void prepareViewHook() override;
|
||||
std::unique_ptr<Row> createRow(not_null<History*> history) override;
|
||||
std::unique_ptr<Row> createRow(not_null<History *> history) override;
|
||||
|
||||
private:
|
||||
base::lambda<QString()> _titleFactory;
|
||||
std::vector<not_null<UserData*>> _selected;
|
||||
|
||||
std::vector<not_null<UserData *>> _selected;
|
||||
};
|
||||
|
||||
PrivacyExceptionsBoxController::PrivacyExceptionsBoxController(base::lambda<QString()> titleFactory, const std::vector<not_null<UserData*>> &selected)
|
||||
: _titleFactory(std::move(titleFactory))
|
||||
, _selected(selected) {
|
||||
}
|
||||
PrivacyExceptionsBoxController::PrivacyExceptionsBoxController(base::lambda<QString()> titleFactory,
|
||||
const std::vector<not_null<UserData *>> &selected)
|
||||
: _titleFactory(std::move(titleFactory))
|
||||
, _selected(selected) {}
|
||||
|
||||
void PrivacyExceptionsBoxController::prepareViewHook() {
|
||||
delegate()->peerListSetTitle(_titleFactory);
|
||||
delegate()->peerListAddSelectedRows(_selected);
|
||||
}
|
||||
|
||||
std::vector<not_null<UserData*>> PrivacyExceptionsBoxController::getResult() const {
|
||||
std::vector<not_null<UserData *>> PrivacyExceptionsBoxController::getResult() const {
|
||||
auto peers = delegate()->peerListCollectSelectedRows();
|
||||
auto users = std::vector<not_null<UserData*>>();
|
||||
auto users = std::vector<not_null<UserData *>>();
|
||||
if (!peers.empty()) {
|
||||
users.reserve(peers.size());
|
||||
for_const (auto peer, peers) {
|
||||
|
@ -75,11 +75,12 @@ std::vector<not_null<UserData*>> PrivacyExceptionsBoxController::getResult() con
|
|||
return users;
|
||||
}
|
||||
|
||||
void PrivacyExceptionsBoxController::rowClicked(not_null<PeerListRow*> row) {
|
||||
void PrivacyExceptionsBoxController::rowClicked(not_null<PeerListRow *> row) {
|
||||
delegate()->peerListSetRowChecked(row, !row->checked());
|
||||
}
|
||||
|
||||
std::unique_ptr<PrivacyExceptionsBoxController::Row> PrivacyExceptionsBoxController::createRow(not_null<History*> history) {
|
||||
std::unique_ptr<PrivacyExceptionsBoxController::Row>
|
||||
PrivacyExceptionsBoxController::createRow(not_null<History *> history) {
|
||||
if (history->peer->isSelf()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -91,10 +92,10 @@ std::unique_ptr<PrivacyExceptionsBoxController::Row> PrivacyExceptionsBoxControl
|
|||
|
||||
} // namespace
|
||||
|
||||
EditPrivacyBox::EditPrivacyBox(QWidget*, std::unique_ptr<Controller> controller) : BoxContent()
|
||||
, _controller(std::move(controller))
|
||||
, _loading(this, lang(lng_contacts_loading), Ui::FlatLabel::InitType::Simple, st::membersAbout) {
|
||||
}
|
||||
EditPrivacyBox::EditPrivacyBox(QWidget *, std::unique_ptr<Controller> controller)
|
||||
: BoxContent()
|
||||
, _controller(std::move(controller))
|
||||
, _loading(this, lang(lng_contacts_loading), Ui::FlatLabel::InitType::Simple, st::membersAbout) {}
|
||||
|
||||
void EditPrivacyBox::prepare() {
|
||||
_controller->setView(this);
|
||||
|
@ -177,34 +178,34 @@ int EditPrivacyBox::countDefaultHeight(int newWidth) {
|
|||
}
|
||||
|
||||
void EditPrivacyBox::editExceptionUsers(Exception exception) {
|
||||
auto controller = std::make_unique<PrivacyExceptionsBoxController>(base::lambda_guarded(this, [this, exception] {
|
||||
return _controller->exceptionBoxTitle(exception);
|
||||
}), exceptionUsers(exception));
|
||||
auto initBox = [this, exception, controller = controller.get()](not_null<PeerListBox*> box) {
|
||||
auto controller = std::make_unique<PrivacyExceptionsBoxController>(
|
||||
base::lambda_guarded(this, [this, exception] { return _controller->exceptionBoxTitle(exception); }),
|
||||
exceptionUsers(exception));
|
||||
auto initBox = [this, exception, controller = controller.get()](not_null<PeerListBox *> box) {
|
||||
box->addButton(langFactory(lng_settings_save), base::lambda_guarded(this, [this, box, exception, controller] {
|
||||
exceptionUsers(exception) = controller->getResult();
|
||||
exceptionLink(exception)->entity()->setText(exceptionLinkText(exception));
|
||||
auto removeFrom = ([exception] {
|
||||
switch (exception) {
|
||||
case Exception::Always: return Exception::Never;
|
||||
case Exception::Never: return Exception::Always;
|
||||
}
|
||||
Unexpected("Invalid exception value.");
|
||||
})();
|
||||
auto &removeFromUsers = exceptionUsers(removeFrom);
|
||||
auto removedSome = false;
|
||||
for (auto user : exceptionUsers(exception)) {
|
||||
auto removedStart = std::remove(removeFromUsers.begin(), removeFromUsers.end(), user);
|
||||
if (removedStart != removeFromUsers.end()) {
|
||||
removeFromUsers.erase(removedStart, removeFromUsers.end());
|
||||
removedSome = true;
|
||||
}
|
||||
}
|
||||
if (removedSome) {
|
||||
exceptionLink(removeFrom)->entity()->setText(exceptionLinkText(removeFrom));
|
||||
}
|
||||
box->closeBox();
|
||||
}));
|
||||
exceptionUsers(exception) = controller->getResult();
|
||||
exceptionLink(exception)->entity()->setText(exceptionLinkText(exception));
|
||||
auto removeFrom = ([exception] {
|
||||
switch (exception) {
|
||||
case Exception::Always: return Exception::Never;
|
||||
case Exception::Never: return Exception::Always;
|
||||
}
|
||||
Unexpected("Invalid exception value.");
|
||||
})();
|
||||
auto &removeFromUsers = exceptionUsers(removeFrom);
|
||||
auto removedSome = false;
|
||||
for (auto user : exceptionUsers(exception)) {
|
||||
auto removedStart = std::remove(removeFromUsers.begin(), removeFromUsers.end(), user);
|
||||
if (removedStart != removeFromUsers.end()) {
|
||||
removeFromUsers.erase(removedStart, removeFromUsers.end());
|
||||
removedSome = true;
|
||||
}
|
||||
}
|
||||
if (removedSome) {
|
||||
exceptionLink(removeFrom)->entity()->setText(exceptionLinkText(removeFrom));
|
||||
}
|
||||
box->closeBox();
|
||||
}));
|
||||
box->addButton(langFactory(lng_cancel), [box] { box->closeBox(); });
|
||||
};
|
||||
Ui::show(Box<PeerListBox>(std::move(controller), std::move(initBox)), KeepOtherLayers);
|
||||
|
@ -246,7 +247,7 @@ style::margins EditPrivacyBox::exceptionLinkMargins() const {
|
|||
return st::editPrivacyLinkMargin;
|
||||
}
|
||||
|
||||
std::vector<not_null<UserData*>> &EditPrivacyBox::exceptionUsers(Exception exception) {
|
||||
std::vector<not_null<UserData *>> &EditPrivacyBox::exceptionUsers(Exception exception) {
|
||||
switch (exception) {
|
||||
case Exception::Always: return _alwaysUsers;
|
||||
case Exception::Never: return _neverUsers;
|
||||
|
@ -286,9 +287,8 @@ void EditPrivacyBox::createWidgets() {
|
|||
widget.create(this, text, Ui::FlatLabel::InitType::Simple, st);
|
||||
};
|
||||
auto createExceptionLink = [this](Exception exception) {
|
||||
exceptionLink(exception).create(this, object_ptr<Ui::LinkButton>(this, exceptionLinkText(exception)), exceptionLinkMargins(), [this] {
|
||||
resizeGetHeight(width());
|
||||
});
|
||||
exceptionLink(exception).create(this, object_ptr<Ui::LinkButton>(this, exceptionLinkText(exception)),
|
||||
exceptionLinkMargins(), [this] { resizeGetHeight(width()); });
|
||||
exceptionLink(exception)->entity()->setClickedCallback([this, exception] { editExceptionUsers(exception); });
|
||||
};
|
||||
|
||||
|
@ -306,9 +306,9 @@ void EditPrivacyBox::createWidgets() {
|
|||
addButton(langFactory(lng_settings_save), [this] {
|
||||
auto someAreDisallowed = (_option != Option::Everyone) || !_neverUsers.empty();
|
||||
_controller->confirmSave(someAreDisallowed, base::lambda_guarded(this, [this] {
|
||||
Auth().api().savePrivacy(_controller->key(), collectResult());
|
||||
closeBox();
|
||||
}));
|
||||
Auth().api().savePrivacy(_controller->key(), collectResult());
|
||||
closeBox();
|
||||
}));
|
||||
});
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
|
@ -326,53 +326,54 @@ void EditPrivacyBox::createWidgets() {
|
|||
}
|
||||
|
||||
void EditPrivacyBox::loadData() {
|
||||
request(MTPaccount_GetPrivacy(_controller->key())).done([this](const MTPaccount_PrivacyRules &result) {
|
||||
Expects(result.type() == mtpc_account_privacyRules);
|
||||
auto &rules = result.c_account_privacyRules();
|
||||
App::feedUsers(rules.vusers);
|
||||
request(MTPaccount_GetPrivacy(_controller->key()))
|
||||
.done([this](const MTPaccount_PrivacyRules &result) {
|
||||
Expects(result.type() == mtpc_account_privacyRules);
|
||||
auto &rules = result.c_account_privacyRules();
|
||||
App::feedUsers(rules.vusers);
|
||||
|
||||
// This is simplified version of privacy rules interpretation.
|
||||
// But it should be fine for all the apps that use the same subset of features.
|
||||
auto optionSet = false;
|
||||
auto setOption = [this, &optionSet](Option option) {
|
||||
if (optionSet) return;
|
||||
optionSet = true;
|
||||
_option = option;
|
||||
};
|
||||
auto feedRule = [this, &setOption](const MTPPrivacyRule &rule) {
|
||||
switch (rule.type()) {
|
||||
case mtpc_privacyValueAllowAll: setOption(Option::Everyone); break;
|
||||
case mtpc_privacyValueAllowContacts: setOption(Option::Contacts); break;
|
||||
case mtpc_privacyValueAllowUsers: {
|
||||
auto &users = rule.c_privacyValueAllowUsers().vusers.v;
|
||||
_alwaysUsers.reserve(_alwaysUsers.size() + users.size());
|
||||
for (auto &userId : users) {
|
||||
auto user = App::user(UserId(userId.v));
|
||||
if (!base::contains(_neverUsers, user) && !base::contains(_alwaysUsers, user)) {
|
||||
_alwaysUsers.push_back(user);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case mtpc_privacyValueDisallowContacts: // not supported, fall through
|
||||
case mtpc_privacyValueDisallowAll: setOption(Option::Nobody); break;
|
||||
case mtpc_privacyValueDisallowUsers: {
|
||||
auto &users = rule.c_privacyValueDisallowUsers().vusers.v;
|
||||
_neverUsers.reserve(_neverUsers.size() + users.size());
|
||||
for (auto &userId : users) {
|
||||
auto user = App::user(UserId(userId.v));
|
||||
if (!base::contains(_alwaysUsers, user) && !base::contains(_neverUsers, user)) {
|
||||
_neverUsers.push_back(user);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
}
|
||||
};
|
||||
for (auto &rule : rules.vrules.v) {
|
||||
feedRule(rule);
|
||||
}
|
||||
feedRule(MTP_privacyValueDisallowAll()); // disallow by default.
|
||||
// This is simplified version of privacy rules interpretation.
|
||||
// But it should be fine for all the apps that use the same subset of features.
|
||||
auto optionSet = false;
|
||||
auto setOption = [this, &optionSet](Option option) {
|
||||
if (optionSet) return;
|
||||
optionSet = true;
|
||||
_option = option;
|
||||
};
|
||||
auto feedRule = [this, &setOption](const MTPPrivacyRule &rule) {
|
||||
switch (rule.type()) {
|
||||
case mtpc_privacyValueAllowAll: setOption(Option::Everyone); break;
|
||||
case mtpc_privacyValueAllowContacts: setOption(Option::Contacts); break;
|
||||
case mtpc_privacyValueAllowUsers: {
|
||||
auto &users = rule.c_privacyValueAllowUsers().vusers.v;
|
||||
_alwaysUsers.reserve(_alwaysUsers.size() + users.size());
|
||||
for (auto &userId : users) {
|
||||
auto user = App::user(UserId(userId.v));
|
||||
if (!base::contains(_neverUsers, user) && !base::contains(_alwaysUsers, user)) {
|
||||
_alwaysUsers.push_back(user);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case mtpc_privacyValueDisallowContacts: // not supported, fall through
|
||||
case mtpc_privacyValueDisallowAll: setOption(Option::Nobody); break;
|
||||
case mtpc_privacyValueDisallowUsers: {
|
||||
auto &users = rule.c_privacyValueDisallowUsers().vusers.v;
|
||||
_neverUsers.reserve(_neverUsers.size() + users.size());
|
||||
for (auto &userId : users) {
|
||||
auto user = App::user(UserId(userId.v));
|
||||
if (!base::contains(_alwaysUsers, user) && !base::contains(_neverUsers, user)) {
|
||||
_neverUsers.push_back(user);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
}
|
||||
};
|
||||
for (auto &rule : rules.vrules.v) {
|
||||
feedRule(rule);
|
||||
}
|
||||
feedRule(MTP_privacyValueDisallowAll()); // disallow by default.
|
||||
|
||||
createWidgets();
|
||||
}).send();
|
||||
createWidgets();
|
||||
})
|
||||
.send();
|
||||
}
|
||||
|
||||
|
|
|
@ -26,12 +26,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
namespace Ui {
|
||||
class FlatLabel;
|
||||
class LinkButton;
|
||||
template <typename Enum>
|
||||
class RadioenumGroup;
|
||||
template <typename Enum>
|
||||
class Radioenum;
|
||||
template <typename Widget>
|
||||
class WidgetSlideWrap;
|
||||
template <typename Enum> class RadioenumGroup;
|
||||
template <typename Enum> class Radioenum;
|
||||
template <typename Widget> class WidgetSlideWrap;
|
||||
} // namespace Ui
|
||||
|
||||
class EditPrivacyBox : public BoxContent, private MTP::Sender {
|
||||
|
@ -81,10 +78,9 @@ public:
|
|||
EditPrivacyBox *_view = nullptr;
|
||||
|
||||
friend class EditPrivacyBox;
|
||||
|
||||
};
|
||||
|
||||
EditPrivacyBox(QWidget*, std::unique_ptr<Controller> controller);
|
||||
EditPrivacyBox(QWidget *, std::unique_ptr<Controller> controller);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
@ -102,7 +98,7 @@ private:
|
|||
|
||||
void editExceptionUsers(Exception exception);
|
||||
QString exceptionLinkText(Exception exception);
|
||||
std::vector<not_null<UserData*>> &exceptionUsers(Exception exception);
|
||||
std::vector<not_null<UserData *>> &exceptionUsers(Exception exception);
|
||||
object_ptr<Ui::WidgetSlideWrap<Ui::LinkButton>> &exceptionLink(Exception exception);
|
||||
|
||||
std::unique_ptr<Controller> _controller;
|
||||
|
@ -110,17 +106,16 @@ private:
|
|||
|
||||
std::shared_ptr<Ui::RadioenumGroup<Option>> _optionGroup;
|
||||
object_ptr<Ui::FlatLabel> _loading;
|
||||
object_ptr<Ui::FlatLabel> _description = { nullptr };
|
||||
object_ptr<Ui::Radioenum<Option>> _everyone = { nullptr };
|
||||
object_ptr<Ui::Radioenum<Option>> _contacts = { nullptr };
|
||||
object_ptr<Ui::Radioenum<Option>> _nobody = { nullptr };
|
||||
object_ptr<Ui::FlatLabel> _warning = { nullptr };
|
||||
object_ptr<Ui::FlatLabel> _exceptionsTitle = { nullptr };
|
||||
object_ptr<Ui::WidgetSlideWrap<Ui::LinkButton>> _alwaysLink = { nullptr };
|
||||
object_ptr<Ui::WidgetSlideWrap<Ui::LinkButton>> _neverLink = { nullptr };
|
||||
object_ptr<Ui::FlatLabel> _exceptionsDescription = { nullptr };
|
||||
|
||||
std::vector<not_null<UserData*>> _alwaysUsers;
|
||||
std::vector<not_null<UserData*>> _neverUsers;
|
||||
object_ptr<Ui::FlatLabel> _description = {nullptr};
|
||||
object_ptr<Ui::Radioenum<Option>> _everyone = {nullptr};
|
||||
object_ptr<Ui::Radioenum<Option>> _contacts = {nullptr};
|
||||
object_ptr<Ui::Radioenum<Option>> _nobody = {nullptr};
|
||||
object_ptr<Ui::FlatLabel> _warning = {nullptr};
|
||||
object_ptr<Ui::FlatLabel> _exceptionsTitle = {nullptr};
|
||||
object_ptr<Ui::WidgetSlideWrap<Ui::LinkButton>> _alwaysLink = {nullptr};
|
||||
object_ptr<Ui::WidgetSlideWrap<Ui::LinkButton>> _neverLink = {nullptr};
|
||||
object_ptr<Ui::FlatLabel> _exceptionsDescription = {nullptr};
|
||||
|
||||
std::vector<not_null<UserData *>> _alwaysUsers;
|
||||
std::vector<not_null<UserData *>> _neverUsers;
|
||||
};
|
||||
|
|
|
@ -19,20 +19,20 @@ Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
|||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "boxes/language_box.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "lang/lang_cloud_manager.h"
|
||||
#include "lang/lang_instance.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
#include "lang/lang_instance.h"
|
||||
#include "lang/lang_cloud_manager.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
|
||||
class LanguageBox::Inner : public TWidget, private base::Subscriber {
|
||||
public:
|
||||
Inner(QWidget *parent, not_null<Languages*> languages);
|
||||
Inner(QWidget *parent, not_null<Languages *> languages);
|
||||
|
||||
void setSelected(int index);
|
||||
void refresh();
|
||||
|
@ -41,14 +41,14 @@ private:
|
|||
void activateCurrent();
|
||||
void languageChanged(int languageIndex);
|
||||
|
||||
not_null<Languages*> _languages;
|
||||
not_null<Languages *> _languages;
|
||||
std::shared_ptr<Ui::RadiobuttonGroup> _group;
|
||||
std::vector<object_ptr<Ui::Radiobutton>> _buttons;
|
||||
|
||||
};
|
||||
|
||||
LanguageBox::Inner::Inner(QWidget *parent, not_null<Languages*> languages) : TWidget(parent)
|
||||
, _languages(languages) {
|
||||
LanguageBox::Inner::Inner(QWidget *parent, not_null<Languages *> languages)
|
||||
: TWidget(parent)
|
||||
, _languages(languages) {
|
||||
_group = std::make_shared<Ui::RadiobuttonGroup>(0);
|
||||
_group->setChangedCallback([this](int value) { languageChanged(value); });
|
||||
subscribe(Lang::Current().updated(), [this] {
|
||||
|
@ -107,16 +107,12 @@ void LanguageBox::Inner::activateCurrent() {
|
|||
|
||||
void LanguageBox::prepare() {
|
||||
refreshLang();
|
||||
subscribe(Lang::Current().updated(), [this] {
|
||||
refreshLang();
|
||||
});
|
||||
subscribe(Lang::Current().updated(), [this] { refreshLang(); });
|
||||
|
||||
_inner = setInnerWidget(object_ptr<Inner>(this, &_languages), st::boxLayerScroll);
|
||||
|
||||
refresh();
|
||||
subscribe(Lang::CurrentCloudManager().languageListChanged(), [this] {
|
||||
refresh();
|
||||
});
|
||||
subscribe(Lang::CurrentCloudManager().languageListChanged(), [this] { refresh(); });
|
||||
}
|
||||
|
||||
void LanguageBox::refreshLang() {
|
||||
|
@ -141,9 +137,10 @@ void LanguageBox::refreshLanguages() {
|
|||
_languages.reserve(list.size() + 1);
|
||||
auto currentId = Lang::Current().id();
|
||||
auto currentIndex = -1;
|
||||
_languages.push_back({ qsl("en"), qsl("English"), qsl("English") });
|
||||
_languages.push_back({qsl("en"), qsl("English"), qsl("English")});
|
||||
for (auto &language : list) {
|
||||
auto isCurrent = (language.id == currentId) || (language.id == Lang::DefaultLanguageId() && currentId.isEmpty());
|
||||
auto isCurrent =
|
||||
(language.id == currentId) || (language.id == Lang::DefaultLanguageId() && currentId.isEmpty());
|
||||
if (language.id != qstr("en")) {
|
||||
if (isCurrent) {
|
||||
currentIndex = _languages.size();
|
||||
|
@ -154,11 +151,11 @@ void LanguageBox::refreshLanguages() {
|
|||
}
|
||||
}
|
||||
if (currentId == qstr("custom")) {
|
||||
_languages.insert(_languages.begin(), { currentId, qsl("Custom LangPack"), qsl("Custom LangPack") });
|
||||
_languages.insert(_languages.begin(), {currentId, qsl("Custom LangPack"), qsl("Custom LangPack")});
|
||||
currentIndex = 0;
|
||||
} else if (currentIndex < 0) {
|
||||
currentIndex = _languages.size();
|
||||
_languages.push_back({ currentId, lang(lng_language_name), lang(lng_language_name) });
|
||||
_languages.push_back({currentId, lang(lng_language_name), lang(lng_language_name)});
|
||||
}
|
||||
_inner->setSelected(currentIndex);
|
||||
}
|
||||
|
|
|
@ -20,8 +20,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "lang/lang_cloud_manager.h"
|
||||
#include "boxes/abstract_box.h"
|
||||
#include "lang/lang_cloud_manager.h"
|
||||
#include "mtproto/sender.h"
|
||||
|
||||
namespace Ui {
|
||||
|
@ -29,10 +29,9 @@ class RadiobuttonGroup;
|
|||
class Radiobutton;
|
||||
} // namespace Ui
|
||||
|
||||
class LanguageBox : public BoxContent, private MTP::Sender {
|
||||
class LanguageBox : public BoxContent, private MTP::Sender {
|
||||
public:
|
||||
LanguageBox(QWidget*) {
|
||||
}
|
||||
LanguageBox(QWidget*) {}
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
@ -48,5 +47,4 @@ private:
|
|||
|
||||
class Inner;
|
||||
QPointer<Inner> _inner;
|
||||
|
||||
};
|
||||
|
|
|
@ -20,19 +20,18 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#include "boxes/local_storage_box.h"
|
||||
|
||||
#include "styles/style_boxes.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwindow.h"
|
||||
#include "app.h" // For App::wnd
|
||||
#include "auth_session.h"
|
||||
#include "facades.h"
|
||||
#include "app.h" // For App::wnd
|
||||
#include "lang/lang_keys.h"
|
||||
#include "layout.h" // For formatSizeText
|
||||
#include "mainwindow.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
|
||||
LocalStorageBox::LocalStorageBox(QWidget *parent)
|
||||
: _clear(this, lang(lng_local_storage_clear), st::boxLinkButton) {
|
||||
}
|
||||
: _clear(this, lang(lng_local_storage_clear), st::boxLinkButton) {}
|
||||
|
||||
void LocalStorageBox::prepare() {
|
||||
setTitle(langFactory(lng_local_storage_title));
|
||||
|
@ -87,12 +86,15 @@ void LocalStorageBox::paintEvent(QPaintEvent *e) {
|
|||
checkLocalStoredCounts();
|
||||
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()));
|
||||
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);
|
||||
top += st::boxTextFont->height + st::localStorageBoxSkip;
|
||||
}
|
||||
if (_audiosCount > 0) {
|
||||
auto text = lng_settings_audios_cached(lt_count, _audiosCount, lt_size, formatSizeText(Local::storageAudiosSize()));
|
||||
auto text =
|
||||
lng_settings_audios_cached(lt_count, _audiosCount, lt_size, formatSizeText(Local::storageAudiosSize()));
|
||||
p.drawTextLeft(st::boxPadding.left(), top, width(), text);
|
||||
top += st::boxTextFont->height + st::localStorageBoxSkip;
|
||||
} else if (_imagesCount <= 0) {
|
||||
|
|
|
@ -30,7 +30,7 @@ class LocalStorageBox : public BoxContent {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
LocalStorageBox(QWidget*);
|
||||
LocalStorageBox(QWidget *);
|
||||
|
||||
private slots:
|
||||
void onTempDirCleared(int task);
|
||||
|
@ -58,5 +58,4 @@ private:
|
|||
|
||||
int _imagesCount = -1;
|
||||
int _audiosCount = -1;
|
||||
|
||||
};
|
||||
|
|
|
@ -29,15 +29,14 @@ void MuteSettingsBox::prepare() {
|
|||
|
||||
object_ptr<Ui::FlatLabel> title(this, st::muteChatTitle);
|
||||
title->setText(App::peerName(_peer, true));
|
||||
title->moveToLeft(st::boxPadding.left(),
|
||||
y + icon->height() / 2 - title->height() / 2);
|
||||
title->moveToLeft(st::boxPadding.left(), y + icon->height() / 2 - title->height() / 2);
|
||||
// the icon is always higher than this chat title
|
||||
y += icon->height() + st::boxMediumSkip;
|
||||
|
||||
const int FOREVER = 8760; // in fact, this is mute only for 1 year
|
||||
const int FOREVER = 8760; // in fact, this is mute only for 1 year
|
||||
auto group = std::make_shared<Ui::RadiobuttonGroup>(FOREVER);
|
||||
y += st::boxOptionListPadding.top();
|
||||
for (int value : { 1, 4, 18, 72, FOREVER }) { // periods in hours
|
||||
for (int value : {1, 4, 18, 72, FOREVER}) { // periods in hours
|
||||
QString text;
|
||||
if (value < 24) {
|
||||
text = lng_mute_duration_hours(lt_count, value);
|
||||
|
@ -53,8 +52,7 @@ void MuteSettingsBox::prepare() {
|
|||
y += st::boxOptionListPadding.bottom() - st::boxOptionListSkip + st::defaultCheckbox.margin.bottom();
|
||||
|
||||
addButton(langFactory(lng_box_ok), [this, group] {
|
||||
App::main()->updateNotifySetting(_peer, NotifySettingSetMuted,
|
||||
SilentNotifiesDontChange, group->value() * 3600);
|
||||
App::main()->updateNotifySetting(_peer, NotifySettingSetMuted, SilentNotifiesDontChange, group->value() * 3600);
|
||||
closeBox();
|
||||
});
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
|
|
@ -14,15 +14,14 @@
|
|||
class MuteSettingsBox : public BoxContent {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MuteSettingsBox(QWidget *parent, not_null<PeerData*> peer)
|
||||
: _peer(peer) {
|
||||
}
|
||||
public:
|
||||
MuteSettingsBox(QWidget *parent, not_null<PeerData *> peer)
|
||||
: _peer(peer) {}
|
||||
|
||||
protected:
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
||||
private:
|
||||
not_null<PeerData*> _peer;
|
||||
private:
|
||||
not_null<PeerData *> _peer;
|
||||
};
|
||||
// vi: ts=4 tw=80
|
||||
|
|
|
@ -20,19 +20,19 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#include "boxes/notifications_box.h"
|
||||
|
||||
#include "app.h" // For App::pixmapFromImageInPlace
|
||||
#include "auth_session.h"
|
||||
#include "config.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/discrete_sliders.h"
|
||||
#include "messenger.h"
|
||||
#include "platform/platform_specific.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_dialogs.h"
|
||||
#include "styles/style_window.h"
|
||||
#include "messenger.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "auth_session.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/discrete_sliders.h"
|
||||
#include "window/notifications_manager.h"
|
||||
#include "platform/platform_specific.h"
|
||||
#include "app.h" // For App::pixmapFromImageInPlace
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -44,12 +44,14 @@ using ChangeType = Window::Notifications::ChangeType;
|
|||
|
||||
class NotificationsBox::SampleWidget : public QWidget {
|
||||
public:
|
||||
SampleWidget(NotificationsBox *owner, const QPixmap &cache) : QWidget(nullptr)
|
||||
, _owner(owner)
|
||||
, _cache(cache) {
|
||||
SampleWidget(NotificationsBox *owner, const QPixmap &cache)
|
||||
: QWidget(nullptr)
|
||||
, _owner(owner)
|
||||
, _cache(cache) {
|
||||
resize(cache.width() / cache.devicePixelRatio(), cache.height() / cache.devicePixelRatio());
|
||||
|
||||
setWindowFlags(Qt::WindowFlags(Qt::FramelessWindowHint) | Qt::WindowStaysOnTopHint | Qt::BypassWindowManagerHint | Qt::NoDropShadowWindowHint | Qt::Tool);
|
||||
setWindowFlags(Qt::WindowFlags(Qt::FramelessWindowHint) | Qt::WindowStaysOnTopHint |
|
||||
Qt::BypassWindowManagerHint | Qt::NoDropShadowWindowHint | Qt::Tool);
|
||||
setAttribute(Qt::WA_MacAlwaysShowToolWindow);
|
||||
setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
|
@ -111,14 +113,12 @@ private:
|
|||
Animation _opacity;
|
||||
bool _hiding = false;
|
||||
bool _deleted = false;
|
||||
|
||||
};
|
||||
|
||||
NotificationsBox::NotificationsBox(QWidget *parent)
|
||||
: _chosenCorner(Global::NotificationsCorner())
|
||||
, _oldCount(snap(Global::NotificationsCount(), 1, kMaxNotificationsCount))
|
||||
, _countSlider(this) {
|
||||
}
|
||||
: _chosenCorner(Global::NotificationsCorner())
|
||||
, _oldCount(snap(Global::NotificationsCount(), 1, kMaxNotificationsCount))
|
||||
, _countSlider(this) {}
|
||||
|
||||
void NotificationsBox::prepare() {
|
||||
addButton(langFactory(lng_close), [this] { closeBox(); });
|
||||
|
@ -151,7 +151,8 @@ void NotificationsBox::paintEvent(QPaintEvent *e) {
|
|||
p.drawTextLeft(contentLeft, st::boxTitlePosition.y(), width(), lang(lng_settings_notifications_position));
|
||||
|
||||
auto screenRect = getScreenRect();
|
||||
p.fillRect(screenRect.x(), screenRect.y(), st::notificationsBoxScreenSize.width(), st::notificationsBoxScreenSize.height(), st::notificationsBoxScreenBg);
|
||||
p.fillRect(screenRect.x(), screenRect.y(), st::notificationsBoxScreenSize.width(),
|
||||
st::notificationsBoxScreenSize.height(), st::notificationsBoxScreenBg);
|
||||
|
||||
auto monitorTop = st::notificationsBoxMonitorTop;
|
||||
st::notificationsBoxMonitor.paint(p, contentLeft, monitorTop, width());
|
||||
|
@ -160,8 +161,12 @@ void NotificationsBox::paintEvent(QPaintEvent *e) {
|
|||
auto screenCorner = static_cast<Notify::ScreenCorner>(corner);
|
||||
auto isLeft = Notify::IsLeftCorner(screenCorner);
|
||||
auto isTop = Notify::IsTopCorner(screenCorner);
|
||||
auto sampleLeft = isLeft ? (screenRect.x() + st::notificationsSampleSkip) : (screenRect.x() + screenRect.width() - st::notificationsSampleSkip - st::notificationSampleSize.width());
|
||||
auto sampleTop = isTop ? (screenRect.y() + st::notificationsSampleTopSkip) : (screenRect.y() + screenRect.height() - st::notificationsSampleBottomSkip - st::notificationSampleSize.height());
|
||||
auto sampleLeft = isLeft ? (screenRect.x() + st::notificationsSampleSkip) :
|
||||
(screenRect.x() + screenRect.width() - st::notificationsSampleSkip -
|
||||
st::notificationSampleSize.width());
|
||||
auto sampleTop = isTop ? (screenRect.y() + st::notificationsSampleTopSkip) :
|
||||
(screenRect.y() + screenRect.height() - st::notificationsSampleBottomSkip -
|
||||
st::notificationSampleSize.height());
|
||||
if (corner == static_cast<int>(_chosenCorner)) {
|
||||
auto count = currentCount();
|
||||
for (int i = 0; i != kMaxNotificationsCount; ++i) {
|
||||
|
@ -209,14 +214,16 @@ int NotificationsBox::getContentLeft() const {
|
|||
QRect NotificationsBox::getScreenRect() const {
|
||||
auto screenLeft = (width() - st::notificationsBoxScreenSize.width()) / 2;
|
||||
auto screenTop = st::notificationsBoxMonitorTop + st::notificationsBoxScreenTop;
|
||||
return QRect(screenLeft, screenTop, st::notificationsBoxScreenSize.width(), st::notificationsBoxScreenSize.height());
|
||||
return QRect(screenLeft, screenTop, st::notificationsBoxScreenSize.width(),
|
||||
st::notificationsBoxScreenSize.height());
|
||||
}
|
||||
|
||||
void NotificationsBox::resizeEvent(QResizeEvent *e) {
|
||||
BoxContent::resizeEvent(e);
|
||||
|
||||
auto screenRect = getScreenRect();
|
||||
auto sliderTop = screenRect.y() + screenRect.height() + st::notificationsBoxCountLabelTop + st::notificationsBoxCountTop;
|
||||
auto sliderTop =
|
||||
screenRect.y() + screenRect.height() + st::notificationsBoxCountLabelTop + st::notificationsBoxCountTop;
|
||||
auto contentLeft = getContentLeft();
|
||||
_countSlider->resizeToWidth(width() - 2 * contentLeft);
|
||||
_countSlider->move(contentLeft, sliderTop);
|
||||
|
@ -225,7 +232,8 @@ void NotificationsBox::resizeEvent(QResizeEvent *e) {
|
|||
void NotificationsBox::prepareNotificationSampleSmall() {
|
||||
auto width = st::notificationSampleSize.width();
|
||||
auto height = st::notificationSampleSize.height();
|
||||
auto sampleImage = QImage(width * cIntRetinaFactor(), height * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
|
||||
auto sampleImage =
|
||||
QImage(width * cIntRetinaFactor(), height * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
|
||||
sampleImage.setDevicePixelRatio(cRetinaFactor());
|
||||
sampleImage.fill(st::notificationBg->c);
|
||||
{
|
||||
|
@ -262,7 +270,9 @@ void NotificationsBox::prepareNotificationSampleSmall() {
|
|||
|
||||
void NotificationsBox::prepareNotificationSampleUserpic() {
|
||||
if (_notificationSampleUserpic.isNull()) {
|
||||
_notificationSampleUserpic = App::pixmapFromImageInPlace(Messenger::Instance().logoNoMargin().scaled(st::notifyPhotoSize * cIntRetinaFactor(), st::notifyPhotoSize * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
_notificationSampleUserpic = App::pixmapFromImageInPlace(Messenger::Instance().logoNoMargin().scaled(
|
||||
st::notifyPhotoSize * cIntRetinaFactor(), st::notifyPhotoSize * cIntRetinaFactor(), Qt::IgnoreAspectRatio,
|
||||
Qt::SmoothTransformation));
|
||||
_notificationSampleUserpic.setDevicePixelRatio(cRetinaFactor());
|
||||
}
|
||||
}
|
||||
|
@ -276,20 +286,24 @@ void NotificationsBox::prepareNotificationSampleLarge() {
|
|||
Painter p(&sampleImage);
|
||||
p.fillRect(0, 0, w - st::notifyBorderWidth, st::notifyBorderWidth, st::notifyBorder->b);
|
||||
p.fillRect(w - st::notifyBorderWidth, 0, st::notifyBorderWidth, h - st::notifyBorderWidth, st::notifyBorder->b);
|
||||
p.fillRect(st::notifyBorderWidth, h - st::notifyBorderWidth, w - st::notifyBorderWidth, st::notifyBorderWidth, st::notifyBorder->b);
|
||||
p.fillRect(st::notifyBorderWidth, h - st::notifyBorderWidth, w - st::notifyBorderWidth, st::notifyBorderWidth,
|
||||
st::notifyBorder->b);
|
||||
p.fillRect(0, st::notifyBorderWidth, st::notifyBorderWidth, h - st::notifyBorderWidth, st::notifyBorder->b);
|
||||
|
||||
prepareNotificationSampleUserpic();
|
||||
p.drawPixmap(st::notifyPhotoPos.x(), st::notifyPhotoPos.y(), _notificationSampleUserpic);
|
||||
|
||||
int itemWidth = w - st::notifyPhotoPos.x() - st::notifyPhotoSize - st::notifyTextLeft - st::notifyClosePos.x() - st::notifyClose.width;
|
||||
int itemWidth = w - st::notifyPhotoPos.x() - st::notifyPhotoSize - st::notifyTextLeft - st::notifyClosePos.x() -
|
||||
st::notifyClose.width;
|
||||
|
||||
auto rectForName = rtlrect(st::notifyPhotoPos.x() + st::notifyPhotoSize + st::notifyTextLeft, st::notifyTextTop, itemWidth, st::msgNameFont->height, w);
|
||||
auto rectForName = rtlrect(st::notifyPhotoPos.x() + st::notifyPhotoSize + st::notifyTextLeft, st::notifyTextTop,
|
||||
itemWidth, st::msgNameFont->height, w);
|
||||
|
||||
auto notifyText = st::dialogsTextFont->elided(lang(lng_notification_sample), itemWidth);
|
||||
p.setFont(st::dialogsTextFont);
|
||||
p.setPen(st::dialogsTextFgService);
|
||||
p.drawText(st::notifyPhotoPos.x() + st::notifyPhotoSize + st::notifyTextLeft, st::notifyItemTop + st::msgNameFont->height + st::dialogsTextFont->ascent, notifyText);
|
||||
p.drawText(st::notifyPhotoPos.x() + st::notifyPhotoSize + st::notifyTextLeft,
|
||||
st::notifyItemTop + st::msgNameFont->height + st::dialogsTextFont->ascent, notifyText);
|
||||
|
||||
p.setPen(st::dialogsNameFg);
|
||||
p.setFont(st::msgNameFont);
|
||||
|
@ -297,7 +311,9 @@ void NotificationsBox::prepareNotificationSampleLarge() {
|
|||
auto notifyTitle = st::msgNameFont->elided(str_const_toString(AppName), rectForName.width());
|
||||
p.drawText(rectForName.left(), rectForName.top() + st::msgNameFont->ascent, notifyTitle);
|
||||
|
||||
st::notifyClose.icon.paint(p, w - st::notifyClosePos.x() - st::notifyClose.width + st::notifyClose.iconPosition.x(), st::notifyClosePos.y() + st::notifyClose.iconPosition.y(), w);
|
||||
st::notifyClose.icon.paint(
|
||||
p, w - st::notifyClosePos.x() - st::notifyClose.width + st::notifyClose.iconPosition.x(),
|
||||
st::notifyClosePos.y() + st::notifyClose.iconPosition.y(), w);
|
||||
}
|
||||
|
||||
_notificationSampleLarge = App::pixmapFromImageInPlace(std::move(sampleImage));
|
||||
|
@ -322,9 +338,12 @@ void NotificationsBox::mouseMoveEvent(QMouseEvent *e) {
|
|||
auto cornerWidth = screenRect.width() / 3;
|
||||
auto cornerHeight = screenRect.height() / 3;
|
||||
auto topLeft = rtlrect(screenRect.x(), screenRect.y(), cornerWidth, cornerHeight, width());
|
||||
auto topRight = rtlrect(screenRect.x() + screenRect.width() - cornerWidth, screenRect.y(), cornerWidth, cornerHeight, width());
|
||||
auto bottomRight = rtlrect(screenRect.x() + screenRect.width() - cornerWidth, screenRect.y() + screenRect.height() - cornerHeight, cornerWidth, cornerHeight, width());
|
||||
auto bottomLeft = rtlrect(screenRect.x(), screenRect.y() + screenRect.height() - cornerHeight, cornerWidth, cornerHeight, width());
|
||||
auto topRight =
|
||||
rtlrect(screenRect.x() + screenRect.width() - cornerWidth, screenRect.y(), cornerWidth, cornerHeight, width());
|
||||
auto bottomRight = rtlrect(screenRect.x() + screenRect.width() - cornerWidth,
|
||||
screenRect.y() + screenRect.height() - cornerHeight, cornerWidth, cornerHeight, width());
|
||||
auto bottomLeft = rtlrect(screenRect.x(), screenRect.y() + screenRect.height() - cornerHeight, cornerWidth,
|
||||
cornerHeight, width());
|
||||
if (topLeft.contains(e->pos())) {
|
||||
setOverCorner(Notify::ScreenCorner::TopLeft);
|
||||
} else if (topRight.contains(e->pos())) {
|
||||
|
@ -347,9 +366,7 @@ void NotificationsBox::setOverCorner(Notify::ScreenCorner corner) {
|
|||
if (corner == _overCorner) {
|
||||
return;
|
||||
}
|
||||
for_const (auto widget, _cornerSamples[static_cast<int>(_overCorner)]) {
|
||||
widget->hideFast();
|
||||
}
|
||||
for_const (auto widget, _cornerSamples[static_cast<int>(_overCorner)]) { widget->hideFast(); }
|
||||
} else {
|
||||
_isOverCorner = true;
|
||||
setCursor(style::cur_pointer);
|
||||
|
@ -369,8 +386,10 @@ void NotificationsBox::setOverCorner(Notify::ScreenCorner corner) {
|
|||
auto r = psDesktopRect();
|
||||
auto isLeft = Notify::IsLeftCorner(_overCorner);
|
||||
auto isTop = Notify::IsTopCorner(_overCorner);
|
||||
auto sampleLeft = (isLeft == rtl()) ? (r.x() + r.width() - st::notifyWidth - st::notifyDeltaX) : (r.x() + st::notifyDeltaX);
|
||||
auto sampleTop = isTop ? (r.y() + st::notifyDeltaY) : (r.y() + r.height() - st::notifyDeltaY - st::notifyMinHeight);
|
||||
auto sampleLeft =
|
||||
(isLeft == rtl()) ? (r.x() + r.width() - st::notifyWidth - st::notifyDeltaX) : (r.x() + st::notifyDeltaX);
|
||||
auto sampleTop =
|
||||
isTop ? (r.y() + st::notifyDeltaY) : (r.y() + r.height() - st::notifyDeltaY - st::notifyMinHeight);
|
||||
for (int i = samplesLeave; i != samplesNeeded; ++i) {
|
||||
auto widget = std::make_unique<SampleWidget>(this, _notificationSampleLarge);
|
||||
widget->move(sampleLeft, sampleTop + (isTop ? 1 : -1) * i * (st::notifyMinHeight + st::notifyDeltaY));
|
||||
|
@ -392,9 +411,7 @@ void NotificationsBox::clearOverCorner() {
|
|||
Auth().notifications().settingsChanged().notify(ChangeType::DemoIsShown);
|
||||
|
||||
for_const (auto &samples, _cornerSamples) {
|
||||
for_const (auto widget, samples) {
|
||||
widget->hideFast();
|
||||
}
|
||||
for_const (auto widget, samples) { widget->hideFast(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -424,9 +441,7 @@ void NotificationsBox::mouseReleaseEvent(QMouseEvent *e) {
|
|||
|
||||
NotificationsBox::~NotificationsBox() {
|
||||
for_const (auto &samples, _cornerSamples) {
|
||||
for_const (auto widget, samples) {
|
||||
widget->detach();
|
||||
}
|
||||
for_const (auto widget, samples) { widget->detach(); }
|
||||
}
|
||||
clearOverCorner();
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ class SettingsSlider;
|
|||
|
||||
class NotificationsBox : public BoxContent {
|
||||
public:
|
||||
NotificationsBox(QWidget*);
|
||||
NotificationsBox(QWidget *);
|
||||
~NotificationsBox();
|
||||
|
||||
protected:
|
||||
|
@ -74,6 +74,5 @@ private:
|
|||
int _oldCount;
|
||||
object_ptr<Ui::SettingsSlider> _countSlider;
|
||||
|
||||
QVector<SampleWidget*> _cornerSamples[4];
|
||||
|
||||
QVector<SampleWidget *> _cornerSamples[4];
|
||||
};
|
||||
|
|
|
@ -20,39 +20,42 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#include "boxes/passcode_box.h"
|
||||
|
||||
#include "lang/lang_keys.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "facades.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwindow.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "facades.h"
|
||||
|
||||
PasscodeBox::PasscodeBox(QWidget*, bool turningOff)
|
||||
: _turningOff(turningOff)
|
||||
, _about(st::boxWidth - st::boxPadding.left() * 1.5)
|
||||
, _oldPasscode(this, st::defaultInputField, langFactory(lng_passcode_enter_old))
|
||||
, _newPasscode(this, st::defaultInputField, langFactory(Global::LocalPasscode() ? lng_passcode_enter_new : lng_passcode_enter_first))
|
||||
, _reenterPasscode(this, st::defaultInputField, langFactory(lng_passcode_confirm_new))
|
||||
, _passwordHint(this, st::defaultInputField, langFactory(lng_cloud_password_hint))
|
||||
, _recoverEmail(this, st::defaultInputField, langFactory(lng_cloud_password_email))
|
||||
, _recover(this, lang(lng_signin_recover)) {
|
||||
}
|
||||
PasscodeBox::PasscodeBox(QWidget *, bool turningOff)
|
||||
: _turningOff(turningOff)
|
||||
, _about(st::boxWidth - st::boxPadding.left() * 1.5)
|
||||
, _oldPasscode(this, st::defaultInputField, langFactory(lng_passcode_enter_old))
|
||||
, _newPasscode(this, st::defaultInputField,
|
||||
langFactory(Global::LocalPasscode() ? lng_passcode_enter_new : lng_passcode_enter_first))
|
||||
, _reenterPasscode(this, st::defaultInputField, langFactory(lng_passcode_confirm_new))
|
||||
, _passwordHint(this, st::defaultInputField, langFactory(lng_cloud_password_hint))
|
||||
, _recoverEmail(this, st::defaultInputField, langFactory(lng_cloud_password_email))
|
||||
, _recover(this, lang(lng_signin_recover)) {}
|
||||
|
||||
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)
|
||||
, _oldPasscode(this, st::defaultInputField, langFactory(lng_cloud_password_enter_old))
|
||||
, _newPasscode(this, st::defaultInputField, langFactory(curSalt.isEmpty() ? lng_cloud_password_enter_first : lng_cloud_password_enter_new))
|
||||
, _reenterPasscode(this, st::defaultInputField, langFactory(lng_cloud_password_confirm_new))
|
||||
, _passwordHint(this, st::defaultInputField, langFactory(curSalt.isEmpty() ? lng_cloud_password_hint : lng_cloud_password_change_hint))
|
||||
, _recoverEmail(this, st::defaultInputField, langFactory(lng_cloud_password_email))
|
||||
, _recover(this, lang(lng_signin_recover)) {
|
||||
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)
|
||||
, _oldPasscode(this, st::defaultInputField, langFactory(lng_cloud_password_enter_old))
|
||||
, _newPasscode(this, st::defaultInputField,
|
||||
langFactory(curSalt.isEmpty() ? lng_cloud_password_enter_first : lng_cloud_password_enter_new))
|
||||
, _reenterPasscode(this, st::defaultInputField, langFactory(lng_cloud_password_confirm_new))
|
||||
, _passwordHint(this, st::defaultInputField,
|
||||
langFactory(curSalt.isEmpty() ? lng_cloud_password_hint : lng_cloud_password_change_hint))
|
||||
, _recoverEmail(this, st::defaultInputField, langFactory(lng_cloud_password_email))
|
||||
, _recover(this, lang(lng_signin_recover)) {
|
||||
if (!hint.isEmpty()) _hintText.setText(st::passcodeTextStyle, lng_signin_hint(lt_password_hint, hint));
|
||||
}
|
||||
|
||||
|
@ -65,17 +68,30 @@ void PasscodeBox::prepare() {
|
|||
if (_turningOff) {
|
||||
_oldPasscode->show();
|
||||
setTitle(langFactory(_cloudPwd ? lng_cloud_password_remove : lng_passcode_remove));
|
||||
setDimensions(st::boxWidth, st::passcodePadding.top() + _oldPasscode->height() + st::passcodeTextLine + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeTextLine : 0) + st::passcodeAboutSkip + _aboutHeight + st::passcodePadding.bottom());
|
||||
setDimensions(st::boxWidth, st::passcodePadding.top() + _oldPasscode->height() + st::passcodeTextLine +
|
||||
((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeTextLine : 0) +
|
||||
st::passcodeAboutSkip + _aboutHeight + st::passcodePadding.bottom());
|
||||
} else {
|
||||
auto has = _cloudPwd ? (!_curSalt.isEmpty()) : Global::LocalPasscode();
|
||||
if (has) {
|
||||
_oldPasscode->show();
|
||||
setTitle(langFactory(_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) + st::passcodeAboutSkip + _aboutHeight + st::passcodePadding.bottom());
|
||||
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) +
|
||||
st::passcodeAboutSkip + _aboutHeight + st::passcodePadding.bottom());
|
||||
} else {
|
||||
_oldPasscode->hide();
|
||||
setTitle(langFactory(_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) + st::passcodeAboutSkip + _aboutHeight + (_cloudPwd ? (st::passcodeLittleSkip + _recoverEmail->height() + st::passcodeSkip) : st::passcodePadding.bottom()));
|
||||
setDimensions(st::boxWidth,
|
||||
st::passcodePadding.top() + _newPasscode->height() + st::passcodeLittleSkip +
|
||||
_reenterPasscode->height() + st::passcodeSkip +
|
||||
(_cloudPwd ? _passwordHint->height() + st::passcodeLittleSkip : 0) +
|
||||
st::passcodeAboutSkip + _aboutHeight +
|
||||
(_cloudPwd ? (st::passcodeLittleSkip + _recoverEmail->height() + st::passcodeSkip) :
|
||||
st::passcodePadding.bottom()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,27 +159,40 @@ void PasscodeBox::paintEvent(QPaintEvent *e) {
|
|||
Painter p(this);
|
||||
|
||||
qint32 w = st::boxWidth - st::boxPadding.left() * 1.5;
|
||||
qint32 abouty = (_passwordHint->isHidden() ? ((_reenterPasscode->isHidden() ? (_oldPasscode->y() + (_hasRecovery && !_hintText.isEmpty() ? st::passcodeTextLine : 0)) : _reenterPasscode->y()) + st::passcodeSkip) : _passwordHint->y()) + _oldPasscode->height() + st::passcodeLittleSkip + st::passcodeAboutSkip;
|
||||
qint32 abouty = (_passwordHint->isHidden() ?
|
||||
((_reenterPasscode->isHidden() ?
|
||||
(_oldPasscode->y() + (_hasRecovery && !_hintText.isEmpty() ? st::passcodeTextLine : 0)) :
|
||||
_reenterPasscode->y()) +
|
||||
st::passcodeSkip) :
|
||||
_passwordHint->y()) +
|
||||
_oldPasscode->height() + st::passcodeLittleSkip + st::passcodeAboutSkip;
|
||||
p.setPen(st::boxTextFg);
|
||||
_about.drawLeft(p, st::boxPadding.left(), abouty, w, width());
|
||||
|
||||
if (!_hintText.isEmpty() && _oldError.isEmpty()) {
|
||||
_hintText.drawLeftElided(p, st::boxPadding.left(), _oldPasscode->y() + _oldPasscode->height() + ((st::passcodeTextLine - st::normalFont->height) / 2), w, width(), 1, style::al_topleft);
|
||||
_hintText.drawLeftElided(p, st::boxPadding.left(),
|
||||
_oldPasscode->y() + _oldPasscode->height() +
|
||||
((st::passcodeTextLine - st::normalFont->height) / 2),
|
||||
w, width(), 1, style::al_topleft);
|
||||
}
|
||||
|
||||
if (!_oldError.isEmpty()) {
|
||||
p.setPen(st::boxTextFgError);
|
||||
p.drawText(QRect(st::boxPadding.left(), _oldPasscode->y() + _oldPasscode->height(), w, st::passcodeTextLine), _oldError, style::al_left);
|
||||
p.drawText(QRect(st::boxPadding.left(), _oldPasscode->y() + _oldPasscode->height(), w, st::passcodeTextLine),
|
||||
_oldError, style::al_left);
|
||||
}
|
||||
|
||||
if (!_newError.isEmpty()) {
|
||||
p.setPen(st::boxTextFgError);
|
||||
p.drawText(QRect(st::boxPadding.left(), _reenterPasscode->y() + _reenterPasscode->height(), w, st::passcodeTextLine), _newError, style::al_left);
|
||||
p.drawText(
|
||||
QRect(st::boxPadding.left(), _reenterPasscode->y() + _reenterPasscode->height(), w, st::passcodeTextLine),
|
||||
_newError, style::al_left);
|
||||
}
|
||||
|
||||
if (!_emailError.isEmpty()) {
|
||||
p.setPen(st::boxTextFgError);
|
||||
p.drawText(QRect(st::boxPadding.left(), _recoverEmail->y() + _recoverEmail->height(), w, st::passcodeTextLine), _emailError, style::al_left);
|
||||
p.drawText(QRect(st::boxPadding.left(), _recoverEmail->y() + _recoverEmail->height(), w, st::passcodeTextLine),
|
||||
_emailError, style::al_left);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -175,16 +204,28 @@ void PasscodeBox::resizeEvent(QResizeEvent *e) {
|
|||
_oldPasscode->resize(w, _oldPasscode->height());
|
||||
_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));
|
||||
_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::passcodeLittleSkip);
|
||||
_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);
|
||||
_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::passcodeLittleSkip + _aboutHeight + st::passcodeLittleSkip);
|
||||
_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));
|
||||
_recover->moveToLeft(
|
||||
st::boxPadding.left(),
|
||||
_oldPasscode->y() + _oldPasscode->height() +
|
||||
(_hintText.isEmpty() ? ((st::passcodeTextLine - _recover->height()) / 2) : st::passcodeTextLine));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,7 +242,9 @@ void PasscodeBox::setInnerFocus() {
|
|||
void PasscodeBox::setPasswordDone(const MTPBool &result) {
|
||||
_setRequest = 0;
|
||||
emit reloadPassword();
|
||||
auto text = lang(_reenterPasscode->isHidden() ? lng_cloud_password_removed : (_oldPasscode->isHidden() ? lng_cloud_password_was_set : lng_cloud_password_updated));
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -319,9 +362,10 @@ void PasscodeBox::onSave(bool force) {
|
|||
}
|
||||
if (!_recoverEmail->isHidden() && email.isEmpty() && !force) {
|
||||
_skipEmailWarning = true;
|
||||
_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);
|
||||
_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);
|
||||
|
@ -336,12 +380,17 @@ void PasscodeBox::onSave(bool force) {
|
|||
if (!_oldPasscode->isHidden()) {
|
||||
hashSha256(oldPasswordData.constData(), oldPasswordData.size(), oldPasswordHash.data());
|
||||
}
|
||||
auto flags = MTPDaccount_passwordInputSettings::Flag::f_new_salt | MTPDaccount_passwordInputSettings::Flag::f_new_password_hash | MTPDaccount_passwordInputSettings::Flag::f_hint;
|
||||
auto flags = MTPDaccount_passwordInputSettings::Flag::f_new_salt |
|
||||
MTPDaccount_passwordInputSettings::Flag::f_new_password_hash |
|
||||
MTPDaccount_passwordInputSettings::Flag::f_hint;
|
||||
if (_oldPasscode->isHidden() || _newPasscode->isHidden()) {
|
||||
flags |= MTPDaccount_passwordInputSettings::Flag::f_email;
|
||||
}
|
||||
MTPaccount_PasswordInputSettings settings(MTP_account_passwordInputSettings(MTP_flags(flags), MTP_bytes(_newSalt), MTP_bytes(newPasswordHash), MTP_string(hint), MTP_string(email)));
|
||||
_setRequest = MTP::send(MTPaccount_UpdatePasswordSettings(MTP_bytes(oldPasswordHash), settings), rpcDone(&PasscodeBox::setPasswordDone), rpcFail(&PasscodeBox::setPasswordFail));
|
||||
MTPaccount_PasswordInputSettings settings(
|
||||
MTP_account_passwordInputSettings(MTP_flags(flags), MTP_bytes(_newSalt), MTP_bytes(newPasswordHash),
|
||||
MTP_string(hint), MTP_string(email)));
|
||||
_setRequest = MTP::send(MTPaccount_UpdatePasswordSettings(MTP_bytes(oldPasswordHash), settings),
|
||||
rpcDone(&PasscodeBox::setPasswordDone), rpcFail(&PasscodeBox::setPasswordFail));
|
||||
}
|
||||
} else {
|
||||
cSetPasscodeBadTries(0);
|
||||
|
@ -389,7 +438,8 @@ void PasscodeBox::onEmailChanged() {
|
|||
void PasscodeBox::onRecoverByEmail() {
|
||||
if (_pattern.isEmpty()) {
|
||||
_pattern = "-";
|
||||
MTP::send(MTPauth_RequestPasswordRecovery(), rpcDone(&PasscodeBox::recoverStarted), rpcFail(&PasscodeBox::recoverStartFail));
|
||||
MTP::send(MTPauth_RequestPasswordRecovery(), rpcDone(&PasscodeBox::recoverStarted),
|
||||
rpcFail(&PasscodeBox::recoverStartFail));
|
||||
} else {
|
||||
recover();
|
||||
}
|
||||
|
@ -420,10 +470,10 @@ bool PasscodeBox::recoverStartFail(const RPCError &error) {
|
|||
return true;
|
||||
}
|
||||
|
||||
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, langFactory(lng_signin_code)) {
|
||||
}
|
||||
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, langFactory(lng_signin_code)) {}
|
||||
|
||||
void RecoverBox::prepare() {
|
||||
setTitle(langFactory(lng_signin_recover_title));
|
||||
|
@ -431,7 +481,8 @@ void RecoverBox::prepare() {
|
|||
addButton(langFactory(lng_passcode_submit), [this] { onSubmit(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
setDimensions(st::boxWidth, st::passcodePadding.top() + st::passcodePadding.bottom() + st::passcodeTextLine + _recoverCode->height() + st::passcodeTextLine);
|
||||
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()));
|
||||
|
@ -445,11 +496,14 @@ void RecoverBox::paintEvent(QPaintEvent *e) {
|
|||
p.setFont(st::normalFont);
|
||||
p.setPen(st::boxTextFg);
|
||||
qint32 w = st::boxWidth - st::boxPadding.left() * 1.5;
|
||||
p.drawText(QRect(st::boxPadding.left(), _recoverCode->y() - st::passcodeTextLine - st::passcodePadding.top(), w, st::passcodePadding.top() + st::passcodeTextLine), _pattern, style::al_left);
|
||||
p.drawText(QRect(st::boxPadding.left(), _recoverCode->y() - st::passcodeTextLine - st::passcodePadding.top(), w,
|
||||
st::passcodePadding.top() + st::passcodeTextLine),
|
||||
_pattern, style::al_left);
|
||||
|
||||
if (!_error.isEmpty()) {
|
||||
p.setPen(st::boxTextFgError);
|
||||
p.drawText(QRect(st::boxPadding.left(), _recoverCode->y() + _recoverCode->height(), w, st::passcodeTextLine), _error, style::al_left);
|
||||
p.drawText(QRect(st::boxPadding.left(), _recoverCode->y() + _recoverCode->height(), w, st::passcodeTextLine),
|
||||
_error, style::al_left);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -457,7 +511,8 @@ 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(), st::passcodePadding.top() + st::passcodePadding.bottom() + st::passcodeTextLine);
|
||||
_recoverCode->moveToLeft(st::boxPadding.left(),
|
||||
st::passcodePadding.top() + st::passcodePadding.bottom() + st::passcodeTextLine);
|
||||
}
|
||||
|
||||
void RecoverBox::setInnerFocus() {
|
||||
|
@ -474,7 +529,8 @@ void RecoverBox::onSubmit() {
|
|||
return;
|
||||
}
|
||||
|
||||
_submitRequest = MTP::send(MTPauth_RecoverPassword(MTP_string(code)), rpcDone(&RecoverBox::codeSubmitDone, true), rpcFail(&RecoverBox::codeSubmitFail));
|
||||
_submitRequest = MTP::send(MTPauth_RecoverPassword(MTP_string(code)), rpcDone(&RecoverBox::codeSubmitDone, true),
|
||||
rpcFail(&RecoverBox::codeSubmitFail));
|
||||
}
|
||||
|
||||
void RecoverBox::onCodeChanged() {
|
||||
|
@ -522,7 +578,7 @@ bool RecoverBox::codeSubmitFail(const RPCError &error) {
|
|||
return true;
|
||||
}
|
||||
if (cDebug()) { // internal server error
|
||||
_error = err + ": " + error.description();
|
||||
_error = err + ": " + error.description();
|
||||
} else {
|
||||
_error = lang(lng_server_error);
|
||||
}
|
||||
|
|
|
@ -32,8 +32,9 @@ class PasscodeBox : public BoxContent, public RPCSender {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PasscodeBox(QWidget*, bool turningOff);
|
||||
PasscodeBox(QWidget*, 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);
|
||||
|
@ -88,14 +89,13 @@ private:
|
|||
object_ptr<Ui::LinkButton> _recover;
|
||||
|
||||
QString _oldError, _newError, _emailError;
|
||||
|
||||
};
|
||||
|
||||
class RecoverBox : public BoxContent, public RPCSender {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
RecoverBox(QWidget*, const QString &pattern);
|
||||
RecoverBox(QWidget *, const QString &pattern);
|
||||
|
||||
public slots:
|
||||
void onSubmit();
|
||||
|
@ -123,5 +123,4 @@ private:
|
|||
object_ptr<Ui::InputField> _recoverCode;
|
||||
|
||||
QString _error;
|
||||
|
||||
};
|
||||
|
|
|
@ -18,29 +18,27 @@ to link the code of portions of this program with the OpenSSL library.
|
|||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "base/algorithm.h"
|
||||
#include "boxes/peer_list_box.h"
|
||||
#include "base/algorithm.h"
|
||||
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_dialogs.h"
|
||||
#include "auth_session.h"
|
||||
#include "mainwidget.h"
|
||||
#include "ui/widgets/multi_select.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/effects/round_checkbox.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "ui/effects/widget_slide_wrap.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwidget.h"
|
||||
#include "observer_peer.h"
|
||||
#include "storage/file_download.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_dialogs.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "ui/effects/round_checkbox.h"
|
||||
#include "ui/effects/widget_slide_wrap.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/multi_select.h"
|
||||
#include "window/themes/window_theme.h"
|
||||
|
||||
PeerListBox::PeerListBox(QWidget*
|
||||
, std::unique_ptr<PeerListController> controller
|
||||
, base::lambda<void(not_null<PeerListBox*>)> init)
|
||||
: _controller(std::move(controller))
|
||||
, _init(std::move(init))
|
||||
{
|
||||
PeerListBox::PeerListBox(QWidget *, std::unique_ptr<PeerListController> controller,
|
||||
base::lambda<void(not_null<PeerListBox *>)> init)
|
||||
: _controller(std::move(controller))
|
||||
, _init(std::move(init)) {
|
||||
Expects(_controller != nullptr);
|
||||
}
|
||||
|
||||
|
@ -159,7 +157,7 @@ void PeerListBox::peerListAppendSearchRow(std::unique_ptr<PeerListRow> row) {
|
|||
_inner->appendSearchRow(std::move(row));
|
||||
}
|
||||
|
||||
void PeerListBox::peerListAppendFoundRow(not_null<PeerListRow*> row) {
|
||||
void PeerListBox::peerListAppendFoundRow(not_null<PeerListRow *> row) {
|
||||
_inner->appendFoundRow(row);
|
||||
}
|
||||
|
||||
|
@ -167,7 +165,7 @@ void PeerListBox::peerListPrependRow(std::unique_ptr<PeerListRow> row) {
|
|||
_inner->prependRow(std::move(row));
|
||||
}
|
||||
|
||||
void PeerListBox::peerListPrependRowFromSearchResult(not_null<PeerListRow*> row) {
|
||||
void PeerListBox::peerListPrependRowFromSearchResult(not_null<PeerListRow *> row) {
|
||||
_inner->prependRowFromSearchResult(row);
|
||||
}
|
||||
|
||||
|
@ -175,19 +173,19 @@ PeerListRow *PeerListBox::peerListFindRow(PeerListRowId id) {
|
|||
return _inner->findRow(id);
|
||||
}
|
||||
|
||||
void PeerListBox::peerListUpdateRow(not_null<PeerListRow*> row) {
|
||||
void PeerListBox::peerListUpdateRow(not_null<PeerListRow *> row) {
|
||||
_inner->updateRow(row);
|
||||
}
|
||||
|
||||
void PeerListBox::peerListRemoveRow(not_null<PeerListRow*> row) {
|
||||
void PeerListBox::peerListRemoveRow(not_null<PeerListRow *> row) {
|
||||
_inner->removeRow(row);
|
||||
}
|
||||
|
||||
void PeerListBox::peerListConvertRowToSearchResult(not_null<PeerListRow*> row) {
|
||||
void PeerListBox::peerListConvertRowToSearchResult(not_null<PeerListRow *> row) {
|
||||
_inner->convertRowToSearchResult(row);
|
||||
}
|
||||
|
||||
void PeerListBox::peerListSetRowChecked(not_null<PeerListRow*> row, bool checked) {
|
||||
void PeerListBox::peerListSetRowChecked(not_null<PeerListRow *> row, bool checked) {
|
||||
auto peer = row->peer();
|
||||
if (checked) {
|
||||
addSelectItem(peer, PeerListRow::SetStyle::Animated);
|
||||
|
@ -207,7 +205,7 @@ int PeerListBox::peerListFullRowsCount() {
|
|||
return _inner->fullRowsCount();
|
||||
}
|
||||
|
||||
not_null<PeerListRow*> PeerListBox::peerListRowAt(int index) {
|
||||
not_null<PeerListRow *> PeerListBox::peerListRowAt(int index) {
|
||||
return _inner->rowAt(index);
|
||||
}
|
||||
|
||||
|
@ -251,21 +249,18 @@ void PeerListBox::peerListSetSearchMode(PeerListSearchMode mode) {
|
|||
|
||||
void PeerListBox::peerListSortRows(base::lambda<bool(PeerListRow &a, PeerListRow &b)> compare) {
|
||||
_inner->reorderRows([compare = std::move(compare)](auto &&begin, auto &&end) {
|
||||
std::sort(begin, end, [compare](auto &&a, auto &&b) {
|
||||
return compare(*a, *b);
|
||||
});
|
||||
std::sort(begin, end, [compare](auto &&a, auto &&b) { return compare(*a, *b); });
|
||||
});
|
||||
}
|
||||
|
||||
void PeerListBox::peerListPartitionRows(base::lambda<bool(PeerListRow &a)> border) {
|
||||
_inner->reorderRows([border = std::move(border)](auto &&begin, auto &&end) {
|
||||
std::stable_partition(begin, end, [border](auto &¤t) {
|
||||
return border(*current);
|
||||
});
|
||||
std::stable_partition(begin, end, [border](auto &¤t) { return border(*current); });
|
||||
});
|
||||
}
|
||||
|
||||
PeerListController::PeerListController(std::unique_ptr<PeerListSearchController> searchController) : _searchController(std::move(searchController)) {
|
||||
PeerListController::PeerListController(std::unique_ptr<PeerListSearchController> searchController)
|
||||
: _searchController(std::move(searchController)) {
|
||||
if (_searchController) {
|
||||
_searchController->setDelegate(this);
|
||||
}
|
||||
|
@ -280,7 +275,7 @@ void PeerListController::search(const QString &query) {
|
|||
_searchController->searchQuery(query);
|
||||
}
|
||||
|
||||
void PeerListController::peerListSearchAddRow(not_null<PeerData*> peer) {
|
||||
void PeerListController::peerListSearchAddRow(not_null<PeerData *> peer) {
|
||||
if (auto row = delegate()->peerListFindRow(peer->id)) {
|
||||
Assert(row->id() == row->peer()->id);
|
||||
delegate()->peerListAppendFoundRow(row);
|
||||
|
@ -318,7 +313,7 @@ void PeerListController::setSearchNoResultsText(const QString &text) {
|
|||
}
|
||||
}
|
||||
|
||||
void PeerListBox::addSelectItem(not_null<PeerData*> peer, PeerListRow::SetStyle style) {
|
||||
void PeerListBox::addSelectItem(not_null<PeerData *> peer, PeerListRow::SetStyle style) {
|
||||
if (!_select) {
|
||||
createMultiSelect();
|
||||
_select->toggleFast(false);
|
||||
|
@ -326,7 +321,8 @@ void PeerListBox::addSelectItem(not_null<PeerData*> peer, PeerListRow::SetStyle
|
|||
if (style == PeerListRow::SetStyle::Fast) {
|
||||
_select->entity()->addItemInBunch(peer->id, peer->shortName(), st::activeButtonBg, PaintUserpicCallback(peer));
|
||||
} else {
|
||||
_select->entity()->addItem(peer->id, peer->shortName(), st::activeButtonBg, PaintUserpicCallback(peer), Ui::MultiSelect::AddItemWay::Default);
|
||||
_select->entity()->addItem(peer->id, peer->shortName(), st::activeButtonBg, PaintUserpicCallback(peer),
|
||||
Ui::MultiSelect::AddItemWay::Default);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -335,7 +331,7 @@ void PeerListBox::peerListFinishSelectedRowsBunch() {
|
|||
_select->entity()->finishItemsBunch();
|
||||
}
|
||||
|
||||
bool PeerListBox::peerListIsRowSelected(not_null<PeerData*> peer) {
|
||||
bool PeerListBox::peerListIsRowSelected(not_null<PeerData *> peer) {
|
||||
return _select ? _select->entity()->hasItem(peer->id) : false;
|
||||
}
|
||||
|
||||
|
@ -343,27 +339,24 @@ int PeerListBox::peerListSelectedRowsCount() {
|
|||
return _select ? _select->entity()->getItemsCount() : 0;
|
||||
}
|
||||
|
||||
std::vector<not_null<PeerData*>> PeerListBox::peerListCollectSelectedRows() {
|
||||
auto result = std::vector<not_null<PeerData*>> {};
|
||||
auto items = _select ? _select->entity()->getItems() : QVector<quint64> {};
|
||||
std::vector<not_null<PeerData *>> PeerListBox::peerListCollectSelectedRows() {
|
||||
auto result = std::vector<not_null<PeerData *>>{};
|
||||
auto items = _select ? _select->entity()->getItems() : QVector<quint64>{};
|
||||
if (!items.empty()) {
|
||||
result.reserve(items.size());
|
||||
for_const (auto itemId, items) {
|
||||
result.push_back(App::peer(itemId));
|
||||
}
|
||||
for_const (auto itemId, items) { result.push_back(App::peer(itemId)); }
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
PeerListRow::PeerListRow(not_null<PeerData*> peer) : PeerListRow(peer, peer->id) {
|
||||
}
|
||||
PeerListRow::PeerListRow(not_null<PeerData *> peer)
|
||||
: PeerListRow(peer, peer->id) {}
|
||||
|
||||
PeerListRow::PeerListRow(not_null<PeerData*> peer, PeerListRowId id)
|
||||
: _id(id)
|
||||
, _peer(peer)
|
||||
, _initialized(false)
|
||||
, _isSearchResult(false) {
|
||||
}
|
||||
PeerListRow::PeerListRow(not_null<PeerData *> peer, PeerListRowId id)
|
||||
: _id(id)
|
||||
, _peer(peer)
|
||||
, _initialized(false)
|
||||
, _isSearchResult(false) {}
|
||||
|
||||
bool PeerListRow::checked() const {
|
||||
return _checkbox && _checkbox->checked();
|
||||
|
@ -423,7 +416,8 @@ void PeerListRow::invalidatePixmapsCache() {
|
|||
void PeerListRow::paintStatusText(Painter &p, int x, int y, int availableWidth, int outerWidth, bool selected) {
|
||||
auto statusHasOnlineColor = (_statusType == PeerListRow::StatusType::Online);
|
||||
p.setFont(st::contactsStatusFont);
|
||||
p.setPen(statusHasOnlineColor ? st::contactsStatusFgOnline : (selected ? st::contactsStatusFgOver : st::contactsStatusFg));
|
||||
p.setPen(statusHasOnlineColor ? st::contactsStatusFgOnline :
|
||||
(selected ? st::contactsStatusFgOver : st::contactsStatusFg));
|
||||
_status.drawLeftElided(p, x, y, availableWidth, outerWidth);
|
||||
}
|
||||
|
||||
|
@ -514,7 +508,8 @@ void PeerListRow::lazyInitialize() {
|
|||
}
|
||||
|
||||
void PeerListRow::createCheckbox(base::lambda<void()> updateCallback) {
|
||||
_checkbox = std::make_unique<Ui::RoundImageCheckbox>(st::contactsPhotoCheckbox, std::move(updateCallback), PaintUserpicCallback(_peer));
|
||||
_checkbox = std::make_unique<Ui::RoundImageCheckbox>(st::contactsPhotoCheckbox, std::move(updateCallback),
|
||||
PaintUserpicCallback(_peer));
|
||||
}
|
||||
|
||||
void PeerListRow::setCheckedInternal(bool checked, SetStyle style) {
|
||||
|
@ -524,20 +519,21 @@ void PeerListRow::setCheckedInternal(bool checked, SetStyle style) {
|
|||
_checkbox->setChecked(checked, speed);
|
||||
}
|
||||
|
||||
PeerListBox::Inner::Inner(QWidget *parent, not_null<PeerListController*> controller) : TWidget(parent)
|
||||
, _controller(controller)
|
||||
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom()) {
|
||||
PeerListBox::Inner::Inner(QWidget *parent, not_null<PeerListController *> controller)
|
||||
: TWidget(parent)
|
||||
, _controller(controller)
|
||||
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom()) {
|
||||
subscribe(Auth().downloaderTaskFinished(), [this] { update(); });
|
||||
|
||||
using UpdateFlag = Notify::PeerUpdate::Flag;
|
||||
auto changes = UpdateFlag::NameChanged | UpdateFlag::PhotoChanged;
|
||||
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(changes, [this](const Notify::PeerUpdate &update) {
|
||||
if (update.flags & UpdateFlag::PhotoChanged) {
|
||||
this->update();
|
||||
} else if (update.flags & UpdateFlag::NameChanged) {
|
||||
handleNameChanged(update);
|
||||
}
|
||||
}));
|
||||
if (update.flags & UpdateFlag::PhotoChanged) {
|
||||
this->update();
|
||||
} else if (update.flags & UpdateFlag::NameChanged) {
|
||||
handleNameChanged(update);
|
||||
}
|
||||
}));
|
||||
subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &update) {
|
||||
if (update.paletteChanged()) {
|
||||
invalidatePixmapsCache();
|
||||
|
@ -566,7 +562,7 @@ void PeerListBox::Inner::appendSearchRow(std::unique_ptr<PeerListRow> row) {
|
|||
}
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::appendFoundRow(not_null<PeerListRow*> row) {
|
||||
void PeerListBox::Inner::appendFoundRow(not_null<PeerListRow *> row) {
|
||||
Expects(showingSearch());
|
||||
auto index = findRowIndex(row);
|
||||
if (index.value < 0) {
|
||||
|
@ -574,13 +570,11 @@ void PeerListBox::Inner::appendFoundRow(not_null<PeerListRow*> row) {
|
|||
}
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::changeCheckState(not_null<PeerListRow*> row, bool checked, PeerListRow::SetStyle style) {
|
||||
row->setChecked(checked, style, [this, row] {
|
||||
updateRow(row);
|
||||
});
|
||||
void PeerListBox::Inner::changeCheckState(not_null<PeerListRow *> row, bool checked, PeerListRow::SetStyle style) {
|
||||
row->setChecked(checked, style, [this, row] { updateRow(row); });
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::addRowEntry(not_null<PeerListRow*> row) {
|
||||
void PeerListBox::Inner::addRowEntry(not_null<PeerListRow *> row) {
|
||||
_rowsById.emplace(row->id(), row);
|
||||
_rowsByPeer[row->peer()].push_back(row);
|
||||
if (addingToSearchIndex()) {
|
||||
|
@ -603,19 +597,17 @@ bool PeerListBox::Inner::addingToSearchIndex() const {
|
|||
return (_searchMode != PeerListSearchMode::Disabled) || !_searchIndex.empty();
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::addToSearchIndex(not_null<PeerListRow*> row) {
|
||||
void PeerListBox::Inner::addToSearchIndex(not_null<PeerListRow *> row) {
|
||||
if (row->isSearchResult()) {
|
||||
return;
|
||||
}
|
||||
|
||||
removeFromSearchIndex(row);
|
||||
row->setNameFirstChars(row->peer()->chars);
|
||||
for_const (auto ch, row->nameFirstChars()) {
|
||||
_searchIndex[ch].push_back(row);
|
||||
}
|
||||
for_const (auto ch, row->nameFirstChars()) { _searchIndex[ch].push_back(row); }
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::removeFromSearchIndex(not_null<PeerListRow*> row) {
|
||||
void PeerListBox::Inner::removeFromSearchIndex(not_null<PeerListRow *> row) {
|
||||
auto &nameFirstChars = row->nameFirstChars();
|
||||
if (!nameFirstChars.empty()) {
|
||||
for_const (auto ch, row->nameFirstChars()) {
|
||||
|
@ -641,7 +633,7 @@ void PeerListBox::Inner::prependRow(std::unique_ptr<PeerListRow> row) {
|
|||
}
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::prependRowFromSearchResult(not_null<PeerListRow*> row) {
|
||||
void PeerListBox::Inner::prependRowFromSearchResult(not_null<PeerListRow *> row) {
|
||||
if (!row->isSearchResult()) {
|
||||
return;
|
||||
}
|
||||
|
@ -679,7 +671,7 @@ PeerListRow *PeerListBox::Inner::findRow(PeerListRowId id) {
|
|||
return (it == _rowsById.cend()) ? nullptr : it->second.get();
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::removeRow(not_null<PeerListRow*> row) {
|
||||
void PeerListBox::Inner::removeRow(not_null<PeerListRow *> row) {
|
||||
auto index = row->absoluteIndex();
|
||||
auto isSearchResult = row->isSearchResult();
|
||||
auto &eraseFrom = isSearchResult ? _searchRows : _rows;
|
||||
|
@ -700,7 +692,7 @@ void PeerListBox::Inner::removeRow(not_null<PeerListRow*> row) {
|
|||
restoreSelection();
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::convertRowToSearchResult(not_null<PeerListRow*> row) {
|
||||
void PeerListBox::Inner::convertRowToSearchResult(not_null<PeerListRow *> row) {
|
||||
if (row->isSearchResult()) {
|
||||
return;
|
||||
} else if (!showingSearch() || !_controller->hasComplexSearch()) {
|
||||
|
@ -721,7 +713,7 @@ int PeerListBox::Inner::fullRowsCount() const {
|
|||
return _rows.size();
|
||||
}
|
||||
|
||||
not_null<PeerListRow*> PeerListBox::Inner::rowAt(int index) const {
|
||||
not_null<PeerListRow *> PeerListBox::Inner::rowAt(int index) const {
|
||||
Expects(index >= 0 && index < _rows.size());
|
||||
return _rows[index].get();
|
||||
}
|
||||
|
@ -785,14 +777,13 @@ void PeerListBox::Inner::refreshRows() {
|
|||
void PeerListBox::Inner::setSearchMode(PeerListSearchMode mode) {
|
||||
if (_searchMode != mode) {
|
||||
if (!addingToSearchIndex()) {
|
||||
for_const (auto &row, _rows) {
|
||||
addToSearchIndex(row.get());
|
||||
}
|
||||
for_const (auto &row, _rows) { addToSearchIndex(row.get()); }
|
||||
}
|
||||
_searchMode = mode;
|
||||
if (_controller->hasComplexSearch()) {
|
||||
if (!_searchLoading) {
|
||||
setSearchLoading(object_ptr<Ui::FlatLabel>(this, lang(lng_contacts_loading), Ui::FlatLabel::InitType::Simple, st::membersAbout));
|
||||
setSearchLoading(object_ptr<Ui::FlatLabel>(this, lang(lng_contacts_loading),
|
||||
Ui::FlatLabel::InitType::Simple, st::membersAbout));
|
||||
}
|
||||
} else {
|
||||
clearSearchRows();
|
||||
|
@ -847,7 +838,8 @@ int PeerListBox::Inner::resizeGetHeight(int newWidth) {
|
|||
_description->setVisible(!showingSearch());
|
||||
}
|
||||
if (_searchNoResults) {
|
||||
_searchNoResults->moveToLeft(st::contactsPadding.left(), labelTop + st::membersAboutLimitPadding.top(), newWidth);
|
||||
_searchNoResults->moveToLeft(st::contactsPadding.left(), labelTop + st::membersAboutLimitPadding.top(),
|
||||
newWidth);
|
||||
_searchNoResults->setVisible(showingSearch() && _filterResults.empty() && !_controller->isSearchLoading());
|
||||
}
|
||||
if (_searchLoading) {
|
||||
|
@ -883,9 +875,7 @@ void PeerListBox::Inner::mousePressEvent(QMouseEvent *e) {
|
|||
|
||||
setPressed(_selected);
|
||||
if (auto row = getRow(_selected.index)) {
|
||||
auto updateCallback = [this, row, hint = _selected.index] {
|
||||
updateRow(row, hint);
|
||||
};
|
||||
auto updateCallback = [this, row, hint = _selected.index] { updateRow(row, hint); };
|
||||
if (_selected.action) {
|
||||
auto actionRect = getActionRect(row, _selected.index);
|
||||
if (!actionRect.isEmpty()) {
|
||||
|
@ -954,7 +944,8 @@ void PeerListBox::Inner::paintRow(Painter &p, TimeMs ms, RowIndex index) {
|
|||
if (row->needsVerifiedIcon()) {
|
||||
auto icon = &st::dialogsVerifiedIcon;
|
||||
namew -= icon->width();
|
||||
icon->paint(p, namex + std::min(name.maxWidth(), namew), st::contactsPadding.top() + st::contactsNameTop, width());
|
||||
icon->paint(p, namex + std::min(name.maxWidth(), namew), st::contactsPadding.top() + st::contactsNameTop,
|
||||
width());
|
||||
}
|
||||
auto nameCheckedRatio = row->disabled() ? 0. : row->checkedRatio();
|
||||
p.setPen(anim::pen(st::contactsNameFg, st::contactsNameCheckedFg, nameCheckedRatio));
|
||||
|
@ -967,7 +958,8 @@ void PeerListBox::Inner::paintRow(Painter &p, TimeMs ms, RowIndex index) {
|
|||
}
|
||||
|
||||
p.setFont(st::contactsStatusFont);
|
||||
if (row->isSearchResult() && !_mentionHighlight.isEmpty() && peer->userName().startsWith(_mentionHighlight, Qt::CaseInsensitive)) {
|
||||
if (row->isSearchResult() && !_mentionHighlight.isEmpty() &&
|
||||
peer->userName().startsWith(_mentionHighlight, Qt::CaseInsensitive)) {
|
||||
auto username = peer->userName();
|
||||
auto availableWidth = statusw;
|
||||
auto highlightedPart = '@' + username.mid(0, _mentionHighlight.size());
|
||||
|
@ -985,7 +977,8 @@ void PeerListBox::Inner::paintRow(Painter &p, TimeMs ms, RowIndex index) {
|
|||
p.setPen(st::contactsStatusFgOnline);
|
||||
p.drawTextLeft(namex, st::contactsPadding.top() + st::contactsStatusTop, width(), highlightedPart);
|
||||
p.setPen(selected ? st::contactsStatusFgOver : st::contactsStatusFg);
|
||||
p.drawTextLeft(namex + highlightedWidth, st::contactsPadding.top() + st::contactsStatusTop, width(), grayedPart);
|
||||
p.drawTextLeft(namex + highlightedWidth, st::contactsPadding.top() + st::contactsStatusTop, width(),
|
||||
grayedPart);
|
||||
}
|
||||
} else {
|
||||
row->paintStatusText(p, namex, st::contactsPadding.top() + st::contactsStatusTop, statusw, width(), selected);
|
||||
|
@ -1003,7 +996,7 @@ void PeerListBox::Inner::selectSkip(int direction) {
|
|||
auto rowsCount = shownRowsCount();
|
||||
auto index = 0;
|
||||
auto firstEnabled = -1, lastEnabled = -1;
|
||||
enumerateShownRows([&firstEnabled, &lastEnabled, &index](not_null<PeerListRow*> row) {
|
||||
enumerateShownRows([&firstEnabled, &lastEnabled, &index](not_null<PeerListRow *> row) {
|
||||
if (!row->disabled()) {
|
||||
if (firstEnabled < 0) {
|
||||
firstEnabled = index;
|
||||
|
@ -1022,8 +1015,8 @@ void PeerListBox::Inner::selectSkip(int direction) {
|
|||
Assert(firstEnabled - 1 <= lastEnabled);
|
||||
|
||||
// Always pass through the first enabled item when changing from / to none selected.
|
||||
if ((_selected.index.value > firstEnabled && newSelectedIndex < firstEnabled)
|
||||
|| (_selected.index.value < firstEnabled && newSelectedIndex > firstEnabled)) {
|
||||
if ((_selected.index.value > firstEnabled && newSelectedIndex < firstEnabled) ||
|
||||
(_selected.index.value < firstEnabled && newSelectedIndex > firstEnabled)) {
|
||||
newSelectedIndex = firstEnabled;
|
||||
}
|
||||
|
||||
|
@ -1037,7 +1030,7 @@ void PeerListBox::Inner::selectSkip(int direction) {
|
|||
newSelectedIndex = lastEnabled;
|
||||
} else if (getRow(RowIndex(newSelectedIndex))->disabled()) {
|
||||
auto delta = (direction > 0) ? 1 : -1;
|
||||
for (newSelectedIndex += delta; ; newSelectedIndex += delta) {
|
||||
for (newSelectedIndex += delta;; newSelectedIndex += delta) {
|
||||
// We must find an enabled row, firstEnabled <= us <= lastEnabled.
|
||||
Assert(newSelectedIndex >= 0 && newSelectedIndex < rowsCount);
|
||||
if (!getRow(RowIndex(newSelectedIndex))->disabled()) {
|
||||
|
@ -1100,7 +1093,7 @@ void PeerListBox::Inner::searchQueryChanged(QString query) {
|
|||
if (_normalizedSearchQuery != normalizedQuery) {
|
||||
setSearchQuery(query, normalizedQuery);
|
||||
if (_controller->searchInLocal() && !searchWordsList.isEmpty()) {
|
||||
auto minimalList = (const std::vector<not_null<PeerListRow*>>*)nullptr;
|
||||
auto minimalList = (const std::vector<not_null<PeerListRow *>> *)nullptr;
|
||||
for_const (auto &searchWord, searchWordsList) {
|
||||
auto searchWordStart = searchWord[0].toLower();
|
||||
auto it = _searchIndex.find(searchWordStart);
|
||||
|
@ -1190,7 +1183,8 @@ void PeerListBox::Inner::updateSelection() {
|
|||
auto in = parentWidget()->rect().contains(parentWidget()->mapFromGlobal(_lastMousePosition));
|
||||
auto selected = Selected();
|
||||
auto rowsPointY = point.y() - rowsTop();
|
||||
selected.index.value = (in && rowsPointY >= 0 && rowsPointY < shownRowsCount() * _rowHeight) ? (rowsPointY / _rowHeight) : -1;
|
||||
selected.index.value =
|
||||
(in && rowsPointY >= 0 && rowsPointY < shownRowsCount() * _rowHeight) ? (rowsPointY / _rowHeight) : -1;
|
||||
if (selected.index.value >= 0) {
|
||||
auto row = getRow(selected.index);
|
||||
if (row->disabled()) {
|
||||
|
@ -1204,7 +1198,7 @@ void PeerListBox::Inner::updateSelection() {
|
|||
setSelected(selected);
|
||||
}
|
||||
|
||||
QRect PeerListBox::Inner::getActionRect(not_null<PeerListRow*> row, RowIndex index) const {
|
||||
QRect PeerListBox::Inner::getActionRect(not_null<PeerListRow *> row, RowIndex index) const {
|
||||
auto actionSize = row->actionSize();
|
||||
if (actionSize.isEmpty()) {
|
||||
return QRect();
|
||||
|
@ -1228,7 +1222,7 @@ int PeerListBox::Inner::getRowTop(RowIndex index) const {
|
|||
return -1;
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::updateRow(not_null<PeerListRow*> row, RowIndex hint) {
|
||||
void PeerListBox::Inner::updateRow(not_null<PeerListRow *> row, RowIndex hint) {
|
||||
updateRow(findRowIndex(row, hint));
|
||||
}
|
||||
|
||||
|
@ -1248,13 +1242,11 @@ void PeerListBox::Inner::updateRow(RowIndex index) {
|
|||
update(0, getRowTop(index), width(), _rowHeight);
|
||||
}
|
||||
|
||||
template <typename Callback>
|
||||
bool PeerListBox::Inner::enumerateShownRows(Callback callback) {
|
||||
template <typename Callback> bool PeerListBox::Inner::enumerateShownRows(Callback callback) {
|
||||
return enumerateShownRows(0, shownRowsCount(), std::move(callback));
|
||||
}
|
||||
|
||||
template <typename Callback>
|
||||
bool PeerListBox::Inner::enumerateShownRows(int from, int to, Callback callback) {
|
||||
template <typename Callback> bool PeerListBox::Inner::enumerateShownRows(int from, int to, Callback callback) {
|
||||
Assert(0 <= from);
|
||||
Assert(from <= to);
|
||||
if (showingSearch()) {
|
||||
|
@ -1288,7 +1280,7 @@ PeerListRow *PeerListBox::Inner::getRow(RowIndex index) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
PeerListBox::Inner::RowIndex PeerListBox::Inner::findRowIndex(not_null<PeerListRow*> row, RowIndex hint) {
|
||||
PeerListBox::Inner::RowIndex PeerListBox::Inner::findRowIndex(not_null<PeerListRow *> row, RowIndex hint) {
|
||||
if (!showingSearch()) {
|
||||
Assert(!row->isSearchResult());
|
||||
return RowIndex(row->absoluteIndex());
|
||||
|
|
|
@ -20,16 +20,15 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "base/timer.h"
|
||||
#include "boxes/abstract_box.h"
|
||||
#include "mtproto/sender.h"
|
||||
#include "base/timer.h"
|
||||
|
||||
namespace Ui {
|
||||
class RippleAnimation;
|
||||
class RoundImageCheckbox;
|
||||
class MultiSelect;
|
||||
template <typename Widget>
|
||||
class WidgetSlideWrap;
|
||||
template <typename Widget> class WidgetSlideWrap;
|
||||
class FlatLabel;
|
||||
} // namespace Ui
|
||||
|
||||
|
@ -46,8 +45,8 @@ inline auto PaintUserpicCallback(PeerData *peer) {
|
|||
using PeerListRowId = quint64;
|
||||
class PeerListRow {
|
||||
public:
|
||||
PeerListRow(not_null<PeerData*> peer);
|
||||
PeerListRow(not_null<PeerData*> peer, PeerListRowId id);
|
||||
PeerListRow(not_null<PeerData *> peer);
|
||||
PeerListRow(not_null<PeerData *> peer, PeerListRowId id);
|
||||
|
||||
enum class State {
|
||||
Active,
|
||||
|
@ -64,7 +63,7 @@ public:
|
|||
// added to the box it is always false.
|
||||
bool checked() const;
|
||||
|
||||
not_null<PeerData*> peer() const {
|
||||
not_null<PeerData *> peer() const {
|
||||
return _peer;
|
||||
}
|
||||
PeerListRowId id() const {
|
||||
|
@ -86,12 +85,9 @@ public:
|
|||
virtual QMargins actionMargins() const {
|
||||
return QMargins();
|
||||
}
|
||||
virtual void addActionRipple(QPoint point, base::lambda<void()> updateCallback) {
|
||||
}
|
||||
virtual void stopLastActionRipple() {
|
||||
}
|
||||
virtual void paintAction(Painter &p, TimeMs ms, int x, int y, int outerWidth, bool actionSelected) {
|
||||
}
|
||||
virtual void addActionRipple(QPoint point, base::lambda<void()> updateCallback) {}
|
||||
virtual void stopLastActionRipple() {}
|
||||
virtual void paintAction(Painter &p, TimeMs ms, int x, int y, int outerWidth, bool actionSelected) {}
|
||||
|
||||
void refreshName();
|
||||
const Text &name() const {
|
||||
|
@ -125,8 +121,7 @@ public:
|
|||
Animated,
|
||||
Fast,
|
||||
};
|
||||
template <typename UpdateCallback>
|
||||
void setChecked(bool checked, SetStyle style, UpdateCallback callback) {
|
||||
template <typename UpdateCallback> void setChecked(bool checked, SetStyle style, UpdateCallback callback) {
|
||||
if (checked && !_checkbox) {
|
||||
createCheckbox(std::move(callback));
|
||||
}
|
||||
|
@ -134,8 +129,7 @@ public:
|
|||
}
|
||||
void invalidatePixmapsCache();
|
||||
|
||||
template <typename UpdateCallback>
|
||||
void addRipple(QSize size, QPoint point, UpdateCallback updateCallback);
|
||||
template <typename UpdateCallback> void addRipple(QSize size, QPoint point, UpdateCallback updateCallback);
|
||||
void stopLastRipple();
|
||||
void paintRipple(Painter &p, TimeMs ms, int x, int y, int outerWidth);
|
||||
void paintUserpic(Painter &p, TimeMs ms, int x, int y, int outerWidth);
|
||||
|
@ -163,7 +157,7 @@ private:
|
|||
void setStatusText(const QString &text);
|
||||
|
||||
PeerListRowId _id = 0;
|
||||
not_null<PeerData*> _peer;
|
||||
not_null<PeerData *> _peer;
|
||||
std::unique_ptr<Ui::RippleAnimation> _ripple;
|
||||
std::unique_ptr<Ui::RoundImageCheckbox> _checkbox;
|
||||
Text _name;
|
||||
|
@ -174,7 +168,6 @@ private:
|
|||
State _disabledState = State::Active;
|
||||
bool _initialized : 1;
|
||||
bool _isSearchResult : 1;
|
||||
|
||||
};
|
||||
|
||||
enum class PeerListSearchMode {
|
||||
|
@ -193,15 +186,15 @@ public:
|
|||
virtual void peerListSetSearchMode(PeerListSearchMode mode) = 0;
|
||||
virtual void peerListAppendRow(std::unique_ptr<PeerListRow> row) = 0;
|
||||
virtual void peerListAppendSearchRow(std::unique_ptr<PeerListRow> row) = 0;
|
||||
virtual void peerListAppendFoundRow(not_null<PeerListRow*> row) = 0;
|
||||
virtual void peerListAppendFoundRow(not_null<PeerListRow *> row) = 0;
|
||||
virtual void peerListPrependRow(std::unique_ptr<PeerListRow> row) = 0;
|
||||
virtual void peerListPrependRowFromSearchResult(not_null<PeerListRow*> row) = 0;
|
||||
virtual void peerListUpdateRow(not_null<PeerListRow*> row) = 0;
|
||||
virtual void peerListRemoveRow(not_null<PeerListRow*> row) = 0;
|
||||
virtual void peerListConvertRowToSearchResult(not_null<PeerListRow*> row) = 0;
|
||||
virtual bool peerListIsRowSelected(not_null<PeerData*> peer) = 0;
|
||||
virtual void peerListSetRowChecked(not_null<PeerListRow*> row, bool checked) = 0;
|
||||
virtual not_null<PeerListRow*> peerListRowAt(int index) = 0;
|
||||
virtual void peerListPrependRowFromSearchResult(not_null<PeerListRow *> row) = 0;
|
||||
virtual void peerListUpdateRow(not_null<PeerListRow *> row) = 0;
|
||||
virtual void peerListRemoveRow(not_null<PeerListRow *> row) = 0;
|
||||
virtual void peerListConvertRowToSearchResult(not_null<PeerListRow *> row) = 0;
|
||||
virtual bool peerListIsRowSelected(not_null<PeerData *> peer) = 0;
|
||||
virtual void peerListSetRowChecked(not_null<PeerListRow *> row, bool checked) = 0;
|
||||
virtual not_null<PeerListRow *> peerListRowAt(int index) = 0;
|
||||
virtual void peerListRefreshRows() = 0;
|
||||
virtual void peerListScrollToTop() = 0;
|
||||
virtual int peerListFullRowsCount() = 0;
|
||||
|
@ -209,8 +202,7 @@ public:
|
|||
virtual void peerListSortRows(base::lambda<bool(PeerListRow &a, PeerListRow &b)> compare) = 0;
|
||||
virtual void peerListPartitionRows(base::lambda<bool(PeerListRow &a)> border) = 0;
|
||||
|
||||
template <typename PeerDataRange>
|
||||
void peerListAddSelectedRows(PeerDataRange &&range) {
|
||||
template <typename PeerDataRange> void peerListAddSelectedRows(PeerDataRange &&range) {
|
||||
for (auto peer : range) {
|
||||
peerListAddSelectedRowInBunch(peer);
|
||||
}
|
||||
|
@ -218,21 +210,19 @@ public:
|
|||
}
|
||||
|
||||
virtual int peerListSelectedRowsCount() = 0;
|
||||
virtual std::vector<not_null<PeerData*>> peerListCollectSelectedRows() = 0;
|
||||
virtual std::vector<not_null<PeerData *>> peerListCollectSelectedRows() = 0;
|
||||
virtual ~PeerListDelegate() = default;
|
||||
|
||||
private:
|
||||
virtual void peerListAddSelectedRowInBunch(not_null<PeerData*> peer) = 0;
|
||||
virtual void peerListAddSelectedRowInBunch(not_null<PeerData *> peer) = 0;
|
||||
virtual void peerListFinishSelectedRowsBunch() = 0;
|
||||
|
||||
};
|
||||
|
||||
class PeerListSearchDelegate {
|
||||
public:
|
||||
virtual void peerListSearchAddRow(not_null<PeerData*> peer) = 0;
|
||||
virtual void peerListSearchAddRow(not_null<PeerData *> peer) = 0;
|
||||
virtual void peerListSearchRefreshRows() = 0;
|
||||
virtual ~PeerListSearchDelegate() = default;
|
||||
|
||||
};
|
||||
|
||||
class PeerListSearchController {
|
||||
|
@ -242,18 +232,17 @@ public:
|
|||
virtual bool loadMoreRows() = 0;
|
||||
virtual ~PeerListSearchController() = default;
|
||||
|
||||
void setDelegate(not_null<PeerListSearchDelegate*> delegate) {
|
||||
void setDelegate(not_null<PeerListSearchDelegate *> delegate) {
|
||||
_delegate = delegate;
|
||||
}
|
||||
|
||||
protected:
|
||||
not_null<PeerListSearchDelegate*> delegate() const {
|
||||
not_null<PeerListSearchDelegate *> delegate() const {
|
||||
return _delegate;
|
||||
}
|
||||
|
||||
private:
|
||||
PeerListSearchDelegate *_delegate = nullptr;
|
||||
|
||||
};
|
||||
|
||||
class PeerListController : public PeerListSearchDelegate {
|
||||
|
@ -261,27 +250,24 @@ public:
|
|||
// Search works only with RowId == peer->id.
|
||||
PeerListController(std::unique_ptr<PeerListSearchController> searchController = nullptr);
|
||||
|
||||
void setDelegate(not_null<PeerListDelegate*> delegate) {
|
||||
void setDelegate(not_null<PeerListDelegate *> delegate) {
|
||||
_delegate = delegate;
|
||||
prepare();
|
||||
}
|
||||
|
||||
virtual void prepare() = 0;
|
||||
virtual void rowClicked(not_null<PeerListRow*> row) = 0;
|
||||
virtual void rowActionClicked(not_null<PeerListRow*> row) {
|
||||
}
|
||||
virtual void loadMoreRows() {
|
||||
}
|
||||
virtual void itemDeselectedHook(not_null<PeerData*> peer) {
|
||||
}
|
||||
virtual void rowClicked(not_null<PeerListRow *> row) = 0;
|
||||
virtual void rowActionClicked(not_null<PeerListRow *> row) {}
|
||||
virtual void loadMoreRows() {}
|
||||
virtual void itemDeselectedHook(not_null<PeerData *> peer) {}
|
||||
bool isSearchLoading() const {
|
||||
return _searchController ? _searchController->isLoading() : false;
|
||||
}
|
||||
virtual std::unique_ptr<PeerListRow> createSearchRow(not_null<PeerData*> peer) {
|
||||
virtual std::unique_ptr<PeerListRow> createSearchRow(not_null<PeerData *> peer) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool isRowSelected(not_null<PeerData*> peer) {
|
||||
bool isRowSelected(not_null<PeerData *> peer) {
|
||||
return delegate()->peerListIsRowSelected(peer);
|
||||
}
|
||||
|
||||
|
@ -291,13 +277,13 @@ public:
|
|||
bool hasComplexSearch() const;
|
||||
void search(const QString &query);
|
||||
|
||||
void peerListSearchAddRow(not_null<PeerData*> peer) override;
|
||||
void peerListSearchAddRow(not_null<PeerData *> peer) override;
|
||||
void peerListSearchRefreshRows() override;
|
||||
|
||||
virtual ~PeerListController() = default;
|
||||
|
||||
protected:
|
||||
not_null<PeerListDelegate*> delegate() const {
|
||||
not_null<PeerListDelegate *> delegate() const {
|
||||
return _delegate;
|
||||
}
|
||||
PeerListSearchController *searchController() const {
|
||||
|
@ -320,12 +306,12 @@ protected:
|
|||
private:
|
||||
PeerListDelegate *_delegate = nullptr;
|
||||
std::unique_ptr<PeerListSearchController> _searchController = nullptr;
|
||||
|
||||
};
|
||||
|
||||
class PeerListBox : public BoxContent, public PeerListDelegate {
|
||||
public:
|
||||
PeerListBox(QWidget*, std::unique_ptr<PeerListController> controller, base::lambda<void(not_null<PeerListBox*>)> init);
|
||||
PeerListBox(QWidget *, std::unique_ptr<PeerListController> controller,
|
||||
base::lambda<void(not_null<PeerListBox *>)> init);
|
||||
|
||||
void peerListSetTitle(base::lambda<QString()> title) override {
|
||||
setTitle(std::move(title));
|
||||
|
@ -340,17 +326,17 @@ public:
|
|||
void peerListSetSearchMode(PeerListSearchMode mode) override;
|
||||
void peerListAppendRow(std::unique_ptr<PeerListRow> row) override;
|
||||
void peerListAppendSearchRow(std::unique_ptr<PeerListRow> row) override;
|
||||
void peerListAppendFoundRow(not_null<PeerListRow*> row) override;
|
||||
void peerListAppendFoundRow(not_null<PeerListRow *> row) override;
|
||||
void peerListPrependRow(std::unique_ptr<PeerListRow> row) override;
|
||||
void peerListPrependRowFromSearchResult(not_null<PeerListRow*> row) override;
|
||||
void peerListUpdateRow(not_null<PeerListRow*> row) override;
|
||||
void peerListRemoveRow(not_null<PeerListRow*> row) override;
|
||||
void peerListConvertRowToSearchResult(not_null<PeerListRow*> row) override;
|
||||
void peerListSetRowChecked(not_null<PeerListRow*> row, bool checked) override;
|
||||
not_null<PeerListRow*> peerListRowAt(int index) override;
|
||||
bool peerListIsRowSelected(not_null<PeerData*> peer) override;
|
||||
void peerListPrependRowFromSearchResult(not_null<PeerListRow *> row) override;
|
||||
void peerListUpdateRow(not_null<PeerListRow *> row) override;
|
||||
void peerListRemoveRow(not_null<PeerListRow *> row) override;
|
||||
void peerListConvertRowToSearchResult(not_null<PeerListRow *> row) override;
|
||||
void peerListSetRowChecked(not_null<PeerListRow *> row, bool checked) override;
|
||||
not_null<PeerListRow *> peerListRowAt(int index) override;
|
||||
bool peerListIsRowSelected(not_null<PeerData *> peer) override;
|
||||
int peerListSelectedRowsCount() override;
|
||||
std::vector<not_null<PeerData*>> peerListCollectSelectedRows() override;
|
||||
std::vector<not_null<PeerData *>> peerListCollectSelectedRows() override;
|
||||
void peerListRefreshRows() override;
|
||||
void peerListScrollToTop() override;
|
||||
int peerListFullRowsCount() override;
|
||||
|
@ -367,26 +353,25 @@ protected:
|
|||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
private:
|
||||
void peerListAddSelectedRowInBunch(not_null<PeerData*> peer) override {
|
||||
void peerListAddSelectedRowInBunch(not_null<PeerData *> peer) override {
|
||||
addSelectItem(peer, PeerListRow::SetStyle::Fast);
|
||||
}
|
||||
void peerListFinishSelectedRowsBunch() override;
|
||||
|
||||
void addSelectItem(not_null<PeerData*> peer, PeerListRow::SetStyle style);
|
||||
void addSelectItem(not_null<PeerData *> peer, PeerListRow::SetStyle style);
|
||||
void createMultiSelect();
|
||||
int getTopScrollSkip() const;
|
||||
void updateScrollSkips();
|
||||
void searchQueryChanged(const QString &query);
|
||||
|
||||
object_ptr<Ui::WidgetSlideWrap<Ui::MultiSelect>> _select = { nullptr };
|
||||
object_ptr<Ui::WidgetSlideWrap<Ui::MultiSelect>> _select = {nullptr};
|
||||
|
||||
class Inner;
|
||||
QPointer<Inner> _inner;
|
||||
|
||||
std::unique_ptr<PeerListController> _controller;
|
||||
base::lambda<void(PeerListBox*)> _init;
|
||||
base::lambda<void(PeerListBox *)> _init;
|
||||
bool _scrollBottomFixed = true;
|
||||
|
||||
};
|
||||
|
||||
// This class is hold in header because it requires Qt preprocessing.
|
||||
|
@ -394,7 +379,7 @@ class PeerListBox::Inner : public TWidget, private base::Subscriber {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Inner(QWidget *parent, not_null<PeerListController*> controller);
|
||||
Inner(QWidget *parent, not_null<PeerListController *> controller);
|
||||
|
||||
void selectSkip(int direction);
|
||||
void selectSkipPage(int height, int direction);
|
||||
|
@ -409,17 +394,17 @@ public:
|
|||
// Interface for the controller.
|
||||
void appendRow(std::unique_ptr<PeerListRow> row);
|
||||
void appendSearchRow(std::unique_ptr<PeerListRow> row);
|
||||
void appendFoundRow(not_null<PeerListRow*> row);
|
||||
void appendFoundRow(not_null<PeerListRow *> row);
|
||||
void prependRow(std::unique_ptr<PeerListRow> row);
|
||||
void prependRowFromSearchResult(not_null<PeerListRow*> row);
|
||||
void prependRowFromSearchResult(not_null<PeerListRow *> row);
|
||||
PeerListRow *findRow(PeerListRowId id);
|
||||
void updateRow(not_null<PeerListRow*> row) {
|
||||
void updateRow(not_null<PeerListRow *> row) {
|
||||
updateRow(row, RowIndex());
|
||||
}
|
||||
void removeRow(not_null<PeerListRow*> row);
|
||||
void convertRowToSearchResult(not_null<PeerListRow*> row);
|
||||
void removeRow(not_null<PeerListRow *> row);
|
||||
void convertRowToSearchResult(not_null<PeerListRow *> row);
|
||||
int fullRowsCount() const;
|
||||
not_null<PeerListRow*> rowAt(int index) const;
|
||||
not_null<PeerListRow *> rowAt(int index) const;
|
||||
void setDescription(object_ptr<Ui::FlatLabel> description);
|
||||
void setSearchLoading(object_ptr<Ui::FlatLabel> loading);
|
||||
void setSearchNoResults(object_ptr<Ui::FlatLabel> noResults);
|
||||
|
@ -427,10 +412,9 @@ public:
|
|||
void refreshRows();
|
||||
|
||||
void setSearchMode(PeerListSearchMode mode);
|
||||
void changeCheckState(not_null<PeerListRow*> row, bool checked, PeerListRow::SetStyle style);
|
||||
void changeCheckState(not_null<PeerListRow *> row, bool checked, PeerListRow::SetStyle style);
|
||||
|
||||
template <typename ReorderCallback>
|
||||
void reorderRows(ReorderCallback &&callback) {
|
||||
template <typename ReorderCallback> void reorderRows(ReorderCallback &&callback) {
|
||||
callback(_rows.begin(), _rows.end());
|
||||
for (auto &searchEntity : _searchIndex) {
|
||||
callback(searchEntity.second.begin(), searchEntity.second.end());
|
||||
|
@ -461,10 +445,9 @@ private:
|
|||
void invalidatePixmapsCache();
|
||||
|
||||
struct RowIndex {
|
||||
RowIndex() {
|
||||
}
|
||||
explicit RowIndex(int value) : value(value) {
|
||||
}
|
||||
RowIndex() {}
|
||||
explicit RowIndex(int value)
|
||||
: value(value) {}
|
||||
int value = -1;
|
||||
};
|
||||
friend inline bool operator==(RowIndex a, RowIndex b) {
|
||||
|
@ -475,12 +458,13 @@ private:
|
|||
}
|
||||
|
||||
struct Selected {
|
||||
Selected() {
|
||||
}
|
||||
Selected(RowIndex index, bool action) : index(index), action(action) {
|
||||
}
|
||||
Selected(int index, bool action) : index(index), action(action) {
|
||||
}
|
||||
Selected() {}
|
||||
Selected(RowIndex index, bool action)
|
||||
: index(index)
|
||||
, action(action) {}
|
||||
Selected(int index, bool action)
|
||||
: index(index)
|
||||
, action(action) {}
|
||||
RowIndex index;
|
||||
bool action = false;
|
||||
};
|
||||
|
@ -499,19 +483,19 @@ private:
|
|||
void loadProfilePhotos();
|
||||
void checkScrollForPreload();
|
||||
|
||||
void updateRow(not_null<PeerListRow*> row, RowIndex hint);
|
||||
void updateRow(not_null<PeerListRow *> row, RowIndex hint);
|
||||
void updateRow(RowIndex row);
|
||||
int getRowTop(RowIndex row) const;
|
||||
PeerListRow *getRow(RowIndex element);
|
||||
RowIndex findRowIndex(not_null<PeerListRow*> row, RowIndex hint = RowIndex());
|
||||
QRect getActionRect(not_null<PeerListRow*> row, RowIndex index) const;
|
||||
RowIndex findRowIndex(not_null<PeerListRow *> row, RowIndex hint = RowIndex());
|
||||
QRect getActionRect(not_null<PeerListRow *> row, RowIndex index) const;
|
||||
|
||||
void paintRow(Painter &p, TimeMs ms, RowIndex index);
|
||||
|
||||
void addRowEntry(not_null<PeerListRow*> row);
|
||||
void addToSearchIndex(not_null<PeerListRow*> row);
|
||||
void addRowEntry(not_null<PeerListRow *> row);
|
||||
void addToSearchIndex(not_null<PeerListRow *> row);
|
||||
bool addingToSearchIndex() const;
|
||||
void removeFromSearchIndex(not_null<PeerListRow*> row);
|
||||
void removeFromSearchIndex(not_null<PeerListRow *> row);
|
||||
void setSearchQuery(const QString &query, const QString &normalizedQuery);
|
||||
bool showingSearch() const {
|
||||
return !_searchQuery.isEmpty();
|
||||
|
@ -519,17 +503,15 @@ private:
|
|||
int shownRowsCount() const {
|
||||
return showingSearch() ? _filterResults.size() : _rows.size();
|
||||
}
|
||||
template <typename Callback>
|
||||
bool enumerateShownRows(Callback callback);
|
||||
template <typename Callback>
|
||||
bool enumerateShownRows(int from, int to, Callback callback);
|
||||
template <typename Callback> bool enumerateShownRows(Callback callback);
|
||||
template <typename Callback> bool enumerateShownRows(int from, int to, Callback callback);
|
||||
|
||||
int rowsTop() const;
|
||||
int labelHeight() const;
|
||||
|
||||
void clearSearchRows();
|
||||
|
||||
not_null<PeerListController*> _controller;
|
||||
not_null<PeerListController *> _controller;
|
||||
PeerListSearchMode _searchMode = PeerListSearchMode::Disabled;
|
||||
|
||||
int _rowHeight = 0;
|
||||
|
@ -541,23 +523,22 @@ private:
|
|||
bool _mouseSelection = false;
|
||||
|
||||
std::vector<std::unique_ptr<PeerListRow>> _rows;
|
||||
std::map<PeerListRowId, not_null<PeerListRow*>> _rowsById;
|
||||
std::map<PeerData*, std::vector<not_null<PeerListRow*>>> _rowsByPeer;
|
||||
std::map<PeerListRowId, not_null<PeerListRow *>> _rowsById;
|
||||
std::map<PeerData *, std::vector<not_null<PeerListRow *>>> _rowsByPeer;
|
||||
|
||||
std::map<QChar, std::vector<not_null<PeerListRow*>>> _searchIndex;
|
||||
std::map<QChar, std::vector<not_null<PeerListRow *>>> _searchIndex;
|
||||
QString _searchQuery;
|
||||
QString _normalizedSearchQuery;
|
||||
QString _mentionHighlight;
|
||||
std::vector<not_null<PeerListRow*>> _filterResults;
|
||||
std::vector<not_null<PeerListRow *>> _filterResults;
|
||||
|
||||
int _aboveHeight = 0;
|
||||
object_ptr<TWidget> _aboveWidget = { nullptr };
|
||||
object_ptr<Ui::FlatLabel> _description = { nullptr };
|
||||
object_ptr<Ui::FlatLabel> _searchNoResults = { nullptr };
|
||||
object_ptr<Ui::FlatLabel> _searchLoading = { nullptr };
|
||||
object_ptr<TWidget> _aboveWidget = {nullptr};
|
||||
object_ptr<Ui::FlatLabel> _description = {nullptr};
|
||||
object_ptr<Ui::FlatLabel> _searchNoResults = {nullptr};
|
||||
object_ptr<Ui::FlatLabel> _searchLoading = {nullptr};
|
||||
|
||||
QPoint _lastMousePosition;
|
||||
|
||||
std::vector<std::unique_ptr<PeerListRow>> _searchRows;
|
||||
|
||||
};
|
||||
|
|
|
@ -18,32 +18,32 @@ to link the code of portions of this program with the OpenSSL library.
|
|||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "base/algorithm.h"
|
||||
#include "boxes/peer_list_controllers.h"
|
||||
#include "apiwrap.h"
|
||||
#include "auth_session.h"
|
||||
#include "base/algorithm.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "dialogs/dialogs_indexed_list.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwidget.h"
|
||||
#include "observer_peer.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_profile.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "observer_peer.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "auth_session.h"
|
||||
#include "apiwrap.h"
|
||||
#include "mainwidget.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "dialogs/dialogs_indexed_list.h"
|
||||
|
||||
namespace {
|
||||
|
||||
base::flat_set<not_null<UserData*>> GetAlreadyInFromPeer(PeerData *peer) {
|
||||
base::flat_set<not_null<UserData *>> GetAlreadyInFromPeer(PeerData *peer) {
|
||||
if (!peer) {
|
||||
return {};
|
||||
}
|
||||
if (auto chat = peer->asChat()) {
|
||||
auto participants = chat->participants.keys();
|
||||
return { participants.cbegin(), participants.cend() };
|
||||
return {participants.cbegin(), participants.cend()};
|
||||
} else if (auto channel = peer->asChannel()) {
|
||||
if (channel->isMegagroup()) {
|
||||
auto &participants = channel->mgInfo->lastParticipants;
|
||||
return { participants.cbegin(), participants.cend() };
|
||||
return {participants.cbegin(), participants.cend()};
|
||||
}
|
||||
}
|
||||
return {};
|
||||
|
@ -53,13 +53,13 @@ base::flat_set<not_null<UserData*>> GetAlreadyInFromPeer(PeerData *peer) {
|
|||
|
||||
// Not used for now.
|
||||
//
|
||||
//MembersAddButton::MembersAddButton(QWidget *parent, const style::TwoIconButton &st) : RippleButton(parent, st.ripple)
|
||||
// MembersAddButton::MembersAddButton(QWidget *parent, const style::TwoIconButton &st) : RippleButton(parent, st.ripple)
|
||||
//, _st(st) {
|
||||
// resize(_st.width, _st.height);
|
||||
// setCursor(style::cur_pointer);
|
||||
//}
|
||||
//
|
||||
//void MembersAddButton::paintEvent(QPaintEvent *e) {
|
||||
// void MembersAddButton::paintEvent(QPaintEvent *e) {
|
||||
// Painter p(this);
|
||||
//
|
||||
// auto ms = getms();
|
||||
|
@ -71,17 +71,18 @@ base::flat_set<not_null<UserData*>> GetAlreadyInFromPeer(PeerData *peer) {
|
|||
// ((over || down) ? _st.iconAboveOver : _st.iconAbove).paint(p, _st.iconPosition, width());
|
||||
//}
|
||||
//
|
||||
//QImage MembersAddButton::prepareRippleMask() const {
|
||||
// QImage MembersAddButton::prepareRippleMask() const {
|
||||
// return Ui::RippleAnimation::ellipseMask(QSize(_st.rippleAreaSize, _st.rippleAreaSize));
|
||||
//}
|
||||
//
|
||||
//QPoint MembersAddButton::prepareRippleStartPosition() const {
|
||||
// QPoint MembersAddButton::prepareRippleStartPosition() const {
|
||||
// return mapFromGlobal(QCursor::pos()) - _st.rippleAreaPosition;
|
||||
//}
|
||||
|
||||
class EditChatAdminsBoxController::LabeledCheckbox : public TWidget, private base::Subscriber {
|
||||
public:
|
||||
LabeledCheckbox(QWidget *parent, const QString &text, bool checked = false, const style::Checkbox &st = st::defaultCheckbox, const style::Check &checkSt = st::defaultCheck);
|
||||
LabeledCheckbox(QWidget *parent, const QString &text, bool checked = false,
|
||||
const style::Checkbox &st = st::defaultCheckbox, const style::Check &checkSt = st::defaultCheck);
|
||||
|
||||
base::Observable<bool> checkedChanged;
|
||||
|
||||
|
@ -89,12 +90,8 @@ public:
|
|||
return _checkbox->checked();
|
||||
}
|
||||
|
||||
void setLabelText(
|
||||
bool checked,
|
||||
const style::TextStyle &st,
|
||||
const QString &text,
|
||||
const TextParseOptions &options = _defaultOptions,
|
||||
int minResizeWidth = QFIXED_MAX);
|
||||
void setLabelText(bool checked, const style::TextStyle &st, const QString &text,
|
||||
const TextParseOptions &options = _defaultOptions, int minResizeWidth = QFIXED_MAX);
|
||||
|
||||
protected:
|
||||
int resizeGetHeight(int newWidth) override;
|
||||
|
@ -105,7 +102,6 @@ private:
|
|||
Text _labelUnchecked;
|
||||
Text _labelChecked;
|
||||
int _labelWidth = 0;
|
||||
|
||||
};
|
||||
|
||||
void PeerListRowWithLink::setActionLink(const QString &action) {
|
||||
|
@ -128,7 +124,10 @@ QSize PeerListRowWithLink::actionSize() const {
|
|||
}
|
||||
|
||||
QMargins PeerListRowWithLink::actionMargins() const {
|
||||
return QMargins(st::contactsCheckPosition.x(), (st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom() - st::normalFont->height) / 2, st::contactsCheckPosition.x(), 0);
|
||||
return QMargins(
|
||||
st::contactsCheckPosition.x(),
|
||||
(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom() - st::normalFont->height) / 2,
|
||||
st::contactsCheckPosition.x(), 0);
|
||||
}
|
||||
|
||||
void PeerListRowWithLink::paintAction(Painter &p, TimeMs ms, int x, int y, int outerWidth, bool actionSelected) {
|
||||
|
@ -164,14 +163,16 @@ bool PeerListGlobalSearchController::searchInCache() {
|
|||
}
|
||||
|
||||
void PeerListGlobalSearchController::searchOnServer() {
|
||||
_requestId = request(MTPcontacts_Search(MTP_string(_query), MTP_int(SearchPeopleLimit))).done([this](const MTPcontacts_Found &result, mtpRequestId requestId) {
|
||||
searchDone(result, requestId);
|
||||
}).fail([this](const RPCError &error, mtpRequestId requestId) {
|
||||
if (_requestId == requestId) {
|
||||
_requestId = 0;
|
||||
delegate()->peerListSearchRefreshRows();
|
||||
}
|
||||
}).send();
|
||||
_requestId =
|
||||
request(MTPcontacts_Search(MTP_string(_query), MTP_int(SearchPeopleLimit)))
|
||||
.done([this](const MTPcontacts_Found &result, mtpRequestId requestId) { searchDone(result, requestId); })
|
||||
.fail([this](const RPCError &error, mtpRequestId requestId) {
|
||||
if (_requestId == requestId) {
|
||||
_requestId = 0;
|
||||
delegate()->peerListSearchRefreshRows();
|
||||
}
|
||||
})
|
||||
.send();
|
||||
_queries.emplace(_requestId, _query);
|
||||
}
|
||||
|
||||
|
@ -205,8 +206,8 @@ bool PeerListGlobalSearchController::isLoading() {
|
|||
return _timer.isActive() || _requestId;
|
||||
}
|
||||
|
||||
ChatsListBoxController::ChatsListBoxController(std::unique_ptr<PeerListSearchController> searchController) : PeerListController(std::move(searchController)) {
|
||||
}
|
||||
ChatsListBoxController::ChatsListBoxController(std::unique_ptr<PeerListSearchController> searchController)
|
||||
: PeerListController(std::move(searchController)) {}
|
||||
|
||||
void ChatsListBoxController::prepare() {
|
||||
setSearchNoResultsText(lang(lng_blocked_list_not_found));
|
||||
|
@ -217,15 +218,9 @@ void ChatsListBoxController::prepare() {
|
|||
rebuildRows();
|
||||
|
||||
auto &sessionData = Auth().data();
|
||||
subscribe(sessionData.contactsLoaded(), [this](bool loaded) {
|
||||
rebuildRows();
|
||||
});
|
||||
subscribe(sessionData.moreChatsLoaded(), [this] {
|
||||
rebuildRows();
|
||||
});
|
||||
subscribe(sessionData.allChatsLoaded(), [this](bool loaded) {
|
||||
checkForEmptyRows();
|
||||
});
|
||||
subscribe(sessionData.contactsLoaded(), [this](bool loaded) { rebuildRows(); });
|
||||
subscribe(sessionData.moreChatsLoaded(), [this] { rebuildRows(); });
|
||||
subscribe(sessionData.allChatsLoaded(), [this](bool loaded) { checkForEmptyRows(); });
|
||||
}
|
||||
|
||||
void ChatsListBoxController::rebuildRows() {
|
||||
|
@ -244,7 +239,7 @@ void ChatsListBoxController::rebuildRows() {
|
|||
if (!wasEmpty && added > 0) {
|
||||
// Place dialogs list before contactsNoDialogs list.
|
||||
delegate()->peerListPartitionRows([](PeerListRow &a) {
|
||||
auto history = static_cast<Row&>(a).history();
|
||||
auto history = static_cast<Row &>(a).history();
|
||||
return history->inChatList(Dialogs::Mode::All);
|
||||
});
|
||||
}
|
||||
|
@ -266,13 +261,13 @@ QString ChatsListBoxController::emptyBoxText() const {
|
|||
return lang(lng_contacts_not_found);
|
||||
}
|
||||
|
||||
std::unique_ptr<PeerListRow> ChatsListBoxController::createSearchRow(not_null<PeerData*> peer) {
|
||||
std::unique_ptr<PeerListRow> ChatsListBoxController::createSearchRow(not_null<PeerData *> peer) {
|
||||
return createRow(App::history(peer));
|
||||
}
|
||||
|
||||
bool ChatsListBoxController::appendRow(not_null<History*> history) {
|
||||
bool ChatsListBoxController::appendRow(not_null<History *> history) {
|
||||
if (auto row = delegate()->peerListFindRow(history->peer->id)) {
|
||||
updateRowHook(static_cast<Row*>(row));
|
||||
updateRowHook(static_cast<Row *>(row));
|
||||
return false;
|
||||
}
|
||||
if (auto row = createRow(history)) {
|
||||
|
@ -282,8 +277,8 @@ bool ChatsListBoxController::appendRow(not_null<History*> history) {
|
|||
return false;
|
||||
}
|
||||
|
||||
ContactsBoxController::ContactsBoxController(std::unique_ptr<PeerListSearchController> searchController) : PeerListController(std::move(searchController)) {
|
||||
}
|
||||
ContactsBoxController::ContactsBoxController(std::unique_ptr<PeerListSearchController> searchController)
|
||||
: PeerListController(std::move(searchController)) {}
|
||||
|
||||
void ContactsBoxController::prepare() {
|
||||
setSearchNoResultsText(lang(lng_blocked_list_not_found));
|
||||
|
@ -295,9 +290,7 @@ void ContactsBoxController::prepare() {
|
|||
rebuildRows();
|
||||
|
||||
auto &sessionData = Auth().data();
|
||||
subscribe(sessionData.contactsLoaded(), [this](bool loaded) {
|
||||
rebuildRows();
|
||||
});
|
||||
subscribe(sessionData.contactsLoaded(), [this](bool loaded) { rebuildRows(); });
|
||||
}
|
||||
|
||||
void ContactsBoxController::rebuildRows() {
|
||||
|
@ -328,18 +321,18 @@ void ContactsBoxController::checkForEmptyRows() {
|
|||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<PeerListRow> ContactsBoxController::createSearchRow(not_null<PeerData*> peer) {
|
||||
std::unique_ptr<PeerListRow> ContactsBoxController::createSearchRow(not_null<PeerData *> peer) {
|
||||
if (auto user = peer->asUser()) {
|
||||
return createRow(user);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ContactsBoxController::rowClicked(not_null<PeerListRow*> row) {
|
||||
void ContactsBoxController::rowClicked(not_null<PeerListRow *> row) {
|
||||
Ui::showPeerHistory(row->peer(), ShowAtUnreadMsgId);
|
||||
}
|
||||
|
||||
bool ContactsBoxController::appendRow(not_null<UserData*> user) {
|
||||
bool ContactsBoxController::appendRow(not_null<UserData *> user) {
|
||||
if (auto row = delegate()->peerListFindRow(user->id)) {
|
||||
updateRowHook(row);
|
||||
return false;
|
||||
|
@ -351,25 +344,22 @@ bool ContactsBoxController::appendRow(not_null<UserData*> user) {
|
|||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<PeerListRow> ContactsBoxController::createRow(not_null<UserData*> user) {
|
||||
std::unique_ptr<PeerListRow> ContactsBoxController::createRow(not_null<UserData *> user) {
|
||||
return std::make_unique<PeerListRow>(user);
|
||||
}
|
||||
|
||||
AddParticipantsBoxController::AddParticipantsBoxController(PeerData *peer)
|
||||
: ContactsBoxController(std::make_unique<PeerListGlobalSearchController>())
|
||||
, _peer(peer)
|
||||
, _alreadyIn(GetAlreadyInFromPeer(peer)) {
|
||||
}
|
||||
: ContactsBoxController(std::make_unique<PeerListGlobalSearchController>())
|
||||
, _peer(peer)
|
||||
, _alreadyIn(GetAlreadyInFromPeer(peer)) {}
|
||||
|
||||
AddParticipantsBoxController::AddParticipantsBoxController(
|
||||
not_null<ChannelData*> channel,
|
||||
base::flat_set<not_null<UserData*>> &&alreadyIn)
|
||||
: ContactsBoxController(std::make_unique<PeerListGlobalSearchController>())
|
||||
, _peer(channel)
|
||||
, _alreadyIn(std::move(alreadyIn)) {
|
||||
}
|
||||
AddParticipantsBoxController::AddParticipantsBoxController(not_null<ChannelData *> channel,
|
||||
base::flat_set<not_null<UserData *>> &&alreadyIn)
|
||||
: ContactsBoxController(std::make_unique<PeerListGlobalSearchController>())
|
||||
, _peer(channel)
|
||||
, _alreadyIn(std::move(alreadyIn)) {}
|
||||
|
||||
void AddParticipantsBoxController::rowClicked(not_null<PeerListRow*> row) {
|
||||
void AddParticipantsBoxController::rowClicked(not_null<PeerListRow *> row) {
|
||||
auto count = fullCount();
|
||||
auto limit = (_peer && _peer->isMegagroup()) ? Global::MegagroupSizeMax() : Global::ChatSizeMax();
|
||||
if (count < limit || row->checked()) {
|
||||
|
@ -380,11 +370,12 @@ void AddParticipantsBoxController::rowClicked(not_null<PeerListRow*> row) {
|
|||
Ui::show(Box<MaxInviteBox>(_peer->asChannel()), KeepOtherLayers);
|
||||
}
|
||||
} else if (count >= Global::ChatSizeMax() && count < Global::MegagroupSizeMax()) {
|
||||
Ui::show(Box<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);
|
||||
}
|
||||
}
|
||||
|
||||
void AddParticipantsBoxController::itemDeselectedHook(not_null<PeerData*> peer) {
|
||||
void AddParticipantsBoxController::itemDeselectedHook(not_null<PeerData *> peer) {
|
||||
updateTitle();
|
||||
}
|
||||
|
||||
|
@ -404,15 +395,15 @@ int AddParticipantsBoxController::alreadyInCount() const {
|
|||
Unexpected("User in AddParticipantsBoxController::alreadyInCount");
|
||||
}
|
||||
|
||||
bool AddParticipantsBoxController::isAlreadyIn(not_null<UserData*> user) const {
|
||||
bool AddParticipantsBoxController::isAlreadyIn(not_null<UserData *> user) const {
|
||||
if (!_peer) {
|
||||
return false;
|
||||
}
|
||||
if (auto chat = _peer->asChat()) {
|
||||
return chat->participants.contains(user);
|
||||
} else if (auto channel = _peer->asChannel()) {
|
||||
return _alreadyIn.contains(user)
|
||||
|| (channel->isMegagroup() && channel->mgInfo->lastParticipants.contains(user));
|
||||
return _alreadyIn.contains(user) ||
|
||||
(channel->isMegagroup() && channel->mgInfo->lastParticipants.contains(user));
|
||||
}
|
||||
Unexpected("User in AddParticipantsBoxController::isAlreadyIn");
|
||||
}
|
||||
|
@ -421,7 +412,7 @@ int AddParticipantsBoxController::fullCount() const {
|
|||
return alreadyInCount() + delegate()->peerListSelectedRowsCount();
|
||||
}
|
||||
|
||||
std::unique_ptr<PeerListRow> AddParticipantsBoxController::createRow(not_null<UserData*> user) {
|
||||
std::unique_ptr<PeerListRow> AddParticipantsBoxController::createRow(not_null<UserData *> user) {
|
||||
if (user->isSelf()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -433,19 +424,19 @@ std::unique_ptr<PeerListRow> AddParticipantsBoxController::createRow(not_null<Us
|
|||
}
|
||||
|
||||
void AddParticipantsBoxController::updateTitle() {
|
||||
auto additional = (_peer && _peer->isChannel() && !_peer->isMegagroup())
|
||||
? QString() :
|
||||
QString("%1 / %2").arg(fullCount()).arg(Global::MegagroupSizeMax());
|
||||
auto additional = (_peer && _peer->isChannel() && !_peer->isMegagroup()) ?
|
||||
QString() :
|
||||
QString("%1 / %2").arg(fullCount()).arg(Global::MegagroupSizeMax());
|
||||
delegate()->peerListSetTitle(langFactory(lng_profile_add_participant));
|
||||
delegate()->peerListSetAdditionalTitle([additional] { return additional; });
|
||||
}
|
||||
|
||||
void AddParticipantsBoxController::Start(not_null<ChatData*> chat) {
|
||||
auto initBox = [chat](not_null<PeerListBox*> box) {
|
||||
void AddParticipantsBoxController::Start(not_null<ChatData *> chat) {
|
||||
auto initBox = [chat](not_null<PeerListBox *> box) {
|
||||
box->addButton(langFactory(lng_participant_invite), [box, chat] {
|
||||
auto rows = box->peerListCollectSelectedRows();
|
||||
if (!rows.empty()) {
|
||||
auto users = std::vector<not_null<UserData*>>();
|
||||
auto users = std::vector<not_null<UserData *>>();
|
||||
for (auto peer : rows) {
|
||||
auto user = peer->asUser();
|
||||
Assert(user != nullptr);
|
||||
|
@ -461,16 +452,14 @@ void AddParticipantsBoxController::Start(not_null<ChatData*> chat) {
|
|||
Ui::show(Box<PeerListBox>(std::make_unique<AddParticipantsBoxController>(chat), std::move(initBox)));
|
||||
}
|
||||
|
||||
void AddParticipantsBoxController::Start(
|
||||
not_null<ChannelData*> channel,
|
||||
base::flat_set<not_null<UserData*>> &&alreadyIn,
|
||||
bool justCreated) {
|
||||
auto initBox = [channel, justCreated](not_null<PeerListBox*> box) {
|
||||
void AddParticipantsBoxController::Start(not_null<ChannelData *> channel,
|
||||
base::flat_set<not_null<UserData *>> &&alreadyIn, bool justCreated) {
|
||||
auto initBox = [channel, justCreated](not_null<PeerListBox *> box) {
|
||||
auto subscription = std::make_shared<base::Subscription>();
|
||||
box->addButton(langFactory(lng_participant_invite), [box, channel, subscription] {
|
||||
auto rows = box->peerListCollectSelectedRows();
|
||||
if (!rows.empty()) {
|
||||
auto users = std::vector<not_null<UserData*>>();
|
||||
auto users = std::vector<not_null<UserData *>>();
|
||||
for (auto peer : rows) {
|
||||
auto user = peer->asUser();
|
||||
Assert(user != nullptr);
|
||||
|
@ -487,41 +476,33 @@ void AddParticipantsBoxController::Start(
|
|||
});
|
||||
box->addButton(langFactory(justCreated ? lng_create_group_skip : lng_cancel), [box] { box->closeBox(); });
|
||||
if (justCreated) {
|
||||
*subscription = box->boxClosing.add_subscription([channel] {
|
||||
Ui::showPeerHistory(channel, ShowAtTheEndMsgId);
|
||||
});
|
||||
*subscription =
|
||||
box->boxClosing.add_subscription([channel] { Ui::showPeerHistory(channel, ShowAtTheEndMsgId); });
|
||||
}
|
||||
};
|
||||
Ui::show(Box<PeerListBox>(std::make_unique<AddParticipantsBoxController>(channel, std::move(alreadyIn)), std::move(initBox)));
|
||||
Ui::show(Box<PeerListBox>(std::make_unique<AddParticipantsBoxController>(channel, std::move(alreadyIn)),
|
||||
std::move(initBox)));
|
||||
}
|
||||
|
||||
void AddParticipantsBoxController::Start(
|
||||
not_null<ChannelData*> channel,
|
||||
base::flat_set<not_null<UserData*>> &&alreadyIn) {
|
||||
void AddParticipantsBoxController::Start(not_null<ChannelData *> channel,
|
||||
base::flat_set<not_null<UserData *>> &&alreadyIn) {
|
||||
Start(channel, std::move(alreadyIn), false);
|
||||
}
|
||||
|
||||
void AddParticipantsBoxController::Start(not_null<ChannelData*> channel) {
|
||||
void AddParticipantsBoxController::Start(not_null<ChannelData *> channel) {
|
||||
Start(channel, {}, true);
|
||||
}
|
||||
|
||||
EditChatAdminsBoxController::LabeledCheckbox::LabeledCheckbox(
|
||||
QWidget *parent,
|
||||
const QString &text,
|
||||
bool checked,
|
||||
const style::Checkbox &st,
|
||||
const style::Check &checkSt)
|
||||
: TWidget(parent)
|
||||
, _checkbox(this, text, checked, st, checkSt) {
|
||||
EditChatAdminsBoxController::LabeledCheckbox::LabeledCheckbox(QWidget *parent, const QString &text, bool checked,
|
||||
const style::Checkbox &st, const style::Check &checkSt)
|
||||
: TWidget(parent)
|
||||
, _checkbox(this, text, checked, st, checkSt) {
|
||||
subscribe(_checkbox->checkedChanged, [this](bool value) { checkedChanged.notify(value, true); });
|
||||
}
|
||||
|
||||
void EditChatAdminsBoxController::LabeledCheckbox::setLabelText(
|
||||
bool checked,
|
||||
const style::TextStyle &st,
|
||||
const QString &text,
|
||||
const TextParseOptions &options,
|
||||
int minResizeWidth) {
|
||||
void EditChatAdminsBoxController::LabeledCheckbox::setLabelText(bool checked, const style::TextStyle &st,
|
||||
const QString &text, const TextParseOptions &options,
|
||||
int minResizeWidth) {
|
||||
auto &label = (checked ? _labelChecked : _labelUnchecked);
|
||||
label = Text(st, text, options, minResizeWidth);
|
||||
}
|
||||
|
@ -530,9 +511,7 @@ int EditChatAdminsBoxController::LabeledCheckbox::resizeGetHeight(int newWidth)
|
|||
_labelWidth = newWidth - st::contactsPadding.left() - st::contactsPadding.right();
|
||||
_checkbox->resizeToNaturalWidth(_labelWidth);
|
||||
_checkbox->moveToLeft(st::contactsPadding.left(), st::contactsAllAdminsTop);
|
||||
auto labelHeight = std::max(
|
||||
_labelChecked.countHeight(_labelWidth),
|
||||
_labelUnchecked.countHeight(_labelWidth));
|
||||
auto labelHeight = std::max(_labelChecked.countHeight(_labelWidth), _labelUnchecked.countHeight(_labelWidth));
|
||||
return st::contactsAboutTop + labelHeight + st::contactsAboutBottom;
|
||||
}
|
||||
|
||||
|
@ -544,17 +523,18 @@ void EditChatAdminsBoxController::LabeledCheckbox::paintEvent(QPaintEvent *e) {
|
|||
p.fillRect(infoRect, st::contactsAboutBg);
|
||||
auto dividerFillTop = rtlrect(0, infoRect.y(), width(), st::profileDividerTop.height(), width());
|
||||
st::profileDividerTop.fill(p, dividerFillTop);
|
||||
auto dividerFillBottom = rtlrect(0, infoRect.y() + infoRect.height() - st::profileDividerBottom.height(), width(), st::profileDividerBottom.height(), width());
|
||||
auto dividerFillBottom = rtlrect(0, infoRect.y() + infoRect.height() - st::profileDividerBottom.height(), width(),
|
||||
st::profileDividerBottom.height(), width());
|
||||
st::profileDividerBottom.fill(p, dividerFillBottom);
|
||||
|
||||
p.setPen(st::contactsAboutFg);
|
||||
(checked() ? _labelChecked : _labelUnchecked).draw(p, st::contactsPadding.left(), st::contactsAboutTop, _labelWidth);
|
||||
(checked() ? _labelChecked : _labelUnchecked)
|
||||
.draw(p, st::contactsPadding.left(), st::contactsAboutTop, _labelWidth);
|
||||
}
|
||||
|
||||
EditChatAdminsBoxController::EditChatAdminsBoxController(not_null<ChatData*> chat)
|
||||
: PeerListController()
|
||||
, _chat(chat) {
|
||||
}
|
||||
EditChatAdminsBoxController::EditChatAdminsBoxController(not_null<ChatData *> chat)
|
||||
: PeerListController()
|
||||
, _chat(chat) {}
|
||||
|
||||
bool EditChatAdminsBoxController::allAreAdmins() const {
|
||||
return _allAdmins->checked();
|
||||
|
@ -570,16 +550,16 @@ void EditChatAdminsBoxController::prepare() {
|
|||
rebuildRows();
|
||||
if (!delegate()->peerListFullRowsCount()) {
|
||||
Auth().api().requestFullPeer(_chat);
|
||||
_adminsUpdatedSubscription = subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(
|
||||
Notify::PeerUpdate::Flag::AdminsChanged, [this](
|
||||
const Notify::PeerUpdate &update) {
|
||||
if (update.peer == _chat) {
|
||||
rebuildRows();
|
||||
if (delegate()->peerListFullRowsCount()) {
|
||||
unsubscribe(_adminsUpdatedSubscription);
|
||||
}
|
||||
}
|
||||
}));
|
||||
_adminsUpdatedSubscription = subscribe(
|
||||
Notify::PeerUpdated(), Notify::PeerUpdatedHandler(Notify::PeerUpdate::Flag::AdminsChanged,
|
||||
[this](const Notify::PeerUpdate &update) {
|
||||
if (update.peer == _chat) {
|
||||
rebuildRows();
|
||||
if (delegate()->peerListFullRowsCount()) {
|
||||
unsubscribe(_adminsUpdatedSubscription);
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
subscribe(_allAdmins->checkedChanged, [this](bool checked) {
|
||||
|
@ -598,7 +578,8 @@ void EditChatAdminsBoxController::prepare() {
|
|||
|
||||
void EditChatAdminsBoxController::createAllAdminsCheckbox() {
|
||||
auto labelWidth = st::boxWideWidth - st::contactsPadding.left() - st::contactsPadding.right();
|
||||
auto checkbox = object_ptr<LabeledCheckbox>(nullptr, lang(lng_chat_all_members_admins), !_chat->adminsEnabled(), st::defaultBoxCheckbox);
|
||||
auto checkbox = object_ptr<LabeledCheckbox>(nullptr, lang(lng_chat_all_members_admins), !_chat->adminsEnabled(),
|
||||
st::defaultBoxCheckbox);
|
||||
checkbox->setLabelText(true, st::defaultTextStyle, lang(lng_chat_about_all_admins), _defaultOptions, labelWidth);
|
||||
checkbox->setLabelText(false, st::defaultTextStyle, lang(lng_chat_about_admins), _defaultOptions, labelWidth);
|
||||
_allAdmins = checkbox;
|
||||
|
@ -612,7 +593,7 @@ void EditChatAdminsBoxController::rebuildRows() {
|
|||
|
||||
auto allAdmins = allAreAdmins();
|
||||
|
||||
auto admins = std::vector<not_null<UserData*>>();
|
||||
auto admins = std::vector<not_null<UserData *>>();
|
||||
auto others = admins;
|
||||
admins.reserve(allAdmins ? _chat->participants.size() : _chat->admins.size());
|
||||
others.reserve(_chat->participants.size());
|
||||
|
@ -633,13 +614,11 @@ void EditChatAdminsBoxController::rebuildRows() {
|
|||
admins.insert(admins.end(), others.begin(), others.end());
|
||||
others.clear();
|
||||
}
|
||||
auto sortByName = [](auto a, auto b) {
|
||||
return (a->name.compare(b->name, Qt::CaseInsensitive) < 0);
|
||||
};
|
||||
auto sortByName = [](auto a, auto b) { return (a->name.compare(b->name, Qt::CaseInsensitive) < 0); };
|
||||
std::sort(admins.begin(), admins.end(), sortByName);
|
||||
std::sort(others.begin(), others.end(), sortByName);
|
||||
|
||||
auto addOne = [this](not_null<UserData*> user) {
|
||||
auto addOne = [this](not_null<UserData *> user) {
|
||||
if (auto row = createRow(user)) {
|
||||
delegate()->peerListAppendRow(std::move(row));
|
||||
}
|
||||
|
@ -655,7 +634,7 @@ void EditChatAdminsBoxController::rebuildRows() {
|
|||
delegate()->peerListRefreshRows();
|
||||
}
|
||||
|
||||
std::unique_ptr<PeerListRow> EditChatAdminsBoxController::createRow(not_null<UserData*> user) {
|
||||
std::unique_ptr<PeerListRow> EditChatAdminsBoxController::createRow(not_null<UserData *> user) {
|
||||
auto result = std::make_unique<PeerListRow>(user);
|
||||
if (allAreAdmins() || user->id == peerFromUser(_chat->creator)) {
|
||||
result->setDisabledState(PeerListRow::State::DisabledChecked);
|
||||
|
@ -663,23 +642,23 @@ std::unique_ptr<PeerListRow> EditChatAdminsBoxController::createRow(not_null<Use
|
|||
return result;
|
||||
}
|
||||
|
||||
void EditChatAdminsBoxController::rowClicked(not_null<PeerListRow*> row) {
|
||||
void EditChatAdminsBoxController::rowClicked(not_null<PeerListRow *> row) {
|
||||
delegate()->peerListSetRowChecked(row, !row->checked());
|
||||
}
|
||||
|
||||
void EditChatAdminsBoxController::Start(not_null<ChatData*> chat) {
|
||||
void EditChatAdminsBoxController::Start(not_null<ChatData *> chat) {
|
||||
auto controller = std::make_unique<EditChatAdminsBoxController>(chat);
|
||||
auto initBox = [chat, controller = controller.get()](not_null<PeerListBox*> box) {
|
||||
auto initBox = [chat, controller = controller.get()](not_null<PeerListBox *> box) {
|
||||
box->addButton(langFactory(lng_settings_save), [box, chat, controller] {
|
||||
auto rows = box->peerListCollectSelectedRows();
|
||||
auto users = std::vector<not_null<UserData*>>();
|
||||
auto users = std::vector<not_null<UserData *>>();
|
||||
for (auto peer : rows) {
|
||||
auto user = peer->asUser();
|
||||
Assert(user != nullptr);
|
||||
Assert(!user->isSelf());
|
||||
users.push_back(peer->asUser());
|
||||
}
|
||||
Auth().api().editChatAdmins(chat, !controller->allAreAdmins(), { users.cbegin(), users.cend() });
|
||||
Auth().api().editChatAdmins(chat, !controller->allAreAdmins(), {users.cbegin(), users.cend()});
|
||||
box->closeBox();
|
||||
});
|
||||
box->addButton(langFactory(lng_cancel), [box] { box->closeBox(); });
|
||||
|
@ -687,21 +666,18 @@ void EditChatAdminsBoxController::Start(not_null<ChatData*> chat) {
|
|||
Ui::show(Box<PeerListBox>(std::move(controller), std::move(initBox)));
|
||||
}
|
||||
|
||||
void AddBotToGroupBoxController::Start(not_null<UserData*> bot) {
|
||||
auto initBox = [bot](not_null<PeerListBox*> box) {
|
||||
void AddBotToGroupBoxController::Start(not_null<UserData *> bot) {
|
||||
auto initBox = [bot](not_null<PeerListBox *> box) {
|
||||
box->addButton(langFactory(lng_cancel), [box] { box->closeBox(); });
|
||||
};
|
||||
Ui::show(Box<PeerListBox>(std::make_unique<AddBotToGroupBoxController>(bot), std::move(initBox)));
|
||||
}
|
||||
|
||||
AddBotToGroupBoxController::AddBotToGroupBoxController(not_null<UserData*> bot)
|
||||
: ChatsListBoxController(SharingBotGame(bot)
|
||||
? std::make_unique<PeerListGlobalSearchController>()
|
||||
: nullptr)
|
||||
, _bot(bot) {
|
||||
}
|
||||
AddBotToGroupBoxController::AddBotToGroupBoxController(not_null<UserData *> bot)
|
||||
: ChatsListBoxController(SharingBotGame(bot) ? std::make_unique<PeerListGlobalSearchController>() : nullptr)
|
||||
, _bot(bot) {}
|
||||
|
||||
void AddBotToGroupBoxController::rowClicked(not_null<PeerListRow*> row) {
|
||||
void AddBotToGroupBoxController::rowClicked(not_null<PeerListRow *> row) {
|
||||
if (sharingBotGame()) {
|
||||
shareBotGame(row->peer());
|
||||
} else {
|
||||
|
@ -709,7 +685,7 @@ void AddBotToGroupBoxController::rowClicked(not_null<PeerListRow*> row) {
|
|||
}
|
||||
}
|
||||
|
||||
void AddBotToGroupBoxController::shareBotGame(not_null<PeerData*> chat) {
|
||||
void AddBotToGroupBoxController::shareBotGame(not_null<PeerData *> chat) {
|
||||
auto weak = base::make_weak_unique(this);
|
||||
auto send = [weak, bot = _bot, chat] {
|
||||
if (!weak) {
|
||||
|
@ -719,16 +695,9 @@ void AddBotToGroupBoxController::shareBotGame(not_null<PeerData*> chat) {
|
|||
auto afterRequestId = history ? history->sendRequestId : 0;
|
||||
auto randomId = rand_value<quint64>();
|
||||
auto gameShortName = bot->botInfo->shareGameShortName;
|
||||
auto inputGame = MTP_inputGameShortName(
|
||||
bot->inputUser,
|
||||
MTP_string(gameShortName));
|
||||
auto request = MTPmessages_SendMedia(
|
||||
MTP_flags(0),
|
||||
chat->input,
|
||||
MTP_int(0),
|
||||
MTP_inputMediaGame(inputGame),
|
||||
MTP_long(randomId),
|
||||
MTPnullMarkup);
|
||||
auto inputGame = MTP_inputGameShortName(bot->inputUser, MTP_string(gameShortName));
|
||||
auto request = MTPmessages_SendMedia(MTP_flags(0), chat->input, MTP_int(0), MTP_inputMediaGame(inputGame),
|
||||
MTP_long(randomId), MTPnullMarkup);
|
||||
auto done = App::main()->rpcDone(&MainWidget::sentUpdatesReceived);
|
||||
auto fail = App::main()->rpcFail(&MainWidget::sendMessageFail);
|
||||
auto requestId = MTP::send(request, done, fail, 0, 0, afterRequestId);
|
||||
|
@ -747,7 +716,7 @@ void AddBotToGroupBoxController::shareBotGame(not_null<PeerData*> chat) {
|
|||
Ui::show(Box<ConfirmBox>(confirmText(), send), KeepOtherLayers);
|
||||
}
|
||||
|
||||
void AddBotToGroupBoxController::addBotToGroup(not_null<PeerData*> chat) {
|
||||
void AddBotToGroupBoxController::addBotToGroup(not_null<PeerData *> chat) {
|
||||
if (auto megagroup = chat->asMegagroup()) {
|
||||
if (!megagroup->canAddMembers()) {
|
||||
Ui::show(Box<InformBox>(lang(lng_error_cant_add_member)), KeepOtherLayers);
|
||||
|
@ -761,26 +730,16 @@ void AddBotToGroupBoxController::addBotToGroup(not_null<PeerData*> chat) {
|
|||
}
|
||||
if (auto &info = bot->botInfo) {
|
||||
if (!info->startGroupToken.isEmpty()) {
|
||||
auto request = MTPmessages_StartBot(
|
||||
bot->inputUser,
|
||||
chat->input,
|
||||
MTP_long(rand_value<quint64>()),
|
||||
MTP_string(info->startGroupToken));
|
||||
auto done = App::main()->rpcDone(
|
||||
&MainWidget::sentUpdatesReceived);
|
||||
auto fail = App::main()->rpcFail(
|
||||
&MainWidget::addParticipantFail,
|
||||
{ bot, chat });
|
||||
auto request = MTPmessages_StartBot(bot->inputUser, chat->input, MTP_long(rand_value<quint64>()),
|
||||
MTP_string(info->startGroupToken));
|
||||
auto done = App::main()->rpcDone(&MainWidget::sentUpdatesReceived);
|
||||
auto fail = App::main()->rpcFail(&MainWidget::addParticipantFail, {bot, chat});
|
||||
MTP::send(request, done, fail);
|
||||
} else {
|
||||
App::main()->addParticipants(
|
||||
chat,
|
||||
{ 1, bot });
|
||||
App::main()->addParticipants(chat, {1, bot});
|
||||
}
|
||||
} else {
|
||||
App::main()->addParticipants(
|
||||
chat,
|
||||
{ 1, bot });
|
||||
App::main()->addParticipants(chat, {1, bot});
|
||||
}
|
||||
Ui::hideLayer();
|
||||
Ui::showPeerHistory(chat, ShowAtUnreadMsgId);
|
||||
|
@ -789,14 +748,14 @@ void AddBotToGroupBoxController::addBotToGroup(not_null<PeerData*> chat) {
|
|||
Ui::show(Box<ConfirmBox>(confirmText, send), KeepOtherLayers);
|
||||
}
|
||||
|
||||
std::unique_ptr<ChatsListBoxController::Row> AddBotToGroupBoxController::createRow(not_null<History*> history) {
|
||||
std::unique_ptr<ChatsListBoxController::Row> AddBotToGroupBoxController::createRow(not_null<History *> history) {
|
||||
if (!needToCreateRow(history->peer)) {
|
||||
return nullptr;
|
||||
}
|
||||
return std::make_unique<Row>(history);
|
||||
}
|
||||
|
||||
bool AddBotToGroupBoxController::needToCreateRow(not_null<PeerData*> peer) const {
|
||||
bool AddBotToGroupBoxController::needToCreateRow(not_null<PeerData *> peer) const {
|
||||
if (sharingBotGame()) {
|
||||
if (!peer->canWrite()) {
|
||||
return false;
|
||||
|
@ -818,7 +777,7 @@ bool AddBotToGroupBoxController::needToCreateRow(not_null<PeerData*> peer) const
|
|||
return false;
|
||||
}
|
||||
|
||||
bool AddBotToGroupBoxController::SharingBotGame(not_null<UserData*> bot) {
|
||||
bool AddBotToGroupBoxController::SharingBotGame(not_null<UserData *> bot) {
|
||||
auto &info = bot->botInfo;
|
||||
return (info && !info->shareGameShortName.isEmpty());
|
||||
}
|
||||
|
@ -828,15 +787,14 @@ bool AddBotToGroupBoxController::sharingBotGame() const {
|
|||
}
|
||||
|
||||
QString AddBotToGroupBoxController::emptyBoxText() const {
|
||||
return lang(Auth().data().allChatsLoaded().value()
|
||||
? (sharingBotGame() ? lng_bot_no_chats : lng_bot_no_groups)
|
||||
: lng_contacts_loading);
|
||||
return lang(Auth().data().allChatsLoaded().value() ? (sharingBotGame() ? lng_bot_no_chats : lng_bot_no_groups) :
|
||||
lng_contacts_loading);
|
||||
}
|
||||
|
||||
QString AddBotToGroupBoxController::noResultsText() const {
|
||||
return lang(Auth().data().allChatsLoaded().value()
|
||||
? (sharingBotGame() ? lng_bot_chats_not_found : lng_bot_groups_not_found)
|
||||
: lng_contacts_loading);
|
||||
return lang(Auth().data().allChatsLoaded().value() ?
|
||||
(sharingBotGame() ? lng_bot_chats_not_found : lng_bot_groups_not_found) :
|
||||
lng_contacts_loading);
|
||||
}
|
||||
|
||||
void AddBotToGroupBoxController::updateLabels() {
|
||||
|
@ -844,9 +802,7 @@ void AddBotToGroupBoxController::updateLabels() {
|
|||
}
|
||||
|
||||
void AddBotToGroupBoxController::prepareViewHook() {
|
||||
delegate()->peerListSetTitle(langFactory(sharingBotGame()
|
||||
? lng_bot_choose_chat
|
||||
: lng_bot_choose_group));
|
||||
delegate()->peerListSetTitle(langFactory(sharingBotGame() ? lng_bot_choose_chat : lng_bot_choose_group));
|
||||
updateLabels();
|
||||
subscribe(Auth().data().allChatsLoaded(), [this](bool) { updateLabels(); });
|
||||
}
|
||||
|
|
|
@ -20,24 +20,24 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "boxes/peer_list_box.h"
|
||||
#include "base/flat_set.h"
|
||||
#include "base/weak_unique_ptr.h"
|
||||
#include "boxes/peer_list_box.h"
|
||||
#include "history/history.h"
|
||||
|
||||
// Not used for now.
|
||||
//
|
||||
//class MembersAddButton : public Ui::RippleButton {
|
||||
//public:
|
||||
// class MembersAddButton : public Ui::RippleButton {
|
||||
// public:
|
||||
// MembersAddButton(QWidget *parent, const style::TwoIconButton &st);
|
||||
//
|
||||
//protected:
|
||||
// protected:
|
||||
// void paintEvent(QPaintEvent *e) override;
|
||||
//
|
||||
// QImage prepareRippleMask() const override;
|
||||
// QPoint prepareRippleStartPosition() const override;
|
||||
//
|
||||
//private:
|
||||
// private:
|
||||
// const style::TwoIconButton &_st;
|
||||
//
|
||||
//};
|
||||
|
@ -58,7 +58,6 @@ private:
|
|||
|
||||
QString _action;
|
||||
int _actionWidth = 0;
|
||||
|
||||
};
|
||||
|
||||
class PeerListGlobalSearchController : public PeerListSearchController, private MTP::Sender {
|
||||
|
@ -81,151 +80,138 @@ private:
|
|||
mtpRequestId _requestId = 0;
|
||||
std::map<QString, MTPcontacts_Found> _cache;
|
||||
std::map<mtpRequestId, QString> _queries;
|
||||
|
||||
};
|
||||
|
||||
class ChatsListBoxController : public PeerListController, protected base::Subscriber {
|
||||
public:
|
||||
ChatsListBoxController(std::unique_ptr<PeerListSearchController> searchController = std::make_unique<PeerListGlobalSearchController>());
|
||||
ChatsListBoxController(std::unique_ptr<PeerListSearchController> searchController =
|
||||
std::make_unique<PeerListGlobalSearchController>());
|
||||
|
||||
void prepare() override final;
|
||||
std::unique_ptr<PeerListRow> createSearchRow(not_null<PeerData*> peer) override final;
|
||||
std::unique_ptr<PeerListRow> createSearchRow(not_null<PeerData *> peer) override final;
|
||||
|
||||
protected:
|
||||
class Row : public PeerListRow {
|
||||
public:
|
||||
Row(not_null<History*> history) : PeerListRow(history->peer), _history(history) {
|
||||
}
|
||||
not_null<History*> history() const {
|
||||
Row(not_null<History *> history)
|
||||
: PeerListRow(history->peer)
|
||||
, _history(history) {}
|
||||
not_null<History *> history() const {
|
||||
return _history;
|
||||
}
|
||||
|
||||
private:
|
||||
not_null<History*> _history;
|
||||
|
||||
not_null<History *> _history;
|
||||
};
|
||||
virtual std::unique_ptr<Row> createRow(not_null<History*> history) = 0;
|
||||
virtual std::unique_ptr<Row> createRow(not_null<History *> history) = 0;
|
||||
virtual void prepareViewHook() = 0;
|
||||
virtual void updateRowHook(not_null<Row*> row) {
|
||||
}
|
||||
virtual void updateRowHook(not_null<Row *> row) {}
|
||||
virtual QString emptyBoxText() const;
|
||||
|
||||
private:
|
||||
void rebuildRows();
|
||||
void checkForEmptyRows();
|
||||
bool appendRow(not_null<History*> history);
|
||||
|
||||
bool appendRow(not_null<History *> history);
|
||||
};
|
||||
|
||||
class ContactsBoxController : public PeerListController, protected base::Subscriber {
|
||||
public:
|
||||
ContactsBoxController(std::unique_ptr<PeerListSearchController> searchController = std::make_unique<PeerListGlobalSearchController>());
|
||||
ContactsBoxController(std::unique_ptr<PeerListSearchController> searchController =
|
||||
std::make_unique<PeerListGlobalSearchController>());
|
||||
|
||||
void prepare() override final;
|
||||
std::unique_ptr<PeerListRow> createSearchRow(not_null<PeerData*> peer) override final;
|
||||
void rowClicked(not_null<PeerListRow*> row) override;
|
||||
std::unique_ptr<PeerListRow> createSearchRow(not_null<PeerData *> peer) override final;
|
||||
void rowClicked(not_null<PeerListRow *> row) override;
|
||||
|
||||
protected:
|
||||
virtual std::unique_ptr<PeerListRow> createRow(not_null<UserData*> user);
|
||||
virtual void prepareViewHook() {
|
||||
}
|
||||
virtual void updateRowHook(not_null<PeerListRow*> row) {
|
||||
}
|
||||
virtual std::unique_ptr<PeerListRow> createRow(not_null<UserData *> user);
|
||||
virtual void prepareViewHook() {}
|
||||
virtual void updateRowHook(not_null<PeerListRow *> row) {}
|
||||
|
||||
private:
|
||||
void rebuildRows();
|
||||
void checkForEmptyRows();
|
||||
bool appendRow(not_null<UserData*> user);
|
||||
|
||||
bool appendRow(not_null<UserData *> user);
|
||||
};
|
||||
|
||||
class EditChatAdminsBoxController : public PeerListController, private base::Subscriber {
|
||||
public:
|
||||
static void Start(not_null<ChatData*> chat);
|
||||
static void Start(not_null<ChatData *> chat);
|
||||
|
||||
EditChatAdminsBoxController(not_null<ChatData*> chat);
|
||||
EditChatAdminsBoxController(not_null<ChatData *> chat);
|
||||
|
||||
bool allAreAdmins() const;
|
||||
|
||||
void prepare() override;
|
||||
void rowClicked(not_null<PeerListRow*> row) override;
|
||||
void rowClicked(not_null<PeerListRow *> row) override;
|
||||
|
||||
private:
|
||||
void createAllAdminsCheckbox();
|
||||
void rebuildRows();
|
||||
std::unique_ptr<PeerListRow> createRow(not_null<UserData*> user);
|
||||
std::unique_ptr<PeerListRow> createRow(not_null<UserData *> user);
|
||||
|
||||
not_null<ChatData*> _chat;
|
||||
not_null<ChatData *> _chat;
|
||||
int _adminsUpdatedSubscription = 0;
|
||||
|
||||
class LabeledCheckbox;
|
||||
QPointer<LabeledCheckbox> _allAdmins;
|
||||
|
||||
};
|
||||
|
||||
class AddParticipantsBoxController : public ContactsBoxController {
|
||||
public:
|
||||
static void Start(not_null<ChatData*> chat);
|
||||
static void Start(not_null<ChannelData*> channel);
|
||||
static void Start(
|
||||
not_null<ChannelData*> channel,
|
||||
base::flat_set<not_null<UserData*>> &&alreadyIn);
|
||||
static void Start(not_null<ChatData *> chat);
|
||||
static void Start(not_null<ChannelData *> channel);
|
||||
static void Start(not_null<ChannelData *> channel, base::flat_set<not_null<UserData *>> &&alreadyIn);
|
||||
|
||||
AddParticipantsBoxController(PeerData *peer);
|
||||
AddParticipantsBoxController(
|
||||
not_null<ChannelData*> channel,
|
||||
base::flat_set<not_null<UserData*>> &&alreadyIn);
|
||||
AddParticipantsBoxController(not_null<ChannelData *> channel, base::flat_set<not_null<UserData *>> &&alreadyIn);
|
||||
|
||||
using ContactsBoxController::ContactsBoxController;
|
||||
|
||||
void rowClicked(not_null<PeerListRow*> row) override;
|
||||
void itemDeselectedHook(not_null<PeerData*> peer) override;
|
||||
void rowClicked(not_null<PeerListRow *> row) override;
|
||||
void itemDeselectedHook(not_null<PeerData *> peer) override;
|
||||
|
||||
protected:
|
||||
void prepareViewHook() override;
|
||||
std::unique_ptr<PeerListRow> createRow(not_null<UserData*> user) override;
|
||||
std::unique_ptr<PeerListRow> createRow(not_null<UserData *> user) override;
|
||||
|
||||
private:
|
||||
static void Start(
|
||||
not_null<ChannelData*> channel,
|
||||
base::flat_set<not_null<UserData*>> &&alreadyIn,
|
||||
bool justCreated);
|
||||
static void Start(not_null<ChannelData *> channel, base::flat_set<not_null<UserData *>> &&alreadyIn,
|
||||
bool justCreated);
|
||||
|
||||
int alreadyInCount() const;
|
||||
bool isAlreadyIn(not_null<UserData*> user) const;
|
||||
bool isAlreadyIn(not_null<UserData *> user) const;
|
||||
int fullCount() const;
|
||||
void updateTitle();
|
||||
|
||||
PeerData *_peer = nullptr;
|
||||
base::flat_set<not_null<UserData*>> _alreadyIn;
|
||||
|
||||
base::flat_set<not_null<UserData *>> _alreadyIn;
|
||||
};
|
||||
|
||||
class AddBotToGroupBoxController : public ChatsListBoxController, public base::enable_weak_from_this {
|
||||
public:
|
||||
static void Start(not_null<UserData*> bot);
|
||||
static void Start(not_null<UserData *> bot);
|
||||
|
||||
AddBotToGroupBoxController(not_null<UserData*> bot);
|
||||
AddBotToGroupBoxController(not_null<UserData *> bot);
|
||||
|
||||
void rowClicked(not_null<PeerListRow*> row) override;
|
||||
void rowClicked(not_null<PeerListRow *> row) override;
|
||||
|
||||
protected:
|
||||
std::unique_ptr<Row> createRow(not_null<History*> history) override;
|
||||
std::unique_ptr<Row> createRow(not_null<History *> history) override;
|
||||
void prepareViewHook() override;
|
||||
QString emptyBoxText() const override;
|
||||
|
||||
private:
|
||||
static bool SharingBotGame(not_null<UserData*> bot);
|
||||
static bool SharingBotGame(not_null<UserData *> bot);
|
||||
|
||||
bool needToCreateRow(not_null<PeerData*> peer) const;
|
||||
bool needToCreateRow(not_null<PeerData *> peer) const;
|
||||
bool sharingBotGame() const;
|
||||
QString noResultsText() const;
|
||||
QString descriptionText() const;
|
||||
void updateLabels();
|
||||
|
||||
void shareBotGame(not_null<PeerData*> chat);
|
||||
void addBotToGroup(not_null<PeerData*> chat);
|
||||
|
||||
not_null<UserData*> _bot;
|
||||
void shareBotGame(not_null<PeerData *> chat);
|
||||
void addBotToGroup(not_null<PeerData *> chat);
|
||||
|
||||
not_null<UserData *> _bot;
|
||||
};
|
||||
|
|
|
@ -21,21 +21,21 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
#include "boxes/photo_crop_box.h"
|
||||
|
||||
#include "lang/lang_keys.h"
|
||||
#include "messenger.h"
|
||||
#include "mainwidget.h"
|
||||
#include "messenger.h"
|
||||
#include "storage/file_upload.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
|
||||
PhotoCropBox::PhotoCropBox(QWidget*, const QImage &img, const PeerId &peer)
|
||||
: _img(img)
|
||||
, _peerId(peer) {
|
||||
PhotoCropBox::PhotoCropBox(QWidget *, const QImage &img, const PeerId &peer)
|
||||
: _img(img)
|
||||
, _peerId(peer) {
|
||||
init(img, nullptr);
|
||||
}
|
||||
|
||||
PhotoCropBox::PhotoCropBox(QWidget*, const QImage &img, PeerData *peer)
|
||||
: _img(img)
|
||||
, _peerId(peer->id) {
|
||||
PhotoCropBox::PhotoCropBox(QWidget *, const QImage &img, PeerData *peer)
|
||||
: _img(img)
|
||||
, _peerId(peer->id) {
|
||||
init(img, peer);
|
||||
}
|
||||
|
||||
|
@ -53,11 +53,12 @@ void PhotoCropBox::prepare() {
|
|||
addButton(langFactory(lng_settings_save), [this] { sendPhoto(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
if (peerToBareInt(_peerId)) {
|
||||
connect(this, SIGNAL(ready(const QImage&)), this, SLOT(onReady(const QImage&)));
|
||||
connect(this, SIGNAL(ready(const QImage &)), this, SLOT(onReady(const QImage &)));
|
||||
}
|
||||
|
||||
qint32 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());
|
||||
|
@ -77,7 +78,8 @@ void PhotoCropBox::prepare() {
|
|||
_thumby = st::boxPhotoPadding.top();
|
||||
setMouseTracking(true);
|
||||
|
||||
setDimensions(st::boxWideWidth, st::boxPhotoPadding.top() + _thumbh + st::boxPhotoPadding.bottom() + st::boxTextFont->height + st::cropSkip);
|
||||
setDimensions(st::boxWideWidth, st::boxPhotoPadding.top() + _thumbh + st::boxPhotoPadding.bottom() +
|
||||
st::boxTextFont->height + st::cropSkip);
|
||||
}
|
||||
|
||||
void PhotoCropBox::mousePressEvent(QMouseEvent *e) {
|
||||
|
@ -231,7 +233,9 @@ void PhotoCropBox::paintEvent(QPaintEvent *e) {
|
|||
|
||||
p.setFont(st::boxTextFont);
|
||||
p.setPen(st::boxPhotoTextFg);
|
||||
p.drawText(QRect(st::boxPhotoPadding.left(), st::boxPhotoPadding.top() + _thumbh + st::boxPhotoPadding.bottom(), width() - st::boxPhotoPadding.left() - st::boxPhotoPadding.right(), st::boxTextFont->height), _title, style::al_top);
|
||||
p.drawText(QRect(st::boxPhotoPadding.left(), st::boxPhotoPadding.top() + _thumbh + st::boxPhotoPadding.bottom(),
|
||||
width() - st::boxPhotoPadding.left() - st::boxPhotoPadding.right(), st::boxTextFont->height),
|
||||
_title, style::al_top);
|
||||
|
||||
p.translate(_thumbx, _thumby);
|
||||
p.drawPixmap(0, 0, _thumb);
|
||||
|
|
|
@ -26,8 +26,8 @@ class PhotoCropBox : public BoxContent {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PhotoCropBox(QWidget*, const QImage &img, const PeerId &peer);
|
||||
PhotoCropBox(QWidget*, const QImage &img, PeerData *peer);
|
||||
PhotoCropBox(QWidget *, const QImage &img, const PeerId &peer);
|
||||
PhotoCropBox(QWidget *, const QImage &img, PeerData *peer);
|
||||
|
||||
qint32 mouseState(QPoint p);
|
||||
|
||||
|
@ -59,5 +59,4 @@ private:
|
|||
QPixmap _thumb;
|
||||
QImage _mask, _fade;
|
||||
PeerId _peerId;
|
||||
|
||||
};
|
||||
|
|
|
@ -20,15 +20,15 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#include "boxes/rate_call_box.h"
|
||||
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_calls.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "mainwindow.h"
|
||||
#include "mainwidget.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -36,10 +36,9 @@ constexpr auto kMaxRating = 5;
|
|||
|
||||
} // namespace
|
||||
|
||||
RateCallBox::RateCallBox(QWidget*, quint64 callId, quint64 callAccessHash)
|
||||
: _callId(callId)
|
||||
, _callAccessHash(callAccessHash) {
|
||||
}
|
||||
RateCallBox::RateCallBox(QWidget *, quint64 callId, quint64 callAccessHash)
|
||||
: _callId(callId)
|
||||
, _callAccessHash(callAccessHash) {}
|
||||
|
||||
void RateCallBox::prepare() {
|
||||
setTitle(langFactory(lng_call_rate_label));
|
||||
|
@ -88,7 +87,8 @@ void RateCallBox::ratingChanged(int value) {
|
|||
_comment->show();
|
||||
_comment->setCtrlEnterSubmit(Ui::CtrlEnterSubmit::Both);
|
||||
_comment->setMaxLength(MaxPhotoCaption);
|
||||
_comment->resize(width() - (st::callRatingPadding.left() + st::callRatingPadding.right()), _comment->height());
|
||||
_comment->resize(width() - (st::callRatingPadding.left() + st::callRatingPadding.right()),
|
||||
_comment->height());
|
||||
|
||||
updateMaxHeight();
|
||||
connect(_comment, SIGNAL(resized()), this, SLOT(onCommentResized()));
|
||||
|
@ -121,14 +121,19 @@ void RateCallBox::onSend() {
|
|||
return;
|
||||
}
|
||||
auto comment = _comment ? _comment->getLastText().trimmed() : QString();
|
||||
_requestId = request(MTPphone_SetCallRating(MTP_inputPhoneCall(MTP_long(_callId), MTP_long(_callAccessHash)), MTP_int(_rating), MTP_string(comment))).done([this](const MTPUpdates &updates) {
|
||||
App::main()->sentUpdatesReceived(updates);
|
||||
closeBox();
|
||||
}).fail([this](const RPCError &error) { closeBox(); }).send();
|
||||
_requestId = request(MTPphone_SetCallRating(MTP_inputPhoneCall(MTP_long(_callId), MTP_long(_callAccessHash)),
|
||||
MTP_int(_rating), MTP_string(comment)))
|
||||
.done([this](const MTPUpdates &updates) {
|
||||
App::main()->sentUpdatesReceived(updates);
|
||||
closeBox();
|
||||
})
|
||||
.fail([this](const RPCError &error) { closeBox(); })
|
||||
.send();
|
||||
}
|
||||
|
||||
void RateCallBox::updateMaxHeight() {
|
||||
auto newHeight = st::callRatingPadding.top() + st::callRatingStarTop + _stars.back()->heightNoMargins() + st::callRatingPadding.bottom();
|
||||
auto newHeight = st::callRatingPadding.top() + st::callRatingStarTop + _stars.back()->heightNoMargins() +
|
||||
st::callRatingPadding.bottom();
|
||||
if (_comment) {
|
||||
newHeight += st::callRatingCommentTop + _comment->height();
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ class RateCallBox : public BoxContent, private MTP::Sender {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
RateCallBox(QWidget*, quint64 callId, quint64 callAccessHash);
|
||||
RateCallBox(QWidget *, quint64 callId, quint64 callAccessHash);
|
||||
|
||||
private slots:
|
||||
void onSend();
|
||||
|
@ -57,8 +57,7 @@ private:
|
|||
int _rating = 0;
|
||||
|
||||
std::vector<object_ptr<Ui::IconButton>> _stars;
|
||||
object_ptr<Ui::InputArea> _comment = { nullptr };
|
||||
object_ptr<Ui::InputArea> _comment = {nullptr};
|
||||
|
||||
mtpRequestId _requestId = 0;
|
||||
|
||||
};
|
||||
|
|
|
@ -20,26 +20,28 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#include "boxes/report_box.h"
|
||||
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "facades.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwindow.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_profile.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "mainwindow.h"
|
||||
#include "facades.h"
|
||||
|
||||
ReportBox::ReportBox(QWidget*, PeerData *peer) : _peer(peer)
|
||||
, _reasonGroup(std::make_shared<Ui::RadioenumGroup<Reason>>(Reason::Spam))
|
||||
, _reasonSpam(this, _reasonGroup, Reason::Spam, lang(lng_report_reason_spam), st::defaultBoxCheckbox)
|
||||
, _reasonViolence(this, _reasonGroup, Reason::Violence, lang(lng_report_reason_violence), st::defaultBoxCheckbox)
|
||||
, _reasonPornography(this, _reasonGroup, Reason::Pornography, lang(lng_report_reason_pornography), st::defaultBoxCheckbox)
|
||||
, _reasonOther(this, _reasonGroup, Reason::Other, lang(lng_report_reason_other), st::defaultBoxCheckbox) {
|
||||
}
|
||||
ReportBox::ReportBox(QWidget *, PeerData *peer)
|
||||
: _peer(peer)
|
||||
, _reasonGroup(std::make_shared<Ui::RadioenumGroup<Reason>>(Reason::Spam))
|
||||
, _reasonSpam(this, _reasonGroup, Reason::Spam, lang(lng_report_reason_spam), st::defaultBoxCheckbox)
|
||||
, _reasonViolence(this, _reasonGroup, Reason::Violence, lang(lng_report_reason_violence), st::defaultBoxCheckbox)
|
||||
, _reasonPornography(this, _reasonGroup, Reason::Pornography, lang(lng_report_reason_pornography),
|
||||
st::defaultBoxCheckbox)
|
||||
, _reasonOther(this, _reasonGroup, Reason::Other, lang(lng_report_reason_other), st::defaultBoxCheckbox) {}
|
||||
|
||||
void ReportBox::prepare() {
|
||||
setTitle(langFactory(_peer->isUser() ? lng_report_bot_title : (_peer->isMegagroup() ? lng_report_group_title : lng_report_title)));
|
||||
setTitle(langFactory(_peer->isUser() ? lng_report_bot_title :
|
||||
(_peer->isMegagroup() ? lng_report_group_title : lng_report_title)));
|
||||
|
||||
addButton(langFactory(lng_report_button), [this] { onReport(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
@ -52,13 +54,19 @@ void ReportBox::prepare() {
|
|||
void ReportBox::resizeEvent(QResizeEvent *e) {
|
||||
BoxContent::resizeEvent(e);
|
||||
|
||||
_reasonSpam->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), st::boxOptionListPadding.top() + _reasonSpam->getMargins().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);
|
||||
_reasonSpam->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(),
|
||||
st::boxOptionListPadding.top() + _reasonSpam->getMargins().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());
|
||||
_reasonOtherText->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left() -
|
||||
st::defaultInputField.textMargins.left(),
|
||||
_reasonOther->bottomNoMargins() + st::newGroupDescriptionPadding.top());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,7 +77,9 @@ void ReportBox::reasonChanged(Reason reason) {
|
|||
_reasonOtherText->show();
|
||||
_reasonOtherText->setCtrlEnterSubmit(Ui::CtrlEnterSubmit::Both);
|
||||
_reasonOtherText->setMaxLength(MaxPhotoCaption);
|
||||
_reasonOtherText->resize(width() - (st::boxPadding.left() + st::boxOptionListPadding.left() + st::boxPadding.right()), _reasonOtherText->height());
|
||||
_reasonOtherText->resize(
|
||||
width() - (st::boxPadding.left() + st::boxOptionListPadding.left() + st::boxPadding.right()),
|
||||
_reasonOtherText->height());
|
||||
|
||||
updateMaxHeight();
|
||||
connect(_reasonOtherText, SIGNAL(resized()), this, SLOT(onReasonResized()));
|
||||
|
@ -113,7 +123,8 @@ void ReportBox::onReport() {
|
|||
}
|
||||
Unexpected("Bad reason group value.");
|
||||
};
|
||||
_requestId = MTP::send(MTPaccount_ReportPeer(_peer->input, getReason()), rpcDone(&ReportBox::reportDone), rpcFail(&ReportBox::reportFail));
|
||||
_requestId = MTP::send(MTPaccount_ReportPeer(_peer->input, getReason()), rpcDone(&ReportBox::reportDone),
|
||||
rpcFail(&ReportBox::reportFail));
|
||||
}
|
||||
|
||||
void ReportBox::reportDone(const MTPBool &result) {
|
||||
|
@ -132,9 +143,12 @@ bool ReportBox::reportFail(const RPCError &error) {
|
|||
}
|
||||
|
||||
void ReportBox::updateMaxHeight() {
|
||||
auto newHeight = st::boxOptionListPadding.top() + _reasonSpam->getMargins().top() + 4 * _reasonSpam->heightNoMargins() + 3 * st::boxOptionListSkip + _reasonSpam->getMargins().bottom() + st::boxOptionListPadding.bottom();
|
||||
auto newHeight = st::boxOptionListPadding.top() + _reasonSpam->getMargins().top() +
|
||||
4 * _reasonSpam->heightNoMargins() + 3 * st::boxOptionListSkip +
|
||||
_reasonSpam->getMargins().bottom() + st::boxOptionListPadding.bottom();
|
||||
if (_reasonOtherText) {
|
||||
newHeight += st::newGroupDescriptionPadding.top() + _reasonOtherText->height() + st::newGroupDescriptionPadding.bottom();
|
||||
newHeight +=
|
||||
st::newGroupDescriptionPadding.top() + _reasonOtherText->height() + st::newGroupDescriptionPadding.bottom();
|
||||
}
|
||||
setDimensions(st::boxWidth, newHeight);
|
||||
}
|
||||
|
|
|
@ -23,10 +23,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
#include "boxes/abstract_box.h"
|
||||
|
||||
namespace Ui {
|
||||
template <typename Enum>
|
||||
class RadioenumGroup;
|
||||
template <typename Enum>
|
||||
class Radioenum;
|
||||
template <typename Enum> class RadioenumGroup;
|
||||
template <typename Enum> class Radioenum;
|
||||
class InputArea;
|
||||
} // namespace Ui
|
||||
|
||||
|
@ -34,7 +32,7 @@ class ReportBox : public BoxContent, public RPCSender {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ReportBox(QWidget*, PeerData *peer);
|
||||
ReportBox(QWidget *, PeerData *peer);
|
||||
|
||||
private slots:
|
||||
void onReport();
|
||||
|
@ -69,8 +67,7 @@ private:
|
|||
object_ptr<Ui::Radioenum<Reason>> _reasonViolence;
|
||||
object_ptr<Ui::Radioenum<Reason>> _reasonPornography;
|
||||
object_ptr<Ui::Radioenum<Reason>> _reasonOther;
|
||||
object_ptr<Ui::InputArea> _reasonOtherText = { nullptr };
|
||||
object_ptr<Ui::InputArea> _reasonOtherText = {nullptr};
|
||||
|
||||
mtpRequestId _requestId = 0;
|
||||
|
||||
};
|
||||
|
|
|
@ -21,61 +21,68 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
#include "boxes/self_destruction_box.h"
|
||||
|
||||
#include "lang/lang_keys.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "styles/style_boxes.h"
|
||||
|
||||
void SelfDestructionBox::prepare() {
|
||||
setTitle(langFactory(lng_self_destruct_title));
|
||||
|
||||
_ttlValues = { 30, 90, 180, 365 };
|
||||
_ttlValues = {30, 90, 180, 365};
|
||||
|
||||
auto fake = object_ptr<Ui::FlatLabel>(this, lang(lng_self_destruct_description), Ui::FlatLabel::InitType::Simple, st::boxLabel);
|
||||
auto boxHeight = st::boxOptionListPadding.top()
|
||||
+ fake->height() + st::boxMediumSkip
|
||||
+ _ttlValues.size() * (st::defaultRadio.diameter + st::boxOptionListSkip) - st::boxOptionListSkip
|
||||
+ st::boxOptionListPadding.bottom() + st::boxPadding.bottom();
|
||||
auto fake = object_ptr<Ui::FlatLabel>(this, lang(lng_self_destruct_description), Ui::FlatLabel::InitType::Simple,
|
||||
st::boxLabel);
|
||||
auto boxHeight = st::boxOptionListPadding.top() + fake->height() + st::boxMediumSkip +
|
||||
_ttlValues.size() * (st::defaultRadio.diameter + st::boxOptionListSkip) - st::boxOptionListSkip +
|
||||
st::boxOptionListPadding.bottom() + st::boxPadding.bottom();
|
||||
fake.destroy();
|
||||
|
||||
setDimensions(st::boxWidth, boxHeight);
|
||||
|
||||
auto loading = object_ptr<Ui::FlatLabel>(this, lang(lng_contacts_loading), Ui::FlatLabel::InitType::Simple, st::membersAbout);
|
||||
auto loading =
|
||||
object_ptr<Ui::FlatLabel>(this, lang(lng_contacts_loading), Ui::FlatLabel::InitType::Simple, st::membersAbout);
|
||||
loading->moveToLeft((st::boxWidth - loading->width()) / 2, boxHeight / 3);
|
||||
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
request(MTPaccount_GetAccountTTL()).done([this, loading = std::move(loading)](const MTPAccountDaysTTL &result) mutable {
|
||||
Expects(result.type() == mtpc_accountDaysTTL);
|
||||
Expects(!_ttlValues.empty());
|
||||
request(MTPaccount_GetAccountTTL())
|
||||
.done([this, loading = std::move(loading)](const MTPAccountDaysTTL &result) mutable {
|
||||
Expects(result.type() == mtpc_accountDaysTTL);
|
||||
Expects(!_ttlValues.empty());
|
||||
|
||||
loading.destroy();
|
||||
auto y = st::boxOptionListPadding.top();
|
||||
_description.create(this, lang(lng_self_destruct_description), Ui::FlatLabel::InitType::Simple, st::boxLabel);
|
||||
_description->moveToLeft(st::boxPadding.left(), y);
|
||||
y += _description->height() + st::boxMediumSkip;
|
||||
loading.destroy();
|
||||
auto y = st::boxOptionListPadding.top();
|
||||
_description.create(this, lang(lng_self_destruct_description), Ui::FlatLabel::InitType::Simple,
|
||||
st::boxLabel);
|
||||
_description->moveToLeft(st::boxPadding.left(), y);
|
||||
y += _description->height() + st::boxMediumSkip;
|
||||
|
||||
auto current = result.c_accountDaysTTL().vdays.v;
|
||||
auto currentAdjusted = _ttlValues[0];
|
||||
for (auto days : _ttlValues) {
|
||||
if (qAbs(current - days) < qAbs(current - currentAdjusted)) {
|
||||
currentAdjusted = days;
|
||||
}
|
||||
}
|
||||
auto group = std::make_shared<Ui::RadiobuttonGroup>(currentAdjusted);
|
||||
auto count = int(_ttlValues.size());
|
||||
_options.reserve(count);
|
||||
for (auto days : _ttlValues) {
|
||||
_options.emplace_back(this, group, days, (days > 364) ? lng_self_destruct_years(lt_count, days / 365) : lng_self_destruct_months(lt_count, std::max(days / 30, 1)), st::langsButton);
|
||||
_options.back()->moveToLeft(st::boxPadding.left(), y);
|
||||
y += _options.back()->heightNoMargins() + st::boxOptionListSkip;
|
||||
}
|
||||
showChildren();
|
||||
auto current = result.c_accountDaysTTL().vdays.v;
|
||||
auto currentAdjusted = _ttlValues[0];
|
||||
for (auto days : _ttlValues) {
|
||||
if (qAbs(current - days) < qAbs(current - currentAdjusted)) {
|
||||
currentAdjusted = days;
|
||||
}
|
||||
}
|
||||
auto group = std::make_shared<Ui::RadiobuttonGroup>(currentAdjusted);
|
||||
auto count = int(_ttlValues.size());
|
||||
_options.reserve(count);
|
||||
for (auto days : _ttlValues) {
|
||||
_options.emplace_back(this, group, days,
|
||||
(days > 364) ? lng_self_destruct_years(lt_count, days / 365) :
|
||||
lng_self_destruct_months(lt_count, std::max(days / 30, 1)),
|
||||
st::langsButton);
|
||||
_options.back()->moveToLeft(st::boxPadding.left(), y);
|
||||
y += _options.back()->heightNoMargins() + st::boxOptionListSkip;
|
||||
}
|
||||
showChildren();
|
||||
|
||||
clearButtons();
|
||||
addButton(langFactory(lng_settings_save), [this, group] {
|
||||
MTP::send(MTPaccount_SetAccountTTL(MTP_accountDaysTTL(MTP_int(group->value()))));
|
||||
closeBox();
|
||||
});
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
}).send();
|
||||
clearButtons();
|
||||
addButton(langFactory(lng_settings_save), [this, group] {
|
||||
MTP::send(MTPaccount_SetAccountTTL(MTP_accountDaysTTL(MTP_int(group->value()))));
|
||||
closeBox();
|
||||
});
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
})
|
||||
.send();
|
||||
}
|
||||
|
|
|
@ -33,16 +33,14 @@ class SelfDestructionBox : public BoxContent, private MTP::Sender {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SelfDestructionBox(QWidget*) {
|
||||
}
|
||||
SelfDestructionBox(QWidget*) {}
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
||||
private:
|
||||
std::vector<int> _ttlValues;
|
||||
object_ptr<Ui::FlatLabel> _description = { nullptr };
|
||||
object_ptr<Ui::FlatLabel> _description = {nullptr};
|
||||
std::shared_ptr<Ui::RadiobuttonGroup> _ttlGroup;
|
||||
std::vector<object_ptr<Ui::Radiobutton>> _options;
|
||||
|
||||
};
|
||||
|
|
|
@ -20,17 +20,17 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#include "boxes/send_files_box.h"
|
||||
|
||||
#include "lang/lang_keys.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "mainwidget.h"
|
||||
#include "history/history_media_types.h"
|
||||
#include "core/file_utilities.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "styles/style_history.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "history/history_media_types.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwidget.h"
|
||||
#include "media/media_clip_reader.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_history.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "window/window_controller.h"
|
||||
|
||||
namespace {
|
||||
|
@ -43,18 +43,18 @@ bool ValidatePhotoDimensions(int width, int height) {
|
|||
|
||||
} // namespace
|
||||
|
||||
SendFilesBox::SendFilesBox(QWidget*, QImage image, CompressConfirm compressed)
|
||||
: _image(image)
|
||||
, _compressConfirm(compressed)
|
||||
, _caption(this, st::confirmCaptionArea, langFactory(lng_photo_caption)) {
|
||||
SendFilesBox::SendFilesBox(QWidget *, QImage image, CompressConfirm compressed)
|
||||
: _image(image)
|
||||
, _compressConfirm(compressed)
|
||||
, _caption(this, st::confirmCaptionArea, langFactory(lng_photo_caption)) {
|
||||
_files.push_back(QString());
|
||||
prepareSingleFileLayout();
|
||||
}
|
||||
|
||||
SendFilesBox::SendFilesBox(QWidget*, const QStringList &files, CompressConfirm compressed)
|
||||
: _files(files)
|
||||
, _compressConfirm(compressed)
|
||||
, _caption(this, st::confirmCaptionArea, langFactory(_files.size() > 1 ? lng_photos_comment : lng_photo_caption)) {
|
||||
SendFilesBox::SendFilesBox(QWidget *, const QStringList &files, CompressConfirm compressed)
|
||||
: _files(files)
|
||||
, _compressConfirm(compressed)
|
||||
, _caption(this, st::confirmCaptionArea, langFactory(_files.size() > 1 ? lng_photos_comment : lng_photo_caption)) {
|
||||
if (_files.size() == 1) {
|
||||
prepareSingleFileLayout();
|
||||
}
|
||||
|
@ -79,8 +79,11 @@ void SendFilesBox::prepareSingleFileLayout() {
|
|||
if (originalWidth > originalHeight) {
|
||||
thumbWidth = (originalWidth * st::msgFileThumbSize) / originalHeight;
|
||||
}
|
||||
auto options = Images::Option::Smooth | Images::Option::RoundedSmall | Images::Option::RoundedTopLeft | Images::Option::RoundedTopRight | Images::Option::RoundedBottomLeft | Images::Option::RoundedBottomRight;
|
||||
_fileThumb = Images::pixmap(image, thumbWidth * cIntRetinaFactor(), 0, options, st::msgFileThumbSize, st::msgFileThumbSize);
|
||||
auto options = Images::Option::Smooth | Images::Option::RoundedSmall | Images::Option::RoundedTopLeft |
|
||||
Images::Option::RoundedTopRight | Images::Option::RoundedBottomLeft |
|
||||
Images::Option::RoundedBottomRight;
|
||||
_fileThumb = Images::pixmap(image, thumbWidth * cIntRetinaFactor(), 0, options, st::msgFileThumbSize,
|
||||
st::msgFileThumbSize);
|
||||
} else {
|
||||
auto maxW = 0;
|
||||
auto maxH = 0;
|
||||
|
@ -100,7 +103,8 @@ void SendFilesBox::prepareSingleFileLayout() {
|
|||
maxH = limitH;
|
||||
}
|
||||
}
|
||||
image = Images::prepare(image, maxW * cIntRetinaFactor(), maxH * cIntRetinaFactor(), Images::Option::Smooth | Images::Option::Blurred, maxW, maxH);
|
||||
image = Images::prepare(image, maxW * cIntRetinaFactor(), maxH * cIntRetinaFactor(),
|
||||
Images::Option::Smooth | Images::Option::Blurred, maxW, maxH);
|
||||
}
|
||||
auto originalWidth = image.width();
|
||||
auto originalHeight = image.height();
|
||||
|
@ -120,7 +124,8 @@ void SendFilesBox::prepareSingleFileLayout() {
|
|||
}
|
||||
_previewLeft = (st::boxWideWidth - _previewWidth) / 2;
|
||||
|
||||
image = std::move(image).scaled(_previewWidth * cIntRetinaFactor(), _previewHeight * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
image = std::move(image).scaled(_previewWidth * cIntRetinaFactor(), _previewHeight * cIntRetinaFactor(),
|
||||
Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
image = Images::prepareOpaque(std::move(image));
|
||||
_preview = App::pixmapFromImageInPlace(std::move(image));
|
||||
_preview.setDevicePixelRatio(cRetinaFactor());
|
||||
|
@ -145,9 +150,8 @@ void SendFilesBox::prepareGifPreview() {
|
|||
return _animated;
|
||||
};
|
||||
if (createGifPreview()) {
|
||||
_gifPreview = Media::Clip::MakeReader(_files.front(), [this](Media::Clip::Notification notification) {
|
||||
clipCallback(notification);
|
||||
});
|
||||
_gifPreview = Media::Clip::MakeReader(
|
||||
_files.front(), [this](Media::Clip::Notification notification) { clipCallback(notification); });
|
||||
if (_gifPreview) _gifPreview->setAutoplay();
|
||||
}
|
||||
}
|
||||
|
@ -162,7 +166,8 @@ void SendFilesBox::clipCallback(Media::Clip::Notification notification) {
|
|||
|
||||
if (_gifPreview && _gifPreview->ready() && !_gifPreview->started()) {
|
||||
auto s = QSize(_previewWidth, _previewHeight);
|
||||
_gifPreview->start(s.width(), s.height(), s.width(), s.height(), ImageRoundRadius::None, ImageRoundCorner::None);
|
||||
_gifPreview->start(s.width(), s.height(), s.width(), s.height(), ImageRoundRadius::None,
|
||||
ImageRoundCorner::None);
|
||||
}
|
||||
|
||||
update();
|
||||
|
@ -219,10 +224,10 @@ void SendFilesBox::tryToReadSingleFile() {
|
|||
}
|
||||
}
|
||||
|
||||
SendFilesBox::SendFilesBox(QWidget*, const QString &phone, const QString &firstname, const QString &lastname)
|
||||
: _contactPhone(phone)
|
||||
, _contactFirstName(firstname)
|
||||
, _contactLastName(lastname) {
|
||||
SendFilesBox::SendFilesBox(QWidget *, const QString &phone, const QString &firstname, const QString &lastname)
|
||||
: _contactPhone(phone)
|
||||
, _contactFirstName(firstname)
|
||||
, _contactLastName(lastname) {
|
||||
auto name = lng_full_name(lt_first_name, _contactFirstName, lt_last_name, _contactLastName);
|
||||
_nameText.setText(st::semiboldTextStyle, name, _textNameOptions);
|
||||
_statusText = _contactPhone;
|
||||
|
@ -241,7 +246,8 @@ void SendFilesBox::prepare() {
|
|||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
if (_compressConfirm != CompressConfirm::None) {
|
||||
auto compressed = (_compressConfirm == CompressConfirm::Auto) ? cCompressPastedImage() : (_compressConfirm == CompressConfirm::Yes);
|
||||
auto compressed = (_compressConfirm == CompressConfirm::Auto) ? cCompressPastedImage() :
|
||||
(_compressConfirm == CompressConfirm::Yes);
|
||||
auto text = lng_send_images_compress(lt_count, _files.size());
|
||||
_compressed.create(this, text, compressed, st::defaultBoxCheckbox);
|
||||
subscribe(_compressed->checkedChanged, [this](bool checked) { onCompressedChange(); });
|
||||
|
@ -286,7 +292,8 @@ 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());
|
||||
_titleText = (_compressConfirm == CompressConfirm::None) ? lng_send_files_selected(lt_count, _files.size()) :
|
||||
lng_send_images_selected(lt_count, _files.size());
|
||||
update();
|
||||
}
|
||||
|
||||
|
@ -295,11 +302,13 @@ void SendFilesBox::updateBoxSize() {
|
|||
if (!_preview.isNull()) {
|
||||
newHeight += st::boxPhotoPadding.top() + _previewHeight;
|
||||
} else if (!_fileThumb.isNull()) {
|
||||
newHeight += st::boxPhotoPadding.top() + st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom();
|
||||
newHeight += st::boxPhotoPadding.top() + st::msgFileThumbPadding.top() + st::msgFileThumbSize +
|
||||
st::msgFileThumbPadding.bottom();
|
||||
} else if (_files.size() > 1) {
|
||||
newHeight += 0;
|
||||
} else {
|
||||
newHeight += st::boxPhotoPadding.top() + st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom();
|
||||
newHeight +=
|
||||
st::boxPhotoPadding.top() + st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom();
|
||||
}
|
||||
if (_compressed) {
|
||||
newHeight += st::boxPhotoCompressedSkip + _compressed->heightNoMargins();
|
||||
|
@ -312,7 +321,8 @@ void SendFilesBox::updateBoxSize() {
|
|||
|
||||
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));
|
||||
onSend((e->modifiers().testFlag(Qt::ControlModifier) || e->modifiers().testFlag(Qt::MetaModifier)) &&
|
||||
e->modifiers().testFlag(Qt::ShiftModifier));
|
||||
} else {
|
||||
BoxContent::keyPressEvent(e);
|
||||
}
|
||||
|
@ -331,21 +341,27 @@ void SendFilesBox::paintEvent(QPaintEvent *e) {
|
|||
|
||||
if (!_preview.isNull()) {
|
||||
if (_previewLeft > st::boxPhotoPadding.left()) {
|
||||
p.fillRect(st::boxPhotoPadding.left(), st::boxPhotoPadding.top(), _previewLeft - st::boxPhotoPadding.left(), _previewHeight, st::confirmBg);
|
||||
p.fillRect(st::boxPhotoPadding.left(), st::boxPhotoPadding.top(), _previewLeft - st::boxPhotoPadding.left(),
|
||||
_previewHeight, st::confirmBg);
|
||||
}
|
||||
if (_previewLeft + _previewWidth < width() - st::boxPhotoPadding.right()) {
|
||||
p.fillRect(_previewLeft + _previewWidth, st::boxPhotoPadding.top(), width() - st::boxPhotoPadding.right() - _previewLeft - _previewWidth, _previewHeight, st::confirmBg);
|
||||
p.fillRect(_previewLeft + _previewWidth, st::boxPhotoPadding.top(),
|
||||
width() - st::boxPhotoPadding.right() - _previewLeft - _previewWidth, _previewHeight,
|
||||
st::confirmBg);
|
||||
}
|
||||
if (_gifPreview && _gifPreview->started()) {
|
||||
auto s = QSize(_previewWidth, _previewHeight);
|
||||
auto paused = controller()->isGifPausedAtLeastFor(Window::GifPauseReason::Layer);
|
||||
auto frame = _gifPreview->current(s.width(), s.height(), s.width(), s.height(), ImageRoundRadius::None, ImageRoundCorner::None, paused ? 0 : getms());
|
||||
auto frame = _gifPreview->current(s.width(), s.height(), s.width(), s.height(), ImageRoundRadius::None,
|
||||
ImageRoundCorner::None, paused ? 0 : getms());
|
||||
p.drawPixmap(_previewLeft, st::boxPhotoPadding.top(), frame);
|
||||
} else {
|
||||
p.drawPixmap(_previewLeft, st::boxPhotoPadding.top(), _preview);
|
||||
}
|
||||
if (_animated && !_gifPreview) {
|
||||
auto inner = QRect(_previewLeft + (_previewWidth - st::msgFileSize) / 2, st::boxPhotoPadding.top() + (_previewHeight - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize);
|
||||
auto inner = QRect(_previewLeft + (_previewWidth - st::msgFileSize) / 2,
|
||||
st::boxPhotoPadding.top() + (_previewHeight - st::msgFileSize) / 2, st::msgFileSize,
|
||||
st::msgFileSize);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(st::msgDateImgBg);
|
||||
|
||||
|
@ -359,7 +375,9 @@ void SendFilesBox::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
} else if (_files.size() < 2) {
|
||||
auto w = width() - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
|
||||
auto h = _fileThumb.isNull() ? (st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom()) : (st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom());
|
||||
auto h = _fileThumb.isNull() ?
|
||||
(st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom()) :
|
||||
(st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom());
|
||||
auto nameleft = 0, nametop = 0, nameright = 0, statustop = 0, linktop = 0;
|
||||
if (_fileThumb.isNull()) {
|
||||
nameleft = st::msgFilePadding.left() + st::msgFileSize + st::msgFilePadding.right();
|
||||
|
@ -373,14 +391,16 @@ void SendFilesBox::paintEvent(QPaintEvent *e) {
|
|||
statustop = st::msgFileThumbStatusTop;
|
||||
linktop = st::msgFileThumbLinkTop;
|
||||
}
|
||||
auto namewidth = w - nameleft - (_fileThumb.isNull() ? st::msgFilePadding.left() : st::msgFileThumbPadding.left());
|
||||
auto namewidth =
|
||||
w - nameleft - (_fileThumb.isNull() ? st::msgFilePadding.left() : st::msgFileThumbPadding.left());
|
||||
qint32 x = (width() - w) / 2, y = st::boxPhotoPadding.top();
|
||||
|
||||
App::roundRect(p, x, y, w, h, st::msgOutBg, MessageOutCorners, &st::msgOutShadow);
|
||||
|
||||
if (_fileThumb.isNull()) {
|
||||
if (_contactPhone.isNull()) {
|
||||
QRect inner(rtlrect(x + st::msgFilePadding.left(), y + st::msgFilePadding.top(), st::msgFileSize, st::msgFileSize, width()));
|
||||
QRect inner(rtlrect(x + st::msgFilePadding.left(), y + st::msgFilePadding.top(), st::msgFileSize,
|
||||
st::msgFileSize, width()));
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(st::msgFileOutBg);
|
||||
|
||||
|
@ -389,13 +409,16 @@ void SendFilesBox::paintEvent(QPaintEvent *e) {
|
|||
p.drawEllipse(inner);
|
||||
}
|
||||
|
||||
auto &icon = _fileIsAudio ? st::historyFileOutPlay : _fileIsImage ? st::historyFileOutImage : st::historyFileOutDocument;
|
||||
auto &icon = _fileIsAudio ? st::historyFileOutPlay :
|
||||
_fileIsImage ? st::historyFileOutImage : st::historyFileOutDocument;
|
||||
icon.paintInCenter(p, inner);
|
||||
} else {
|
||||
_contactPhotoEmpty.paint(p, x + st::msgFilePadding.left(), y + st::msgFilePadding.top(), width(), st::msgFileSize);
|
||||
_contactPhotoEmpty.paint(p, x + st::msgFilePadding.left(), y + st::msgFilePadding.top(), width(),
|
||||
st::msgFileSize);
|
||||
}
|
||||
} else {
|
||||
QRect rthumb(rtlrect(x + st::msgFileThumbPadding.left(), y + st::msgFileThumbPadding.top(), st::msgFileThumbSize, st::msgFileThumbSize, width()));
|
||||
QRect rthumb(rtlrect(x + st::msgFileThumbPadding.left(), y + st::msgFileThumbPadding.top(),
|
||||
st::msgFileThumbSize, st::msgFileThumbSize, width()));
|
||||
p.drawPixmap(rthumb.topLeft(), _fileThumb);
|
||||
}
|
||||
p.setFont(st::semiboldFont);
|
||||
|
@ -417,7 +440,8 @@ void SendFilesBox::resizeEvent(QResizeEvent *e) {
|
|||
void SendFilesBox::updateControlsGeometry() {
|
||||
auto bottom = height();
|
||||
if (_caption) {
|
||||
_caption->resize(st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right(), _caption->height());
|
||||
_caption->resize(st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right(),
|
||||
_caption->height());
|
||||
_caption->moveToLeft(st::boxPhotoPadding.left(), bottom - _caption->height());
|
||||
bottom -= st::boxPhotoCaptionSkip + _caption->height();
|
||||
}
|
||||
|
@ -443,13 +467,17 @@ void SendFilesBox::onSend(bool ctrlShiftEnter) {
|
|||
_confirmed = true;
|
||||
if (_confirmedCallback) {
|
||||
auto compressed = _compressed ? _compressed->checked() : false;
|
||||
auto caption = _caption ? TextUtilities::PrepareForSending(_caption->getLastText(), TextUtilities::PrepareTextOption::CheckLinks) : QString();
|
||||
_confirmedCallback(_files, _animated ? QImage() : _image, std::move(_information), compressed, caption, ctrlShiftEnter);
|
||||
auto caption = _caption ? TextUtilities::PrepareForSending(_caption->getLastText(),
|
||||
TextUtilities::PrepareTextOption::CheckLinks) :
|
||||
QString();
|
||||
_confirmedCallback(_files, _animated ? QImage() : _image, std::move(_information), compressed, caption,
|
||||
ctrlShiftEnter);
|
||||
}
|
||||
closeBox();
|
||||
}
|
||||
|
||||
EditCaptionBox::EditCaptionBox(QWidget*, HistoryMedia *media, FullMsgId msgId) : _msgId(msgId) {
|
||||
EditCaptionBox::EditCaptionBox(QWidget *, HistoryMedia *media, FullMsgId msgId)
|
||||
: _msgId(msgId) {
|
||||
Expects(media->canEditCaption());
|
||||
|
||||
QSize dimensions;
|
||||
|
@ -460,21 +488,21 @@ EditCaptionBox::EditCaptionBox(QWidget*, HistoryMedia *media, FullMsgId msgId) :
|
|||
switch (media->type()) {
|
||||
case MediaTypeGif: {
|
||||
_animated = true;
|
||||
doc = static_cast<HistoryGif*>(media)->getDocument();
|
||||
doc = static_cast<HistoryGif *>(media)->getDocument();
|
||||
dimensions = doc->dimensions;
|
||||
image = doc->thumb;
|
||||
} break;
|
||||
|
||||
case MediaTypePhoto: {
|
||||
_photo = true;
|
||||
auto photo = static_cast<HistoryPhoto*>(media)->photo();
|
||||
auto photo = static_cast<HistoryPhoto *>(media)->photo();
|
||||
dimensions = QSize(photo->full->width(), photo->full->height());
|
||||
image = photo->full;
|
||||
} break;
|
||||
|
||||
case MediaTypeVideo: {
|
||||
_animated = true;
|
||||
doc = static_cast<HistoryVideo*>(media)->getDocument();
|
||||
doc = static_cast<HistoryVideo *>(media)->getDocument();
|
||||
dimensions = doc->dimensions;
|
||||
image = doc->thumb;
|
||||
} break;
|
||||
|
@ -483,7 +511,7 @@ EditCaptionBox::EditCaptionBox(QWidget*, HistoryMedia *media, FullMsgId msgId) :
|
|||
case MediaTypeMusicFile:
|
||||
case MediaTypeVoiceFile: {
|
||||
_doc = true;
|
||||
doc = static_cast<HistoryDocument*>(media)->getDocument();
|
||||
doc = static_cast<HistoryDocument *>(media)->getDocument();
|
||||
image = doc->thumb;
|
||||
} break;
|
||||
}
|
||||
|
@ -499,8 +527,11 @@ EditCaptionBox::EditCaptionBox(QWidget*, HistoryMedia *media, FullMsgId msgId) :
|
|||
} else {
|
||||
_thumbw = st::msgFileThumbSize;
|
||||
}
|
||||
auto options = Images::Option::Smooth | Images::Option::RoundedSmall | Images::Option::RoundedTopLeft | Images::Option::RoundedTopRight | Images::Option::RoundedBottomLeft | Images::Option::RoundedBottomRight;
|
||||
_thumb = Images::pixmap(image->pix().toImage(), _thumbw * cIntRetinaFactor(), 0, options, st::msgFileThumbSize, st::msgFileThumbSize);
|
||||
auto options = Images::Option::Smooth | Images::Option::RoundedSmall | Images::Option::RoundedTopLeft |
|
||||
Images::Option::RoundedTopRight | Images::Option::RoundedBottomLeft |
|
||||
Images::Option::RoundedBottomRight;
|
||||
_thumb = Images::pixmap(image->pix().toImage(), _thumbw * cIntRetinaFactor(), 0, options,
|
||||
st::msgFileThumbSize, st::msgFileThumbSize);
|
||||
}
|
||||
|
||||
if (doc) {
|
||||
|
@ -532,12 +563,14 @@ EditCaptionBox::EditCaptionBox(QWidget*, HistoryMedia *media, FullMsgId msgId) :
|
|||
maxH = limitH;
|
||||
}
|
||||
}
|
||||
_thumb = image->pixNoCache(maxW * cIntRetinaFactor(), maxH * cIntRetinaFactor(), Images::Option::Smooth | Images::Option::Blurred, maxW, maxH);
|
||||
_thumb = image->pixNoCache(maxW * cIntRetinaFactor(), maxH * cIntRetinaFactor(),
|
||||
Images::Option::Smooth | Images::Option::Blurred, maxW, maxH);
|
||||
prepareGifPreview(doc);
|
||||
} else {
|
||||
maxW = dimensions.width();
|
||||
maxH = dimensions.height();
|
||||
_thumb = image->pixNoCache(maxW * cIntRetinaFactor(), maxH * cIntRetinaFactor(), Images::Option::Smooth, maxW, maxH);
|
||||
_thumb = image->pixNoCache(maxW * cIntRetinaFactor(), maxH * cIntRetinaFactor(), Images::Option::Smooth,
|
||||
maxW, maxH);
|
||||
}
|
||||
qint32 tw = _thumb.width(), th = _thumb.height();
|
||||
if (!tw || !th) {
|
||||
|
@ -558,7 +591,9 @@ EditCaptionBox::EditCaptionBox(QWidget*, HistoryMedia *media, FullMsgId msgId) :
|
|||
}
|
||||
_thumbx = (st::boxWideWidth - _thumbw) / 2;
|
||||
|
||||
_thumb = App::pixmapFromImageInPlace(_thumb.toImage().scaled(_thumbw * cIntRetinaFactor(), _thumbh * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
_thumb = App::pixmapFromImageInPlace(_thumb.toImage().scaled(_thumbw * cIntRetinaFactor(),
|
||||
_thumbh * cIntRetinaFactor(),
|
||||
Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
_thumb.setDevicePixelRatio(cRetinaFactor());
|
||||
}
|
||||
Assert(_animated || _photo || _doc);
|
||||
|
@ -569,14 +604,11 @@ EditCaptionBox::EditCaptionBox(QWidget*, HistoryMedia *media, FullMsgId msgId) :
|
|||
}
|
||||
|
||||
void EditCaptionBox::prepareGifPreview(DocumentData *document) {
|
||||
auto createGifPreview = [document] {
|
||||
return (document && document->isAnimation());
|
||||
};
|
||||
auto createGifPreview = [document] { return (document && document->isAnimation()); };
|
||||
auto createGifPreviewResult = createGifPreview(); // Clang freeze workaround.
|
||||
if (createGifPreviewResult) {
|
||||
_gifPreview = Media::Clip::MakeReader(document, _msgId, [this](Media::Clip::Notification notification) {
|
||||
clipCallback(notification);
|
||||
});
|
||||
_gifPreview = Media::Clip::MakeReader(
|
||||
document, _msgId, [this](Media::Clip::Notification notification) { clipCallback(notification); });
|
||||
if (_gifPreview) _gifPreview->setAutoplay();
|
||||
}
|
||||
}
|
||||
|
@ -591,7 +623,8 @@ void EditCaptionBox::clipCallback(Media::Clip::Notification notification) {
|
|||
|
||||
if (_gifPreview && _gifPreview->ready() && !_gifPreview->started()) {
|
||||
auto s = QSize(_thumbw, _thumbh);
|
||||
_gifPreview->start(s.width(), s.height(), s.width(), s.height(), ImageRoundRadius::None, ImageRoundCorner::None);
|
||||
_gifPreview->start(s.width(), s.height(), s.width(), s.height(), ImageRoundRadius::None,
|
||||
ImageRoundCorner::None);
|
||||
}
|
||||
|
||||
update();
|
||||
|
@ -626,7 +659,8 @@ void EditCaptionBox::onCaptionResized() {
|
|||
}
|
||||
|
||||
void EditCaptionBox::updateBoxSize() {
|
||||
auto newHeight = st::boxPhotoPadding.top() + st::boxPhotoCaptionSkip + _field->height() + errorTopSkip() + st::normalFont->height;
|
||||
auto newHeight = st::boxPhotoPadding.top() + st::boxPhotoCaptionSkip + _field->height() + errorTopSkip() +
|
||||
st::normalFont->height;
|
||||
if (_photo || _animated) {
|
||||
newHeight += _thumbh;
|
||||
} else if (_thumbw) {
|
||||
|
@ -650,21 +684,25 @@ void EditCaptionBox::paintEvent(QPaintEvent *e) {
|
|||
|
||||
if (_photo || _animated) {
|
||||
if (_thumbx > st::boxPhotoPadding.left()) {
|
||||
p.fillRect(st::boxPhotoPadding.left(), st::boxPhotoPadding.top(), _thumbx - st::boxPhotoPadding.left(), _thumbh, st::confirmBg);
|
||||
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);
|
||||
p.fillRect(_thumbx + _thumbw, st::boxPhotoPadding.top(),
|
||||
width() - st::boxPhotoPadding.right() - _thumbx - _thumbw, _thumbh, st::confirmBg);
|
||||
}
|
||||
if (_gifPreview && _gifPreview->started()) {
|
||||
auto s = QSize(_thumbw, _thumbh);
|
||||
auto paused = controller()->isGifPausedAtLeastFor(Window::GifPauseReason::Layer);
|
||||
auto frame = _gifPreview->current(s.width(), s.height(), s.width(), s.height(), ImageRoundRadius::None, ImageRoundCorner::None, paused ? 0 : getms());
|
||||
auto frame = _gifPreview->current(s.width(), s.height(), s.width(), s.height(), ImageRoundRadius::None,
|
||||
ImageRoundCorner::None, paused ? 0 : getms());
|
||||
p.drawPixmap(_thumbx, st::boxPhotoPadding.top(), frame);
|
||||
} else {
|
||||
p.drawPixmap(_thumbx, st::boxPhotoPadding.top(), _thumb);
|
||||
}
|
||||
if (_animated && !_gifPreview) {
|
||||
QRect inner(_thumbx + (_thumbw - st::msgFileSize) / 2, st::boxPhotoPadding.top() + (_thumbh - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize);
|
||||
QRect inner(_thumbx + (_thumbw - st::msgFileSize) / 2,
|
||||
st::boxPhotoPadding.top() + (_thumbh - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(st::msgDateImgBg);
|
||||
|
||||
|
@ -693,12 +731,12 @@ void EditCaptionBox::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
qint32 namewidth = w - nameleft - 0;
|
||||
if (namewidth > _statusw) {
|
||||
//w -= (namewidth - _statusw);
|
||||
//namewidth = _statusw;
|
||||
// w -= (namewidth - _statusw);
|
||||
// namewidth = _statusw;
|
||||
}
|
||||
qint32 x = (width() - w) / 2, y = st::boxPhotoPadding.top();
|
||||
|
||||
// App::roundRect(p, x, y, w, h, st::msgInBg, MessageInCorners, &st::msgInShadow);
|
||||
// App::roundRect(p, x, y, w, h, st::msgInBg, MessageInCorners, &st::msgInShadow);
|
||||
|
||||
if (_thumbw) {
|
||||
QRect rthumb(rtlrect(x + 0, y + 0, st::msgFileThumbSize, st::msgFileThumbSize, width()));
|
||||
|
@ -713,7 +751,8 @@ void EditCaptionBox::paintEvent(QPaintEvent *e) {
|
|||
p.drawEllipse(inner);
|
||||
}
|
||||
|
||||
auto icon = &(_isAudio ? st::historyFileInPlay : _isImage ? st::historyFileInImage : st::historyFileInDocument);
|
||||
auto icon =
|
||||
&(_isAudio ? st::historyFileInPlay : _isImage ? st::historyFileInImage : st::historyFileInDocument);
|
||||
icon->paintInCenter(p, inner);
|
||||
}
|
||||
p.setFont(st::semiboldFont);
|
||||
|
@ -740,7 +779,8 @@ void EditCaptionBox::paintEvent(QPaintEvent *e) {
|
|||
void EditCaptionBox::resizeEvent(QResizeEvent *e) {
|
||||
BoxContent::resizeEvent(e);
|
||||
_field->resize(st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right(), _field->height());
|
||||
_field->moveToLeft(st::boxPhotoPadding.left(), height() - st::normalFont->height - errorTopSkip() - _field->height());
|
||||
_field->moveToLeft(st::boxPhotoPadding.left(),
|
||||
height() - st::normalFont->height - errorTopSkip() - _field->height());
|
||||
}
|
||||
|
||||
void EditCaptionBox::setInnerFocus() {
|
||||
|
@ -766,7 +806,10 @@ void EditCaptionBox::onSave(bool ctrlShiftEnter) {
|
|||
flags |= MTPmessages_EditMessage::Flag::f_entities;
|
||||
}
|
||||
auto text = TextUtilities::PrepareForSending(_field->getLastText(), TextUtilities::PrepareTextOption::CheckLinks);
|
||||
_saveRequestId = MTP::send(MTPmessages_EditMessage(MTP_flags(flags), item->history()->peer->input, MTP_int(item->id), MTP_string(text), MTPnullMarkup, sentEntities), rpcDone(&EditCaptionBox::saveDone), rpcFail(&EditCaptionBox::saveFail));
|
||||
_saveRequestId =
|
||||
MTP::send(MTPmessages_EditMessage(MTP_flags(flags), item->history()->peer->input, MTP_int(item->id),
|
||||
MTP_string(text), MTPnullMarkup, sentEntities),
|
||||
rpcDone(&EditCaptionBox::saveDone), rpcFail(&EditCaptionBox::saveFail));
|
||||
}
|
||||
|
||||
void EditCaptionBox::saveDone(const MTPUpdates &updates) {
|
||||
|
@ -782,7 +825,8 @@ bool EditCaptionBox::saveFail(const RPCError &error) {
|
|||
|
||||
_saveRequestId = 0;
|
||||
QString err = error.type();
|
||||
if (err == qstr("MESSAGE_ID_INVALID") || err == qstr("CHAT_ADMIN_REQUIRED") || err == qstr("MESSAGE_EDIT_TIME_EXPIRED")) {
|
||||
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")) {
|
||||
closeBox();
|
||||
|
|
|
@ -21,8 +21,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
#pragma once
|
||||
|
||||
#include "boxes/abstract_box.h"
|
||||
#include "storage/localimageloader.h"
|
||||
#include "history/history_media.h"
|
||||
#include "storage/localimageloader.h"
|
||||
|
||||
namespace Ui {
|
||||
class Checkbox;
|
||||
|
@ -34,11 +34,14 @@ class SendFilesBox : public BoxContent {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SendFilesBox(QWidget*, QImage image, CompressConfirm compressed);
|
||||
SendFilesBox(QWidget*, const QStringList &files, CompressConfirm compressed);
|
||||
SendFilesBox(QWidget*, const QString &phone, const QString &firstname, const QString &lastname);
|
||||
SendFilesBox(QWidget *, QImage image, CompressConfirm compressed);
|
||||
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, const QImage &image, std::unique_ptr<FileLoadTask::MediaInformation> information, bool compressed, const QString &caption, bool ctrlShiftEnter)> callback) {
|
||||
void setConfirmedCallback(base::lambda<void(const QStringList &files, const QImage &image,
|
||||
std::unique_ptr<FileLoadTask::MediaInformation> information,
|
||||
bool compressed, const QString &caption, bool ctrlShiftEnter)>
|
||||
callback) {
|
||||
_confirmedCallback = std::move(callback);
|
||||
}
|
||||
void setCancelledCallback(base::lambda<void()> callback) {
|
||||
|
@ -99,22 +102,24 @@ private:
|
|||
QString _contactLastName;
|
||||
EmptyUserpic _contactPhotoEmpty;
|
||||
|
||||
base::lambda<void(const QStringList &files, const QImage &image, std::unique_ptr<FileLoadTask::MediaInformation> information, bool compressed, const QString &caption, bool ctrlShiftEnter)> _confirmedCallback;
|
||||
base::lambda<void(const QStringList &files, const QImage &image,
|
||||
std::unique_ptr<FileLoadTask::MediaInformation> information, bool compressed,
|
||||
const QString &caption, bool ctrlShiftEnter)>
|
||||
_confirmedCallback;
|
||||
base::lambda<void()> _cancelledCallback;
|
||||
bool _confirmed = false;
|
||||
|
||||
object_ptr<Ui::InputArea> _caption = { nullptr };
|
||||
object_ptr<Ui::Checkbox> _compressed = { nullptr };
|
||||
object_ptr<Ui::InputArea> _caption = {nullptr};
|
||||
object_ptr<Ui::Checkbox> _compressed = {nullptr};
|
||||
|
||||
QPointer<Ui::RoundButton> _send;
|
||||
|
||||
};
|
||||
|
||||
class EditCaptionBox : public BoxContent, public RPCSender {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
EditCaptionBox(QWidget*, HistoryMedia *media, FullMsgId msgId);
|
||||
EditCaptionBox(QWidget *, HistoryMedia *media, FullMsgId msgId);
|
||||
|
||||
public slots:
|
||||
void onCaptionResized();
|
||||
|
@ -148,7 +153,7 @@ private:
|
|||
QPixmap _thumb;
|
||||
Media::Clip::ReaderPointer _gifPreview;
|
||||
|
||||
object_ptr<Ui::InputArea> _field = { nullptr };
|
||||
object_ptr<Ui::InputArea> _field = {nullptr};
|
||||
|
||||
int _thumbx = 0;
|
||||
int _thumby = 0;
|
||||
|
@ -164,5 +169,4 @@ private:
|
|||
mtpRequestId _saveRequestId = 0;
|
||||
|
||||
QString _error;
|
||||
|
||||
};
|
||||
|
|
|
@ -20,19 +20,18 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#include "boxes/sessions_box.h"
|
||||
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "countries.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
#include "countries.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "styles/style_boxes.h"
|
||||
|
||||
SessionsBox::SessionsBox(QWidget*)
|
||||
: _shortPollTimer(this) {
|
||||
}
|
||||
SessionsBox::SessionsBox(QWidget *)
|
||||
: _shortPollTimer(this) {}
|
||||
|
||||
void SessionsBox::prepare() {
|
||||
setTitle(langFactory(lng_sessions_other_header));
|
||||
|
@ -85,7 +84,8 @@ void SessionsBox::gotAuthorizations(const MTPaccount_Authorizations &result) {
|
|||
setLoading(false);
|
||||
|
||||
auto availCurrent = st::boxWideWidth - st::sessionPadding.left() - st::sessionTerminateSkip;
|
||||
auto availOther = availCurrent - st::sessionTerminate.iconPosition.x();// -st::sessionTerminate.width - st::sessionTerminateSkip;
|
||||
auto availOther =
|
||||
availCurrent - st::sessionTerminate.iconPosition.x(); // -st::sessionTerminate.width - st::sessionTerminateSkip;
|
||||
|
||||
_list.clear();
|
||||
if (result.type() != mtpc_account_authorizations) {
|
||||
|
@ -104,24 +104,26 @@ void SessionsBox::gotAuthorizations(const MTPaccount_Authorizations &result) {
|
|||
Data data;
|
||||
data.hash = d.vhash.v;
|
||||
|
||||
QString appName, appVer = qs(d.vapp_version), systemVer = qs(d.vsystem_version), deviceModel = qs(d.vdevice_model);
|
||||
QString appName, appVer = qs(d.vapp_version), systemVer = qs(d.vsystem_version),
|
||||
deviceModel = qs(d.vdevice_model);
|
||||
if (d.vapi_id.v == 2040 || d.vapi_id.v == 17349) {
|
||||
appName = str_const_toString(AppName);
|
||||
// if (systemVer == qstr("windows")) {
|
||||
// deviceModel = qsl("Windows");
|
||||
// } else if (systemVer == qstr("os x")) {
|
||||
// deviceModel = qsl("OS X");
|
||||
// } else if (systemVer == qstr("linux")) {
|
||||
// deviceModel = qsl("Linux");
|
||||
// }
|
||||
// if (systemVer == qstr("windows")) {
|
||||
// deviceModel = qsl("Windows");
|
||||
// } else if (systemVer == qstr("os x")) {
|
||||
// deviceModel = qsl("OS X");
|
||||
// } else if (systemVer == qstr("linux")) {
|
||||
// deviceModel = qsl("Linux");
|
||||
// }
|
||||
if (appVer == QString::number(appVer.toInt())) {
|
||||
qint32 ver = appVer.toInt();
|
||||
appVer = QString("%1.%2").arg(ver / 1000000).arg((ver % 1000000) / 1000) + ((ver % 1000) ? ('.' + QString::number(ver % 1000)) : QString());
|
||||
//} else {
|
||||
// appVer = QString();
|
||||
appVer = QString("%1.%2").arg(ver / 1000000).arg((ver % 1000000) / 1000) +
|
||||
((ver % 1000) ? ('.' + QString::number(ver % 1000)) : QString());
|
||||
//} else {
|
||||
// appVer = QString();
|
||||
}
|
||||
} else {
|
||||
appName = qs(d.vapp_name);// +qsl(" for ") + qs(d.vplatform);
|
||||
appName = qs(d.vapp_name); // +qsl(" for ") + qs(d.vplatform);
|
||||
if (appVer.indexOf('(') >= 0) appVer = appVer.mid(appVer.indexOf('('));
|
||||
}
|
||||
data.name = appName;
|
||||
|
@ -129,13 +131,14 @@ void SessionsBox::gotAuthorizations(const MTPaccount_Authorizations &result) {
|
|||
data.nameWidth = st::sessionNameFont->width(data.name);
|
||||
|
||||
QString country = qs(d.vcountry), platform = qs(d.vplatform);
|
||||
//CountriesByISO2::const_iterator j = countries.constFind(country);
|
||||
//if (j != countries.cend()) country = QString::fromUtf8(j.value()->name);
|
||||
// CountriesByISO2::const_iterator j = countries.constFind(country);
|
||||
// if (j != countries.cend()) country = QString::fromUtf8(j.value()->name);
|
||||
|
||||
MTPint active = d.vdate_active.v ? d.vdate_active : d.vdate_created;
|
||||
data.activeTime = active.v;
|
||||
|
||||
data.info = qs(d.vdevice_model) + qstr(", ") + (platform.isEmpty() ? QString() : platform + ' ') + qs(d.vsystem_version);
|
||||
data.info = qs(d.vdevice_model) + qstr(", ") + (platform.isEmpty() ? QString() : platform + ' ') +
|
||||
qs(d.vsystem_version);
|
||||
data.ip = qs(d.vip) + (country.isEmpty() ? QString() : QString::fromUtf8(" \xe2\x80\x93 ") + country);
|
||||
if (!data.hash || (d.vflags.v & 1)) {
|
||||
data.active = lang(lng_sessions_header);
|
||||
|
@ -213,7 +216,7 @@ void SessionsBox::onShortPollAuthorizations() {
|
|||
|
||||
void SessionsBox::onCheckNewAuthorization() {
|
||||
onShortPollAuthorizations();
|
||||
// _shortPollTimer.start(1000);
|
||||
// _shortPollTimer.start(1000);
|
||||
}
|
||||
|
||||
void SessionsBox::onAllTerminated() {
|
||||
|
@ -228,10 +231,11 @@ void SessionsBox::onTerminateAll() {
|
|||
setLoading(true);
|
||||
}
|
||||
|
||||
SessionsBox::Inner::Inner(QWidget *parent, SessionsBox::List *list, SessionsBox::Data *current) : TWidget(parent)
|
||||
, _list(list)
|
||||
, _current(current)
|
||||
, _terminateAll(this, lang(lng_sessions_terminate_all), st::sessionTerminateAllButton) {
|
||||
SessionsBox::Inner::Inner(QWidget *parent, SessionsBox::List *list, SessionsBox::Data *current)
|
||||
: TWidget(parent)
|
||||
, _list(list)
|
||||
, _current(current)
|
||||
, _terminateAll(this, lang(lng_sessions_terminate_all), st::sessionTerminateAllButton) {
|
||||
connect(_terminateAll, SIGNAL(clicked()), this, SLOT(onTerminateAll()));
|
||||
_terminateAll->hide();
|
||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
|
@ -242,7 +246,10 @@ void SessionsBox::Inner::paintEvent(QPaintEvent *e) {
|
|||
Painter p(this);
|
||||
|
||||
p.fillRect(r, st::boxBg);
|
||||
qint32 x = st::sessionPadding.left(), xact = st::sessionTerminateSkip + st::sessionTerminate.iconPosition.x();// st::sessionTerminateSkip + st::sessionTerminate.width + st::sessionTerminateSkip;
|
||||
qint32 x = st::sessionPadding.left(),
|
||||
xact = st::sessionTerminateSkip +
|
||||
st::sessionTerminate.iconPosition
|
||||
.x(); // st::sessionTerminateSkip + st::sessionTerminate.width + st::sessionTerminateSkip;
|
||||
qint32 w = width();
|
||||
|
||||
if (_current->active.isEmpty() && _list->isEmpty()) {
|
||||
|
@ -264,15 +271,19 @@ void SessionsBox::Inner::paintEvent(QPaintEvent *e) {
|
|||
|
||||
p.setFont(st::sessionInfoFont);
|
||||
p.setPen(st::boxTextFg);
|
||||
p.drawTextLeft(x, st::sessionPadding.top() + st::sessionNameFont->height, w, _current->info, _current->infoWidth);
|
||||
p.drawTextLeft(x, st::sessionPadding.top() + st::sessionNameFont->height, w, _current->info,
|
||||
_current->infoWidth);
|
||||
p.setPen(st::sessionInfoFg);
|
||||
p.drawTextLeft(x, st::sessionPadding.top() + st::sessionNameFont->height + st::sessionInfoFont->height, w, _current->ip, _current->ipWidth);
|
||||
p.drawTextLeft(x, st::sessionPadding.top() + st::sessionNameFont->height + st::sessionInfoFont->height, w,
|
||||
_current->ip, _current->ipWidth);
|
||||
}
|
||||
p.translate(0, st::sessionCurrentHeight - st::sessionCurrentPadding.top());
|
||||
if (_list->isEmpty()) {
|
||||
p.setFont(st::sessionInfoFont);
|
||||
p.setPen(st::sessionInfoFg);
|
||||
p.drawText(QRect(st::sessionPadding.left(), 0, width() - st::sessionPadding.left() - st::sessionPadding.right(), st::noContactsHeight), lang(lng_sessions_other_desc), style::al_topleft);
|
||||
p.drawText(QRect(st::sessionPadding.left(), 0, width() - st::sessionPadding.left() - st::sessionPadding.right(),
|
||||
st::noContactsHeight),
|
||||
lang(lng_sessions_other_desc), style::al_topleft);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -296,7 +307,8 @@ void SessionsBox::Inner::paintEvent(QPaintEvent *e) {
|
|||
p.setPen(st::boxTextFg);
|
||||
p.drawTextLeft(x, st::sessionPadding.top() + st::sessionNameFont->height, w, auth.info, auth.infoWidth);
|
||||
p.setPen(st::sessionInfoFg);
|
||||
p.drawTextLeft(x, st::sessionPadding.top() + st::sessionNameFont->height + st::sessionInfoFont->height, w, auth.ip, auth.ipWidth);
|
||||
p.drawTextLeft(x, st::sessionPadding.top() + st::sessionNameFont->height + st::sessionInfoFont->height, w,
|
||||
auth.ip, auth.ipWidth);
|
||||
|
||||
p.translate(0, st::sessionHeight);
|
||||
}
|
||||
|
@ -306,32 +318,45 @@ void SessionsBox::Inner::onTerminate() {
|
|||
for (auto i = _terminateButtons.begin(), e = _terminateButtons.end(); i != e; ++i) {
|
||||
if (i.value()->isOver()) {
|
||||
if (_terminateBox) _terminateBox->deleteLater();
|
||||
_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));
|
||||
auto i = _terminateButtons.find(terminating);
|
||||
if (i != _terminateButtons.cend()) {
|
||||
i.value()->clearState();
|
||||
i.value()->hide();
|
||||
}
|
||||
})), 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));
|
||||
auto i = _terminateButtons.find(terminating);
|
||||
if (i != _terminateButtons.cend()) {
|
||||
i.value()->clearState();
|
||||
i.value()->hide();
|
||||
}
|
||||
})),
|
||||
KeepOtherLayers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SessionsBox::Inner::onTerminateAll() {
|
||||
if (_terminateBox) _terminateBox->deleteLater();
|
||||
_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);
|
||||
_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(quint64 hash, const MTPBool &result) {
|
||||
|
@ -367,7 +392,8 @@ bool SessionsBox::Inner::terminateAllFail(const RPCError &error) {
|
|||
}
|
||||
|
||||
void SessionsBox::Inner::resizeEvent(QResizeEvent *e) {
|
||||
_terminateAll->moveToLeft(st::sessionPadding.left(), st::sessionCurrentPadding.top() + st::sessionHeight + st::sessionCurrentPadding.bottom());
|
||||
_terminateAll->moveToLeft(st::sessionPadding.left(),
|
||||
st::sessionCurrentPadding.top() + st::sessionHeight + st::sessionCurrentPadding.bottom());
|
||||
}
|
||||
|
||||
void SessionsBox::Inner::listUpdated() {
|
||||
|
@ -385,7 +411,8 @@ void SessionsBox::Inner::listUpdated() {
|
|||
j = _terminateButtons.insert(_list->at(i).hash, new Ui::IconButton(this, st::sessionTerminate));
|
||||
connect(j.value(), SIGNAL(clicked()), this, SLOT(onTerminate()));
|
||||
}
|
||||
j.value()->moveToRight(st::sessionTerminateSkip, st::sessionCurrentHeight + i * st::sessionHeight + st::sessionTerminateTop, width());
|
||||
j.value()->moveToRight(st::sessionTerminateSkip,
|
||||
st::sessionCurrentHeight + i * st::sessionHeight + st::sessionTerminateTop, width());
|
||||
j.value()->show();
|
||||
}
|
||||
for (TerminateButtons::iterator i = _terminateButtons.begin(); i != _terminateButtons.cend();) {
|
||||
|
@ -396,6 +423,7 @@ void SessionsBox::Inner::listUpdated() {
|
|||
i = _terminateButtons.erase(i);
|
||||
}
|
||||
}
|
||||
resize(width(), _list->isEmpty() ? (st::sessionCurrentHeight + st::noContactsHeight) : (st::sessionCurrentHeight + _list->size() * st::sessionHeight));
|
||||
resize(width(), _list->isEmpty() ? (st::sessionCurrentHeight + st::noContactsHeight) :
|
||||
(st::sessionCurrentHeight + _list->size() * st::sessionHeight));
|
||||
update();
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ class SessionsBox : public BoxContent, public RPCSender {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SessionsBox(QWidget*);
|
||||
SessionsBox(QWidget *);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
@ -72,7 +72,6 @@ private:
|
|||
|
||||
object_ptr<SingleTimer> _shortPollTimer;
|
||||
mtpRequestId _shortPollRequest = 0;
|
||||
|
||||
};
|
||||
|
||||
// This class is hold in header because it requires Qt preprocessing.
|
||||
|
@ -107,10 +106,9 @@ private:
|
|||
SessionsBox::List *_list;
|
||||
SessionsBox::Data *_current;
|
||||
|
||||
typedef QMap<quint64, Ui::IconButton*> TerminateButtons;
|
||||
typedef QMap<quint64, Ui::IconButton *> TerminateButtons;
|
||||
TerminateButtons _terminateButtons;
|
||||
|
||||
object_ptr<Ui::LinkButton> _terminateAll;
|
||||
QPointer<ConfirmBox> _terminateBox;
|
||||
|
||||
};
|
||||
|
|
|
@ -20,35 +20,35 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#include "boxes/share_box.h"
|
||||
|
||||
#include "dialogs/dialogs_indexed_list.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_history.h"
|
||||
#include "observer_peer.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwindow.h"
|
||||
#include "mainwidget.h"
|
||||
#include "base/qthelp_url.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "apiwrap.h"
|
||||
#include "ui/toast/toast.h"
|
||||
#include "ui/widgets/multi_select.h"
|
||||
#include "auth_session.h"
|
||||
#include "base/qthelp_url.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "boxes/peer_list_box.h"
|
||||
#include "dialogs/dialogs_indexed_list.h"
|
||||
#include "history/history_media_types.h"
|
||||
#include "history/history_message.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
#include "messenger.h"
|
||||
#include "observer_peer.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_history.h"
|
||||
#include "ui/toast/toast.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/multi_select.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "window/themes/window_theme.h"
|
||||
#include "boxes/peer_list_box.h"
|
||||
#include "auth_session.h"
|
||||
#include "messenger.h"
|
||||
|
||||
ShareBox::ShareBox(QWidget*, CopyCallback &©Callback, SubmitCallback &&submitCallback, FilterCallback &&filterCallback)
|
||||
: _copyCallback(std::move(copyCallback))
|
||||
, _submitCallback(std::move(submitCallback))
|
||||
, _filterCallback(std::move(filterCallback))
|
||||
, _select(this, st::contactsMultiSelect, langFactory(lng_participant_filter))
|
||||
, _searchTimer(this) {
|
||||
}
|
||||
ShareBox::ShareBox(QWidget *, CopyCallback &©Callback, SubmitCallback &&submitCallback,
|
||||
FilterCallback &&filterCallback)
|
||||
: _copyCallback(std::move(copyCallback))
|
||||
, _submitCallback(std::move(submitCallback))
|
||||
, _filterCallback(std::move(filterCallback))
|
||||
, _select(this, st::contactsMultiSelect, langFactory(lng_participant_filter))
|
||||
, _searchTimer(this) {}
|
||||
|
||||
void ShareBox::prepare() {
|
||||
_select->resizeToWidth(st::boxWideWidth);
|
||||
|
@ -57,7 +57,7 @@ void ShareBox::prepare() {
|
|||
setTitle(langFactory(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(_inner, SIGNAL(mustScrollTo(int, int)), this, SLOT(onMustScrollTo(int, int)));
|
||||
|
||||
createButtons();
|
||||
|
||||
|
@ -74,9 +74,8 @@ void ShareBox::prepare() {
|
|||
_select->setResizedCallback([this] { updateScrollSkips(); });
|
||||
_select->setSubmittedCallback([this](bool) { _inner->onSelectActive(); });
|
||||
connect(_inner, SIGNAL(searchByUsername()), this, SLOT(onNeedSearchByUsername()));
|
||||
_inner->setPeerSelectedChangedCallback([this](PeerData *peer, bool checked) {
|
||||
onPeerSelectedChanged(peer, checked);
|
||||
});
|
||||
_inner->setPeerSelectedChangedCallback(
|
||||
[this](PeerData *peer, bool checked) { onPeerSelectedChanged(peer, checked); });
|
||||
|
||||
_searchTimer->setSingleShot(true);
|
||||
connect(_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchByUsername()));
|
||||
|
@ -116,7 +115,8 @@ bool ShareBox::onSearchByUsername(bool searchCache) {
|
|||
} else if (_peopleQuery != query) {
|
||||
_peopleQuery = query;
|
||||
_peopleFull = false;
|
||||
_peopleRequest = MTP::send(MTPcontacts_Search(MTP_string(_peopleQuery), MTP_int(SearchPeopleLimit)), rpcDone(&ShareBox::peopleReceived), rpcFail(&ShareBox::peopleFailed));
|
||||
_peopleRequest = MTP::send(MTPcontacts_Search(MTP_string(_peopleQuery), MTP_int(SearchPeopleLimit)),
|
||||
rpcDone(&ShareBox::peopleReceived), rpcFail(&ShareBox::peopleFailed));
|
||||
_peopleQueries.insert(_peopleRequest, _peopleQuery);
|
||||
}
|
||||
}
|
||||
|
@ -274,9 +274,10 @@ void ShareBox::scrollAnimationCallback() {
|
|||
// scrollArea()->scrollToY(scrollTop);
|
||||
}
|
||||
|
||||
ShareBox::Inner::Inner(QWidget *parent, ShareBox::FilterCallback &&filterCallback) : TWidget(parent)
|
||||
, _filterCallback(std::move(filterCallback))
|
||||
, _chatsIndexed(std::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Add)) {
|
||||
ShareBox::Inner::Inner(QWidget *parent, ShareBox::FilterCallback &&filterCallback)
|
||||
: TWidget(parent)
|
||||
, _filterCallback(std::move(filterCallback))
|
||||
, _chatsIndexed(std::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Add)) {
|
||||
_rowsTop = st::shareRowsTop;
|
||||
_rowHeight = st::shareRowHeight;
|
||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
|
@ -294,9 +295,9 @@ ShareBox::Inner::Inner(QWidget *parent, ShareBox::FilterCallback &&filterCallbac
|
|||
|
||||
using UpdateFlag = Notify::PeerUpdate::Flag;
|
||||
auto observeEvents = UpdateFlag::NameChanged | UpdateFlag::PhotoChanged;
|
||||
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(observeEvents, [this](const Notify::PeerUpdate &update) {
|
||||
notifyPeerUpdated(update);
|
||||
}));
|
||||
subscribe(Notify::PeerUpdated(),
|
||||
Notify::PeerUpdatedHandler(observeEvents,
|
||||
[this](const Notify::PeerUpdate &update) { notifyPeerUpdated(update); }));
|
||||
subscribe(Auth().downloaderTaskFinished(), [this] { update(); });
|
||||
|
||||
subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &update) {
|
||||
|
@ -307,9 +308,7 @@ ShareBox::Inner::Inner(QWidget *parent, ShareBox::FilterCallback &&filterCallbac
|
|||
}
|
||||
|
||||
void ShareBox::Inner::invalidateCache() {
|
||||
for_const (auto data, _dataMap) {
|
||||
data->checkbox.invalidateCache();
|
||||
}
|
||||
for_const (auto data, _dataMap) { data->checkbox.invalidateCache(); }
|
||||
}
|
||||
|
||||
void ShareBox::Inner::setVisibleTopBottom(int visibleTop, int visibleBottom) {
|
||||
|
@ -376,12 +375,12 @@ void ShareBox::Inner::repaintChatAtIndex(int index) {
|
|||
|
||||
ShareBox::Inner::Chat *ShareBox::Inner::getChatAtIndex(int index) {
|
||||
if (index < 0) return nullptr;
|
||||
auto row = ([this, index]() -> Dialogs::Row* {
|
||||
auto row = ([this, index]() -> Dialogs::Row * {
|
||||
if (_filter.isEmpty()) return _chatsIndexed->rowAtY(index, 1);
|
||||
return (index < _filtered.size()) ? _filtered[index] : nullptr;
|
||||
})();
|
||||
if (row) {
|
||||
return static_cast<Chat*>(row->attached);
|
||||
return static_cast<Chat *>(row->attached);
|
||||
}
|
||||
|
||||
if (!_filter.isEmpty()) {
|
||||
|
@ -464,7 +463,7 @@ void ShareBox::Inner::loadProfilePhotos(int yFrom) {
|
|||
}
|
||||
|
||||
ShareBox::Inner::Chat *ShareBox::Inner::getChat(Dialogs::Row *row) {
|
||||
auto data = static_cast<Chat*>(row->attached);
|
||||
auto data = static_cast<Chat *>(row->attached);
|
||||
if (!data) {
|
||||
auto peer = row->history()->peer;
|
||||
auto i = _dataMap.constFind(peer);
|
||||
|
@ -484,9 +483,8 @@ void ShareBox::Inner::setActive(int active) {
|
|||
if (active != _active) {
|
||||
auto changeNameFg = [this](int index, double from, double to) {
|
||||
if (auto chat = getChatAtIndex(index)) {
|
||||
chat->nameActive.start([this, peer = chat->peer] {
|
||||
repaintChat(peer);
|
||||
}, from, to, st::shareActivateDuration);
|
||||
chat->nameActive.start([this, peer = chat->peer] { repaintChat(peer); }, from, to,
|
||||
st::shareActivateDuration);
|
||||
}
|
||||
};
|
||||
changeNameFg(_active, 1., 0.);
|
||||
|
@ -516,10 +514,9 @@ void ShareBox::Inner::paintChat(Painter &p, TimeMs ms, Chat *chat, int index) {
|
|||
}
|
||||
|
||||
ShareBox::Inner::Chat::Chat(PeerData *peer, base::lambda<void()> updateCallback)
|
||||
: peer(peer)
|
||||
, checkbox(st::sharePhotoCheckbox, updateCallback, PaintUserpicCallback(peer))
|
||||
, name(st::sharePhotoCheckbox.imageRadius * 2) {
|
||||
}
|
||||
: peer(peer)
|
||||
, checkbox(st::sharePhotoCheckbox, updateCallback, PaintUserpicCallback(peer))
|
||||
, name(st::sharePhotoCheckbox.imageRadius * 2) {}
|
||||
|
||||
void ShareBox::Inner::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
|
@ -601,7 +598,8 @@ void ShareBox::Inner::updateUpon(const QPoint &pos) {
|
|||
auto left = _rowsLeft + std::floor(column * _rowWidthReal) + st::shareColumnSkip / 2;
|
||||
auto top = _rowsTop + row * _rowHeight + st::sharePhotoTop;
|
||||
auto xupon = (x >= left) && (x < left + (_rowWidth - st::shareColumnSkip));
|
||||
auto yupon = (y >= top) && (y < top + st::sharePhotoCheckbox.imageRadius * 2 + st::shareNameTop + st::shareNameStyle.font->height * 2);
|
||||
auto yupon = (y >= top) && (y < top + st::sharePhotoCheckbox.imageRadius * 2 + st::shareNameTop +
|
||||
st::shareNameStyle.font->height * 2);
|
||||
auto upon = (xupon && yupon) ? (row * _columnCount + column) : -1;
|
||||
if (upon >= displayedChatsCount()) {
|
||||
upon = -1;
|
||||
|
@ -783,13 +781,11 @@ void ShareBox::Inner::refresh() {
|
|||
}
|
||||
|
||||
ShareBox::Inner::~Inner() {
|
||||
for_const (auto chat, _dataMap) {
|
||||
delete chat;
|
||||
}
|
||||
for_const (auto chat, _dataMap) { delete chat; }
|
||||
}
|
||||
|
||||
QVector<PeerData*> ShareBox::Inner::selected() const {
|
||||
QVector<PeerData*> result;
|
||||
QVector<PeerData *> ShareBox::Inner::selected() const {
|
||||
QVector<PeerData *> result;
|
||||
result.reserve(_dataMap.size());
|
||||
for_const (auto chat, _dataMap) {
|
||||
if (chat->checkbox.checked()) {
|
||||
|
@ -801,10 +797,10 @@ QVector<PeerData*> ShareBox::Inner::selected() const {
|
|||
|
||||
QString AppendShareGameScoreUrl(const QString &url, const FullMsgId &fullId) {
|
||||
auto shareHashData = QByteArray(0x10, Qt::Uninitialized);
|
||||
auto shareHashDataInts = reinterpret_cast<qint32*>(shareHashData.data());
|
||||
auto channel = fullId.channel ? App::channelLoaded(fullId.channel) : static_cast<ChannelData*>(nullptr);
|
||||
auto shareHashDataInts = reinterpret_cast<qint32 *>(shareHashData.data());
|
||||
auto channel = fullId.channel ? App::channelLoaded(fullId.channel) : static_cast<ChannelData *>(nullptr);
|
||||
auto channelAccessHash = channel ? channel->access : 0ULL;
|
||||
auto channelAccessHashInts = reinterpret_cast<qint32*>(&channelAccessHash);
|
||||
auto channelAccessHashInts = reinterpret_cast<qint32 *>(&channelAccessHash);
|
||||
shareHashDataInts[0] = Auth().userId();
|
||||
shareHashDataInts[1] = fullId.channel;
|
||||
shareHashDataInts[2] = fullId.msg;
|
||||
|
@ -816,10 +812,11 @@ QString AppendShareGameScoreUrl(const QString &url, const FullMsgId &fullId) {
|
|||
hashSha1(shareHashData.constData(), shareHashData.size(), shareHashEncrypted.data());
|
||||
|
||||
// Mix in channel access hash to the first 64 bits of SHA1 of data.
|
||||
*reinterpret_cast<quint64*>(shareHashEncrypted.data()) ^= *reinterpret_cast<quint64*>(channelAccessHashInts);
|
||||
*reinterpret_cast<quint64 *>(shareHashEncrypted.data()) ^= *reinterpret_cast<quint64 *>(channelAccessHashInts);
|
||||
|
||||
// Encrypt data.
|
||||
if (!Local::encrypt(shareHashData.constData(), shareHashEncrypted.data() + key128Size, shareHashData.size(), shareHashEncrypted.constData())) {
|
||||
if (!Local::encrypt(shareHashData.constData(), shareHashEncrypted.data() + key128Size, shareHashData.size(),
|
||||
shareHashEncrypted.constData())) {
|
||||
return url;
|
||||
}
|
||||
|
||||
|
@ -845,7 +842,8 @@ QString AppendShareGameScoreUrl(const QString &url, const FullMsgId &fullId) {
|
|||
void ShareGameScoreByHash(const QString &hash) {
|
||||
auto key128Size = 0x10;
|
||||
|
||||
auto hashEncrypted = QByteArray::fromBase64(hash.toLatin1(), QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
|
||||
auto hashEncrypted =
|
||||
QByteArray::fromBase64(hash.toLatin1(), QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
|
||||
if (hashEncrypted.size() <= key128Size || (hashEncrypted.size() % 0x10) != 0) {
|
||||
Ui::show(Box<InformBox>(lang(lng_confirm_phone_link_invalid)));
|
||||
return;
|
||||
|
@ -853,16 +851,18 @@ void ShareGameScoreByHash(const QString &hash) {
|
|||
|
||||
// Decrypt data.
|
||||
auto hashData = QByteArray(hashEncrypted.size() - key128Size, Qt::Uninitialized);
|
||||
if (!Local::decrypt(hashEncrypted.constData() + key128Size, hashData.data(), hashEncrypted.size() - key128Size, hashEncrypted.constData())) {
|
||||
if (!Local::decrypt(hashEncrypted.constData() + key128Size, hashData.data(), hashEncrypted.size() - key128Size,
|
||||
hashEncrypted.constData())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Count SHA1() of data.
|
||||
char dataSha1[20] = { 0 };
|
||||
char dataSha1[20] = {0};
|
||||
hashSha1(hashData.constData(), hashData.size(), dataSha1);
|
||||
|
||||
// Mix out channel access hash from the first 64 bits of SHA1 of data.
|
||||
auto channelAccessHash = *reinterpret_cast<quint64*>(hashEncrypted.data()) ^ *reinterpret_cast<quint64*>(dataSha1);
|
||||
auto channelAccessHash =
|
||||
*reinterpret_cast<quint64 *>(hashEncrypted.data()) ^ *reinterpret_cast<quint64 *>(dataSha1);
|
||||
|
||||
// Check next 64 bits of SHA1() of data.
|
||||
auto skipSha1Part = sizeof(channelAccessHash);
|
||||
|
@ -871,14 +871,14 @@ void ShareGameScoreByHash(const QString &hash) {
|
|||
return;
|
||||
}
|
||||
|
||||
auto hashDataInts = reinterpret_cast<qint32*>(hashData.data());
|
||||
auto hashDataInts = reinterpret_cast<qint32 *>(hashData.data());
|
||||
if (!AuthSession::Exists() || hashDataInts[0] != Auth().userId()) {
|
||||
Ui::show(Box<InformBox>(lang(lng_share_wrong_user)));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check first 32 bits of channel access hash.
|
||||
auto channelAccessHashInts = reinterpret_cast<qint32*>(&channelAccessHash);
|
||||
auto channelAccessHashInts = reinterpret_cast<qint32 *>(&channelAccessHash);
|
||||
if (channelAccessHashInts[0] != hashDataInts[3]) {
|
||||
Ui::show(Box<InformBox>(lang(lng_share_wrong_user)));
|
||||
return;
|
||||
|
@ -909,16 +909,18 @@ void ShareGameScoreByHash(const QString &hash) {
|
|||
if (channel || !channelId) {
|
||||
resolveMessageAndShareScore(channel);
|
||||
} else {
|
||||
auto requestChannelIds = MTP_vector<MTPInputChannel>(1, MTP_inputChannel(MTP_int(channelId), MTP_long(channelAccessHash)));
|
||||
auto requestChannelIds =
|
||||
MTP_vector<MTPInputChannel>(1, MTP_inputChannel(MTP_int(channelId), MTP_long(channelAccessHash)));
|
||||
auto requestChannel = MTPchannels_GetChannels(requestChannelIds);
|
||||
MTP::send(requestChannel, rpcDone([channelId, resolveMessageAndShareScore](const MTPmessages_Chats &result) {
|
||||
if (auto chats = Api::getChatsFromMessagesChats(result)) {
|
||||
App::feedChats(*chats);
|
||||
}
|
||||
if (auto channel = App::channelLoaded(channelId)) {
|
||||
resolveMessageAndShareScore(channel);
|
||||
}
|
||||
}));
|
||||
MTP::send(requestChannel,
|
||||
rpcDone([channelId, resolveMessageAndShareScore](const MTPmessages_Chats &result) {
|
||||
if (auto chats = Api::getChatsFromMessagesChats(result)) {
|
||||
App::feedChats(*chats);
|
||||
}
|
||||
if (auto channel = App::channelLoaded(channelId)) {
|
||||
resolveMessageAndShareScore(channel);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,8 +20,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "boxes/abstract_box.h"
|
||||
#include "base/observer.h"
|
||||
#include "boxes/abstract_box.h"
|
||||
#include "ui/effects/round_checkbox.h"
|
||||
|
||||
namespace Dialogs {
|
||||
|
@ -45,9 +45,9 @@ class ShareBox : public BoxContent, public RPCSender {
|
|||
|
||||
public:
|
||||
using CopyCallback = base::lambda<void()>;
|
||||
using SubmitCallback = base::lambda<void(const QVector<PeerData*> &)>;
|
||||
using FilterCallback = base::lambda<bool(PeerData*)>;
|
||||
ShareBox(QWidget*, CopyCallback &©Callback, SubmitCallback &&submitCallback, FilterCallback &&filterCallback);
|
||||
using SubmitCallback = base::lambda<void(const QVector<PeerData *> &)>;
|
||||
using FilterCallback = base::lambda<bool(PeerData *)>;
|
||||
ShareBox(QWidget *, CopyCallback &©Callback, SubmitCallback &&submitCallback, FilterCallback &&filterCallback);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
@ -104,7 +104,6 @@ private:
|
|||
PeopleQueries _peopleQueries;
|
||||
|
||||
Animation _scrollAnimation;
|
||||
|
||||
};
|
||||
|
||||
// This class is hold in header because it requires Qt preprocessing.
|
||||
|
@ -117,7 +116,7 @@ public:
|
|||
void setPeerSelectedChangedCallback(base::lambda<void(PeerData *peer, bool selected)> callback);
|
||||
void peerUnselected(PeerData *peer);
|
||||
|
||||
QVector<PeerData*> selected() const;
|
||||
QVector<PeerData *> selected() const;
|
||||
bool hasSelected() const;
|
||||
|
||||
void peopleReceived(const QString &query, const QVector<MTPPeer> &people);
|
||||
|
@ -195,12 +194,12 @@ private:
|
|||
ShareBox::FilterCallback _filterCallback;
|
||||
std::unique_ptr<Dialogs::IndexedList> _chatsIndexed;
|
||||
QString _filter;
|
||||
using FilteredDialogs = QVector<Dialogs::Row*>;
|
||||
using FilteredDialogs = QVector<Dialogs::Row *>;
|
||||
FilteredDialogs _filtered;
|
||||
|
||||
using DataMap = QMap<PeerData*, Chat*>;
|
||||
using DataMap = QMap<PeerData *, Chat *>;
|
||||
DataMap _dataMap;
|
||||
using SelectedChats = OrderedSet<PeerData*>;
|
||||
using SelectedChats = OrderedSet<PeerData *>;
|
||||
SelectedChats _selected;
|
||||
|
||||
base::lambda<void(PeerData *peer, bool selected)> _peerSelectedChangedCallback;
|
||||
|
@ -209,9 +208,8 @@ private:
|
|||
|
||||
bool _searching = false;
|
||||
QString _lastQuery;
|
||||
using ByUsernameRows = QVector<PeerData*>;
|
||||
using ByUsernameDatas = QVector<Chat*>;
|
||||
using ByUsernameRows = QVector<PeerData *>;
|
||||
using ByUsernameDatas = QVector<Chat *>;
|
||||
ByUsernameRows _byUsernameFiltered;
|
||||
ByUsernameDatas d_byUsernameFiltered;
|
||||
|
||||
};
|
||||
|
|
|
@ -20,20 +20,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#include "boxes/sticker_set_box.h"
|
||||
|
||||
#include "apiwrap.h"
|
||||
#include "auth_session.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "chat_helpers/stickers.h"
|
||||
#include "dialogs/dialogs_layout.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
#include "chat_helpers/stickers.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "apiwrap.h"
|
||||
#include "messenger.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "dialogs/dialogs_layout.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_chat_helpers.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "auth_session.h"
|
||||
#include "messenger.h"
|
||||
#include <QApplication>
|
||||
#include <QClipboard>
|
||||
|
||||
|
@ -43,9 +43,8 @@ constexpr auto kStickersPanelPerRow = Stickers::kPanelPerRow;
|
|||
|
||||
} // namespace
|
||||
|
||||
StickerSetBox::StickerSetBox(QWidget*, const MTPInputStickerSet &set)
|
||||
: _set(set) {
|
||||
}
|
||||
StickerSetBox::StickerSetBox(QWidget *, const MTPInputStickerSet &set)
|
||||
: _set(set) {}
|
||||
|
||||
void StickerSetBox::prepare() {
|
||||
setTitle(langFactory(lng_contacts_loading));
|
||||
|
@ -104,10 +103,14 @@ void StickerSetBox::resizeEvent(QResizeEvent *e) {
|
|||
_inner->resize(width(), _inner->height());
|
||||
}
|
||||
|
||||
StickerSetBox::Inner::Inner(QWidget *parent, const MTPInputStickerSet &set) : TWidget(parent)
|
||||
, _input(set) {
|
||||
StickerSetBox::Inner::Inner(QWidget *parent, const MTPInputStickerSet &set)
|
||||
: TWidget(parent)
|
||||
, _input(set) {
|
||||
switch (set.type()) {
|
||||
case mtpc_inputStickerSetID: _setId = set.c_inputStickerSetID().vid.v; _setAccess = set.c_inputStickerSetID().vaccess_hash.v; break;
|
||||
case mtpc_inputStickerSetID:
|
||||
_setId = set.c_inputStickerSetID().vid.v;
|
||||
_setAccess = set.c_inputStickerSetID().vaccess_hash.v;
|
||||
break;
|
||||
case mtpc_inputStickerSetShortName: _setShortName = qs(set.c_inputStickerSetShortName().vshort_name); break;
|
||||
}
|
||||
MTP::send(MTPmessages_GetStickerSet(_input), rpcDone(&Inner::gotSet), rpcFail(&Inner::failedSet));
|
||||
|
@ -170,7 +173,9 @@ void StickerSetBox::Inner::gotSet(const MTPmessages_StickerSet &set) {
|
|||
auto &sets = Global::RefStickerSets();
|
||||
auto it = sets.find(_setId);
|
||||
if (it != sets.cend()) {
|
||||
auto clientFlags = it->flags & (MTPDstickerSet_ClientFlag::f_featured | MTPDstickerSet_ClientFlag::f_not_loaded | MTPDstickerSet_ClientFlag::f_unread | MTPDstickerSet_ClientFlag::f_special);
|
||||
auto clientFlags =
|
||||
it->flags & (MTPDstickerSet_ClientFlag::f_featured | MTPDstickerSet_ClientFlag::f_not_loaded |
|
||||
MTPDstickerSet_ClientFlag::f_unread | MTPDstickerSet_ClientFlag::f_special);
|
||||
_setFlags |= clientFlags;
|
||||
it->flags = _setFlags;
|
||||
it->stickers = _pack;
|
||||
|
@ -183,7 +188,8 @@ void StickerSetBox::Inner::gotSet(const MTPmessages_StickerSet &set) {
|
|||
Ui::show(Box<InformBox>(lang(lng_stickers_not_found)));
|
||||
} else {
|
||||
qint32 rows = _pack.size() / kStickersPanelPerRow + ((_pack.size() % kStickersPanelPerRow) ? 1 : 0);
|
||||
resize(st::stickersPadding.left() + kStickersPanelPerRow * st::stickersSize.width(), st::stickersPadding.top() + rows * st::stickersSize.height() + st::stickersPadding.bottom());
|
||||
resize(st::stickersPadding.left() + kStickersPanelPerRow * st::stickersSize.width(),
|
||||
st::stickersPadding.top() + rows * st::stickersSize.height() + st::stickersPadding.bottom());
|
||||
}
|
||||
_loaded = true;
|
||||
|
||||
|
@ -216,7 +222,8 @@ void StickerSetBox::Inner::installDone(const MTPmessages_StickerSetInstallResult
|
|||
_setFlags |= MTPDstickerSet::Flag::f_installed;
|
||||
auto it = sets.find(_setId);
|
||||
if (it == sets.cend()) {
|
||||
it = sets.insert(_setId, Stickers::Set(_setId, _setAccess, _setTitle, _setShortName, _setCount, _setHash, _setFlags));
|
||||
it = sets.insert(_setId,
|
||||
Stickers::Set(_setId, _setAccess, _setTitle, _setShortName, _setCount, _setHash, _setFlags));
|
||||
} else {
|
||||
it->flags = _setFlags;
|
||||
}
|
||||
|
@ -319,13 +326,15 @@ void StickerSetBox::Inner::setSelected(int selected) {
|
|||
|
||||
void StickerSetBox::Inner::startOverAnimation(int index, double from, double to) {
|
||||
if (index >= 0 && index < _packOvers.size()) {
|
||||
_packOvers[index].start([this, index] {
|
||||
int row = index / kStickersPanelPerRow;
|
||||
int column = index % kStickersPanelPerRow;
|
||||
int left = st::stickersPadding.left() + column * st::stickersSize.width();
|
||||
int top = st::stickersPadding.top() + row * st::stickersSize.height();
|
||||
rtlupdate(left, top, st::stickersSize.width(), st::stickersSize.height());
|
||||
}, from, to, st::emojiPanDuration);
|
||||
_packOvers[index].start(
|
||||
[this, index] {
|
||||
int row = index / kStickersPanelPerRow;
|
||||
int column = index % kStickersPanelPerRow;
|
||||
int left = st::stickersPadding.left() + column * st::stickersSize.width();
|
||||
int top = st::stickersPadding.top() + row * st::stickersSize.height();
|
||||
rtlupdate(left, top, st::stickersSize.width(), st::stickersSize.height());
|
||||
},
|
||||
from, to, st::emojiPanDuration);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -340,8 +349,12 @@ void StickerSetBox::Inner::onPreview() {
|
|||
qint32 StickerSetBox::Inner::stickerFromGlobalPos(const QPoint &p) const {
|
||||
QPoint l(mapFromGlobal(p));
|
||||
if (rtl()) l.setX(width() - l.x());
|
||||
qint32 row = (l.y() >= st::stickersPadding.top()) ? std::floor((l.y() - st::stickersPadding.top()) / st::stickersSize.height()) : -1;
|
||||
qint32 col = (l.x() >= st::stickersPadding.left()) ? std::floor((l.x() - st::stickersPadding.left()) / st::stickersSize.width()) : -1;
|
||||
qint32 row = (l.y() >= st::stickersPadding.top()) ?
|
||||
std::floor((l.y() - st::stickersPadding.top()) / st::stickersSize.height()) :
|
||||
-1;
|
||||
qint32 col = (l.x() >= st::stickersPadding.left()) ?
|
||||
std::floor((l.x() - st::stickersPadding.left()) / st::stickersSize.width()) :
|
||||
-1;
|
||||
if (row >= 0 && col >= 0 && col < kStickersPanelPerRow) {
|
||||
qint32 result = row * kStickersPanelPerRow + col;
|
||||
return (result < _pack.size()) ? result : -1;
|
||||
|
@ -357,7 +370,8 @@ void StickerSetBox::Inner::paintEvent(QPaintEvent *e) {
|
|||
|
||||
auto ms = getms();
|
||||
qint32 rows = _pack.size() / kStickersPanelPerRow + ((_pack.size() % kStickersPanelPerRow) ? 1 : 0);
|
||||
qint32 from = std::floor(e->rect().top() / st::stickersSize.height()), to = std::floor(e->rect().bottom() / st::stickersSize.height()) + 1;
|
||||
qint32 from = std::floor(e->rect().top() / st::stickersSize.height()),
|
||||
to = std::floor(e->rect().bottom() / st::stickersSize.height()) + 1;
|
||||
|
||||
for (qint32 i = from; i < to; ++i) {
|
||||
for (qint32 j = 0; j < kStickersPanelPerRow; ++j) {
|
||||
|
@ -366,7 +380,8 @@ void StickerSetBox::Inner::paintEvent(QPaintEvent *e) {
|
|||
Assert(index < _packOvers.size());
|
||||
|
||||
DocumentData *doc = _pack.at(index);
|
||||
QPoint pos(st::stickersPadding.left() + j * st::stickersSize.width(), st::stickersPadding.top() + i * st::stickersSize.height());
|
||||
QPoint pos(st::stickersPadding.left() + j * st::stickersSize.width(),
|
||||
st::stickersPadding.top() + i * st::stickersSize.height());
|
||||
|
||||
if (auto over = _packOvers[index].current(ms, (index == _selected) ? 1. : 0.)) {
|
||||
p.setOpacity(over);
|
||||
|
@ -374,7 +389,6 @@ void StickerSetBox::Inner::paintEvent(QPaintEvent *e) {
|
|||
if (rtl()) tl.setX(width() - tl.x() - st::stickersSize.width());
|
||||
App::roundRect(p, QRect(tl, st::stickersSize), st::emojiPanHover, StickerHoverCorners);
|
||||
p.setOpacity(1);
|
||||
|
||||
}
|
||||
bool goodThumb = !doc->thumb->isNull() && ((doc->thumb->width() >= 128) || (doc->thumb->height() >= 128));
|
||||
if (goodThumb) {
|
||||
|
@ -388,7 +402,9 @@ void StickerSetBox::Inner::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
}
|
||||
|
||||
double coef = std::min((st::stickersSize.width() - st::buttonRadius * 2) / double(doc->dimensions.width()), (st::stickersSize.height() - st::buttonRadius * 2) / double(doc->dimensions.height()));
|
||||
double coef =
|
||||
std::min((st::stickersSize.width() - st::buttonRadius * 2) / double(doc->dimensions.width()),
|
||||
(st::stickersSize.height() - st::buttonRadius * 2) / double(doc->dimensions.height()));
|
||||
if (coef > 1) coef = 1;
|
||||
qint32 w = std::round(coef * doc->dimensions.width()), h = std::round(coef * doc->dimensions.height());
|
||||
if (w < 1) w = 1;
|
||||
|
@ -415,7 +431,9 @@ bool StickerSetBox::Inner::loaded() const {
|
|||
qint32 StickerSetBox::Inner::notInstalled() const {
|
||||
if (!_loaded) return 0;
|
||||
auto it = Global::StickerSets().constFind(_setId);
|
||||
if (it == Global::StickerSets().cend() || !(it->flags & MTPDstickerSet::Flag::f_installed) || (it->flags & MTPDstickerSet::Flag::f_archived)) return _pack.size();
|
||||
if (it == Global::StickerSets().cend() || !(it->flags & MTPDstickerSet::Flag::f_installed) ||
|
||||
(it->flags & MTPDstickerSet::Flag::f_archived))
|
||||
return _pack.size();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -424,15 +442,15 @@ bool StickerSetBox::Inner::official() const {
|
|||
}
|
||||
|
||||
base::lambda<TextWithEntities()> StickerSetBox::Inner::title() const {
|
||||
auto text = TextWithEntities { _setTitle };
|
||||
auto text = TextWithEntities{_setTitle};
|
||||
if (_loaded) {
|
||||
if (_pack.isEmpty()) {
|
||||
return [] { return TextWithEntities { lang(lng_attach_failed), EntitiesInText() }; };
|
||||
return [] { return TextWithEntities{lang(lng_attach_failed), EntitiesInText()}; };
|
||||
} else {
|
||||
TextUtilities::ParseEntities(text, TextParseMentions);
|
||||
}
|
||||
} else {
|
||||
return [] { return TextWithEntities { lang(lng_contacts_loading), EntitiesInText() }; };
|
||||
return [] { return TextWithEntities{lang(lng_contacts_loading), EntitiesInText()}; };
|
||||
}
|
||||
return [text] { return text; };
|
||||
}
|
||||
|
@ -447,8 +465,8 @@ void StickerSetBox::Inner::install() {
|
|||
return;
|
||||
}
|
||||
if (_installRequest) return;
|
||||
_installRequest = MTP::send(MTPmessages_InstallStickerSet(_input, MTP_bool(false)), rpcDone(&Inner::installDone), rpcFail(&Inner::installFail));
|
||||
_installRequest = MTP::send(MTPmessages_InstallStickerSet(_input, MTP_bool(false)), rpcDone(&Inner::installDone),
|
||||
rpcFail(&Inner::installFail));
|
||||
}
|
||||
|
||||
StickerSetBox::Inner::~Inner() {
|
||||
}
|
||||
StickerSetBox::Inner::~Inner() {}
|
||||
|
|
|
@ -33,7 +33,7 @@ class StickerSetBox : public BoxContent, public RPCSender {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
StickerSetBox(QWidget*, const MTPInputStickerSet &set);
|
||||
StickerSetBox(QWidget *, const MTPInputStickerSet &set);
|
||||
|
||||
signals:
|
||||
void installed(quint64 id);
|
||||
|
@ -57,7 +57,6 @@ private:
|
|||
|
||||
class Inner;
|
||||
QPointer<Inner> _inner;
|
||||
|
||||
};
|
||||
|
||||
// This class is hold in header because it requires Qt preprocessing.
|
||||
|
@ -129,5 +128,4 @@ private:
|
|||
|
||||
QTimer _previewTimer;
|
||||
int _previewShown = -1;
|
||||
|
||||
};
|
||||
|
|
|
@ -20,25 +20,25 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#include "stickers_box.h"
|
||||
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwidget.h"
|
||||
#include "chat_helpers/stickers.h"
|
||||
#include "apiwrap.h"
|
||||
#include "auth_session.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "boxes/sticker_set_box.h"
|
||||
#include "apiwrap.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "chat_helpers/stickers.h"
|
||||
#include "dialogs/dialogs_layout.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwidget.h"
|
||||
#include "messenger.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_chat_helpers.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "ui/effects/slide_animation.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/discrete_sliders.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "auth_session.h"
|
||||
#include "messenger.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -55,7 +55,8 @@ int stickerPacksCount(bool includeArchivedOfficial) {
|
|||
for (auto i = 0, l = order.size(); i < l; ++i) {
|
||||
auto it = sets.constFind(order.at(i));
|
||||
if (it != sets.cend()) {
|
||||
if (!(it->flags & MTPDstickerSet::Flag::f_archived) || ((it->flags & MTPDstickerSet::Flag::f_official) && includeArchivedOfficial)) {
|
||||
if (!(it->flags & MTPDstickerSet::Flag::f_archived) ||
|
||||
((it->flags & MTPDstickerSet::Flag::f_official) && includeArchivedOfficial)) {
|
||||
++result;
|
||||
}
|
||||
}
|
||||
|
@ -77,10 +78,10 @@ private:
|
|||
|
||||
QString _text;
|
||||
Dialogs::Layout::UnreadBadgeStyle _st;
|
||||
|
||||
};
|
||||
|
||||
StickersBox::CounterWidget::CounterWidget(QWidget *parent) : TWidget(parent) {
|
||||
StickersBox::CounterWidget::CounterWidget(QWidget *parent)
|
||||
: TWidget(parent) {
|
||||
setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
|
||||
_st.sizeId = Dialogs::Layout::UnreadBadgeInStickersBox;
|
||||
|
@ -119,12 +120,11 @@ void StickersBox::CounterWidget::updateCounter() {
|
|||
update();
|
||||
}
|
||||
|
||||
template <typename ...Args>
|
||||
StickersBox::Tab::Tab(int index, Args&&... args)
|
||||
: _index(index)
|
||||
, _widget(std::forward<Args>(args)...)
|
||||
, _weak(_widget) {
|
||||
}
|
||||
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);
|
||||
|
@ -139,20 +139,20 @@ 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) {
|
||||
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) {
|
||||
_tabs->setRippleTopRoundRadius(st::boxRadius);
|
||||
}
|
||||
|
||||
StickersBox::StickersBox(QWidget*, not_null<ChannelData*> megagroup)
|
||||
: _section(Section::Installed)
|
||||
, _installed(0, this, megagroup)
|
||||
, _megagroupSet(megagroup) {
|
||||
StickersBox::StickersBox(QWidget *, not_null<ChannelData *> megagroup)
|
||||
: _section(Section::Installed)
|
||||
, _installed(0, this, megagroup)
|
||||
, _megagroupSet(megagroup) {
|
||||
subscribe(_installed.widget()->scrollToY, [this](int y) { onScrollToY(y); });
|
||||
}
|
||||
|
||||
|
@ -243,9 +243,7 @@ void StickersBox::prepare() {
|
|||
preloadArchivedSets();
|
||||
}
|
||||
setNoContentMargin(true);
|
||||
_tabs->setSectionActivatedCallback([this] {
|
||||
switchTab();
|
||||
});
|
||||
_tabs->setSectionActivatedCallback([this] { switchTab(); });
|
||||
refreshTabs();
|
||||
}
|
||||
if (_installed.widget() && _section != Section::Installed) _installed.widget()->hide();
|
||||
|
@ -261,7 +259,10 @@ void StickersBox::prepare() {
|
|||
}
|
||||
|
||||
if (_megagroupSet) {
|
||||
addButton(langFactory(lng_settings_save), [this] { _installed.widget()->saveGroupSet(); closeBox(); });
|
||||
addButton(langFactory(lng_settings_save), [this] {
|
||||
_installed.widget()->saveGroupSet();
|
||||
closeBox();
|
||||
});
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
} else {
|
||||
addButton(langFactory(lng_about_done), [this] { closeBox(); });
|
||||
|
@ -310,8 +311,8 @@ void StickersBox::refreshTabs() {
|
|||
_tabIndices.push_back(Section::Archived);
|
||||
}
|
||||
_tabs->setSections(sections);
|
||||
if ((_tab == &_archived && !_tabIndices.contains(Section::Archived))
|
||||
|| (_tab == &_featured && !_tabIndices.contains(Section::Featured))) {
|
||||
if ((_tab == &_archived && !_tabIndices.contains(Section::Archived)) ||
|
||||
(_tab == &_featured && !_tabIndices.contains(Section::Featured))) {
|
||||
switchTab();
|
||||
} else if (_tab == &_archived) {
|
||||
_tabs->setActiveSectionFast(_tabIndices.indexOf(Section::Archived));
|
||||
|
@ -327,7 +328,8 @@ void StickersBox::loadMoreArchived() {
|
|||
}
|
||||
|
||||
quint64 lastId = 0;
|
||||
for (auto setIt = Global::ArchivedStickerSetsOrder().cend(), e = Global::ArchivedStickerSetsOrder().cbegin(); setIt != e;) {
|
||||
for (auto setIt = Global::ArchivedStickerSetsOrder().cend(), e = Global::ArchivedStickerSetsOrder().cbegin();
|
||||
setIt != e;) {
|
||||
--setIt;
|
||||
auto it = Global::StickerSets().constFind(*setIt);
|
||||
if (it != Global::StickerSets().cend()) {
|
||||
|
@ -337,7 +339,9 @@ void StickersBox::loadMoreArchived() {
|
|||
}
|
||||
}
|
||||
}
|
||||
_archivedRequestId = MTP::send(MTPmessages_GetArchivedStickers(MTP_flags(0), MTP_long(lastId), MTP_int(kArchivedLimitPerPage)), rpcDone(&StickersBox::getArchivedDone, lastId));
|
||||
_archivedRequestId =
|
||||
MTP::send(MTPmessages_GetArchivedStickers(MTP_flags(0), MTP_long(lastId), MTP_int(kArchivedLimitPerPage)),
|
||||
rpcDone(&StickersBox::getArchivedDone, lastId));
|
||||
}
|
||||
|
||||
void StickersBox::paintEvent(QPaintEvent *e) {
|
||||
|
@ -456,7 +460,8 @@ void StickersBox::installSet(quint64 setId) {
|
|||
_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));
|
||||
MTP::send(MTPmessages_InstallStickerSet(Stickers::inputSetId(*it), MTP_boolFalse()),
|
||||
rpcDone(&StickersBox::installDone), rpcFail(&StickersBox::installFail, setId));
|
||||
|
||||
Stickers::InstallLocally(setId);
|
||||
}
|
||||
|
@ -486,10 +491,8 @@ void StickersBox::preloadArchivedSets() {
|
|||
if (!_tabs) return;
|
||||
if (!_archivedRequestId) {
|
||||
_archivedRequestId =
|
||||
MTP::send(MTPmessages_GetArchivedStickers(MTP_flags(0),
|
||||
MTP_long(0),
|
||||
MTP_int(kArchivedLimitFirstRequest)),
|
||||
rpcDone(&StickersBox::getArchivedDone, Q_UINT64_C(0)));
|
||||
MTP::send(MTPmessages_GetArchivedStickers(MTP_flags(0), MTP_long(0), MTP_int(kArchivedLimitFirstRequest)),
|
||||
rpcDone(&StickersBox::getArchivedDone, Q_UINT64_C(0)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -572,49 +575,57 @@ void StickersBox::setInnerFocus() {
|
|||
|
||||
StickersBox::~StickersBox() = default;
|
||||
|
||||
StickersBox::Inner::Row::Row(quint64 id, DocumentData *sticker, qint32 count, const QString &title, int titleWidth, bool installed, bool official, bool unread, bool archived, bool removed, qint32 pixw, qint32 pixh) : id(id)
|
||||
, sticker(sticker)
|
||||
, count(count)
|
||||
, title(title)
|
||||
, titleWidth(titleWidth)
|
||||
, installed(installed)
|
||||
, official(official)
|
||||
, unread(unread)
|
||||
, archived(archived)
|
||||
, removed(removed)
|
||||
, pixw(pixw)
|
||||
, pixh(pixh) {
|
||||
}
|
||||
StickersBox::Inner::Row::Row(quint64 id, DocumentData *sticker, qint32 count, const QString &title, int titleWidth,
|
||||
bool installed, bool official, bool unread, bool archived, bool removed, qint32 pixw,
|
||||
qint32 pixh)
|
||||
: id(id)
|
||||
, sticker(sticker)
|
||||
, count(count)
|
||||
, title(title)
|
||||
, titleWidth(titleWidth)
|
||||
, installed(installed)
|
||||
, official(official)
|
||||
, unread(unread)
|
||||
, archived(archived)
|
||||
, removed(removed)
|
||||
, pixw(pixw)
|
||||
, pixh(pixh) {}
|
||||
|
||||
StickersBox::Inner::Row::~Row() = default;
|
||||
|
||||
StickersBox::Inner::Inner(QWidget *parent, StickersBox::Section section) : TWidget(parent)
|
||||
, _section(section)
|
||||
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
|
||||
, _a_shifting(animation(this, &Inner::step_shifting))
|
||||
, _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)) {
|
||||
StickersBox::Inner::Inner(QWidget *parent, StickersBox::Section section)
|
||||
: TWidget(parent)
|
||||
, _section(section)
|
||||
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
|
||||
, _a_shifting(animation(this, &Inner::step_shifting))
|
||||
, _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)) {
|
||||
setup();
|
||||
}
|
||||
|
||||
StickersBox::Inner::Inner(QWidget *parent, not_null<ChannelData*> megagroup) : TWidget(parent)
|
||||
, _section(StickersBox::Section::Installed)
|
||||
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
|
||||
, _a_shifting(animation(this, &Inner::step_shifting))
|
||||
, _itemsTop(st::membersMarginTop)
|
||||
, _megagroupSet(megagroup)
|
||||
, _megagroupSetInput(_megagroupSet->mgInfo->stickerSet)
|
||||
, _megagroupSetField(this, st::groupStickersField, [] { return qsl("stickerset"); }, QString(), true)
|
||||
, _megagroupDivider(this)
|
||||
, _megagroupSubTitle(this, lang(lng_stickers_group_from_your), Ui::FlatLabel::InitType::Simple, st::boxTitle) {
|
||||
StickersBox::Inner::Inner(QWidget *parent, not_null<ChannelData *> megagroup)
|
||||
: TWidget(parent)
|
||||
, _section(StickersBox::Section::Installed)
|
||||
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
|
||||
, _a_shifting(animation(this, &Inner::step_shifting))
|
||||
, _itemsTop(st::membersMarginTop)
|
||||
, _megagroupSet(megagroup)
|
||||
, _megagroupSetInput(_megagroupSet->mgInfo->stickerSet)
|
||||
, _megagroupSetField(this, st::groupStickersField, [] { return qsl("stickerset"); }, QString(), true)
|
||||
, _megagroupDivider(this)
|
||||
, _megagroupSubTitle(this, lang(lng_stickers_group_from_your), Ui::FlatLabel::InitType::Simple, st::boxTitle) {
|
||||
_megagroupSetField->setLinkPlaceholder(Messenger::Instance().createInternalLink(qsl("addstickers/")));
|
||||
_megagroupSetField->setPlaceholderHidden(false);
|
||||
_megagroupSetAddressChangedTimer.setCallback([this] { handleMegagroupSetAddressChange(); });
|
||||
connect(_megagroupSetField, &Ui::MaskedInputField::changed, this, [this] { _megagroupSetAddressChangedTimer.callOnce(kHandleMegagroupSetAddressChangeTimeout); });
|
||||
connect(_megagroupSetField, &Ui::MaskedInputField::submitted, this, [this] { _megagroupSetAddressChangedTimer.cancel(); handleMegagroupSetAddressChange(); });
|
||||
connect(_megagroupSetField, &Ui::MaskedInputField::changed, this,
|
||||
[this] { _megagroupSetAddressChangedTimer.callOnce(kHandleMegagroupSetAddressChangeTimeout); });
|
||||
connect(_megagroupSetField, &Ui::MaskedInputField::submitted, this, [this] {
|
||||
_megagroupSetAddressChangedTimer.cancel();
|
||||
handleMegagroupSetAddressChange();
|
||||
});
|
||||
|
||||
setup();
|
||||
}
|
||||
|
@ -683,12 +694,14 @@ void StickersBox::Inner::updateControlsGeometry() {
|
|||
if (_megagroupSet) {
|
||||
auto top = st::groupStickersFieldPadding.top();
|
||||
auto fieldLeft = st::boxLayerTitlePosition.x();
|
||||
_megagroupSetField->setGeometryToLeft(fieldLeft, top, width() - fieldLeft - st::groupStickersFieldPadding.right(), _megagroupSetField->height());
|
||||
_megagroupSetField->setGeometryToLeft(
|
||||
fieldLeft, top, width() - fieldLeft - st::groupStickersFieldPadding.right(), _megagroupSetField->height());
|
||||
top += _megagroupSetField->height() + st::groupStickersFieldPadding.bottom();
|
||||
if (_megagroupSelectedRemove) {
|
||||
_megagroupSelectedShadow->setGeometryToLeft(0, top, width(), st::lineWidth);
|
||||
top += st::lineWidth;
|
||||
_megagroupSelectedRemove->moveToRight(st::groupStickersRemovePosition.x(), top + st::groupStickersRemovePosition.y());
|
||||
_megagroupSelectedRemove->moveToRight(st::groupStickersRemovePosition.x(),
|
||||
top + st::groupStickersRemovePosition.y());
|
||||
top += _rowHeight;
|
||||
}
|
||||
_megagroupDivider->setGeometryToLeft(0, top, width(), _megagroupDivider->height());
|
||||
|
@ -736,7 +749,10 @@ void StickersBox::Inner::paintRow(Painter &p, Row *set, int index, TimeMs ms) {
|
|||
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));
|
||||
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);
|
||||
Ui::Shadow::paint(p, row, width(), st::boxRoundShadow);
|
||||
p.setOpacity(1);
|
||||
|
@ -762,14 +778,16 @@ void StickersBox::Inner::paintRow(Painter &p, Row *set, int index, TimeMs ms) {
|
|||
if (!_megagroupSet && _section == Section::Installed) {
|
||||
stickerx += st::stickersReorderIcon.width() + st::stickersReorderSkip;
|
||||
if (!set->isRecentSet()) {
|
||||
st::stickersReorderIcon.paint(p, st::contactsPadding.left(), (_rowHeight - st::stickersReorderIcon.height()) / 2, width());
|
||||
st::stickersReorderIcon.paint(p, st::contactsPadding.left(),
|
||||
(_rowHeight - st::stickersReorderIcon.height()) / 2, width());
|
||||
}
|
||||
}
|
||||
|
||||
if (set->sticker) {
|
||||
set->sticker->thumb->load();
|
||||
auto pix = set->sticker->thumb->pix(set->pixw, set->pixh);
|
||||
p.drawPixmapLeft(stickerx + (st::contactsPhotoSize - set->pixw) / 2, st::contactsPadding.top() + (st::contactsPhotoSize - set->pixh) / 2, width(), pix);
|
||||
p.drawPixmapLeft(stickerx + (st::contactsPhotoSize - set->pixw) / 2,
|
||||
st::contactsPadding.top() + (st::contactsPhotoSize - set->pixh) / 2, width(), pix);
|
||||
}
|
||||
|
||||
int namex = stickerx + st::contactsPhotoSize + st::contactsPadding.left();
|
||||
|
@ -788,7 +806,9 @@ void StickersBox::Inner::paintRow(Painter &p, Row *set, int index, TimeMs ms) {
|
|||
|
||||
{
|
||||
PainterHighQualityEnabler hq(p);
|
||||
p.drawEllipse(rtlrect(namex + set->titleWidth + st::stickersFeaturedUnreadSkip, namey + st::stickersFeaturedUnreadTop, st::stickersFeaturedUnreadSize, st::stickersFeaturedUnreadSize, width()));
|
||||
p.drawEllipse(rtlrect(namex + set->titleWidth + st::stickersFeaturedUnreadSkip,
|
||||
namey + st::stickersFeaturedUnreadTop, st::stickersFeaturedUnreadSize,
|
||||
st::stickersFeaturedUnreadSize, width()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -807,7 +827,8 @@ void StickersBox::Inner::paintFakeButton(Painter &p, Row *set, int index, TimeMs
|
|||
auto rect = relativeButtonRect(removeButton);
|
||||
if (_section != Section::Installed && set->installed && !set->archived && !set->removed) {
|
||||
// Checkbox after installed from Trending or Archived.
|
||||
int checkx = width() - (st::contactsPadding.right() + st::contactsCheckPosition.x() + (rect.width() + st::stickersFeaturedInstalled.width()) / 2);
|
||||
int checkx = width() - (st::contactsPadding.right() + st::contactsCheckPosition.x() +
|
||||
(rect.width() + st::stickersFeaturedInstalled.width()) / 2);
|
||||
int checky = st::contactsPadding.top() + (st::contactsPhotoSize - st::stickersFeaturedInstalled.height()) / 2;
|
||||
st::stickersFeaturedInstalled.paint(p, QPoint(checkx, checky), width());
|
||||
} else {
|
||||
|
@ -896,7 +917,8 @@ void StickersBox::Inner::setActionDown(int newActionDown) {
|
|||
}
|
||||
if (set->ripple) {
|
||||
auto rect = relativeButtonRect(removeButton);
|
||||
set->ripple->add(mapFromGlobal(QCursor::pos()) - QPoint(myrtlrect(rect).x(), _itemsTop + _actionDown * _rowHeight + rect.y()));
|
||||
set->ripple->add(mapFromGlobal(QCursor::pos()) -
|
||||
QPoint(myrtlrect(rect).x(), _itemsTop + _actionDown * _rowHeight + rect.y()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -931,18 +953,19 @@ void StickersBox::Inner::setPressed(int pressed) {
|
|||
auto &set = _rows[_pressed];
|
||||
auto rippleMask = Ui::RippleAnimation::rectMask(QSize(width(), _rowHeight));
|
||||
if (!_rows[_pressed]->ripple) {
|
||||
_rows[_pressed]->ripple = std::make_unique<Ui::RippleAnimation>(st::contactsRipple, std::move(rippleMask), [this, index = _pressed] {
|
||||
update(0, _itemsTop + index * _rowHeight, width(), _rowHeight);
|
||||
});
|
||||
_rows[_pressed]->ripple = std::make_unique<Ui::RippleAnimation>(
|
||||
st::contactsRipple, std::move(rippleMask),
|
||||
[this, index = _pressed] { update(0, _itemsTop + index * _rowHeight, width(), _rowHeight); });
|
||||
}
|
||||
_rows[_pressed]->ripple->add(mapFromGlobal(QCursor::pos()) - QPoint(0, _itemsTop + _pressed * _rowHeight));
|
||||
}
|
||||
}
|
||||
|
||||
void StickersBox::Inner::ensureRipple(const style::RippleAnimation &st, QImage mask, bool removeButton) {
|
||||
_rows[_actionDown]->ripple = std::make_unique<Ui::RippleAnimation>(st, std::move(mask), [this, index = _actionDown, removeButton] {
|
||||
update(myrtlrect(relativeButtonRect(removeButton).translated(0, _itemsTop + index * _rowHeight)));
|
||||
});
|
||||
_rows[_actionDown]->ripple =
|
||||
std::make_unique<Ui::RippleAnimation>(st, std::move(mask), [this, index = _actionDown, removeButton] {
|
||||
update(myrtlrect(relativeButtonRect(removeButton).translated(0, _itemsTop + index * _rowHeight)));
|
||||
});
|
||||
}
|
||||
|
||||
void StickersBox::Inner::mouseMoveEvent(QMouseEvent *e) {
|
||||
|
@ -960,14 +983,16 @@ void StickersBox::Inner::onUpdateSelected() {
|
|||
++firstSetIndex;
|
||||
}
|
||||
if (_dragStart.y() > local.y() && _dragging > 0) {
|
||||
shift = -floorclamp(_dragStart.y() - local.y() + (_rowHeight / 2), _rowHeight, 0, _dragging - firstSetIndex);
|
||||
shift =
|
||||
-floorclamp(_dragStart.y() - local.y() + (_rowHeight / 2), _rowHeight, 0, _dragging - firstSetIndex);
|
||||
for (qint32 from = _dragging, to = _dragging + shift; from > to; --from) {
|
||||
qSwap(_rows[from], _rows[from - 1]);
|
||||
_rows[from]->yadd = anim::value(_rows[from]->yadd.current() - _rowHeight, 0);
|
||||
_animStartTimes[from] = ms;
|
||||
}
|
||||
} else if (_dragStart.y() < local.y() && _dragging + 1 < _rows.size()) {
|
||||
shift = floorclamp(local.y() - _dragStart.y() + (_rowHeight / 2), _rowHeight, 0, _rows.size() - _dragging - 1);
|
||||
shift =
|
||||
floorclamp(local.y() - _dragStart.y() + (_rowHeight / 2), _rowHeight, 0, _rows.size() - _dragging - 1);
|
||||
for (qint32 from = _dragging, to = _dragging + shift; from < to; ++from) {
|
||||
qSwap(_rows[from], _rows[from + 1]);
|
||||
_rows[from]->yadd = anim::value(_rows[from]->yadd.current() + _rowHeight, 0);
|
||||
|
@ -1005,7 +1030,8 @@ void StickersBox::Inner::onUpdateSelected() {
|
|||
selected = floorclamp(local.y() - _itemsTop, _rowHeight, 0, _rows.size() - 1);
|
||||
local.setY(local.y() - _itemsTop - selected * _rowHeight);
|
||||
auto &set = _rows[selected];
|
||||
if (!_megagroupSet && (_section == Section::Installed || !set->installed || set->archived || set->removed)) {
|
||||
if (!_megagroupSet &&
|
||||
(_section == Section::Installed || !set->installed || set->archived || set->removed)) {
|
||||
auto removeButton = (_section == Section::Installed && !set->removed);
|
||||
auto rect = myrtlrect(relativeButtonRect(removeButton));
|
||||
actionSel = rect.contains(local) ? selected : -1;
|
||||
|
@ -1013,7 +1039,8 @@ void StickersBox::Inner::onUpdateSelected() {
|
|||
actionSel = -1;
|
||||
}
|
||||
if (!_megagroupSet && _section == Section::Installed && !set->isRecentSet()) {
|
||||
auto dragAreaWidth = st::contactsPadding.left() + st::stickersReorderIcon.width() + st::stickersReorderSkip;
|
||||
auto dragAreaWidth =
|
||||
st::contactsPadding.left() + st::stickersReorderIcon.width() + st::stickersReorderSkip;
|
||||
auto dragArea = myrtlrect(0, 0, dragAreaWidth, _rowHeight);
|
||||
inDragArea = dragArea.contains(local);
|
||||
}
|
||||
|
@ -1021,7 +1048,8 @@ void StickersBox::Inner::onUpdateSelected() {
|
|||
selected = -1;
|
||||
}
|
||||
if (_selected != selected) {
|
||||
if ((_megagroupSet || _section != Section::Installed) && ((_selected >= 0 || _pressed >= 0) != (selected >= 0 || _pressed >= 0))) {
|
||||
if ((_megagroupSet || _section != Section::Installed) &&
|
||||
((_selected >= 0 || _pressed >= 0) != (selected >= 0 || _pressed >= 0))) {
|
||||
if (!inDragArea) {
|
||||
setCursor((selected >= 0 || _pressed >= 0) ? style::cur_pointer : style::cur_default);
|
||||
}
|
||||
|
@ -1030,7 +1058,8 @@ void StickersBox::Inner::onUpdateSelected() {
|
|||
}
|
||||
if (_inDragArea != inDragArea) {
|
||||
_inDragArea = inDragArea;
|
||||
setCursor(_inDragArea ? style::cur_sizeall : (_selected >= 0 || _pressed >= 0) ? style::cur_pointer : style::cur_default);
|
||||
setCursor(_inDragArea ? style::cur_sizeall :
|
||||
(_selected >= 0 || _pressed >= 0) ? style::cur_pointer : style::cur_default);
|
||||
}
|
||||
setActionSel(actionSel);
|
||||
emit draggingScrollDelta(0);
|
||||
|
@ -1042,7 +1071,7 @@ double StickersBox::Inner::aboveShadowOpacity() const {
|
|||
|
||||
auto dx = 0;
|
||||
auto dy = qAbs(_above * _rowHeight + std::round(_rows[_above]->yadd.current()) - _started * _rowHeight);
|
||||
return std::min((dx + dy) * 2. / _rowHeight, 1.);
|
||||
return std::min((dx + dy) * 2. / _rowHeight, 1.);
|
||||
}
|
||||
|
||||
void StickersBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
|
||||
|
@ -1092,8 +1121,11 @@ void StickersBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
|
|||
|
||||
void StickersBox::Inner::saveGroupSet() {
|
||||
Expects(_megagroupSet != nullptr);
|
||||
auto oldId = (_megagroupSet->mgInfo->stickerSet.type() == mtpc_inputStickerSetID) ? _megagroupSet->mgInfo->stickerSet.c_inputStickerSetID().vid.v : 0;
|
||||
auto newId = (_megagroupSetInput.type() == mtpc_inputStickerSetID) ? _megagroupSetInput.c_inputStickerSetID().vid.v : 0;
|
||||
auto oldId = (_megagroupSet->mgInfo->stickerSet.type() == mtpc_inputStickerSetID) ?
|
||||
_megagroupSet->mgInfo->stickerSet.c_inputStickerSetID().vid.v :
|
||||
0;
|
||||
auto newId =
|
||||
(_megagroupSetInput.type() == mtpc_inputStickerSetID) ? _megagroupSetInput.c_inputStickerSetID().vid.v : 0;
|
||||
if (newId != oldId) {
|
||||
Auth().api().setGroupStickerSet(_megagroupSet, _megagroupSetInput);
|
||||
App::main()->onStickersInstalled(Stickers::MegagroupSetId);
|
||||
|
@ -1142,7 +1174,8 @@ void StickersBox::Inner::step_shifting(TimeMs ms, bool timer) {
|
|||
if (updateMin < 0 || updateMin > _above) updateMin = _above;
|
||||
if (updateMax < _above) updateMin = _above;
|
||||
if (_aboveShadowFadeStart + st::stickersRowDuration > ms && ms > _aboveShadowFadeStart) {
|
||||
_aboveShadowFadeOpacity.update(double(ms - _aboveShadowFadeStart) / st::stickersRowDuration, anim::sineInOut);
|
||||
_aboveShadowFadeOpacity.update(double(ms - _aboveShadowFadeStart) / st::stickersRowDuration,
|
||||
anim::sineInOut);
|
||||
animating = true;
|
||||
} else {
|
||||
_aboveShadowFadeOpacity.finish();
|
||||
|
@ -1189,7 +1222,8 @@ void StickersBox::Inner::setActionSel(qint32 actionSel) {
|
|||
_actionSel = actionSel;
|
||||
if (_actionSel >= 0) update(0, _itemsTop + _actionSel * _rowHeight, width(), _rowHeight);
|
||||
if (_section == Section::Installed) {
|
||||
setCursor((_actionSel >= 0 && (_actionDown < 0 || _actionDown == _actionSel)) ? style::cur_pointer : style::cur_default);
|
||||
setCursor((_actionSel >= 0 && (_actionDown < 0 || _actionDown == _actionSel)) ? style::cur_pointer :
|
||||
style::cur_default);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1204,14 +1238,18 @@ void StickersBox::Inner::handleMegagroupSetAddressChange() {
|
|||
}
|
||||
}
|
||||
} else if (!_megagroupSetRequestId) {
|
||||
_megagroupSetRequestId = request(MTPmessages_GetStickerSet(MTP_inputStickerSetShortName(MTP_string(text)))).done([this](const MTPmessages_StickerSet &result) {
|
||||
_megagroupSetRequestId = 0;
|
||||
auto set = Stickers::FeedSetFull(result);
|
||||
setMegagroupSelectedSet(MTP_inputStickerSetID(MTP_long(set->id), MTP_long(set->access)));
|
||||
}).fail([this](const RPCError &error) {
|
||||
_megagroupSetRequestId = 0;
|
||||
setMegagroupSelectedSet(MTP_inputStickerSetEmpty());
|
||||
}).send();
|
||||
_megagroupSetRequestId =
|
||||
request(MTPmessages_GetStickerSet(MTP_inputStickerSetShortName(MTP_string(text))))
|
||||
.done([this](const MTPmessages_StickerSet &result) {
|
||||
_megagroupSetRequestId = 0;
|
||||
auto set = Stickers::FeedSetFull(result);
|
||||
setMegagroupSelectedSet(MTP_inputStickerSetID(MTP_long(set->id), MTP_long(set->access)));
|
||||
})
|
||||
.fail([this](const RPCError &error) {
|
||||
_megagroupSetRequestId = 0;
|
||||
setMegagroupSelectedSet(MTP_inputStickerSetEmpty());
|
||||
})
|
||||
.send();
|
||||
} else {
|
||||
_megagroupSetAddressChangedTimer.callOnce(kHandleMegagroupSetAddressChangeTimeout);
|
||||
}
|
||||
|
@ -1242,7 +1280,7 @@ void StickersBox::Inner::rebuildMegagroupSet() {
|
|||
auto titleWidth = 0;
|
||||
auto title = fillSetTitle(*it, maxNameWidth, &titleWidth);
|
||||
auto count = fillSetCount(*it);
|
||||
auto sticker = (DocumentData*)nullptr;
|
||||
auto sticker = (DocumentData *)nullptr;
|
||||
auto pixw = 0, pixh = 0;
|
||||
fillSetCover(*it, &sticker, &pixw, &pixh);
|
||||
auto installed = true, official = false, unread = false, archived = false, removed = false;
|
||||
|
@ -1250,15 +1288,14 @@ void StickersBox::Inner::rebuildMegagroupSet() {
|
|||
_megagroupSetField->setText(it->shortName);
|
||||
_megagroupSetField->finishAnimations();
|
||||
}
|
||||
_megagroupSelectedSet = std::make_unique<Row>(it->id, sticker, count, title, titleWidth, installed, official, unread, archived, removed, pixw, pixh);
|
||||
_megagroupSelectedSet = std::make_unique<Row>(it->id, sticker, count, title, titleWidth, installed, official,
|
||||
unread, archived, removed, pixw, pixh);
|
||||
_itemsTop += st::lineWidth + _rowHeight;
|
||||
|
||||
if (!_megagroupSelectedRemove) {
|
||||
_megagroupSelectedRemove.create(this, st::groupStickersRemove);
|
||||
_megagroupSelectedRemove->showFast();
|
||||
_megagroupSelectedRemove->setClickedCallback([this] {
|
||||
setMegagroupSelectedSet(MTP_inputStickerSetEmpty());
|
||||
});
|
||||
_megagroupSelectedRemove->setClickedCallback([this] { setMegagroupSelectedSet(MTP_inputStickerSetEmpty()); });
|
||||
_megagroupSelectedShadow.create(this);
|
||||
updateControlsGeometry();
|
||||
}
|
||||
|
@ -1268,7 +1305,8 @@ void StickersBox::Inner::rebuild() {
|
|||
_itemsTop = st::membersMarginTop;
|
||||
|
||||
if (_megagroupSet) {
|
||||
_itemsTop += st::groupStickersFieldPadding.top() + _megagroupSetField->height() + st::groupStickersFieldPadding.bottom();
|
||||
_itemsTop +=
|
||||
st::groupStickersFieldPadding.top() + _megagroupSetField->height() + st::groupStickersFieldPadding.bottom();
|
||||
_itemsTop += _megagroupDivider->height() + st::groupStickersSubTitleHeight;
|
||||
rebuildMegagroupSet();
|
||||
}
|
||||
|
@ -1336,7 +1374,7 @@ void StickersBox::Inner::updateRows() {
|
|||
if (it != sets.cend()) {
|
||||
auto &set = it.value();
|
||||
if (!row->sticker) {
|
||||
auto sticker = (DocumentData*)nullptr;
|
||||
auto sticker = (DocumentData *)nullptr;
|
||||
auto pixw = 0, pixh = 0;
|
||||
fillSetCover(set, &sticker, &pixw, &pixh);
|
||||
if (sticker) {
|
||||
|
@ -1404,11 +1442,13 @@ void StickersBox::Inner::rebuildAppendSet(const Stickers::Set &set, int maxNameW
|
|||
QString title = fillSetTitle(set, maxNameWidth, &titleWidth);
|
||||
int count = fillSetCount(set);
|
||||
|
||||
_rows.push_back(std::make_unique<Row>(set.id, sticker, count, title, titleWidth, installed, official, unread, archived, removed, pixw, pixh));
|
||||
_rows.push_back(std::make_unique<Row>(set.id, sticker, count, title, titleWidth, installed, official, unread,
|
||||
archived, removed, pixw, pixh));
|
||||
_animStartTimes.push_back(0);
|
||||
}
|
||||
|
||||
void StickersBox::Inner::fillSetCover(const Stickers::Set &set, DocumentData **outSticker, int *outWidth, int *outHeight) const {
|
||||
void StickersBox::Inner::fillSetCover(const Stickers::Set &set, DocumentData **outSticker, int *outWidth,
|
||||
int *outHeight) const {
|
||||
if (set.stickers.isEmpty()) {
|
||||
*outSticker = nullptr;
|
||||
*outWidth = *outHeight = 0;
|
||||
|
@ -1465,7 +1505,8 @@ QString StickersBox::Inner::fillSetTitle(const Stickers::Set &set, int maxNameWi
|
|||
return result;
|
||||
}
|
||||
|
||||
void StickersBox::Inner::fillSetFlags(const Stickers::Set &set, bool *outInstalled, bool *outOfficial, bool *outUnread, bool *outArchived) {
|
||||
void StickersBox::Inner::fillSetFlags(const Stickers::Set &set, bool *outInstalled, bool *outOfficial, bool *outUnread,
|
||||
bool *outArchived) {
|
||||
*outInstalled = (set.flags & MTPDstickerSet::Flag::f_installed);
|
||||
*outOfficial = (set.flags & MTPDstickerSet::Flag::f_official);
|
||||
*outArchived = (set.flags & MTPDstickerSet::Flag::f_archived);
|
||||
|
@ -1476,8 +1517,7 @@ void StickersBox::Inner::fillSetFlags(const Stickers::Set &set, bool *outInstall
|
|||
}
|
||||
}
|
||||
|
||||
template <typename Check>
|
||||
Stickers::Order StickersBox::Inner::collectSets(Check check) const {
|
||||
template <typename Check> Stickers::Order StickersBox::Inner::collectSets(Check check) const {
|
||||
Stickers::Order result;
|
||||
result.reserve(_rows.size());
|
||||
for_const (auto &row, _rows) {
|
||||
|
@ -1489,21 +1529,15 @@ Stickers::Order StickersBox::Inner::collectSets(Check check) const {
|
|||
}
|
||||
|
||||
Stickers::Order StickersBox::Inner::getOrder() const {
|
||||
return collectSets([](Row *row) {
|
||||
return !row->archived && !row->removed && !row->isRecentSet();
|
||||
});
|
||||
return collectSets([](Row *row) { return !row->archived && !row->removed && !row->isRecentSet(); });
|
||||
}
|
||||
|
||||
Stickers::Order StickersBox::Inner::getFullOrder() const {
|
||||
return collectSets([](Row *row) {
|
||||
return !row->isRecentSet();
|
||||
});
|
||||
return collectSets([](Row *row) { return !row->isRecentSet(); });
|
||||
}
|
||||
|
||||
Stickers::Order StickersBox::Inner::getRemovedSets() const {
|
||||
return collectSets([](Row *row) {
|
||||
return row->removed;
|
||||
});
|
||||
return collectSets([](Row *row) { return row->removed; });
|
||||
}
|
||||
|
||||
int StickersBox::Inner::getRowIndex(quint64 setId) const {
|
||||
|
|
|
@ -20,8 +20,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "boxes/abstract_box.h"
|
||||
#include "base/timer.h"
|
||||
#include "boxes/abstract_box.h"
|
||||
#include "mtproto/sender.h"
|
||||
|
||||
class ConfirmBox;
|
||||
|
@ -46,8 +46,8 @@ public:
|
|||
Featured,
|
||||
Archived,
|
||||
};
|
||||
StickersBox(QWidget*, Section section);
|
||||
StickersBox(QWidget*, not_null<ChannelData*> megagroup);
|
||||
StickersBox(QWidget *, Section section);
|
||||
StickersBox(QWidget *, not_null<ChannelData *> megagroup);
|
||||
|
||||
void setInnerFocus() override;
|
||||
|
||||
|
@ -65,8 +65,7 @@ private:
|
|||
public:
|
||||
Tab() = default;
|
||||
|
||||
template <typename ...Args>
|
||||
Tab(int index, Args&&... args);
|
||||
template <typename... Args> Tab(int index, Args &&... args);
|
||||
|
||||
object_ptr<Inner> takeWidget();
|
||||
void returnWidget(object_ptr<Inner> widget);
|
||||
|
@ -85,10 +84,9 @@ private:
|
|||
|
||||
private:
|
||||
int _index = 0;
|
||||
object_ptr<Inner> _widget = { nullptr };
|
||||
object_ptr<Inner> _widget = {nullptr};
|
||||
QPointer<Inner> _weak;
|
||||
int _scrollTop = 0;
|
||||
|
||||
};
|
||||
|
||||
void handleStickersUpdated();
|
||||
|
@ -110,11 +108,11 @@ private:
|
|||
void loadMoreArchived();
|
||||
void getArchivedDone(quint64 offsetId, const MTPmessages_ArchivedStickers &result);
|
||||
|
||||
object_ptr<Ui::SettingsSlider> _tabs = { nullptr };
|
||||
object_ptr<Ui::SettingsSlider> _tabs = {nullptr};
|
||||
QList<Section> _tabIndices;
|
||||
|
||||
class CounterWidget;
|
||||
object_ptr<CounterWidget> _unreadBadge = { nullptr };
|
||||
object_ptr<CounterWidget> _unreadBadge = {nullptr};
|
||||
|
||||
Section _section;
|
||||
|
||||
|
@ -126,7 +124,7 @@ private:
|
|||
ChannelData *_megagroupSet = nullptr;
|
||||
|
||||
std::unique_ptr<Ui::SlideAnimation> _slideAnimation;
|
||||
object_ptr<BoxLayerTitleShadow> _titleShadow = { nullptr };
|
||||
object_ptr<BoxLayerTitleShadow> _titleShadow = {nullptr};
|
||||
|
||||
mtpRequestId _archivedRequestId = 0;
|
||||
bool _archivedLoaded = false;
|
||||
|
@ -135,7 +133,6 @@ private:
|
|||
|
||||
Stickers::Order _localOrder;
|
||||
Stickers::Order _localRemoved;
|
||||
|
||||
};
|
||||
|
||||
int stickerPacksCount(bool includeArchivedOfficial = false);
|
||||
|
@ -147,7 +144,7 @@ class StickersBox::Inner : public TWidget, private base::Subscriber, private MTP
|
|||
public:
|
||||
using Section = StickersBox::Section;
|
||||
Inner(QWidget *parent, Section section);
|
||||
Inner(QWidget *parent, not_null<ChannelData*> megagroup);
|
||||
Inner(QWidget *parent, not_null<ChannelData *> megagroup);
|
||||
|
||||
base::Observable<int> scrollToY;
|
||||
void setInnerFocus();
|
||||
|
@ -199,7 +196,8 @@ public slots:
|
|||
|
||||
private:
|
||||
struct Row {
|
||||
Row(quint64 id, DocumentData *sticker, qint32 count, const QString &title, int titleWidth, bool installed, bool official, bool unread, bool archived, bool removed, qint32 pixw, qint32 pixh);
|
||||
Row(quint64 id, DocumentData *sticker, qint32 count, const QString &title, int titleWidth, bool installed,
|
||||
bool official, bool unread, bool archived, bool removed, qint32 pixw, qint32 pixh);
|
||||
bool isRecentSet() const {
|
||||
return (id == Stickers::CloudRecentSetId);
|
||||
}
|
||||
|
@ -221,8 +219,7 @@ private:
|
|||
std::unique_ptr<Ui::RippleAnimation> ripple;
|
||||
};
|
||||
|
||||
template <typename Check>
|
||||
Stickers::Order collectSets(Check check) const;
|
||||
template <typename Check> Stickers::Order collectSets(Check check) const;
|
||||
|
||||
void checkLoadMore();
|
||||
void updateScrollbarWidth();
|
||||
|
@ -250,7 +247,8 @@ private:
|
|||
void fillSetCover(const Stickers::Set &set, DocumentData **outSticker, int *outWidth, int *outHeight) const;
|
||||
int fillSetCount(const Stickers::Set &set) const;
|
||||
QString fillSetTitle(const Stickers::Set &set, int maxNameWidth, int *outTitleWidth) const;
|
||||
void fillSetFlags(const Stickers::Set &set, bool *outInstalled, bool *outOfficial, bool *outUnread, bool *outArchived);
|
||||
void fillSetFlags(const Stickers::Set &set, bool *outInstalled, bool *outOfficial, bool *outUnread,
|
||||
bool *outArchived);
|
||||
void rebuildMegagroupSet();
|
||||
void handleMegagroupSetAddressChange();
|
||||
void setMegagroupSelectedSet(const MTPInputStickerSet &set);
|
||||
|
@ -299,12 +297,11 @@ private:
|
|||
ChannelData *_megagroupSet = nullptr;
|
||||
MTPInputStickerSet _megagroupSetInput = MTP_inputStickerSetEmpty();
|
||||
std::unique_ptr<Row> _megagroupSelectedSet;
|
||||
object_ptr<Ui::UsernameInput> _megagroupSetField = { nullptr };
|
||||
object_ptr<BoxLayerTitleShadow> _megagroupSelectedShadow = { nullptr };
|
||||
object_ptr<Ui::CrossButton> _megagroupSelectedRemove = { nullptr };
|
||||
object_ptr<BoxContentDivider> _megagroupDivider = { nullptr };
|
||||
object_ptr<Ui::FlatLabel> _megagroupSubTitle = { nullptr };
|
||||
object_ptr<Ui::UsernameInput> _megagroupSetField = {nullptr};
|
||||
object_ptr<BoxLayerTitleShadow> _megagroupSelectedShadow = {nullptr};
|
||||
object_ptr<Ui::CrossButton> _megagroupSelectedRemove = {nullptr};
|
||||
object_ptr<BoxContentDivider> _megagroupDivider = {nullptr};
|
||||
object_ptr<Ui::FlatLabel> _megagroupSubTitle = {nullptr};
|
||||
base::Timer _megagroupSetAddressChangedTimer;
|
||||
mtpRequestId _megagroupSetRequestId = 0;
|
||||
|
||||
};
|
||||
|
|
|
@ -20,24 +20,23 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#include "boxes/username_box.h"
|
||||
|
||||
#include "lang/lang_keys.h"
|
||||
#include "application.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
#include "messenger.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "ui/toast/toast.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/toast/toast.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "messenger.h"
|
||||
#include <QApplication>
|
||||
#include <QClipboard>
|
||||
|
||||
UsernameBox::UsernameBox(QWidget*)
|
||||
: _username(this, st::defaultInputField, [] { return qsl("@username"); }, App::self()->username, false)
|
||||
, _link(this, QString(), st::boxLinkButton)
|
||||
, _about(st::boxWidth - st::usernamePadding.left())
|
||||
, _checkTimer(this) {
|
||||
}
|
||||
UsernameBox::UsernameBox(QWidget *)
|
||||
: _username(this, st::defaultInputField, [] { return qsl("@username"); }, App::self()->username, false)
|
||||
, _link(this, QString(), st::boxLinkButton)
|
||||
, _about(st::boxWidth - st::usernamePadding.left())
|
||||
, _checkTimer(this) {}
|
||||
|
||||
void UsernameBox::prepare() {
|
||||
_goodText = App::self()->username.isEmpty() ? QString() : lang(lng_username_available);
|
||||
|
@ -52,7 +51,9 @@ void UsernameBox::prepare() {
|
|||
connect(_link, SIGNAL(clicked()), this, SLOT(onLinkClick()));
|
||||
|
||||
_about.setRichText(st::usernameTextStyle, lang(lng_username_about));
|
||||
setDimensions(st::boxWidth, st::usernamePadding.top() + _username->height() + st::usernameSkip + _about.countHeight(st::boxWidth - st::usernamePadding.left()) + 3 * st::usernameTextStyle.lineHeight + st::usernamePadding.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());
|
||||
|
||||
_checkTimer->setSingleShot(true);
|
||||
connect(_checkTimer, SIGNAL(timeout()), this, SLOT(onCheck()));
|
||||
|
@ -72,23 +73,34 @@ void UsernameBox::paintEvent(QPaintEvent *e) {
|
|||
p.setFont(st::boxTextFont);
|
||||
if (!_errorText.isEmpty()) {
|
||||
p.setPen(st::boxTextFgError);
|
||||
p.drawTextLeft(st::usernamePadding.left(), _username->y() + _username->height() + ((st::usernameSkip - st::boxTextFont->height) / 2), width(), _errorText);
|
||||
p.drawTextLeft(st::usernamePadding.left(),
|
||||
_username->y() + _username->height() + ((st::usernameSkip - st::boxTextFont->height) / 2),
|
||||
width(), _errorText);
|
||||
} else if (!_goodText.isEmpty()) {
|
||||
p.setPen(st::boxTextFgGood);
|
||||
p.drawTextLeft(st::usernamePadding.left(), _username->y() + _username->height() + ((st::usernameSkip - st::boxTextFont->height) / 2), width(), _goodText);
|
||||
p.drawTextLeft(st::usernamePadding.left(),
|
||||
_username->y() + _username->height() + ((st::usernameSkip - st::boxTextFont->height) / 2),
|
||||
width(), _goodText);
|
||||
} else {
|
||||
p.setPen(st::usernameDefaultFg);
|
||||
p.drawTextLeft(st::usernamePadding.left(), _username->y() + _username->height() + ((st::usernameSkip - st::boxTextFont->height) / 2), width(), lang(lng_username_choose));
|
||||
p.drawTextLeft(st::usernamePadding.left(),
|
||||
_username->y() + _username->height() + ((st::usernameSkip - st::boxTextFont->height) / 2),
|
||||
width(), lang(lng_username_choose));
|
||||
}
|
||||
p.setPen(st::boxTextFg);
|
||||
qint32 availw = st::boxWidth - st::usernamePadding.left(), h = _about.countHeight(availw);
|
||||
_about.drawLeft(p, st::usernamePadding.left(), _username->y() + _username->height() + st::usernameSkip, availw, width());
|
||||
_about.drawLeft(p, st::usernamePadding.left(), _username->y() + _username->height() + st::usernameSkip, availw,
|
||||
width());
|
||||
|
||||
qint32 linky = _username->y() + _username->height() + st::usernameSkip + h + st::usernameTextStyle.lineHeight + ((st::usernameTextStyle.lineHeight - st::boxTextFont->height) / 2);
|
||||
qint32 linky = _username->y() + _username->height() + st::usernameSkip + h + st::usernameTextStyle.lineHeight +
|
||||
((st::usernameTextStyle.lineHeight - st::boxTextFont->height) / 2);
|
||||
if (_link->isHidden()) {
|
||||
p.drawTextLeft(st::usernamePadding.left(), linky, width(), lang(lng_username_link_willbe));
|
||||
p.setPen(st::usernameDefaultFg);
|
||||
p.drawTextLeft(st::usernamePadding.left(), linky + st::usernameTextStyle.lineHeight + ((st::usernameTextStyle.lineHeight - st::boxTextFont->height) / 2), width(), Messenger::Instance().createInternalLinkFull(qsl("username")));
|
||||
p.drawTextLeft(st::usernamePadding.left(),
|
||||
linky + st::usernameTextStyle.lineHeight +
|
||||
((st::usernameTextStyle.lineHeight - st::boxTextFont->height) / 2),
|
||||
width(), Messenger::Instance().createInternalLinkFull(qsl("username")));
|
||||
} else {
|
||||
p.drawTextLeft(st::usernamePadding.left(), linky, width(), lang(lng_username_link));
|
||||
}
|
||||
|
@ -101,15 +113,19 @@ void UsernameBox::resizeEvent(QResizeEvent *e) {
|
|||
_username->moveToLeft(st::usernamePadding.left(), st::usernamePadding.top());
|
||||
|
||||
qint32 availw = st::boxWidth - st::usernamePadding.left(), h = _about.countHeight(availw);
|
||||
qint32 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));
|
||||
qint32 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));
|
||||
}
|
||||
|
||||
void UsernameBox::onSave() {
|
||||
if (_saveRequestId) return;
|
||||
|
||||
_sentUsername = getName();
|
||||
_saveRequestId = MTP::send(MTPaccount_UpdateUsername(MTP_string(_sentUsername)), rpcDone(&UsernameBox::onUpdateDone), rpcFail(&UsernameBox::onUpdateFail));
|
||||
_saveRequestId = MTP::send(MTPaccount_UpdateUsername(MTP_string(_sentUsername)),
|
||||
rpcDone(&UsernameBox::onUpdateDone), rpcFail(&UsernameBox::onUpdateFail));
|
||||
}
|
||||
|
||||
void UsernameBox::onCheck() {
|
||||
|
@ -119,7 +135,8 @@ void UsernameBox::onCheck() {
|
|||
QString name = getName();
|
||||
if (name.size() >= MinUsernameLength) {
|
||||
_checkUsername = name;
|
||||
_checkRequestId = MTP::send(MTPaccount_CheckUsername(MTP_string(name)), rpcDone(&UsernameBox::onCheckDone), rpcFail(&UsernameBox::onCheckFail));
|
||||
_checkRequestId = MTP::send(MTPaccount_CheckUsername(MTP_string(name)), rpcDone(&UsernameBox::onCheckDone),
|
||||
rpcFail(&UsernameBox::onCheckFail));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,7 +153,8 @@ void UsernameBox::onChanged() {
|
|||
qint32 len = name.size();
|
||||
for (qint32 i = 0; i < len; ++i) {
|
||||
QChar ch = name.at(i);
|
||||
if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z') && (ch < '0' || ch > '9') && ch != '_' && (ch != '@' || i > 0)) {
|
||||
if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z') && (ch < '0' || ch > '9') && ch != '_' &&
|
||||
(ch != '@' || i > 0)) {
|
||||
if (_errorText != lang(lng_username_bad_symbols)) {
|
||||
_errorText = lang(lng_username_bad_symbols);
|
||||
update();
|
||||
|
@ -177,7 +195,9 @@ bool UsernameBox::onUpdateFail(const RPCError &error) {
|
|||
_saveRequestId = 0;
|
||||
QString err(error.type());
|
||||
if (err == qstr("USERNAME_NOT_MODIFIED") || _sentUsername == App::self()->username) {
|
||||
App::self()->setName(TextUtilities::SingleLine(App::self()->firstName), TextUtilities::SingleLine(App::self()->lastName), TextUtilities::SingleLine(App::self()->nameOrPhone), TextUtilities::SingleLine(_sentUsername));
|
||||
App::self()->setName(
|
||||
TextUtilities::SingleLine(App::self()->firstName), TextUtilities::SingleLine(App::self()->lastName),
|
||||
TextUtilities::SingleLine(App::self()->nameOrPhone), TextUtilities::SingleLine(_sentUsername));
|
||||
closeBox();
|
||||
return true;
|
||||
} else if (err == qstr("USERNAME_INVALID")) {
|
||||
|
@ -199,7 +219,8 @@ bool UsernameBox::onUpdateFail(const RPCError &error) {
|
|||
|
||||
void UsernameBox::onCheckDone(const MTPBool &result) {
|
||||
_checkRequestId = 0;
|
||||
QString newError = (mtpIsTrue(result) || _checkUsername == App::self()->username) ? QString() : lang(lng_username_occupied);
|
||||
QString newError =
|
||||
(mtpIsTrue(result) || _checkUsername == App::self()->username) ? QString() : lang(lng_username_occupied);
|
||||
QString newGood = newError.isEmpty() ? lang(lng_username_available) : QString();
|
||||
if (_errorText != newError || _goodText != newGood) {
|
||||
_errorText = newError;
|
||||
|
@ -233,7 +254,8 @@ QString UsernameBox::getName() const {
|
|||
|
||||
void UsernameBox::updateLinkText() {
|
||||
QString uname = getName();
|
||||
_link->setText(st::boxTextFont->elided(Messenger::Instance().createInternalLinkFull(uname), st::boxWidth - st::usernamePadding.left() - st::usernamePadding.right()));
|
||||
_link->setText(st::boxTextFont->elided(Messenger::Instance().createInternalLinkFull(uname),
|
||||
st::boxWidth - st::usernamePadding.left() - st::usernamePadding.right()));
|
||||
if (uname.isEmpty()) {
|
||||
if (!_link->isHidden()) {
|
||||
_link->hide();
|
||||
|
|
|
@ -31,7 +31,7 @@ class UsernameBox : public BoxContent, public RPCSender {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
UsernameBox(QWidget*);
|
||||
UsernameBox(QWidget *);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
@ -67,5 +67,4 @@ private:
|
|||
|
||||
Text _about;
|
||||
object_ptr<QTimer> _checkTimer;
|
||||
|
||||
};
|
||||
|
|
|
@ -20,14 +20,14 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#include "calls/calls_box_controller.h"
|
||||
|
||||
#include "styles/style_calls.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "observer_peer.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "app.h"
|
||||
#include "calls/calls_instance.h"
|
||||
#include "history/history_media_types.h"
|
||||
#include "app.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "observer_peer.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_calls.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
|
||||
namespace Calls {
|
||||
namespace {
|
||||
|
@ -53,9 +53,7 @@ public:
|
|||
void addItem(HistoryItem *item) {
|
||||
Expects(canAddItem(item));
|
||||
_items.push_back(item);
|
||||
std::sort(_items.begin(), _items.end(), [](HistoryItem *a, HistoryItem *b) {
|
||||
return (a->id > b->id);
|
||||
});
|
||||
std::sort(_items.begin(), _items.end(), [](HistoryItem *a, HistoryItem *b) { return (a->id > b->id); });
|
||||
refreshStatus();
|
||||
}
|
||||
void itemRemoved(HistoryItem *item) {
|
||||
|
@ -97,18 +95,18 @@ private:
|
|||
void refreshStatus();
|
||||
static Type ComputeType(HistoryItem *item);
|
||||
|
||||
std::vector<HistoryItem*> _items;
|
||||
std::vector<HistoryItem *> _items;
|
||||
QDate _date;
|
||||
Type _type;
|
||||
|
||||
std::unique_ptr<Ui::RippleAnimation> _actionRipple;
|
||||
|
||||
};
|
||||
|
||||
BoxController::Row::Row(HistoryItem *item) : PeerListRow(item->history()->peer, item->id)
|
||||
, _items(1, item)
|
||||
, _date(item->date.date())
|
||||
, _type(ComputeType(item)) {
|
||||
BoxController::Row::Row(HistoryItem *item)
|
||||
: PeerListRow(item->history()->peer, item->id)
|
||||
, _items(1, item)
|
||||
, _date(item->date.date())
|
||||
, _type(ComputeType(item)) {
|
||||
refreshStatus();
|
||||
}
|
||||
|
||||
|
@ -132,7 +130,8 @@ void BoxController::Row::paintStatusText(Painter &p, int x, int y, int available
|
|||
void BoxController::Row::paintAction(Painter &p, TimeMs ms, int x, int y, int outerWidth, bool actionSelected) {
|
||||
auto size = actionSize();
|
||||
if (_actionRipple) {
|
||||
_actionRipple->paint(p, x + st::callReDial.rippleAreaPosition.x(), y + st::callReDial.rippleAreaPosition.y(), outerWidth, ms);
|
||||
_actionRipple->paint(p, x + st::callReDial.rippleAreaPosition.x(), y + st::callReDial.rippleAreaPosition.y(),
|
||||
outerWidth, ms);
|
||||
if (_actionRipple->empty()) {
|
||||
_actionRipple.reset();
|
||||
}
|
||||
|
@ -154,7 +153,9 @@ void BoxController::Row::refreshStatus() {
|
|||
}
|
||||
return lng_call_box_status_date(lt_date, langDayOfMonthFull(_date), lt_time, time);
|
||||
};
|
||||
setCustomStatus((_items.size() > 1) ? lng_call_box_status_group(lt_count, QString::number(_items.size()), lt_status, text()) : text());
|
||||
setCustomStatus((_items.size() > 1) ?
|
||||
lng_call_box_status_group(lt_count, QString::number(_items.size()), lt_status, text()) :
|
||||
text());
|
||||
}
|
||||
|
||||
BoxController::Row::Type BoxController::Row::ComputeType(HistoryItem *item) {
|
||||
|
@ -162,7 +163,7 @@ BoxController::Row::Type BoxController::Row::ComputeType(HistoryItem *item) {
|
|||
return Type::Out;
|
||||
} else if (auto media = item->getMedia()) {
|
||||
if (media->type() == MediaTypeCall) {
|
||||
auto reason = static_cast<HistoryCall*>(media)->reason();
|
||||
auto reason = static_cast<HistoryCall *>(media)->reason();
|
||||
if (reason == HistoryCall::FinishReason::Busy || reason == HistoryCall::FinishReason::Missed) {
|
||||
return Type::Missed;
|
||||
}
|
||||
|
@ -173,8 +174,10 @@ BoxController::Row::Type BoxController::Row::ComputeType(HistoryItem *item) {
|
|||
|
||||
void BoxController::Row::addActionRipple(QPoint point, base::lambda<void()> updateCallback) {
|
||||
if (!_actionRipple) {
|
||||
auto mask = Ui::RippleAnimation::ellipseMask(QSize(st::callReDial.rippleAreaSize, st::callReDial.rippleAreaSize));
|
||||
_actionRipple = std::make_unique<Ui::RippleAnimation>(st::callReDial.ripple, std::move(mask), std::move(updateCallback));
|
||||
auto mask =
|
||||
Ui::RippleAnimation::ellipseMask(QSize(st::callReDial.rippleAreaSize, st::callReDial.rippleAreaSize));
|
||||
_actionRipple =
|
||||
std::make_unique<Ui::RippleAnimation>(st::callReDial.ripple, std::move(mask), std::move(updateCallback));
|
||||
}
|
||||
_actionRipple->add(point - st::callReDial.rippleAreaPosition);
|
||||
}
|
||||
|
@ -216,41 +219,49 @@ void BoxController::loadMoreRows() {
|
|||
return;
|
||||
}
|
||||
|
||||
_loadRequestId = request(MTPmessages_Search(MTP_flags(0), MTP_inputPeerEmpty(), MTP_string(QString()), MTP_inputUserEmpty(), MTP_inputMessagesFilterPhoneCalls(MTP_flags(0)), MTP_int(0), MTP_int(0), MTP_int(_offsetId), MTP_int(0), MTP_int(_offsetId ? kFirstPageCount : kPerPageCount), MTP_int(0), MTP_int(0))).done([this](const MTPmessages_Messages &result) {
|
||||
_loadRequestId = 0;
|
||||
_loadRequestId =
|
||||
request(MTPmessages_Search(MTP_flags(0), MTP_inputPeerEmpty(), MTP_string(QString()), MTP_inputUserEmpty(),
|
||||
MTP_inputMessagesFilterPhoneCalls(MTP_flags(0)), MTP_int(0), MTP_int(0),
|
||||
MTP_int(_offsetId), MTP_int(0), MTP_int(_offsetId ? kFirstPageCount : kPerPageCount),
|
||||
MTP_int(0), MTP_int(0)))
|
||||
.done([this](const MTPmessages_Messages &result) {
|
||||
_loadRequestId = 0;
|
||||
|
||||
auto handleResult = [this](auto &data) {
|
||||
App::feedUsers(data.vusers);
|
||||
App::feedChats(data.vchats);
|
||||
receivedCalls(data.vmessages.v);
|
||||
};
|
||||
auto handleResult = [this](auto &data) {
|
||||
App::feedUsers(data.vusers);
|
||||
App::feedChats(data.vchats);
|
||||
receivedCalls(data.vmessages.v);
|
||||
};
|
||||
|
||||
switch (result.type()) {
|
||||
case mtpc_messages_messages: handleResult(result.c_messages_messages()); _allLoaded = true; break;
|
||||
case mtpc_messages_messagesSlice: handleResult(result.c_messages_messagesSlice()); break;
|
||||
case mtpc_messages_channelMessages: {
|
||||
LOG(("API Error: received messages.channelMessages! (Calls::BoxController::preloadRows)"));
|
||||
handleResult(result.c_messages_channelMessages());
|
||||
} break;
|
||||
switch (result.type()) {
|
||||
case mtpc_messages_messages:
|
||||
handleResult(result.c_messages_messages());
|
||||
_allLoaded = true;
|
||||
break;
|
||||
case mtpc_messages_messagesSlice: handleResult(result.c_messages_messagesSlice()); break;
|
||||
case mtpc_messages_channelMessages: {
|
||||
LOG(("API Error: received messages.channelMessages! (Calls::BoxController::preloadRows)"));
|
||||
handleResult(result.c_messages_channelMessages());
|
||||
} break;
|
||||
|
||||
default: Unexpected("Type of messages.Messages (Calls::BoxController::preloadRows)");
|
||||
}
|
||||
}).fail([this](const RPCError &error) {
|
||||
_loadRequestId = 0;
|
||||
}).send();
|
||||
default: Unexpected("Type of messages.Messages (Calls::BoxController::preloadRows)");
|
||||
}
|
||||
})
|
||||
.fail([this](const RPCError &error) { _loadRequestId = 0; })
|
||||
.send();
|
||||
}
|
||||
|
||||
void BoxController::refreshAbout() {
|
||||
setDescriptionText(delegate()->peerListFullRowsCount() ? QString() : lang(lng_call_box_about));
|
||||
}
|
||||
|
||||
void BoxController::rowClicked(not_null<PeerListRow*> row) {
|
||||
auto itemsRow = static_cast<Row*>(row.get());
|
||||
void BoxController::rowClicked(not_null<PeerListRow *> row) {
|
||||
auto itemsRow = static_cast<Row *>(row.get());
|
||||
auto itemId = itemsRow->maxItemId();
|
||||
Ui::showPeerHistoryAsync(row->peer()->id, itemId);
|
||||
}
|
||||
|
||||
void BoxController::rowActionClicked(not_null<PeerListRow*> row) {
|
||||
void BoxController::rowActionClicked(not_null<PeerListRow *> row) {
|
||||
auto user = row->peer()->asUser();
|
||||
Assert(user != nullptr);
|
||||
|
||||
|
@ -285,9 +296,10 @@ bool BoxController::insertRow(HistoryItem *item, InsertWay way) {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
(way == InsertWay::Append) ? delegate()->peerListAppendRow(createRow(item)) : delegate()->peerListPrependRow(createRow(item));
|
||||
(way == InsertWay::Append) ? delegate()->peerListAppendRow(createRow(item)) :
|
||||
delegate()->peerListPrependRow(createRow(item));
|
||||
delegate()->peerListSortRows([](PeerListRow &a, PeerListRow &b) {
|
||||
return static_cast<Row&>(a).maxItemId() > static_cast<Row&>(b).maxItemId();
|
||||
return static_cast<Row &>(a).maxItemId() > static_cast<Row &>(b).maxItemId();
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
@ -296,11 +308,11 @@ BoxController::Row *BoxController::rowForItem(HistoryItem *item) {
|
|||
auto v = delegate();
|
||||
if (auto fullRowsCount = v->peerListFullRowsCount()) {
|
||||
auto itemId = item->id;
|
||||
auto lastRow = static_cast<Row*>(v->peerListRowAt(fullRowsCount - 1).get());
|
||||
auto lastRow = static_cast<Row *>(v->peerListRowAt(fullRowsCount - 1).get());
|
||||
if (itemId < lastRow->minItemId()) {
|
||||
return lastRow;
|
||||
}
|
||||
auto firstRow = static_cast<Row*>(v->peerListRowAt(0).get());
|
||||
auto firstRow = static_cast<Row *>(v->peerListRowAt(0).get());
|
||||
if (itemId > firstRow->maxItemId()) {
|
||||
return firstRow;
|
||||
}
|
||||
|
@ -312,18 +324,18 @@ BoxController::Row *BoxController::rowForItem(HistoryItem *item) {
|
|||
auto right = fullRowsCount;
|
||||
while (left + 1 < right) {
|
||||
auto middle = (right + left) / 2;
|
||||
auto middleRow = static_cast<Row*>(v->peerListRowAt(middle).get());
|
||||
auto middleRow = static_cast<Row *>(v->peerListRowAt(middle).get());
|
||||
if (middleRow->maxItemId() >= itemId) {
|
||||
left = middle;
|
||||
} else {
|
||||
right = middle;
|
||||
}
|
||||
}
|
||||
auto result = static_cast<Row*>(v->peerListRowAt(left).get());
|
||||
auto result = static_cast<Row *>(v->peerListRowAt(left).get());
|
||||
// Check for rowAt(left)->minItemId > itemId > rowAt(left + 1)->maxItemId.
|
||||
// In that case we sometimes need to return rowAt(left + 1), not rowAt(left).
|
||||
if (result->minItemId() > itemId && left + 1 < fullRowsCount) {
|
||||
auto possibleResult = static_cast<Row*>(v->peerListRowAt(left + 1).get());
|
||||
auto possibleResult = static_cast<Row *>(v->peerListRowAt(left + 1).get());
|
||||
Assert(possibleResult->maxItemId() < itemId);
|
||||
if (possibleResult->canAddItem(item)) {
|
||||
return possibleResult;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue