Alpha 0.10.23: small tiled background performance improved.

Also some error texts improved. Also Ctrl+W closes MediaView now.
This commit is contained in:
John Preston 2017-01-01 20:45:20 +04:00
parent eec5b78054
commit c65a280b9d
35 changed files with 419 additions and 237 deletions

View File

@ -126,6 +126,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
"lng_edit_error" = "You cannot edit this message";
"lng_join_channel_error" = "Sorry, you have joined too many channels and supergroups. Please leave some before joining.";
"lng_error_phone_flood" = "Sorry, you have deleted and re-created your account too many times recently. Please wait for a few days before signing up again.";
"lng_error_start_minimized_passcoded" = "You have set a local passcode, so the app can't be launched minimized. App will ask you to enter the passcode before it can start working.";
"lng_edit_deleted" = "This message was deleted";
"lng_edit_too_long" = "Your message text is too long";
@ -753,9 +754,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
"lng_report_spam_sure_group" = "Are you sure you want to report spam in this group?";
"lng_report_spam_sure_channel" = "Are you sure you want to report spam in this channel?";
"lng_report_spam_ok" = "Report";
"lng_cant_send_to_not_contact" = "Sorry, you can only send messages to\nmutual contacts at the moment.\n{more_info}";
"lng_cant_invite_not_contact" = "Sorry, you can only add mutual contacts\nto groups at the moment.\n{more_info}";
"lng_cant_invite_not_contact_channel" = "Sorry, you can only add mutual contacts\nto channels at the moment.\n{more_info}";
"lng_cant_send_to_not_contact" = "You have contacted too many non-contacts today, please try again tomorrow. You will be able to reply today if this user messages you first. {more_info}";
"lng_cant_invite_not_contact" = "You can't add this user because you have contacted too many non-contacts today. Please try again tomorrow. You can ask another member to add this user to the group. {more_info}";
"lng_cant_more_info" = "More info »";
"lng_cant_invite_banned" = "Sorry, only admin can add this user.";
"lng_cant_invite_privacy" = "Sorry, you cannot add this user to groups because of their privacy settings.";

View File

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

View File

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

View File

@ -44,8 +44,12 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "observer_peer.h"
#include "apiwrap.h"
QString cantInviteError() {
return lng_cant_invite_not_contact(lt_more_info, textcmdLink(qsl("https://telegram.me/spambot"), lang(lng_cant_more_info)));
QString PeerFloodErrorText(PeerFloodType type) {
auto link = textcmdLink(qsl("https://telegram.me/spambot"), lang(lng_cant_more_info));
if (type == PeerFloodType::InviteGroup) {
return lng_cant_invite_not_contact(lt_more_info, link);
}
return lng_cant_send_to_not_contact(lt_more_info, link);
}
ContactsBox::ContactsBox(QWidget*, ChatData *chat, MembersFilter filter)
@ -360,6 +364,8 @@ void ContactsBox::inviteParticipants() {
void ContactsBox::createGroup() {
if (_saveRequestId) return;
Ui::show(Box<InformBox>(PeerFloodErrorText(PeerFloodType::Send)), KeepOtherLayers);
return;
auto users = _inner->selectedInputs();
if (users.isEmpty() || (users.size() == 1 && users.at(0).type() == mtpc_inputUserSelf)) {
@ -512,7 +518,7 @@ bool ContactsBox::creationFail(const RPCError &error) {
_select->entity()->setInnerFocus();
return true;
} else if (error.type() == "PEER_FLOOD") {
Ui::show(Box<InformBox>(cantInviteError()), KeepOtherLayers);
Ui::show(Box<InformBox>(PeerFloodErrorText(PeerFloodType::InviteGroup)), KeepOtherLayers);
return true;
} else if (error.type() == qstr("USER_RESTRICTED")) {
Ui::show(Box<InformBox>(lang(lng_cant_do_this)));
@ -718,7 +724,7 @@ void ContactsBox::Inner::addBot() {
history->sendRequestId = requestId;
}
} else if (!info->startGroupToken.isEmpty()) {
MTP::send(MTPmessages_StartBot(_bot->inputUser, _addToPeer->input, MTP_long(rand_value<uint64>()), MTP_string(info->startGroupToken)), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::addParticipantFail, _bot));
MTP::send(MTPmessages_StartBot(_bot->inputUser, _addToPeer->input, MTP_long(rand_value<uint64>()), MTP_string(info->startGroupToken)), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::addParticipantFail, { _bot, _addToPeer }));
} else {
App::main()->addParticipants(_addToPeer, QVector<UserData*>(1, _bot));
}

View File

@ -39,7 +39,12 @@ template <typename Widget>
class WidgetSlideWrap;
} // namespace Ui
QString cantInviteError();
enum class PeerFloodType {
Send,
InviteGroup,
InviteChannel,
};
QString PeerFloodErrorText(PeerFloodType type);
inline Ui::RoundImageCheckbox::PaintRoundImage PaintUserpicCallback(PeerData *peer) {
return [peer](Painter &p, int x, int y, int outerWidth, int size) {

View File

@ -24,7 +24,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#define BETA_VERSION_MACRO (0ULL)
constexpr int AppVersion = 10022;
constexpr str_const AppVersionStr = "0.10.22";
constexpr int AppVersion = 10023;
constexpr str_const AppVersionStr = "0.10.23";
constexpr bool AppAlphaVersion = true;
constexpr uint64 AppBetaVersion = BETA_VERSION_MACRO;

View File

@ -316,7 +316,7 @@ PeerData *getPeerForMouseAction() {
bool hideWindowNoQuit() {
if (!App::quitting()) {
if (auto w = App::wnd()) {
w->hideNoQuit();
return w->hideNoQuit();
}
}
return false;

View File

@ -1089,7 +1089,7 @@ bool History::addToOverview(MediaOverviewType type, MsgId msgId, AddToOverviewMe
if (overviewCountData[type] > 0) {
++overviewCountData[type];
}
if (App::wnd()) App::wnd()->mediaOverviewUpdated(peer, type);
Notify::mediaOverviewUpdated(peer, type);
}
return true;
}
@ -1110,7 +1110,7 @@ void History::eraseFromOverview(MediaOverviewType type, MsgId msgId) {
break;
}
}
if (App::wnd()) App::wnd()->mediaOverviewUpdated(peer, type);
Notify::mediaOverviewUpdated(peer, type);
}
HistoryItem *History::addNewItem(HistoryItem *adding, bool newMsg) {
@ -1375,8 +1375,11 @@ void History::addOlderSlice(const QVector<MTPMessage> &slice) {
}
}
}
for (int32 t = 0; t < OverviewCount; ++t) {
if ((mask & (1 << t)) && App::wnd()) App::wnd()->mediaOverviewUpdated(peer, MediaOverviewType(t));
if (mask) {
Notify::PeerUpdate update(peer);
update.flags |= Notify::PeerUpdate::Flag::SharedMediaChanged;
update.mediaTypesMask |= mask;
Notify::peerUpdatedDelayed(update);
}
}
@ -1453,8 +1456,11 @@ void History::checkAddAllToOverview() {
mask |= item->addToOverview(AddToOverviewBack);
}
}
for (int32 t = 0; t < OverviewCount; ++t) {
if ((mask & (1 << t)) && App::wnd()) App::wnd()->mediaOverviewUpdated(peer, MediaOverviewType(t));
if (mask) {
Notify::PeerUpdate update(peer);
update.flags |= Notify::PeerUpdate::Flag::SharedMediaChanged;
update.mediaTypesMask |= mask;
Notify::peerUpdatedDelayed(update);
}
}
@ -2009,7 +2015,7 @@ void History::clear(bool leaveItems) {
}
overview[i].clear();
overviewIds[i].clear();
if (App::wnd() && !App::quitting()) App::wnd()->mediaOverviewUpdated(peer, MediaOverviewType(i));
if (!App::quitting()) Notify::mediaOverviewUpdated(peer, MediaOverviewType(i));
}
}
clearBlocks(leaveItems);

View File

@ -5294,7 +5294,7 @@ void HistoryWidget::onBotStart() {
sendBotCommand(_peer, _peer->asUser(), qsl("/start"), 0);
} else {
uint64 randomId = rand_value<uint64>();
MTP::send(MTPmessages_StartBot(_peer->asUser()->inputUser, MTP_inputPeerEmpty(), MTP_long(randomId), MTP_string(token)), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::addParticipantFail, _peer->asUser()));
MTP::send(MTPmessages_StartBot(_peer->asUser()->inputUser, MTP_inputPeerEmpty(), MTP_long(randomId), MTP_string(token)), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::addParticipantFail, { _peer->asUser(), (PeerData*)nullptr }));
_peer->asUser()->botInfo->startToken = QString();
if (_keyboard->hasMarkup()) {
@ -8791,19 +8791,27 @@ void HistoryWidget::paintEvent(QPaintEvent *e) {
int fromy = App::main()->backgroundFromY(), x = 0, y = 0;
QPixmap cached = App::main()->cachedBackground(fill, x, y);
if (cached.isNull()) {
auto &pix = Window::Theme::Background()->image();
if (Window::Theme::Background()->tile()) {
int left = r.left(), top = r.top(), right = r.left() + r.width(), bottom = r.top() + r.height();
float64 w = pix.width() / cRetinaFactor(), h = pix.height() / cRetinaFactor();
int sx = qFloor(left / w), sy = qFloor((top - fromy) / h), cx = qCeil(right / w), cy = qCeil((bottom - fromy) / h);
for (int i = sx; i < cx; ++i) {
for (int j = sy; j < cy; ++j) {
auto &pix = Window::Theme::Background()->pixmapForTiled();
auto left = r.left();
auto top = r.top();
auto right = r.left() + r.width();
auto bottom = r.top() + r.height();
auto w = pix.width() / cRetinaFactor();
auto h = pix.height() / cRetinaFactor();
auto sx = qFloor(left / w);
auto sy = qFloor((top - fromy) / h);
auto cx = qCeil(right / w);
auto cy = qCeil((bottom - fromy) / h);
for (auto i = sx; i < cx; ++i) {
for (auto j = sy; j < cy; ++j) {
p.drawPixmap(QPointF(i * w, fromy + j * h), pix);
}
}
} else {
PainterHighQualityEnabler hq(p);
auto &pix = Window::Theme::Background()->pixmap();
QRect to, from;
Window::Theme::ComputeBackgroundRects(fill, pix.size(), to, from);
to.moveTop(to.top() + fromy);

View File

@ -1720,7 +1720,7 @@ void _writeMtpData() {
key->write(data.stream);
}
mtp.writeEncrypted(data, _localKey);
mtp.writeEncrypted(data);
}
void _readMtpData() {

View File

@ -148,6 +148,11 @@ MainWidget::MainWidget(QWidget *parent) : TWidget(parent)
subscribe(Adaptive::Changed(), [this]() { updateAdaptiveLayout(); });
auto observeEvents = Notify::PeerUpdate::Flag::SharedMediaChanged;
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(observeEvents, [this](const Notify::PeerUpdate &update) {
mediaOverviewUpdated(update);
}));
_dialogs->show();
if (Adaptive::OneColumn()) {
_history->hide();
@ -919,8 +924,9 @@ void MainWidget::clearHistory(PeerData *peer) {
void MainWidget::addParticipants(PeerData *chatOrChannel, const QVector<UserData*> &users) {
if (chatOrChannel->isChat()) {
for (QVector<UserData*>::const_iterator i = users.cbegin(), e = users.cend(); i != e; ++i) {
MTP::send(MTPmessages_AddChatUser(chatOrChannel->asChat()->inputChat, (*i)->inputUser, MTP_int(ForwardOnAdd)), rpcDone(&MainWidget::sentUpdatesReceived), rpcFail(&MainWidget::addParticipantFail, *i), 0, 5);
auto chat = chatOrChannel->asChat();
for_const (auto user, users) {
MTP::send(MTPmessages_AddChatUser(chat->inputChat, user->inputUser, MTP_int(ForwardOnAdd)), rpcDone(&MainWidget::sentUpdatesReceived), rpcFail(&MainWidget::addParticipantFail, { user, chat }), 0, 5);
}
} else if (chatOrChannel->isChannel()) {
QVector<MTPInputUser> inputUsers;
@ -938,7 +944,7 @@ void MainWidget::addParticipants(PeerData *chatOrChannel, const QVector<UserData
}
}
bool MainWidget::addParticipantFail(UserData *user, const RPCError &error) {
bool MainWidget::addParticipantFail(UserAndPeer data, const RPCError &error) {
if (MTP::isDefaultHandledError(error)) return false;
QString text = lang(lng_failed_add_participant);
@ -949,10 +955,10 @@ bool MainWidget::addParticipantFail(UserData *user, const RPCError &error) {
text = lang(lng_cant_invite_privacy);
} else if (error.type() == qstr("USER_NOT_MUTUAL_CONTACT")) { // trying to return user who does not have me in contacts
text = lang(lng_failed_add_not_mutual);
} else if (error.type() == qstr("USER_ALREADY_PARTICIPANT") && user->botInfo) {
} else if (error.type() == qstr("USER_ALREADY_PARTICIPANT") && data.user->botInfo) {
text = lang(lng_bot_already_in_group);
} else if (error.type() == qstr("PEER_FLOOD")) {
text = cantInviteError();
text = PeerFloodErrorText((data.peer->isChat() || data.peer->isMegagroup()) ? PeerFloodType::InviteGroup : PeerFloodType::InviteChannel);
}
Ui::show(Box<InformBox>(text));
return false;
@ -970,7 +976,7 @@ bool MainWidget::addParticipantsFail(ChannelData *channel, const RPCError &error
} else if (error.type() == qstr("USER_NOT_MUTUAL_CONTACT")) { // trying to return user who does not have me in contacts
text = lang(channel->isMegagroup() ? lng_failed_add_not_mutual : lng_failed_add_not_mutual_channel);
} else if (error.type() == qstr("PEER_FLOOD")) {
text = cantInviteError();
text = PeerFloodErrorText(PeerFloodType::InviteGroup);
}
Ui::show(Box<InformBox>(text));
return false;
@ -1060,22 +1066,30 @@ bool MainWidget::sendMessageFail(const RPCError &error) {
if (MTP::isDefaultHandledError(error)) return false;
if (error.type() == qstr("PEER_FLOOD")) {
Ui::show(Box<InformBox>(cantInviteError()));
Ui::show(Box<InformBox>(PeerFloodErrorText(PeerFloodType::Send)));
return true;
}
return false;
}
void MainWidget::onCacheBackground() {
auto &bg = Window::Theme::Background()->image();
if (Window::Theme::Background()->tile()) {
QImage result(_willCacheFor.width() * cIntRetinaFactor(), _willCacheFor.height() * cIntRetinaFactor(), QImage::Format_RGB32);
auto &bg = Window::Theme::Background()->pixmapForTiled();
auto result = QImage(_willCacheFor.width() * cIntRetinaFactor(), _willCacheFor.height() * cIntRetinaFactor(), QImage::Format_RGB32);
result.setDevicePixelRatio(cRetinaFactor());
{
QPainter p(&result);
int left = 0, top = 0, right = _willCacheFor.width(), bottom = _willCacheFor.height();
float64 w = bg.width() / cRetinaFactor(), h = bg.height() / cRetinaFactor();
int sx = 0, sy = 0, cx = qCeil(_willCacheFor.width() / w), cy = qCeil(_willCacheFor.height() / h);
auto left = 0;
auto top = 0;
auto right = _willCacheFor.width();
auto bottom = _willCacheFor.height();
auto w = bg.width() / cRetinaFactor();
auto h = bg.height() / cRetinaFactor();
auto sx = 0;
auto sy = 0;
auto cx = qCeil(_willCacheFor.width() / w);
auto cy = qCeil(_willCacheFor.height() / h);
for (int i = sx; i < cx; ++i) {
for (int j = sy; j < cy; ++j) {
p.drawPixmap(QPointF(i * w, j * h), bg);
@ -1086,6 +1100,8 @@ void MainWidget::onCacheBackground() {
_cachedY = 0;
_cachedBackground = App::pixmapFromImageInPlace(std_::move(result));
} else {
auto &bg = Window::Theme::Background()->pixmap();
QRect to, from;
Window::Theme::ComputeBackgroundRects(_willCacheFor, bg.size(), to, from);
_cachedX = to.x();
@ -1370,12 +1386,13 @@ void MainWidget::overviewPreloaded(PeerData *peer, const MTPmessages_Messages &r
App::history(peer->id)->overviewSliceDone(type, result, true);
if (App::wnd()) App::wnd()->mediaOverviewUpdated(peer, type);
Notify::mediaOverviewUpdated(peer, type);
}
void MainWidget::mediaOverviewUpdated(PeerData *peer, MediaOverviewType type) {
void MainWidget::mediaOverviewUpdated(const Notify::PeerUpdate &update) {
auto peer = update.peer;
if (_overview && (_overview->peer() == peer || _overview->peer()->migrateFrom() == peer)) {
_overview->mediaOverviewUpdated(peer, type);
_overview->mediaOverviewUpdated(update);
int32 mask = 0;
History *h = peer ? App::historyLoaded((peer->migrateTo() ? peer->migrateTo() : peer)->id) : 0;
@ -1472,7 +1489,7 @@ void MainWidget::overviewLoaded(History *history, const MTPmessages_Messages &re
history->overviewSliceDone(type, result);
if (App::wnd()) App::wnd()->mediaOverviewUpdated(history->peer, type);
Notify::mediaOverviewUpdated(history->peer, type);
}
void MainWidget::sendReadRequest(PeerData *peer, MsgId upTo) {
@ -2385,7 +2402,13 @@ void MainWidget::showMediaOverview(PeerData *peer, MediaOverviewType type, bool
_mediaTypeMask = 0;
_topBar->show();
resizeEvent(nullptr);
mediaOverviewUpdated(peer, type);
// Send a fake update.
Notify::PeerUpdate update(peer);
update.flags |= Notify::PeerUpdate::Flag::SharedMediaChanged;
update.mediaTypesMask |= (1 << type);
mediaOverviewUpdated(update);
_overview->setLastScrollTop(lastScrollTop);
if (!animationParams.oldContentCache.isNull()) {
_overview->showAnimated(back ? Window::SlideDirection::FromLeft : Window::SlideDirection::FromRight, animationParams);
@ -4453,11 +4476,11 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
if (msg.msg) {
if (auto msgRow = App::histItemById(msg)) {
if (App::histItemById(msg.channel, d.vid.v)) {
History *h = msgRow->history();
bool wasLast = (h->lastMsg == msgRow);
auto history = msgRow->history();
auto wasLast = (history->lastMsg == msgRow);
msgRow->destroy();
if (wasLast && !h->lastMsg) {
checkPeerHistory(h->peer);
if (wasLast && !history->lastMsg) {
checkPeerHistory(history->peer);
}
_history->peerMessagesUpdated();
} else {
@ -4666,7 +4689,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
}
}
App::markPeerUpdated(user);
if (App::wnd()) App::wnd()->mediaOverviewUpdated(user, OverviewCount);
Notify::mediaOverviewUpdated(user, OverviewCount);
}
} break;

View File

@ -24,6 +24,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "history/history_common.h"
#include "core/single_timer.h"
namespace Notify {
struct PeerUpdate;
} // namespace Notify
namespace Dialogs {
class Row;
} // namespace Dialogs
@ -260,7 +264,11 @@ public:
void deleteAllFromUser(ChannelData *channel, UserData *from);
void addParticipants(PeerData *chatOrChannel, const QVector<UserData*> &users);
bool addParticipantFail(UserData *user, const RPCError &e);
struct UserAndPeer {
UserData *user;
PeerData *peer;
};
bool addParticipantFail(UserAndPeer data, const RPCError &e);
bool addParticipantsFail(ChannelData *channel, const RPCError &e); // for multi invite in channels
void kickParticipant(ChatData *chat, UserData *user);
@ -302,7 +310,6 @@ public:
void searchMessages(const QString &query, PeerData *inPeer);
bool preloadOverview(PeerData *peer, MediaOverviewType type);
void preloadOverviews(PeerData *peer);
void mediaOverviewUpdated(PeerData *peer, MediaOverviewType type);
void changingMsgId(HistoryItem *row, MsgId newId);
void itemEdited(HistoryItem *item);
@ -496,6 +503,7 @@ private:
void messagesAffected(PeerData *peer, const MTPmessages_AffectedMessages &result);
void overviewLoaded(History *history, const MTPmessages_Messages &result, mtpRequestId req);
void mediaOverviewUpdated(const Notify::PeerUpdate &update);
Window::SectionSlideParams prepareShowAnimation(bool willHaveTopBarShadow);
void showWideSectionAnimated(const Window::SectionMemento *memento, bool back, bool saveInStack);

View File

@ -118,9 +118,6 @@ MainWindow::MainWindow() {
connect(&_notifyWaitTimer, SIGNAL(timeout()), this, SLOT(notifyShowNext()));
_isActiveTimer.setSingleShot(true);
connect(&_isActiveTimer, SIGNAL(timeout()), this, SLOT(updateIsActive()));
connect(&_autoLockTimer, SIGNAL(timeout()), this, SLOT(checkAutoLock()));
subscribe(Global::RefSelfChanged(), [this]() { updateGlobalMenu(); });
@ -173,7 +170,9 @@ void MainWindow::initHook() {
void MainWindow::onWindowActiveChanged() {
checkHistoryActivation();
QTimer::singleShot(1, this, SLOT(updateTrayMenu()));
QTimer::singleShot(1, base::lambda_slot_once(this, [this] {
updateTrayMenu();
}), SLOT(action()));
}
void MainWindow::firstShow() {
@ -207,20 +206,14 @@ void MainWindow::firstShow() {
createMediaView();
}
void MainWindow::clearWidgets() {
void MainWindow::clearWidgetsHook() {
auto wasMain = (_main != nullptr);
Ui::hideLayer(true);
_passcode.destroyDelayed();
_main.destroy();
_intro.destroy();
if (_mediaView) {
hideMediaview();
_mediaView->rpcClear();
}
if (wasMain) {
App::clearHistories();
}
updateGlobalMenu();
}
QPixmap MainWindow::grabInner() {
@ -261,7 +254,7 @@ void MainWindow::setupPasscode() {
updateControlsGeometry();
if (_main) _main->hide();
if (_mediaView) _mediaView->hide();
hideMediaview();
Ui::hideSettingsAndLayer(true);
if (_intro) _intro->hide();
if (animated) {
@ -300,9 +293,6 @@ void MainWindow::setupIntro() {
cSetDialogsReceived(false);
if (_intro && !_intro->isHidden() && !_main) return;
if (_mediaView) {
_mediaView->clearData();
}
Ui::hideSettingsAndLayer(true);
auto animated = (_main || _passcode);
@ -447,31 +437,6 @@ PasscodeWidget *MainWindow::passcodeWidget() {
return _passcode;
}
void MainWindow::showPhoto(const PhotoOpenClickHandler *lnk, HistoryItem *item) {
return (!item && lnk->peer()) ? showPhoto(lnk->photo(), lnk->peer()) : showPhoto(lnk->photo(), item);
}
void MainWindow::showPhoto(PhotoData *photo, HistoryItem *item) {
if (_mediaView->isHidden()) Ui::hideLayer(true);
_mediaView->showPhoto(photo, item);
_mediaView->activateWindow();
_mediaView->setFocus();
}
void MainWindow::showPhoto(PhotoData *photo, PeerData *peer) {
if (_mediaView->isHidden()) Ui::hideLayer(true);
_mediaView->showPhoto(photo, peer);
_mediaView->activateWindow();
_mediaView->setFocus();
}
void MainWindow::showDocument(DocumentData *doc, HistoryItem *item) {
if (_mediaView->isHidden()) Ui::hideLayer(true);
_mediaView->showDocument(doc, item);
_mediaView->activateWindow();
_mediaView->setFocus();
}
void MainWindow::ui_showBox(object_ptr<BoxContent> box, ShowLayerOptions options) {
if (box) {
if (!_layerBg) {
@ -504,10 +469,6 @@ bool MainWindow::ui_isLayerShown() {
return _layerBg != nullptr;
}
bool MainWindow::ui_isMediaViewShown() {
return _mediaView && !_mediaView->isHidden();
}
void MainWindow::ui_showMediaPreview(DocumentData *document) {
if (!document || ((!document->isAnimation() || !document->loaded()) && !document->sticker())) return;
if (!_mediaPreview) {
@ -538,8 +499,8 @@ void MainWindow::ui_hideMediaPreview() {
}
PeerData *MainWindow::ui_getPeerForMouseAction() {
if (_mediaView && !_mediaView->isHidden()) {
return _mediaView->ui_getPeerForMouseAction();
if (Ui::isMediaViewShown()) {
return Platform::MainWindow::ui_getPeerForMouseAction();
} else if (_main) {
return _main->ui_getPeerForMouseAction();
}
@ -579,8 +540,9 @@ void MainWindow::themeUpdated(const Window::Theme::BackgroundUpdate &data) {
}
}
bool MainWindow::doWeReadServerHistory() const {
return isActive(false) && _main && !Ui::isLayerShown() && _main->doWeReadServerHistory();
bool MainWindow::doWeReadServerHistory() {
updateIsActive(0);
return isActive() && _main && !Ui::isLayerShown() && _main->doWeReadServerHistory();
}
void MainWindow::checkHistoryActivation() {
@ -694,7 +656,8 @@ void MainWindow::updateTrayMenu(bool force) {
auto minimizeAction = actions.at(1);
minimizeAction->setDisabled(!isVisible());
} else {
auto active = isActive(false);
updateIsActive(0);
auto active = isActive();
auto toggleAction = actions.at(0);
disconnect(toggleAction, SIGNAL(triggered(bool)), this, SLOT(minimizeToTray()));
disconnect(toggleAction, SIGNAL(triggered(bool)), this, SLOT(showFromTray()));
@ -752,14 +715,6 @@ void MainWindow::onLogout() {
}));
}
void MainWindow::updateGlobalMenu() {
#ifdef Q_OS_MAC
if (App::wnd()) {
psMacUpdateMenu();
}
#endif
}
void MainWindow::quitFromTray() {
App::quit();
}
@ -811,20 +766,23 @@ void MainWindow::fixOrder() {
void MainWindow::showFromTray(QSystemTrayIcon::ActivationReason reason) {
if (reason != QSystemTrayIcon::Context) {
QTimer::singleShot(1, this, SLOT(updateTrayMenu()));
QTimer::singleShot(1, this, SLOT(updateGlobalMenu()));
QTimer::singleShot(1, base::lambda_slot_once(this, [this] {
updateTrayMenu();
updateGlobalMenu();
}), SLOT(action()));
activate();
Notify::unreadCounterUpdated();
}
}
void MainWindow::toggleTray(QSystemTrayIcon::ActivationReason reason) {
if ((cPlatform() == dbipMac || cPlatform() == dbipMacOld) && isActive(false)) return;
updateIsActive(0);
if ((cPlatform() == dbipMac || cPlatform() == dbipMacOld) && isActive()) return;
if (reason == QSystemTrayIcon::Context) {
updateTrayMenu(true);
QTimer::singleShot(1, this, SLOT(psShowTrayMenu()));
} else {
if (isActive(false)) {
if (isActive()) {
minimizeToTray();
} else {
showFromTray(reason);
@ -1366,38 +1324,12 @@ void MainWindow::sendPaths() {
}
}
void MainWindow::mediaOverviewUpdated(PeerData *peer, MediaOverviewType type) {
if (_main) _main->mediaOverviewUpdated(peer, type);
if (_mediaView && !_mediaView->isHidden()) {
_mediaView->mediaOverviewUpdated(peer, type);
}
if (type != OverviewCount) {
Notify::PeerUpdate update(peer);
update.flags |= Notify::PeerUpdate::Flag::SharedMediaChanged;
update.mediaTypesMask |= (1 << type);
Notify::peerUpdatedDelayed(update);
}
}
void MainWindow::documentUpdated(DocumentData *doc) {
if (!_mediaView || _mediaView->isHidden()) return;
_mediaView->documentUpdated(doc);
}
void MainWindow::changingMsgId(HistoryItem *row, MsgId newId) {
if (_main) _main->changingMsgId(row, newId);
if (!_mediaView || _mediaView->isHidden()) return;
_mediaView->changingMsgId(row, newId);
Platform::MainWindow::changingMsgId(row, newId);
}
bool MainWindow::isActive(bool cached) const {
if (cached) return _isActive;
return isActiveWindow() && isVisible() && !(windowState() & Qt::WindowMinimized);
}
void MainWindow::updateIsActive(int timeout) {
if (timeout) return _isActiveTimer.start(timeout);
_isActive = isActive(false);
void MainWindow::updateIsActiveHook() {
if (_main) _main->updateOnline();
}

View File

@ -98,12 +98,7 @@ public:
MainWidget *mainWidget();
PasscodeWidget *passcodeWidget();
void showPhoto(const PhotoOpenClickHandler *lnk, HistoryItem *item = 0);
void showPhoto(PhotoData *photo, HistoryItem *item);
void showPhoto(PhotoData *photo, PeerData *item);
void showDocument(DocumentData *doc, HistoryItem *item);
bool doWeReadServerHistory() const;
bool doWeReadServerHistory();
void activate();
@ -135,11 +130,7 @@ public:
void sendPaths();
void mediaOverviewUpdated(PeerData *peer, MediaOverviewType type);
void documentUpdated(DocumentData *doc);
void changingMsgId(HistoryItem *row, MsgId newId);
bool isActive(bool cached = true) const;
void changingMsgId(HistoryItem *row, MsgId newId) override;
QImage iconWithCounter(int size, int count, style::color bg, style::color fg, bool smallIcon) override;
@ -152,15 +143,15 @@ public:
}
void showMainMenu();
void updateTrayMenu(bool force = false) override;
void ui_showBox(object_ptr<BoxContent> box, ShowLayerOptions options);
void ui_hideSettingsAndLayer(ShowLayerOptions options);
bool ui_isLayerShown();
bool ui_isMediaViewShown();
void ui_showMediaPreview(DocumentData *document);
void ui_showMediaPreview(PhotoData *photo);
void ui_hideMediaPreview();
PeerData *ui_getPeerForMouseAction();
PeerData *ui_getPeerForMouseAction() override;
protected:
bool eventFilter(QObject *o, QEvent *e) override;
@ -168,10 +159,10 @@ protected:
void resizeEvent(QResizeEvent *e) override;
void initHook() override;
void updateIsActiveHook() override;
void clearWidgetsHook() override;
public slots:
void updateIsActive(int timeout = 0);
void checkAutoLock();
void showSettings();
@ -190,13 +181,11 @@ public slots:
void onClearFailed(int task, void *manager);
void notifyShowNext();
void updateTrayMenu(bool force = false);
void onShowAddContact();
void onShowNewGroup();
void onShowNewChannel();
void onLogout();
void updateGlobalMenu(); // for OS X top menu
void app_activateClickHandler(ClickHandlerPtr handler, Qt::MouseButton button);
@ -239,16 +228,11 @@ private:
object_ptr<LayerStackWidget> _layerBg = { nullptr };
object_ptr<MediaPreviewWidget> _mediaPreview = { nullptr };
QTimer _isActiveTimer;
bool _isActive = false;
object_ptr<ConnectingWidget> _connecting = { nullptr };
object_ptr<Window::Theme::WarningWidget> _testingThemeWarning = { nullptr };
Local::ClearManager *_clearManager = nullptr;
void clearWidgets();
bool _inactivePress = false;
QTimer _inactiveTimer;

View File

@ -36,6 +36,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "history/history_media_types.h"
#include "window/window_theme_preview.h"
#include "core/task_queue.h"
#include "observer_peer.h"
namespace {
@ -90,6 +91,10 @@ MediaView::MediaView(QWidget*) : TWidget(nullptr)
updateControls();
}
});
auto observeEvents = Notify::PeerUpdate::Flag::SharedMediaChanged;
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(observeEvents, [this](const Notify::PeerUpdate &update) {
mediaOverviewUpdated(update);
}));
generateTransparentBrush();
@ -148,8 +153,8 @@ void MediaView::moveToScreen() {
_saveMsg.moveTo((width() - _saveMsg.width()) / 2, (height() - _saveMsg.height()) / 2);
}
void MediaView::mediaOverviewUpdated(PeerData *peer, MediaOverviewType type) {
if (!_photo && !_doc) return;
void MediaView::mediaOverviewUpdated(const Notify::PeerUpdate &update) {
if (isHidden() || (!_photo && !_doc)) return;
if (_photo && _overview == OverviewChatPhotos && _history && !_history->peer->isUser()) {
auto lastChatPhoto = computeLastOverviewChatPhoto();
if (_index < 0 && _photo == lastChatPhoto.photo && _photo == _additionalChatPhoto) {
@ -161,7 +166,7 @@ void MediaView::mediaOverviewUpdated(PeerData *peer, MediaOverviewType type) {
computeAdditionalChatPhoto(_history->peer, lastChatPhoto.photo);
}
if (_history && (_history->peer == peer || (_migrated && _migrated->peer == peer)) && type == _overview && _msgid) {
if (_history && (_history->peer == update.peer || (_migrated && _migrated->peer == update.peer)) && (update.mediaTypesMask & (1 << _overview)) && _msgid) {
_index = -1;
if (_msgmigrated) {
for (int i = 0, l = _migrated->overview[_overview].size(); i < l; ++i) {
@ -180,7 +185,7 @@ void MediaView::mediaOverviewUpdated(PeerData *peer, MediaOverviewType type) {
}
updateControls();
preloadData(0);
} else if (_user == peer && type == OverviewCount) {
} else if (_user == update.peer && update.mediaTypesMask & (1 << OverviewCount)) {
if (!_photo) return;
_index = -1;
@ -243,7 +248,12 @@ void MediaView::changingMsgId(HistoryItem *row, MsgId newId) {
if (row->id == _msgid) {
_msgid = newId;
}
mediaOverviewUpdated(row->history()->peer, _overview);
// Send a fake update.
Notify::PeerUpdate update(row->history()->peer);
update.flags |= Notify::PeerUpdate::Flag::SharedMediaChanged;
update.mediaTypesMask |= (1 << _overview);
mediaOverviewUpdated(update);
}
void MediaView::updateDocSize() {
@ -767,7 +777,7 @@ void MediaView::onSaveAs() {
psBringToBack(this);
auto filter = qsl("JPEG Image (*.jpg);;") + filedialogAllFilesFilter();
bool gotName = filedialogGetSaveFile(file, lang(lng_save_photo), filter, filedialogDefaultName(qsl("photo"), qsl(".jpg")));
auto gotName = filedialogGetSaveFile(file, lang(lng_save_photo), filter, filedialogDefaultName(qsl("photo"), qsl(".jpg")));
psShowOverAll(this);
if (gotName) {
if (!file.isEmpty()) {
@ -1451,7 +1461,7 @@ void MediaView::initThemePreview() {
};
Window::Theme::CurrentData current;
current.backgroundId = Window::Theme::Background()->id();
current.backgroundImage = Window::Theme::Background()->image();
current.backgroundImage = Window::Theme::Background()->pixmap();
current.backgroundTiled = Window::Theme::Background()->tile();
base::TaskQueue::Normal().Put([path, current, callback = mutable_ready(std_::move(ready))]() {
auto preview = Window::Theme::GeneratePreview(path, current);
@ -2841,12 +2851,12 @@ void MediaView::userPhotosLoaded(UserData *u, const MTPphotos_Photos &photos, mt
u->photosCount = 0;
}
for (QVector<MTPPhoto>::const_iterator i = v->cbegin(), e = v->cend(); i != e; ++i) {
PhotoData *photo = App::feedPhoto(*i);
for (auto i = v->cbegin(), e = v->cend(); i != e; ++i) {
auto photo = App::feedPhoto(*i);
photo->thumb->load();
u->photos.push_back(photo);
}
if (App::wnd()) App::wnd()->mediaOverviewUpdated(u, OverviewCount);
Notify::mediaOverviewUpdated(u, OverviewCount);
}
void MediaView::updateHeader() {

View File

@ -41,6 +41,10 @@ struct Preview;
} // namespace Theme
} // namespace Window
namespace Notify {
struct PeerUpdate;
} // namespace Notify
struct AudioPlaybackState;
class MediaView : public TWidget, private base::Subscriber, public RPCSender, public ClickHandlerHost {
@ -67,7 +71,7 @@ public:
updateOver(mapFromGlobal(QCursor::pos()));
}
void mediaOverviewUpdated(PeerData *peer, MediaOverviewType type);
void mediaOverviewUpdated(const Notify::PeerUpdate &update);
void documentUpdated(DocumentData *doc);
void changingMsgId(HistoryItem *row, MsgId newId);

View File

@ -91,6 +91,13 @@ inline void peerUpdatedDelayed(PeerData *peer, PeerUpdate::Flags events) {
}
void peerUpdatedSendDelayed();
inline void mediaOverviewUpdated(PeerData *peer, MediaOverviewType type) {
PeerUpdate update(peer);
update.flags |= PeerUpdate::Flag::SharedMediaChanged;
update.mediaTypesMask |= (1 << type);
peerUpdatedDelayed(update);
}
class PeerUpdatedHandler {
public:
template <typename Lambda>

View File

@ -43,6 +43,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "history/history_media_types.h"
#include "history/history_service_layout.h"
#include "media/media_audio.h"
#include "observer_peer.h"
// flick scroll taken from http://qt-project.org/doc/qt-4.8/demos-embedded-anomaly-src-flickcharm-cpp.html
@ -2164,8 +2165,8 @@ void OverviewWidget::doneShow() {
onScroll();
}
void OverviewWidget::mediaOverviewUpdated(PeerData *p, MediaOverviewType t) {
if ((peer() == p || migratePeer() == p) && t == type()) {
void OverviewWidget::mediaOverviewUpdated(const Notify::PeerUpdate &update) {
if ((peer() == update.peer || migratePeer() == update.peer) && (update.mediaTypesMask & (1 << type()))) {
_inner->mediaOverviewUpdated();
onScroll();
updateTopBarSelection();

View File

@ -40,6 +40,10 @@ class FlatInput;
class CrossButton;
} // namespace Ui
namespace Notify {
struct PeerUpdate;
} // namespace Notify
class OverviewWidget;
class OverviewInner : public TWidget, public Ui::AbstractTooltipShower, public RPCSender, private base::Subscriber {
Q_OBJECT
@ -305,7 +309,7 @@ public:
void doneShow();
void mediaOverviewUpdated(PeerData *peer, MediaOverviewType type);
void mediaOverviewUpdated(const Notify::PeerUpdate &update);
void changingMsgId(HistoryItem *row, MsgId newId);
void itemRemoved(HistoryItem *item);

View File

@ -195,7 +195,7 @@ void MainWindow::initHook() {
setWindowIcon(wndIcon);
}
bool MainWindow::psHasTrayIcon() const {
bool MainWindow::hasTrayIcon() const {
return trayIcon || ((useAppIndicator || (useStatusIcon && trayIconChecked)) && (cWorkMode() != dbiwmWindowOnly));
}

View File

@ -61,7 +61,7 @@ protected:
void initHook() override;
void unreadCounterChangedHook() override;
bool psHasTrayIcon() const;
bool hasTrayIcon() const override;
QSystemTrayIcon *trayIcon = nullptr;
QMenu *trayIconMenu = nullptr;

View File

@ -82,11 +82,11 @@ protected:
void unreadCounterChangedHook() override;
QImage psTrayIcon(bool selected = false) const;
bool psHasTrayIcon() const {
bool hasTrayIcon() const override {
return trayIcon;
}
void psMacUpdateMenu();
void updateGlobalMenuHook() override;
QSystemTrayIcon *trayIcon = nullptr;
QMenu *trayIconMenu = nullptr;

View File

@ -391,8 +391,6 @@ void MainWindow::psFirstShow() {
setPositionInited();
createGlobalMenu();
psMacUpdateMenu();
}
void MainWindow::createGlobalMenu() {
@ -436,6 +434,8 @@ void MainWindow::createGlobalMenu() {
psNewChannel = window->addAction(lang(lng_mac_menu_new_channel), App::wnd(), SLOT(onShowNewChannel()));
window->addSeparator();
psShowTelegram = window->addAction(lang(lng_mac_menu_show), App::wnd(), SLOT(showFromTray()));
updateGlobalMenu();
}
namespace {
@ -492,10 +492,10 @@ void MainWindow::psUpdateSysMenu(Qt::WindowState state) {
void MainWindow::psUpdateMargins() {
}
void MainWindow::psMacUpdateMenu() {
if (!positionInited()) return;
void MainWindow::updateGlobalMenuHook() {
if (!App::wnd() || !positionInited()) return;
QWidget *focused = QApplication::focusWidget();
auto focused = QApplication::focusWidget();
bool isLogged = !!App::self(), canUndo = false, canRedo = false, canCut = false, canCopy = false, canPaste = false, canDelete = false, canSelectAll = false;
if (auto edit = qobject_cast<QLineEdit*>(focused)) {
canCut = canCopy = canDelete = edit->hasSelectedText();
@ -513,6 +513,7 @@ void MainWindow::psMacUpdateMenu() {
canCopy = list->canCopySelected();
canDelete = list->canDeleteSelected();
}
App::wnd()->updateIsActive(0);
_forceDisabled(psLogout, !isLogged && !App::passcoded());
_forceDisabled(psUndo, !canUndo);
_forceDisabled(psRedo, !canRedo);
@ -525,7 +526,7 @@ void MainWindow::psMacUpdateMenu() {
_forceDisabled(psAddContact, !isLogged || App::passcoded());
_forceDisabled(psNewGroup, !isLogged || App::passcoded());
_forceDisabled(psNewChannel, !isLogged || App::passcoded());
_forceDisabled(psShowTelegram, App::wnd()->isActive(false));
_forceDisabled(psShowTelegram, App::wnd()->isActive());
}
void MainWindow::psFlash() {
@ -540,7 +541,7 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *evt) {
QEvent::Type t = evt->type();
if (t == QEvent::FocusIn || t == QEvent::FocusOut) {
if (qobject_cast<QLineEdit*>(obj) || qobject_cast<QTextEdit*>(obj) || qobject_cast<HistoryInner*>(obj)) {
psMacUpdateMenu();
updateGlobalMenu();
}
}
return Window::MainWindow::eventFilter(obj, evt);

View File

@ -693,6 +693,14 @@ void MainWindow::psSetupTrayIcon() {
trayIcon->show();
}
void MainWindow::showTrayTooltip() {
if (trayIcon && !cSeenTrayTooltip()) {
trayIcon->showMessage(str_const_toString(AppName), lang(lng_tray_icon_text), QSystemTrayIcon::Information, 10000);
cSetSeenTrayTooltip(true);
Local::writeSettings();
}
}
void MainWindow::psUpdateWorkmode() {
switch (cWorkMode()) {
case dbiwmWindowAndTray: {
@ -809,7 +817,7 @@ void MainWindow::psFirstShow() {
setWindowState(Qt::WindowMaximized);
}
if ((cLaunchMode() == LaunchModeAutoStart && cStartMinimized()) || cStartInTray()) {
if ((cLaunchMode() == LaunchModeAutoStart && cStartMinimized() && !App::passcoded()) || cStartInTray()) {
setWindowState(Qt::WindowMinimized);
if (cWorkMode() == dbiwmTrayOnly || cWorkMode() == dbiwmWindowAndTray) {
hide();

View File

@ -93,7 +93,7 @@ protected:
int32 screenNameChecksum(const QString &name) const override;
void unreadCounterChangedHook() override;
bool psHasTrayIcon() const {
bool hasTrayIcon() const override {
return trayIcon;
}
@ -106,6 +106,8 @@ protected:
void psSetupTrayIcon();
virtual void placeSmallCounter(QImage &img, int size, int count, style::color bg, const QPoint &shift, style::color color) = 0;
void showTrayTooltip() override;
QTimer psUpdatedPositionTimer;
private:

View File

@ -73,8 +73,8 @@ void SharedMediaWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) {
return;
}
bool updated = false;
for (int i = 0; i < OverviewCount; ++i) {
auto updated = false;
for (auto i = 0; i != OverviewCount; ++i) {
if (update.mediaTypesMask & (1 << i)) {
refreshButton(static_cast<MediaOverviewType>(i));
updated = true;

View File

@ -173,7 +173,7 @@ void BackgroundRow::updateImage() {
Painter p(&back);
PainterHighQualityEnabler hq(p);
auto &pix = Window::Theme::Background()->image();
auto &pix = Window::Theme::Background()->pixmap();
int sx = (pix.width() > pix.height()) ? ((pix.width() - pix.height()) / 2) : 0;
int sy = (pix.height() > pix.width()) ? ((pix.height() - pix.width()) / 2) : 0;
int s = (pix.width() > pix.height()) ? pix.height() : pix.width();

View File

@ -193,7 +193,10 @@ void GeneralWidget::refreshControls() {
addChildRow(_enableTaskbarIcon, marginLarge, lang(lng_settings_workmode_window), SLOT(onEnableTaskbarIcon()), (cWorkMode() == dbiwmWindowOnly || cWorkMode() == dbiwmWindowAndTray));
addChildRow(_autoStart, marginSmall, lang(lng_settings_auto_start), SLOT(onAutoStart()), cAutoStart());
addChildRow(_startMinimized, marginLarge, slidedPadding, lang(lng_settings_start_min), SLOT(onStartMinimized()), cStartMinimized());
addChildRow(_startMinimized, marginLarge, slidedPadding, lang(lng_settings_start_min), SLOT(onStartMinimized()), (cStartMinimized() && !Global::LocalPasscode()));
subscribe(Global::RefLocalPasscodeChanged(), [this] {
_startMinimized->entity()->setChecked(cStartMinimized() && !Global::LocalPasscode());
});
if (!cAutoStart()) {
_startMinimized->hideFast();
}
@ -310,8 +313,18 @@ void GeneralWidget::onAutoStart() {
}
void GeneralWidget::onStartMinimized() {
cSetStartMinimized(_startMinimized->entity()->checked());
Local::writeSettings();
auto checked = _startMinimized->entity()->checked();
if (Global::LocalPasscode()) {
if (checked) {
_startMinimized->entity()->setChecked(false);
Ui::show(Box<InformBox>(lang(lng_error_start_minimized_passcoded)));
}
return;
}
if (cStartMinimized() != checked) {
cSetStartMinimized(checked);
Local::writeSettings();
}
}
void GeneralWidget::onAddInSendTo() {

View File

@ -50,7 +50,13 @@ Tooltip::Tooltip() : TWidget(nullptr) {
void Tooltip::onShow() {
if (_shower) {
QString text = (App::wnd() && App::wnd()->isActive(false)) ? _shower->tooltipText() : QString();
auto text = QString();
if (auto window = App::wnd()) {
window->updateIsActive(0);
if (window->isActive()) {
text = _shower->tooltipText();
}
}
if (text.isEmpty()) {
Hide();
} else {

View File

@ -33,7 +33,8 @@ namespace Window {
MainWindow::MainWindow() : QWidget()
, _positionUpdatedTimer(this)
, _body(this)
, _titleText(qsl("Telegram")) {
, _titleText(qsl("Telegram"))
, _isActiveTimer(this) {
subscribe(Theme::Background(), [this](const Theme::BackgroundUpdate &data) {
if (data.paletteChanged()) {
if (_title) {
@ -43,11 +44,14 @@ MainWindow::MainWindow() : QWidget()
}
});
subscribe(Global::RefUnreadCounterUpdate(), [this] { updateUnreadCounter(); });
_isActiveTimer->setSingleShot(true);
connect(_isActiveTimer, SIGNAL(timeout()), this, SLOT(updateIsActiveByTimer()));
}
bool MainWindow::hideNoQuit() {
if (_mediaView && !_mediaView->isHidden()) {
_mediaView->hide();
hideMediaview();
return true;
}
if (cWorkMode() == dbiwmTrayOnly || cWorkMode() == dbiwmWindowAndTray) {
@ -62,6 +66,59 @@ bool MainWindow::hideNoQuit() {
Ui::showChatsList();
return true;
}
return false;
}
void MainWindow::clearWidgets() {
Ui::hideLayer(true);
if (_mediaView) {
hideMediaview();
_mediaView->rpcClear();
_mediaView->clearData();
}
clearWidgetsHook();
updateGlobalMenu();
}
void MainWindow::showPhoto(const PhotoOpenClickHandler *lnk, HistoryItem *item) {
return (!item && lnk->peer()) ? showPhoto(lnk->photo(), lnk->peer()) : showPhoto(lnk->photo(), item);
}
void MainWindow::showPhoto(PhotoData *photo, HistoryItem *item) {
if (_mediaView->isHidden()) Ui::hideLayer(true);
_mediaView->showPhoto(photo, item);
_mediaView->activateWindow();
_mediaView->setFocus();
}
void MainWindow::showPhoto(PhotoData *photo, PeerData *peer) {
if (_mediaView->isHidden()) Ui::hideLayer(true);
_mediaView->showPhoto(photo, peer);
_mediaView->activateWindow();
_mediaView->setFocus();
}
void MainWindow::showDocument(DocumentData *doc, HistoryItem *item) {
if (_mediaView->isHidden()) Ui::hideLayer(true);
_mediaView->showDocument(doc, item);
_mediaView->activateWindow();
_mediaView->setFocus();
}
bool MainWindow::ui_isMediaViewShown() {
return _mediaView && !_mediaView->isHidden();
}
void MainWindow::updateIsActive(int timeout) {
if (timeout) {
return _isActiveTimer->start(timeout);
}
_isActive = computeIsActive();
updateIsActiveHook();
}
bool MainWindow::computeIsActive() const {
return isActiveWindow() && isVisible() && !(windowState() & Qt::WindowMinimized);
}
void MainWindow::hideMediaview() {
@ -251,22 +308,31 @@ void MainWindow::savePosition(Qt::WindowState state) {
}
bool MainWindow::minimizeToTray() {
if (App::quitting() || !psHasTrayIcon()) return false;
if (App::quitting() || !hasTrayIcon()) return false;
closeWithoutDestroy();
if (cPlatform() == dbipWindows && trayIcon && !cSeenTrayTooltip()) {
trayIcon->showMessage(str_const_toString(AppName), lang(lng_tray_icon_text), QSystemTrayIcon::Information, 10000);
cSetSeenTrayTooltip(true);
Local::writeSettings();
}
updateIsActive(Global::OfflineBlurTimeout());
updateTrayMenu();
updateGlobalMenu();
showTrayTooltip();
return true;
}
void MainWindow::closeWithoutDestroy() {
hide();
void MainWindow::documentUpdated(DocumentData *doc) {
if (!_mediaView || _mediaView->isHidden()) return;
_mediaView->documentUpdated(doc);
}
void MainWindow::changingMsgId(HistoryItem *row, MsgId newId) {
if (!_mediaView || _mediaView->isHidden()) return;
_mediaView->changingMsgId(row, newId);
}
PeerData *MainWindow::ui_getPeerForMouseAction() {
if (_mediaView && !_mediaView->isHidden()) {
return _mediaView->ui_getPeerForMouseAction();
}
return nullptr;
}
MainWindow::~MainWindow() = default;

View File

@ -39,6 +39,10 @@ public:
void init();
HitTestResult hitTest(const QPoint &p) const;
void updateIsActive(int timeout);
bool isActive() const {
return _isActive;
}
bool positionInited() const {
return _positionInited;
@ -51,16 +55,33 @@ public:
return _titleText;
}
void showPhoto(const PhotoOpenClickHandler *lnk, HistoryItem *item = 0);
void showPhoto(PhotoData *photo, HistoryItem *item);
void showPhoto(PhotoData *photo, PeerData *item);
void showDocument(DocumentData *doc, HistoryItem *item);
bool ui_isMediaViewShown();
QWidget *filedialogParent();
virtual void updateTrayMenu(bool force = false) {
}
// TODO: rewrite using base::Observable
void documentUpdated(DocumentData *doc);
virtual void changingMsgId(HistoryItem *row, MsgId newId);
virtual ~MainWindow();
TWidget *bodyWidget() {
return _body.data();
}
virtual PeerData *ui_getPeerForMouseAction();
public slots:
bool minimizeToTray();
void updateGlobalMenu() {
updateGlobalMenuHook();
}
protected:
void resizeEvent(QResizeEvent *e) override;
@ -70,6 +91,13 @@ protected:
virtual void initHook() {
}
virtual void updateIsActiveHook() {
}
void clearWidgets();
virtual void clearWidgetsHook() {
}
virtual void stateChangedHook(Qt::WindowState state) {
}
@ -83,6 +111,15 @@ protected:
hide();
}
virtual void updateGlobalMenuHook() {
}
virtual bool hasTrayIcon() const {
return false;
}
virtual void showTrayTooltip() {
}
// This one is overriden in Windows for historical reasons.
virtual int32 screenNameChecksum(const QString &name) const;
@ -95,6 +132,9 @@ private slots:
savePosition();
}
void onReActivate();
void updateIsActiveByTimer() {
updateIsActive(0);
}
private:
void updatePalette();
@ -102,6 +142,8 @@ private:
void updateUnreadCounter();
void initSize();
bool computeIsActive() const;
object_ptr<QTimer> _positionUpdatedTimer;
bool _positionInited = false;
@ -110,6 +152,9 @@ private:
QString _titleText;
object_ptr<QTimer> _isActiveTimer;
bool _isActive = false;
object_ptr<MediaView> _mediaView = { nullptr };
};

View File

@ -36,6 +36,8 @@ constexpr int kThemeFileSizeLimit = 5 * 1024 * 1024;
constexpr int kThemeBackgroundSizeLimit = 4 * 1024 * 1024;
constexpr int kThemeSchemeSizeLimit = 1024 * 1024;
constexpr int kMinimumTiledSize = 512;
struct Data {
struct Applying {
QString path;
@ -335,6 +337,8 @@ void initColor(style::color color, float64 hue, float64 saturation) {
}
void initColorsFromBackground(const QImage &img) {
t_assert(img.format() == QImage::Format_ARGB32_Premultiplied);
uint64 components[3] = { 0 };
uint64 componentsScroll[3] = { 0 };
auto w = img.width();
@ -409,25 +413,50 @@ void ChatBackground::setImage(int32 id, QImage &&image) {
Local::writeBackground(_id, (_id == kDefaultBackground || _id == kInitialBackground) ? QImage() : image);
setPreparedImage(prepareBackgroundImage(std_::move(image)));
}
t_assert(!_image.isNull());
t_assert(!_pixmap.isNull() && !_pixmapForTiled.isNull());
notify(BackgroundUpdate(BackgroundUpdate::Type::New, _tile));
}
void ChatBackground::setPreparedImage(QImage &&image) {
image = std_::move(image).convertToFormat(QImage::Format_ARGB32_Premultiplied);
if (_id != kThemeBackground && _id != internal::kTestingThemeBackground) {
initColorsFromBackground(image);
}
_image = App::pixmapFromImageInPlace(std_::move(image));
auto width = image.width();
auto height = image.height();
t_assert(width > 0 && height > 0);
auto isSmallForTiled = (width < kMinimumTiledSize || height < kMinimumTiledSize);
if (isSmallForTiled) {
auto repeatTimesX = qCeil(kMinimumTiledSize / float64(width));
auto repeatTimesY = qCeil(kMinimumTiledSize / float64(height));
auto imageForTiled = QImage(width * repeatTimesX, height * repeatTimesY, QImage::Format_ARGB32_Premultiplied);
imageForTiled.setDevicePixelRatio(image.devicePixelRatio());
auto imageForTiledBytes = imageForTiled.bits();
auto bytesInLine = width * sizeof(uint32);
for (auto timesY = 0; timesY != repeatTimesY; ++timesY) {
auto imageBytes = image.constBits();
for (auto y = 0; y != height; ++y) {
for (auto timesX = 0; timesX != repeatTimesX; ++timesX) {
memcpy(imageForTiledBytes, imageBytes, bytesInLine);
imageForTiledBytes += bytesInLine;
}
imageBytes += image.bytesPerLine();
imageForTiledBytes += imageForTiled.bytesPerLine() - (repeatTimesX * bytesInLine);
}
}
_pixmapForTiled = App::pixmapFromImageInPlace(std_::move(imageForTiled));
}
_pixmap = App::pixmapFromImageInPlace(std_::move(image));
if (!isSmallForTiled) {
_pixmapForTiled = _pixmap;
}
}
int32 ChatBackground::id() const {
return _id;
}
const QPixmap &ChatBackground::image() const {
return _image;
}
bool ChatBackground::tile() const {
return _tile;
}
@ -441,7 +470,7 @@ bool ChatBackground::tileForSave() const {
}
void ChatBackground::ensureStarted() {
if (_image.isNull()) {
if (_pixmap.isNull()) {
// We should start first, otherwise the default call
// to start() will reset this value to _themeTile.
start();
@ -479,7 +508,7 @@ void ChatBackground::saveForRevert() {
ensureStarted();
if (_id != internal::kTestingThemeBackground && _id != internal::kTestingDefaultBackground) {
_idForRevert = _id;
_imageForRevert = std_::move(_image).toImage();
_imageForRevert = std_::move(_pixmap).toImage();
_tileForRevert = _tile;
}
}
@ -507,7 +536,7 @@ void ChatBackground::setTestingDefaultTheme() {
void ChatBackground::keepApplied() {
if (_id == internal::kTestingThemeBackground) {
_id = kThemeBackground;
_themeImage = _image.toImage();
_themeImage = _pixmap.toImage();
_themeTile = _tile;
writeNewBackgroundSettings();
} else if (_id == internal::kTestingDefaultBackground) {

View File

@ -103,7 +103,12 @@ public:
void revert();
int32 id() const;
const QPixmap &image() const;
const QPixmap &pixmap() const {
return _pixmap;
}
const QPixmap &pixmapForTiled() const {
return _pixmapForTiled;
}
bool tile() const;
bool tileForSave() const;
@ -114,7 +119,8 @@ private:
void writeNewBackgroundSettings();
int32 _id = internal::kUninitializedBackground;
QPixmap _image;
QPixmap _pixmap;
QPixmap _pixmapForTiled;
bool _tile = false;
QImage _themeImage;

View File

@ -413,18 +413,26 @@ void Generator::paintHistoryBackground() {
}
_p->setClipRect(_history);
if (tiled) {
auto left = _history.x(), top = _history.y(), right = _history.x() + _history.width(), bottom = _history.y() + _history.height();
auto w = background.width() / cRetinaFactor();
auto h = background.height() / cRetinaFactor();
auto sx = qFloor(left / w);
auto sy = qFloor((top - fromy) / h);
auto cx = qCeil(right / w);
auto cy = qCeil((bottom - fromy) / h);
for (auto i = sx; i != cx; ++i) {
for (auto j = sy; j != cy; ++j) {
_p->drawImage(QPointF(_history.x() + i * w, _history.y() + fromy + j * h), background);
auto width = background.width();
auto height = background.height();
auto repeatTimesX = qCeil(_history.width() * cIntRetinaFactor() / float64(width));
auto repeatTimesY = qCeil((_history.height() - fromy) * cIntRetinaFactor() / float64(height));
auto imageForTiled = QImage(width * repeatTimesX, height * repeatTimesY, QImage::Format_ARGB32_Premultiplied);
imageForTiled.setDevicePixelRatio(background.devicePixelRatio());
auto imageForTiledBytes = imageForTiled.bits();
auto bytesInLine = width * sizeof(uint32);
for (auto timesY = 0; timesY != repeatTimesY; ++timesY) {
auto imageBytes = background.constBits();
for (auto y = 0; y != height; ++y) {
for (auto timesX = 0; timesX != repeatTimesX; ++timesX) {
memcpy(imageForTiledBytes, imageBytes, bytesInLine);
imageForTiledBytes += bytesInLine;
}
imageBytes += background.bytesPerLine();
imageForTiledBytes += imageForTiled.bytesPerLine() - (repeatTimesX * bytesInLine);
}
}
_p->drawImage(_history.x(), _history.y() + fromy, imageForTiled);
} else {
PainterHighQualityEnabler hq(*_p);

View File

@ -1,6 +1,6 @@
AppVersion 10022
AppVersion 10023
AppVersionStrMajor 0.10
AppVersionStrSmall 0.10.22
AppVersionStr 0.10.22
AppVersionStrSmall 0.10.23
AppVersionStr 0.10.23
AlphaChannel 1
BetaVersion 0