mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-08-29 21:48:26 +00:00
Merge branch 'dev'
This commit is contained in:
commit
10bd2b680d
@ -636,7 +636,7 @@
|
||||
"/usr/local/Qt-5.5.1/plugins/platforms",
|
||||
"/usr/local/Qt-5.5.1/plugins/imageformats",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.7;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.8;
|
||||
OBJROOT = ./../Mac/ReleaseIntermediateStyle;
|
||||
OTHER_CFLAGS = (
|
||||
"-pipe",
|
||||
@ -727,7 +727,7 @@
|
||||
"/usr/local/Qt-5.5.1/plugins/platforms",
|
||||
"/usr/local/Qt-5.5.1/plugins/imageformats",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.7;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.8;
|
||||
OBJROOT = ./../Mac/DebugIntermediateStyle;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_CFLAGS = (
|
||||
|
@ -383,7 +383,7 @@ to link the code of portions of this program with the OpenSSL library.\n\
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE\n\
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org\n\
|
||||
*/\n";
|
||||
tout << "#pragma once\n\n#include \"ui/style.h\"\n\nnamespace style {\n";
|
||||
tout << "#pragma once\n\n#include \"ui/style_core.h\"\n\nnamespace style {\n";
|
||||
for (int i = 0, l = byIndex.size(); i < l; ++i) {
|
||||
ClassData &cls(byIndex[i]);
|
||||
classes.insert(cls.name, cls);
|
||||
@ -513,7 +513,7 @@ typedef QPair<ScalarType, ScalarValue> ScalarData;
|
||||
typedef QPair<string, ScalarData> Scalar;
|
||||
typedef QMap<string, ScalarData> Fields;
|
||||
typedef QPair<string, Fields> ObjectData;
|
||||
typedef QPair<string, ObjectData> Object;
|
||||
typedef QPair<string, ObjectData> Object;
|
||||
typedef QVector<Object> Objects;
|
||||
typedef QVector<Scalar> Scalars;
|
||||
|
||||
@ -636,7 +636,7 @@ ScalarValue prepareNumber(int variant, const string &token, const char *&text, c
|
||||
ScalarValue prepareColorRGB(int variant, const string &name, const char *&text, const char *end) {
|
||||
StyleGenTokenType type;
|
||||
string token;
|
||||
|
||||
|
||||
readStyleGenToken(text, end, type, token);
|
||||
if (type != stConsStart) throw Exception(QString("Unexpected token %1 while reading rgb() cons!").arg(type));
|
||||
|
||||
@ -675,7 +675,7 @@ ScalarValue prepareColorRGB(int variant, const string &name, const char *&text,
|
||||
ScalarValue prepareColorRGBA(int variant, const string &name, const char *&text, const char *end) {
|
||||
StyleGenTokenType type;
|
||||
string token;
|
||||
|
||||
|
||||
readStyleGenToken(text, end, type, token);
|
||||
if (type != stConsStart) throw Exception(QString("Unexpected token %1 while reading rgba() cons!").arg(type));
|
||||
|
||||
@ -721,7 +721,7 @@ ScalarValue prepareColorRGBA(int variant, const string &name, const char *&text,
|
||||
ScalarValue prepareRect(int variant, const char *&text, const char *end) {
|
||||
StyleGenTokenType type;
|
||||
string token;
|
||||
|
||||
|
||||
readStyleGenToken(text, end, type, token);
|
||||
if (type != stConsStart) throw Exception(QString("Unexpected token %1 while reading rect() cons!").arg(type));
|
||||
|
||||
@ -859,7 +859,7 @@ ScalarValue prepareSprite(int variant, const char *&text, const char *end) {
|
||||
ScalarValue preparePoint(int variant, const char *&text, const char *end) {
|
||||
StyleGenTokenType type;
|
||||
string token;
|
||||
|
||||
|
||||
readStyleGenToken(text, end, type, token);
|
||||
if (type != stConsStart) throw Exception(QString("Unexpected token %1 while reading point() cons!").arg(type));
|
||||
|
||||
@ -892,7 +892,7 @@ ScalarValue preparePoint(int variant, const char *&text, const char *end) {
|
||||
ScalarValue prepareSize(int variant, const char *&text, const char *end) {
|
||||
StyleGenTokenType type;
|
||||
string token;
|
||||
|
||||
|
||||
readStyleGenToken(text, end, type, token);
|
||||
if (type != stConsStart) throw Exception(QString("Unexpected token %1 while reading size() cons!").arg(type));
|
||||
|
||||
@ -925,7 +925,7 @@ ScalarValue prepareSize(int variant, const char *&text, const char *end) {
|
||||
ScalarValue prepareTransition(int variant, const char *&text, const char *end) {
|
||||
StyleGenTokenType type;
|
||||
string token;
|
||||
|
||||
|
||||
readStyleGenToken(text, end, type, token);
|
||||
if (type != stConsStart) throw Exception(QString("Unexpected token %1 while reading transition() cons!").arg(type));
|
||||
|
||||
@ -942,7 +942,7 @@ ScalarValue prepareTransition(int variant, const char *&text, const char *end) {
|
||||
ScalarValue prepareCursor(int variant, const char *&text, const char *end) {
|
||||
StyleGenTokenType type;
|
||||
string token;
|
||||
|
||||
|
||||
readStyleGenToken(text, end, type, token);
|
||||
if (type != stConsStart) throw Exception(QString("Unexpected token %1 while reading cursor() cons!").arg(type));
|
||||
|
||||
@ -959,7 +959,7 @@ ScalarValue prepareCursor(int variant, const char *&text, const char *end) {
|
||||
ScalarValue prepareAlign(int variant, const char *&text, const char *end) {
|
||||
StyleGenTokenType type;
|
||||
string token;
|
||||
|
||||
|
||||
readStyleGenToken(text, end, type, token);
|
||||
if (type != stConsStart) throw Exception(QString("Unexpected token %1 while reading align() cons!").arg(type));
|
||||
|
||||
@ -976,7 +976,7 @@ ScalarValue prepareAlign(int variant, const char *&text, const char *end) {
|
||||
ScalarValue prepareMargins(int variant, const char *&text, const char *end) {
|
||||
StyleGenTokenType type;
|
||||
string token;
|
||||
|
||||
|
||||
readStyleGenToken(text, end, type, token);
|
||||
if (type != stConsStart) throw Exception(QString("Unexpected token %1 while reading margins() cons!").arg(type));
|
||||
|
||||
@ -1049,7 +1049,7 @@ QMap<int, Fonts> fonts;
|
||||
ScalarValue prepareFont(int variant, const string &name, const char *&text, const char *end) {
|
||||
StyleGenTokenType type;
|
||||
string token;
|
||||
|
||||
|
||||
ScalarValue sizeScalar, familyScalar;
|
||||
|
||||
string size, family;
|
||||
@ -1534,7 +1534,7 @@ to link the code of portions of this program with the OpenSSL library.\n\
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE\n\
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org\n\
|
||||
*/\n";
|
||||
tout << "#pragma once\n\n#include \"ui/style.h\"\n\nnamespace st {\n";
|
||||
tout << "#pragma once\n\n#include \"ui/style_core.h\"\n\nnamespace st {\n";
|
||||
tcpp << "\
|
||||
/*\n\
|
||||
Created from \'/Resources/style.txt\' by \'/MetaStyle\' project\n\
|
||||
@ -1594,7 +1594,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org\n\
|
||||
tcpp << "\tColorDatas _colorsMap;\n";
|
||||
tcpp << "\tint _spriteWidth = " << spriteWidths[0] << ";\n\n";
|
||||
tcpp << "\tvoid startManager() {\n";
|
||||
|
||||
|
||||
tcpp << "\n\t\tif (cRetina()) {\n";
|
||||
tcpp << "\t\t\tcSetRealScale(dbisOne);\n";
|
||||
tcpp << "\t\t\t_spriteWidth = " << spriteWidths[variantsCount - 1] << ";\n\n";
|
||||
|
@ -23,7 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
#include "lang.h"
|
||||
|
||||
#include "application.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
#include "mainwidget.h"
|
||||
#include "apiwrap.h"
|
||||
|
||||
|
@ -31,7 +31,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
#include <libexif/exif-data.h>
|
||||
#endif
|
||||
#include "localstorage.h"
|
||||
|
||||
#include "apiwrap.h"
|
||||
#include "numbers.h"
|
||||
|
||||
namespace {
|
||||
@ -146,23 +146,29 @@ namespace App {
|
||||
return AppClass::app();
|
||||
}
|
||||
|
||||
Window *wnd() {
|
||||
MainWindow *wnd() {
|
||||
return AppClass::wnd();
|
||||
}
|
||||
|
||||
MainWidget *main() {
|
||||
Window *w(wnd());
|
||||
return w ? w->mainWidget() : 0;
|
||||
if (auto w = wnd()) {
|
||||
return w->mainWidget();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SettingsWidget *settings() {
|
||||
Window *w(wnd());
|
||||
return w ? w->settingsWidget() : 0;
|
||||
if (auto w = wnd()) {
|
||||
return w->settingsWidget();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool passcoded() {
|
||||
Window *w(wnd());
|
||||
return w ? w->passcodeWidget() : 0;
|
||||
if (auto w = wnd()) {
|
||||
return w->passcodeWidget();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
FileUploader *uploader() {
|
||||
@ -181,7 +187,7 @@ namespace {
|
||||
if (audioPlayer()) {
|
||||
audioPlayer()->stopAndClear();
|
||||
}
|
||||
if (Window *w = wnd()) {
|
||||
if (auto w = wnd()) {
|
||||
w->tempDirDelete(Local::ClearManagerAll);
|
||||
w->notifyClearFast();
|
||||
w->setupIntro(true);
|
||||
@ -196,7 +202,7 @@ namespace {
|
||||
globalNotifyChatsPtr = UnknownNotifySettings;
|
||||
if (App::uploader()) App::uploader()->clear();
|
||||
clearStorageImages();
|
||||
if (Window *w = wnd()) {
|
||||
if (auto w = wnd()) {
|
||||
w->getTitle()->updateBackButton();
|
||||
w->updateTitleStatus();
|
||||
w->getTitle()->resizeEvent(0);
|
||||
@ -1762,22 +1768,22 @@ namespace {
|
||||
|
||||
void historyItemDetached(HistoryItem *item) {
|
||||
if (::hoveredItem == item) {
|
||||
hoveredItem(0);
|
||||
hoveredItem(nullptr);
|
||||
}
|
||||
if (::pressedItem == item) {
|
||||
pressedItem(0);
|
||||
pressedItem(nullptr);
|
||||
}
|
||||
if (::hoveredLinkItem == item) {
|
||||
hoveredLinkItem(0);
|
||||
hoveredLinkItem(nullptr);
|
||||
}
|
||||
if (::pressedLinkItem == item) {
|
||||
pressedLinkItem(0);
|
||||
pressedLinkItem(nullptr);
|
||||
}
|
||||
if (::contextItem == item) {
|
||||
contextItem(0);
|
||||
contextItem(nullptr);
|
||||
}
|
||||
if (::mousedItem == item) {
|
||||
mousedItem(0);
|
||||
mousedItem(nullptr);
|
||||
}
|
||||
if (App::wnd()) {
|
||||
App::wnd()->notifyItemRemoved(item);
|
||||
|
@ -20,10 +20,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "basic_types.h"
|
||||
#include "core/basic_types.h"
|
||||
|
||||
class AppClass;
|
||||
class Window;
|
||||
class MainWindow;
|
||||
class MainWidget;
|
||||
class SettingsWidget;
|
||||
class ApiWrap;
|
||||
@ -48,7 +48,7 @@ class LayeredWidget;
|
||||
|
||||
namespace App {
|
||||
AppClass *app();
|
||||
Window *wnd();
|
||||
MainWindow *wnd();
|
||||
MainWidget *main();
|
||||
SettingsWidget *settings();
|
||||
bool passcoded();
|
||||
|
@ -20,20 +20,16 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "application.h"
|
||||
|
||||
#include "ui/style.h"
|
||||
|
||||
#include "shortcuts.h"
|
||||
|
||||
#include "pspecific.h"
|
||||
#include "fileuploader.h"
|
||||
#include "mainwidget.h"
|
||||
|
||||
#include "lang.h"
|
||||
#include "boxes/confirmbox.h"
|
||||
#include "langloaderplain.h"
|
||||
|
||||
#include "localstorage.h"
|
||||
|
||||
#include "autoupdater.h"
|
||||
|
||||
namespace {
|
||||
@ -90,14 +86,7 @@ namespace {
|
||||
|
||||
AppClass *AppObject = 0;
|
||||
|
||||
Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
||||
, _secondInstance(false)
|
||||
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
||||
, _updateReply(0)
|
||||
, _updateThread(0)
|
||||
, _updateChecker(0)
|
||||
#endif
|
||||
{
|
||||
Application::Application(int &argc, char **argv) : QApplication(argc, argv) {
|
||||
QByteArray d(QFile::encodeName(QDir(cWorkingDir()).absolutePath()));
|
||||
char h[33] = { 0 };
|
||||
hashMd5Hex(d.constData(), d.size(), h);
|
||||
@ -718,7 +707,7 @@ AppClass::AppClass() : QObject()
|
||||
|
||||
QMimeDatabase().mimeTypeForName(qsl("text/plain")); // create mime database
|
||||
|
||||
_window = new Window();
|
||||
_window = new MainWindow();
|
||||
_window->createWinId();
|
||||
_window->init();
|
||||
|
||||
@ -905,6 +894,12 @@ void AppClass::call_handleHistoryUpdate() {
|
||||
Notify::handlePendingHistoryUpdate();
|
||||
}
|
||||
|
||||
void AppClass::call_handleUnreadCounterUpdate() {
|
||||
if (auto w = App::wnd()) {
|
||||
w->updateUnreadCounter();
|
||||
}
|
||||
}
|
||||
|
||||
void AppClass::killDownloadSessions() {
|
||||
uint64 ms = getms(), left = MTPAckSendWaiting + MTPKillFileSessionTimeout;
|
||||
for (QMap<int32, uint64>::iterator i = killDownloadSessionTimes.begin(); i != killDownloadSessionTimes.end(); ) {
|
||||
@ -1035,8 +1030,8 @@ void AppClass::checkMapVersion() {
|
||||
if (Local::oldMapVersion()) {
|
||||
QString versionFeatures;
|
||||
if ((cDevVersion() || cBetaVersion()) && Local::oldMapVersion() < 9041) {
|
||||
// versionFeatures = QString::fromUtf8("\xe2\x80\x94 Design improvements\n\xe2\x80\x94 Bug fixes and other minor improvements");
|
||||
versionFeatures = langNewVersionText();
|
||||
versionFeatures = QString::fromUtf8("\xe2\x80\x94 Select and copy text in photo / video captions and web page previews\n\xe2\x80\x94 Media player shortcuts are enabled only when player is opened");
|
||||
// versionFeatures = langNewVersionText();
|
||||
} else if (Local::oldMapVersion() < 9041) {
|
||||
versionFeatures = langNewVersionText();
|
||||
} else {
|
||||
@ -1053,7 +1048,7 @@ void AppClass::checkMapVersion() {
|
||||
AppClass::~AppClass() {
|
||||
Shortcuts::finish();
|
||||
|
||||
if (Window *w = _window) {
|
||||
if (auto w = _window) {
|
||||
_window = 0;
|
||||
delete w;
|
||||
}
|
||||
@ -1086,7 +1081,7 @@ AppClass *AppClass::app() {
|
||||
return AppObject;
|
||||
}
|
||||
|
||||
Window *AppClass::wnd() {
|
||||
MainWindow *AppClass::wnd() {
|
||||
return AppObject ? AppObject->_window : 0;
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
#include "pspecific.h"
|
||||
|
||||
class UpdateChecker;
|
||||
@ -56,7 +56,7 @@ private:
|
||||
QLocalServer _localServer;
|
||||
QLocalSocket _localSocket;
|
||||
LocalClients _localClients;
|
||||
bool _secondInstance;
|
||||
bool _secondInstance = false;
|
||||
|
||||
void singleInstanceChecked();
|
||||
|
||||
@ -98,10 +98,10 @@ public slots:
|
||||
private:
|
||||
|
||||
SingleTimer _updateCheckTimer;
|
||||
QNetworkReply *_updateReply;
|
||||
QNetworkReply *_updateReply = nullptr;
|
||||
QNetworkAccessManager _updateManager;
|
||||
QThread *_updateThread;
|
||||
UpdateChecker *_updateChecker;
|
||||
QThread *_updateThread = nullptr;
|
||||
UpdateChecker *_updateChecker = nullptr;
|
||||
|
||||
#endif
|
||||
};
|
||||
@ -153,7 +153,7 @@ public:
|
||||
~AppClass();
|
||||
|
||||
static AppClass *app();
|
||||
static Window *wnd();
|
||||
static MainWindow *wnd();
|
||||
static MainWidget *main();
|
||||
|
||||
FileUploader *uploader();
|
||||
@ -202,6 +202,7 @@ public slots:
|
||||
void onAppStateChanged(Qt::ApplicationState state);
|
||||
|
||||
void call_handleHistoryUpdate();
|
||||
void call_handleUnreadCounterUpdate();
|
||||
|
||||
private:
|
||||
|
||||
@ -212,7 +213,7 @@ private:
|
||||
|
||||
uint64 _lastActionTime;
|
||||
|
||||
Window *_window;
|
||||
MainWindow *_window;
|
||||
FileUploader *_uploader;
|
||||
Translator *_translator;
|
||||
|
||||
|
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "basic_types.h"
|
||||
#include "core/basic_types.h"
|
||||
|
||||
void audioInit();
|
||||
bool audioWorks();
|
||||
|
@ -23,7 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
|
||||
#include "aboutbox.h"
|
||||
#include "mainwidget.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include "autoupdater.h"
|
||||
#include "boxes/confirmbox.h"
|
||||
|
@ -25,7 +25,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
|
||||
#include "abstractbox.h"
|
||||
#include "mainwidget.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
void BlueTitleShadow::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
|
@ -28,7 +28,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
#include "photocropbox.h"
|
||||
#include "ui/filedialog.h"
|
||||
#include "mainwidget.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
#include "apiwrap.h"
|
||||
|
||||
AddContactBox::AddContactBox(QString fname, QString lname, QString phone) : AbstractBox(st::boxWidth)
|
||||
, _user(0)
|
||||
|
@ -26,7 +26,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
#include "autolockbox.h"
|
||||
#include "confirmbox.h"
|
||||
#include "mainwidget.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
AutoLockBox::AutoLockBox() :
|
||||
_close(this, lang(lng_box_ok), st::defaultBoxButton) {
|
||||
|
@ -23,7 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
|
||||
#include "backgroundbox.h"
|
||||
#include "mainwidget.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
#include "settingswidget.h"
|
||||
|
||||
BackgroundInner::BackgroundInner() :
|
||||
|
@ -23,9 +23,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
|
||||
#include "confirmbox.h"
|
||||
#include "mainwidget.h"
|
||||
#include "window.h"
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "apiwrap.h"
|
||||
#include "application.h"
|
||||
#include "core/click_handler_types.h"
|
||||
|
||||
TextParseOptions _confirmBoxTextOptions = {
|
||||
TextParseLinks | TextParseMultiline | TextParseRichText, // flags
|
||||
@ -118,10 +119,10 @@ void ConfirmBox::updateHover() {
|
||||
QPoint m(mapFromGlobal(_lastMousePos));
|
||||
|
||||
textstyleSet(&st::boxTextStyle);
|
||||
ClickHandlerPtr handler = _text.linkLeft(m.x() - st::boxPadding.left(), m.y() - st::boxPadding.top(), _textWidth, width(), style::al_left);
|
||||
auto state = _text.getStateLeft(m.x() - st::boxPadding.left(), m.y() - st::boxPadding.top(), _textWidth, width());
|
||||
textstyleRestore();
|
||||
|
||||
ClickHandler::setActive(handler, this);
|
||||
ClickHandler::setActive(state.link, this);
|
||||
}
|
||||
|
||||
void ConfirmBox::closePressed() {
|
||||
|
@ -25,7 +25,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
|
||||
#include "connectionbox.h"
|
||||
#include "mainwidget.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
ConnectionBox::ConnectionBox() : AbstractBox(st::boxWidth)
|
||||
, _hostInput(this, st::connectionHostInputField, lang(lng_connection_host_ph), cConnectionProxy().host)
|
||||
|
@ -26,11 +26,12 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
#include "boxes/addcontactbox.h"
|
||||
#include "boxes/contactsbox.h"
|
||||
#include "mainwidget.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
#include "application.h"
|
||||
#include "ui/filedialog.h"
|
||||
#include "boxes/photocropbox.h"
|
||||
#include "boxes/confirmbox.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)));
|
||||
@ -956,7 +957,6 @@ void ContactsInner::peopleReceived(const QString &query, const QVector<MTPPeer>
|
||||
if (p->asUser()->botInfo->cantJoinGroups) continue;
|
||||
}
|
||||
if (_channel) {
|
||||
if (_channel->isMegagroup() && _membersFilter == MembersFilterAdmins) continue;
|
||||
if (!_channel->isMegagroup() && _membersFilter != MembersFilterAdmins) continue;
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
|
||||
#include "emojibox.h"
|
||||
#include "mainwidget.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
namespace {
|
||||
// copied from genemoji.cpp
|
||||
|
@ -26,7 +26,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
#include "languagebox.h"
|
||||
#include "confirmbox.h"
|
||||
#include "mainwidget.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include "langloaderplain.h"
|
||||
|
||||
|
@ -23,7 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
|
||||
#include "passcodebox.h"
|
||||
#include "confirmbox.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include "localstorage.h"
|
||||
|
||||
|
@ -25,7 +25,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
|
||||
#include "sessionsbox.h"
|
||||
#include "mainwidget.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include "countries.h"
|
||||
#include "confirmbox.h"
|
||||
|
@ -23,10 +23,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
|
||||
#include "stickersetbox.h"
|
||||
#include "mainwidget.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
#include "settingswidget.h"
|
||||
#include "boxes/confirmbox.h"
|
||||
|
||||
#include "apiwrap.h"
|
||||
#include "localstorage.h"
|
||||
|
||||
StickerSetInner::StickerSetInner(const MTPInputStickerSet &set) : TWidget()
|
||||
|
@ -24,7 +24,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
#include "application.h"
|
||||
#include "usernamebox.h"
|
||||
#include "mainwidget.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
UsernameBox::UsernameBox() : AbstractBox(st::boxWidth),
|
||||
_save(this, lang(lng_settings_save), st::defaultBoxButton),
|
||||
|
@ -20,9 +20,9 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
static const int32 AppVersion = 9042;
|
||||
static const wchar_t *AppVersionStr = L"0.9.42";
|
||||
static const bool DevVersion = false;
|
||||
static const int32 AppVersion = 9043;
|
||||
static const wchar_t *AppVersionStr = L"0.9.43";
|
||||
static const bool DevVersion = true;
|
||||
//#define BETA_VERSION (9040128ULL) // just comment this line to build public version
|
||||
|
||||
static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)";
|
||||
|
63
Telegram/SourceFiles/core/click_handler.cpp
Normal file
63
Telegram/SourceFiles/core/click_handler.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "core/click_handler.h"
|
||||
|
||||
ClickHandlerHost::~ClickHandlerHost() {
|
||||
ClickHandler::hostDestroyed(this);
|
||||
}
|
||||
|
||||
NeverFreedPointer<ClickHandlerPtr> ClickHandler::_active;
|
||||
NeverFreedPointer<ClickHandlerPtr> ClickHandler::_pressed;
|
||||
ClickHandlerHost *ClickHandler::_activeHost = nullptr;
|
||||
ClickHandlerHost *ClickHandler::_pressedHost = nullptr;
|
||||
|
||||
bool ClickHandler::setActive(const ClickHandlerPtr &p, ClickHandlerHost *host) {
|
||||
if ((_active && (*_active == p)) || (!_active && !p)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// emit clickHandlerActiveChanged only when there is no
|
||||
// other pressed click handler currently, if there is
|
||||
// this method will be called when it is unpressed
|
||||
if (_active && *_active) {
|
||||
bool emitClickHandlerActiveChanged = (!_pressed || !*_pressed || *_pressed == *_active);
|
||||
ClickHandlerPtr wasactive = *_active;
|
||||
(*_active).clear();
|
||||
if (_activeHost) {
|
||||
if (emitClickHandlerActiveChanged) {
|
||||
_activeHost->clickHandlerActiveChanged(wasactive, false);
|
||||
}
|
||||
_activeHost = nullptr;
|
||||
}
|
||||
}
|
||||
if (p) {
|
||||
_active.makeIfNull();
|
||||
*_active = p;
|
||||
if ((_activeHost = host)) {
|
||||
bool emitClickHandlerActiveChanged = (!_pressed || !*_pressed || *_pressed == *_active);
|
||||
if (emitClickHandlerActiveChanged) {
|
||||
_activeHost->clickHandlerActiveChanged(*_active, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
158
Telegram/SourceFiles/core/click_handler.h
Normal file
158
Telegram/SourceFiles/core/click_handler.h
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
class ClickHandler;
|
||||
using ClickHandlerPtr = QSharedPointer<ClickHandler>;
|
||||
|
||||
class ClickHandlerHost {
|
||||
protected:
|
||||
|
||||
virtual void clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) {
|
||||
}
|
||||
virtual void clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) {
|
||||
}
|
||||
virtual ~ClickHandlerHost() = 0;
|
||||
friend class ClickHandler;
|
||||
|
||||
};
|
||||
|
||||
class ClickHandler {
|
||||
public:
|
||||
|
||||
virtual void onClick(Qt::MouseButton) const = 0;
|
||||
|
||||
virtual QString tooltip() const {
|
||||
return QString();
|
||||
}
|
||||
virtual void copyToClipboard() const {
|
||||
}
|
||||
virtual QString copyToClipboardContextItem() const {
|
||||
return QString();
|
||||
}
|
||||
virtual QString text() const {
|
||||
return QString();
|
||||
}
|
||||
virtual QString dragText() const {
|
||||
return text();
|
||||
}
|
||||
|
||||
virtual ~ClickHandler() {
|
||||
}
|
||||
|
||||
// this method should be called on mouse over a click handler
|
||||
// it returns true if something was changed or false otherwise
|
||||
static bool setActive(const ClickHandlerPtr &p, ClickHandlerHost *host = nullptr);
|
||||
|
||||
// this method should be called when mouse leaves the host
|
||||
// it returns true if something was changed or false otherwise
|
||||
static bool clearActive(ClickHandlerHost *host = nullptr) {
|
||||
if (host && _activeHost != host) {
|
||||
return false;
|
||||
}
|
||||
return setActive(ClickHandlerPtr(), host);
|
||||
}
|
||||
|
||||
// this method should be called on mouse pressed
|
||||
static void pressed() {
|
||||
unpressed();
|
||||
if (!_active || !*_active) {
|
||||
return;
|
||||
}
|
||||
_pressed.makeIfNull();
|
||||
*_pressed = *_active;
|
||||
if ((_pressedHost = _activeHost)) {
|
||||
_pressedHost->clickHandlerPressedChanged(*_pressed, true);
|
||||
}
|
||||
}
|
||||
|
||||
// this method should be called on mouse released
|
||||
// the activated click handler is returned
|
||||
static ClickHandlerPtr unpressed() {
|
||||
if (_pressed && *_pressed) {
|
||||
bool activated = (_active && *_active == *_pressed);
|
||||
ClickHandlerPtr waspressed = *_pressed;
|
||||
(*_pressed).clear();
|
||||
if (_pressedHost) {
|
||||
_pressedHost->clickHandlerPressedChanged(waspressed, false);
|
||||
_pressedHost = nullptr;
|
||||
}
|
||||
|
||||
if (activated) {
|
||||
return *_active;
|
||||
} else if (_active && *_active && _activeHost) {
|
||||
// emit clickHandlerActiveChanged for current active
|
||||
// click handler, which we didn't emit while we has
|
||||
// a pressed click handler
|
||||
_activeHost->clickHandlerActiveChanged(*_active, true);
|
||||
}
|
||||
}
|
||||
return ClickHandlerPtr();
|
||||
}
|
||||
|
||||
static ClickHandlerPtr getActive() {
|
||||
return _active ? *_active : ClickHandlerPtr();
|
||||
}
|
||||
static ClickHandlerPtr getPressed() {
|
||||
return _pressed ? *_pressed : ClickHandlerPtr();
|
||||
}
|
||||
|
||||
static bool showAsActive(const ClickHandlerPtr &p) {
|
||||
if (!p || !_active || p != *_active) {
|
||||
return false;
|
||||
}
|
||||
return !_pressed || !*_pressed || (p == *_pressed);
|
||||
}
|
||||
static bool showAsPressed(const ClickHandlerPtr &p) {
|
||||
if (!p || !_active || p != *_active) {
|
||||
return false;
|
||||
}
|
||||
return _pressed && (p == *_pressed);
|
||||
}
|
||||
static void hostDestroyed(ClickHandlerHost *host) {
|
||||
if (_activeHost == host) {
|
||||
_activeHost = nullptr;
|
||||
}
|
||||
if (_pressedHost == host) {
|
||||
_pressedHost = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static NeverFreedPointer<ClickHandlerPtr> _active;
|
||||
static NeverFreedPointer<ClickHandlerPtr> _pressed;
|
||||
static ClickHandlerHost *_activeHost;
|
||||
static ClickHandlerHost *_pressedHost;
|
||||
|
||||
};
|
||||
|
||||
class LeftButtonClickHandler : public ClickHandler {
|
||||
public:
|
||||
void onClick(Qt::MouseButton button) const override final {
|
||||
if (button != Qt::LeftButton) return;
|
||||
onClickImpl();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void onClickImpl() const = 0;
|
||||
|
||||
};
|
139
Telegram/SourceFiles/core/click_handler_types.cpp
Normal file
139
Telegram/SourceFiles/core/click_handler_types.cpp
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "core/click_handler_types.h"
|
||||
|
||||
#include "lang.h"
|
||||
#include "pspecific.h"
|
||||
#include "boxes/confirmbox.h"
|
||||
|
||||
QString UrlClickHandler::copyToClipboardContextItem() const {
|
||||
return lang(isEmail() ? lng_context_copy_email : lng_context_copy_link);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
QString tryConvertUrlToLocal(const QString &url) {
|
||||
QRegularExpressionMatch telegramMeUser = QRegularExpression(qsl("^https?://telegram\\.me/([a-zA-Z0-9\\.\\_]+)(/?\\?|/?$|/(\\d+)/?(?:\\?|$))"), QRegularExpression::CaseInsensitiveOption).match(url);
|
||||
QRegularExpressionMatch telegramMeGroup = QRegularExpression(qsl("^https?://telegram\\.me/joinchat/([a-zA-Z0-9\\.\\_\\-]+)(\\?|$)"), QRegularExpression::CaseInsensitiveOption).match(url);
|
||||
QRegularExpressionMatch telegramMeStickers = QRegularExpression(qsl("^https?://telegram\\.me/addstickers/([a-zA-Z0-9\\.\\_]+)(\\?|$)"), QRegularExpression::CaseInsensitiveOption).match(url);
|
||||
QRegularExpressionMatch telegramMeShareUrl = QRegularExpression(qsl("^https?://telegram\\.me/share/url\\?(.+)$"), QRegularExpression::CaseInsensitiveOption).match(url);
|
||||
if (telegramMeGroup.hasMatch()) {
|
||||
return qsl("tg://join?invite=") + myUrlEncode(telegramMeGroup.captured(1));
|
||||
} else if (telegramMeStickers.hasMatch()) {
|
||||
return qsl("tg://addstickers?set=") + myUrlEncode(telegramMeStickers.captured(1));
|
||||
} else if (telegramMeShareUrl.hasMatch()) {
|
||||
return qsl("tg://msg_url?") + telegramMeShareUrl.captured(1);
|
||||
} else if (telegramMeUser.hasMatch()) {
|
||||
QString params = url.mid(telegramMeUser.captured(0).size()), postParam;
|
||||
if (QRegularExpression(qsl("^/\\d+/?(?:\\?|$)")).match(telegramMeUser.captured(2)).hasMatch()) {
|
||||
postParam = qsl("&post=") + telegramMeUser.captured(3);
|
||||
}
|
||||
return qsl("tg://resolve/?domain=") + myUrlEncode(telegramMeUser.captured(1)) + postParam + (params.isEmpty() ? QString() : '&' + params);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void UrlClickHandler::doOpen(QString url) {
|
||||
PopupTooltip::Hide();
|
||||
|
||||
if (isEmail(url)) {
|
||||
QUrl u(qstr("mailto:") + url);
|
||||
if (!QDesktopServices::openUrl(u)) {
|
||||
psOpenFile(u.toString(QUrl::FullyEncoded), true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
url = tryConvertUrlToLocal(url);
|
||||
|
||||
if (url.startsWith(qstr("tg://"), Qt::CaseInsensitive)) {
|
||||
App::openLocalUrl(url);
|
||||
} else {
|
||||
QDesktopServices::openUrl(url);
|
||||
}
|
||||
}
|
||||
|
||||
void HiddenUrlClickHandler::onClick(Qt::MouseButton button) const {
|
||||
QString u = url();
|
||||
|
||||
u = tryConvertUrlToLocal(u);
|
||||
|
||||
if (u.startsWith(qstr("tg://"))) {
|
||||
App::openLocalUrl(u);
|
||||
} else {
|
||||
Ui::showLayer(new ConfirmLinkBox(u));
|
||||
}
|
||||
}
|
||||
|
||||
QString LocationClickHandler::copyToClipboardContextItem() const {
|
||||
return lang(lng_context_copy_link);
|
||||
}
|
||||
|
||||
void LocationClickHandler::onClick(Qt::MouseButton button) const {
|
||||
if (!psLaunchMaps(_coords)) {
|
||||
QDesktopServices::openUrl(_text);
|
||||
}
|
||||
}
|
||||
|
||||
void LocationClickHandler::setup() {
|
||||
QString latlon(qsl("%1,%2").arg(_coords.lat).arg(_coords.lon));
|
||||
_text = qsl("https://maps.google.com/maps?q=") + latlon + qsl("&ll=") + latlon + qsl("&z=16");
|
||||
}
|
||||
|
||||
QString MentionClickHandler::copyToClipboardContextItem() const {
|
||||
return lang(lng_context_copy_mention);
|
||||
}
|
||||
|
||||
void MentionClickHandler::onClick(Qt::MouseButton button) const {
|
||||
if (button == Qt::LeftButton || button == Qt::MiddleButton) {
|
||||
App::openPeerByName(_tag.mid(1), ShowAtProfileMsgId);
|
||||
}
|
||||
}
|
||||
|
||||
QString HashtagClickHandler::copyToClipboardContextItem() const {
|
||||
return lang(lng_context_copy_hashtag);
|
||||
}
|
||||
|
||||
void HashtagClickHandler::onClick(Qt::MouseButton button) const {
|
||||
if (button == Qt::LeftButton || button == Qt::MiddleButton) {
|
||||
App::searchByHashtag(_tag, Ui::getPeerForMouseAction());
|
||||
}
|
||||
}
|
||||
|
||||
void BotCommandClickHandler::onClick(Qt::MouseButton button) const {
|
||||
if (button == Qt::LeftButton || button == Qt::MiddleButton) {
|
||||
if (PeerData *peer = Ui::getPeerForMouseAction()) {
|
||||
UserData *bot = peer->isUser() ? peer->asUser() : nullptr;
|
||||
if (auto item = App::hoveredLinkItem()) {
|
||||
if (!bot) {
|
||||
bot = item->fromOriginal()->asUser(); // may return nullptr
|
||||
}
|
||||
}
|
||||
Ui::showPeerHistory(peer, ShowAtTheEndMsgId);
|
||||
App::sendBotCommand(peer, bot, _cmd);
|
||||
} else {
|
||||
App::insertBotCommand(_cmd);
|
||||
}
|
||||
}
|
||||
}
|
181
Telegram/SourceFiles/core/click_handler_types.h
Normal file
181
Telegram/SourceFiles/core/click_handler_types.h
Normal file
@ -0,0 +1,181 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "core/click_handler.h"
|
||||
|
||||
class TextClickHandler : public ClickHandler {
|
||||
public:
|
||||
|
||||
TextClickHandler(bool fullDisplayed = true) : _fullDisplayed(fullDisplayed) {
|
||||
}
|
||||
|
||||
void copyToClipboard() const override {
|
||||
QString u = url();
|
||||
if (!u.isEmpty()) {
|
||||
QApplication::clipboard()->setText(u);
|
||||
}
|
||||
}
|
||||
|
||||
QString tooltip() const override {
|
||||
return _fullDisplayed ? QString() : readable();
|
||||
}
|
||||
|
||||
void setFullDisplayed(bool full) {
|
||||
_fullDisplayed = full;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual QString url() const = 0;
|
||||
virtual QString readable() const {
|
||||
return url();
|
||||
}
|
||||
|
||||
bool _fullDisplayed;
|
||||
|
||||
};
|
||||
|
||||
class UrlClickHandler : public TextClickHandler {
|
||||
public:
|
||||
UrlClickHandler(const QString &url, bool fullDisplayed = true) : TextClickHandler(fullDisplayed), _url(url) {
|
||||
if (isEmail()) {
|
||||
_readable = _url;
|
||||
} else {
|
||||
QUrl u(_url), good(u.isValid() ? u.toEncoded() : QString());
|
||||
_readable = good.isValid() ? good.toDisplayString() : _url;
|
||||
}
|
||||
}
|
||||
QString copyToClipboardContextItem() const override;
|
||||
|
||||
QString text() const override {
|
||||
return _url;
|
||||
}
|
||||
QString dragText() const override {
|
||||
return url();
|
||||
}
|
||||
|
||||
static void doOpen(QString url);
|
||||
void onClick(Qt::MouseButton button) const override {
|
||||
if (button == Qt::LeftButton || button == Qt::MiddleButton) {
|
||||
doOpen(url());
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
QString url() const override {
|
||||
if (isEmail()) {
|
||||
return _url;
|
||||
}
|
||||
|
||||
QUrl u(_url), good(u.isValid() ? u.toEncoded() : QString());
|
||||
QString result(good.isValid() ? QString::fromUtf8(good.toEncoded()) : _url);
|
||||
|
||||
if (!QRegularExpression(qsl("^[a-zA-Z]+:")).match(result).hasMatch()) { // no protocol
|
||||
return qsl("http://") + result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
QString readable() const override {
|
||||
return _readable;
|
||||
}
|
||||
|
||||
private:
|
||||
static bool isEmail(const QString &url) {
|
||||
int at = url.indexOf('@'), slash = url.indexOf('/');
|
||||
return ((at > 0) && (slash < 0 || slash > at));
|
||||
}
|
||||
bool isEmail() const {
|
||||
return isEmail(_url);
|
||||
}
|
||||
|
||||
QString _url, _readable;
|
||||
|
||||
};
|
||||
typedef QSharedPointer<TextClickHandler> TextClickHandlerPtr;
|
||||
|
||||
class HiddenUrlClickHandler : public UrlClickHandler {
|
||||
public:
|
||||
HiddenUrlClickHandler(QString url) : UrlClickHandler(url, false) {
|
||||
}
|
||||
void onClick(Qt::MouseButton button) const override;
|
||||
|
||||
};
|
||||
|
||||
class MentionClickHandler : public TextClickHandler {
|
||||
public:
|
||||
MentionClickHandler(const QString &tag) : _tag(tag) {
|
||||
}
|
||||
QString copyToClipboardContextItem() const override;
|
||||
|
||||
QString text() const override {
|
||||
return _tag;
|
||||
}
|
||||
void onClick(Qt::MouseButton button) const override;
|
||||
|
||||
protected:
|
||||
QString url() const override {
|
||||
return _tag;
|
||||
}
|
||||
|
||||
private:
|
||||
QString _tag;
|
||||
|
||||
};
|
||||
|
||||
class HashtagClickHandler : public TextClickHandler {
|
||||
public:
|
||||
HashtagClickHandler(const QString &tag) : _tag(tag) {
|
||||
}
|
||||
QString copyToClipboardContextItem() const override;
|
||||
|
||||
QString text() const override {
|
||||
return _tag;
|
||||
}
|
||||
void onClick(Qt::MouseButton button) const override;
|
||||
|
||||
protected:
|
||||
QString url() const override {
|
||||
return _tag;
|
||||
}
|
||||
|
||||
private:
|
||||
QString _tag;
|
||||
|
||||
};
|
||||
|
||||
class BotCommandClickHandler : public TextClickHandler {
|
||||
public:
|
||||
BotCommandClickHandler(const QString &cmd) : _cmd(cmd) {
|
||||
}
|
||||
QString text() const override {
|
||||
return _cmd;
|
||||
}
|
||||
void onClick(Qt::MouseButton button) const override;
|
||||
|
||||
protected:
|
||||
QString url() const override {
|
||||
return _cmd;
|
||||
}
|
||||
|
||||
private:
|
||||
QString _cmd;
|
||||
|
||||
};
|
@ -93,7 +93,7 @@ void paintRow(Painter &p, History *history, HistoryItem *item, int w, bool activ
|
||||
p.drawSprite(QPoint(rectForName.left() + rectForName.width() + st::dlgCheckLeft, rectForName.top() + st::dlgCheckTop), *check);
|
||||
}
|
||||
|
||||
paintItemCallback(nameleft, namewidth);
|
||||
paintItemCallback(nameleft, namewidth, item);
|
||||
}
|
||||
|
||||
if (history->peer->isUser() && history->peer->isVerified()) {
|
||||
@ -132,10 +132,10 @@ QImage colorizeCircleHalf(int size, int half, int xoffset, style::color color) {
|
||||
int a = color->c.alpha() + 1;
|
||||
int fg_r = color->c.red() * a, fg_g = color->c.green() * a, fg_b = color->c.blue() * a, fg_a = 255 * a;
|
||||
|
||||
QImage result(size, size, QImage::Format_ARGB32_Premultiplied);
|
||||
QImage result(half, size, QImage::Format_ARGB32_Premultiplied);
|
||||
uchar *bits = result.bits(), *maskbits = unreadBadgeStyle->circle.bits();
|
||||
int bpl = result.bytesPerLine(), maskbpl = unreadBadgeStyle->circle.bytesPerLine();
|
||||
for (int x = 0; x < size; ++x) {
|
||||
for (int x = 0; x < half; ++x) {
|
||||
for (int y = 0; y < size; ++y) {
|
||||
int s = y * bpl + (x * 4);
|
||||
int o = maskbits[y * maskbpl + x + xoffset] + 1;
|
||||
@ -194,7 +194,7 @@ void paintUnreadCount(Painter &p, const QString &text, int top, int w, bool acti
|
||||
void RowPainter::paint(Painter &p, const Row *row, int w, bool active, bool selected, bool onlyBackground) {
|
||||
auto history = row->history();
|
||||
auto item = history->lastMsg;
|
||||
paintRow(p, history, item, w, active, selected, onlyBackground, [&p, w, active, history, item](int nameleft, int namewidth) {
|
||||
paintRow(p, history, item, w, active, selected, onlyBackground, [&p, w, active, history](int nameleft, int namewidth, HistoryItem *item) {
|
||||
int32 unread = history->unreadCount();
|
||||
if (history->peer->migrateFrom()) {
|
||||
if (History *h = App::historyLoaded(history->peer->migrateFrom()->id)) {
|
||||
@ -219,7 +219,7 @@ void RowPainter::paint(Painter &p, const Row *row, int w, bool active, bool sele
|
||||
void RowPainter::paint(Painter &p, const FakeRow *row, int w, bool active, bool selected, bool onlyBackground) {
|
||||
auto item = row->item();
|
||||
auto history = item->history();
|
||||
paintRow(p, history, item, w, active, selected, onlyBackground, [&p, row, active, item](int nameleft, int namewidth) {
|
||||
paintRow(p, history, item, w, active, selected, onlyBackground, [&p, row, active](int nameleft, int namewidth, HistoryItem *item) {
|
||||
int lastWidth = namewidth, texttop = st::dlgPaddingVer + st::dlgFont->height + st::dlgSep;
|
||||
item->drawInDialog(p, QRect(nameleft, texttop, lastWidth, st::dlgFont->height), active, row->_cacheFor, row->_cache);
|
||||
});
|
||||
|
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "ui/text.h"
|
||||
#include "ui/text/text.h"
|
||||
|
||||
class History;
|
||||
class HistoryItem;
|
||||
|
@ -26,13 +26,14 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
#include "ui/style.h"
|
||||
#include "lang.h"
|
||||
#include "application.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
#include "dialogswidget.h"
|
||||
#include "mainwidget.h"
|
||||
#include "boxes/addcontactbox.h"
|
||||
#include "boxes/contactsbox.h"
|
||||
#include "boxes/confirmbox.h"
|
||||
#include "localstorage.h"
|
||||
#include "apiwrap.h"
|
||||
|
||||
DialogsInner::DialogsInner(QWidget *parent, MainWidget *main) : SplittedWidget(parent)
|
||||
, dialogs(std_::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Date))
|
||||
@ -1027,7 +1028,7 @@ void DialogsInner::dialogsReceived(const QVector<MTPDialog> &added) {
|
||||
}
|
||||
}
|
||||
|
||||
if (App::wnd()) App::wnd()->updateCounter();
|
||||
Notify::unreadCounterUpdated();
|
||||
if (!_sel && !shownDialogs()->isEmpty()) {
|
||||
_sel = *shownDialogs()->cbegin();
|
||||
_importantSwitchSel = false;
|
||||
@ -1935,7 +1936,7 @@ void DialogsWidget::unreadCountsReceived(const QVector<MTPDialog> &dialogs) {
|
||||
if (History *h = App::historyLoaded(peerFromMTP(d.vpeer))) {
|
||||
App::main()->applyNotifySetting(MTP_notifyPeer(d.vpeer), d.vnotify_settings, h);
|
||||
if (d.vunread_count.v >= h->unreadCount()) {
|
||||
h->setUnreadCount(d.vunread_count.v, false);
|
||||
h->setUnreadCount(d.vunread_count.v);
|
||||
h->inboxReadBefore = d.vread_inbox_max_id.v + 1;
|
||||
}
|
||||
}
|
||||
@ -1953,14 +1954,13 @@ void DialogsWidget::unreadCountsReceived(const QVector<MTPDialog> &dialogs) {
|
||||
App::main()->applyNotifySetting(MTP_notifyPeer(d.vpeer), d.vnotify_settings, h);
|
||||
int32 unreadCount = h->isMegagroup() ? d.vunread_count.v : d.vunread_important_count.v;
|
||||
if (unreadCount >= h->unreadCount()) {
|
||||
h->setUnreadCount(unreadCount, false);
|
||||
h->setUnreadCount(unreadCount);
|
||||
h->inboxReadBefore = d.vread_inbox_max_id.v + 1;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
if (App::wnd()) App::wnd()->updateCounter();
|
||||
}
|
||||
|
||||
void DialogsWidget::dialogsReceived(const MTPmessages_Dialogs &dialogs, mtpRequestId req) {
|
||||
|
@ -28,7 +28,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
#include "historywidget.h"
|
||||
#include "localstorage.h"
|
||||
#include "lang.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
#include "apiwrap.h"
|
||||
#include "mainwidget.h"
|
||||
|
||||
@ -1349,7 +1349,7 @@ void StickerPanInner::paintInlineItems(Painter &p, const QRect &r) {
|
||||
int w = item->width();
|
||||
if (left + w > fromx) {
|
||||
p.translate(left, top);
|
||||
item->paint(p, r.translated(-left, -top), 0, &context);
|
||||
item->paint(p, r.translated(-left, -top), &context);
|
||||
p.translate(-left, -top);
|
||||
}
|
||||
left += w;
|
||||
|
@ -20,12 +20,11 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
#include "mainwidget.h"
|
||||
#include "application.h"
|
||||
|
||||
#include "core/click_handler_types.h"
|
||||
#include "boxes/confirmbox.h"
|
||||
|
||||
#include "layerwidget.h"
|
||||
#include "lang.h"
|
||||
|
||||
@ -34,12 +33,16 @@ Q_DECLARE_METATYPE(Qt::MouseButton);
|
||||
|
||||
namespace App {
|
||||
|
||||
void sendBotCommand(PeerData *peer, const QString &cmd, MsgId replyTo) {
|
||||
if (MainWidget *m = main()) m->sendBotCommand(peer, cmd, replyTo);
|
||||
void sendBotCommand(PeerData *peer, UserData *bot, const QString &cmd, MsgId replyTo) {
|
||||
if (auto m = main()) {
|
||||
m->sendBotCommand(peer, bot, cmd, replyTo);
|
||||
}
|
||||
}
|
||||
|
||||
bool insertBotCommand(const QString &cmd, bool specialGif) {
|
||||
if (MainWidget *m = main()) return m->insertBotCommand(cmd, specialGif);
|
||||
if (auto m = main()) {
|
||||
return m->insertBotCommand(cmd, specialGif);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -60,7 +63,7 @@ void activateBotCommand(const HistoryItem *msg, int row, int col) {
|
||||
// Copy string before passing it to the sending method
|
||||
// because the original button can be destroyed inside.
|
||||
MsgId replyTo = (msg->id > 0) ? msg->id : 0;
|
||||
sendBotCommand(msg->history()->peer, QString(button->text), replyTo);
|
||||
sendBotCommand(msg->history()->peer, msg->fromOriginal()->asUser(), QString(button->text), replyTo);
|
||||
} break;
|
||||
|
||||
case HistoryMessageReplyMarkup::Button::Callback: {
|
||||
@ -136,13 +139,13 @@ void removeDialog(History *history) {
|
||||
}
|
||||
|
||||
void showSettings() {
|
||||
if (Window *w = wnd()) {
|
||||
if (auto w = wnd()) {
|
||||
w->showSettings();
|
||||
}
|
||||
}
|
||||
|
||||
void activateClickHandler(ClickHandlerPtr handler, Qt::MouseButton button) {
|
||||
if (Window *w = wnd()) {
|
||||
if (auto w = wnd()) {
|
||||
qRegisterMetaType<ClickHandlerPtr>();
|
||||
qRegisterMetaType<Qt::MouseButton>();
|
||||
QMetaObject::invokeMethod(w, "app_activateClickHandler", Qt::QueuedConnection, Q_ARG(ClickHandlerPtr, handler), Q_ARG(Qt::MouseButton, button));
|
||||
@ -150,7 +153,7 @@ void activateClickHandler(ClickHandlerPtr handler, Qt::MouseButton button) {
|
||||
}
|
||||
|
||||
void logOutDelayed() {
|
||||
if (Window *w = App::wnd()) {
|
||||
if (auto w = App::wnd()) {
|
||||
QMetaObject::invokeMethod(w, "onLogoutSure", Qt::QueuedConnection);
|
||||
}
|
||||
}
|
||||
@ -160,25 +163,25 @@ void logOutDelayed() {
|
||||
namespace Ui {
|
||||
|
||||
void showMediaPreview(DocumentData *document) {
|
||||
if (Window *w = App::wnd()) {
|
||||
if (auto w = App::wnd()) {
|
||||
w->ui_showMediaPreview(document);
|
||||
}
|
||||
}
|
||||
|
||||
void showMediaPreview(PhotoData *photo) {
|
||||
if (Window *w = App::wnd()) {
|
||||
if (auto w = App::wnd()) {
|
||||
w->ui_showMediaPreview(photo);
|
||||
}
|
||||
}
|
||||
|
||||
void hideMediaPreview() {
|
||||
if (Window *w = App::wnd()) {
|
||||
if (auto w = App::wnd()) {
|
||||
w->ui_hideMediaPreview();
|
||||
}
|
||||
}
|
||||
|
||||
void showLayer(LayeredWidget *box, ShowLayerOptions options) {
|
||||
if (Window *w = App::wnd()) {
|
||||
if (auto w = App::wnd()) {
|
||||
w->ui_showLayer(box, options);
|
||||
} else {
|
||||
delete box;
|
||||
@ -186,16 +189,16 @@ void showLayer(LayeredWidget *box, ShowLayerOptions options) {
|
||||
}
|
||||
|
||||
void hideLayer(bool fast) {
|
||||
if (Window *w = App::wnd()) w->ui_showLayer(0, ShowLayerOptions(CloseOtherLayers) | (fast ? ForceFastShowLayer : AnimatedShowLayer));
|
||||
if (auto w = App::wnd()) w->ui_showLayer(0, ShowLayerOptions(CloseOtherLayers) | (fast ? ForceFastShowLayer : AnimatedShowLayer));
|
||||
}
|
||||
|
||||
bool isLayerShown() {
|
||||
if (Window *w = App::wnd()) return w->ui_isLayerShown();
|
||||
if (auto w = App::wnd()) return w->ui_isLayerShown();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isMediaViewShown() {
|
||||
if (Window *w = App::wnd()) return w->ui_isMediaViewShown();
|
||||
if (auto w = App::wnd()) return w->ui_isMediaViewShown();
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -236,7 +239,7 @@ void showPeerHistoryAsync(const PeerId &peer, MsgId msgId) {
|
||||
}
|
||||
|
||||
PeerData *getPeerForMouseAction() {
|
||||
if (Window *w = App::wnd()) {
|
||||
if (auto w = App::wnd()) {
|
||||
return w->ui_getPeerForMouseAction();
|
||||
}
|
||||
return nullptr;
|
||||
@ -244,7 +247,7 @@ PeerData *getPeerForMouseAction() {
|
||||
|
||||
bool hideWindowNoQuit() {
|
||||
if (!App::quitting()) {
|
||||
if (Window *w = App::wnd()) {
|
||||
if (auto w = App::wnd()) {
|
||||
if (cWorkMode() == dbiwmTrayOnly || cWorkMode() == dbiwmWindowAndTray) {
|
||||
return w->minimizeToTray();
|
||||
} else if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) {
|
||||
@ -327,6 +330,10 @@ void handlePendingHistoryUpdate() {
|
||||
Global::RefPendingRepaintItems().clear();
|
||||
}
|
||||
|
||||
void unreadCounterUpdated() {
|
||||
Global::RefHandleUnreadCounterUpdate().call();
|
||||
}
|
||||
|
||||
} // namespace Notify
|
||||
|
||||
#define DefineReadOnlyVar(Namespace, Type, Name) const Type &Name() { \
|
||||
@ -480,6 +487,7 @@ namespace internal {
|
||||
struct Data {
|
||||
uint64 LaunchId = 0;
|
||||
SingleDelayedCall HandleHistoryUpdate = { App::app(), "call_handleHistoryUpdate" };
|
||||
SingleDelayedCall HandleUnreadCounterUpdate = { App::app(), "call_handleUnreadCounterUpdate" };
|
||||
|
||||
Adaptive::Layout AdaptiveLayout = Adaptive::NormalLayout;
|
||||
bool AdaptiveForWide = true;
|
||||
@ -542,6 +550,7 @@ void finish() {
|
||||
|
||||
DefineReadOnlyVar(Global, uint64, LaunchId);
|
||||
DefineRefVar(Global, SingleDelayedCall, HandleHistoryUpdate);
|
||||
DefineRefVar(Global, SingleDelayedCall, HandleUnreadCounterUpdate);
|
||||
|
||||
DefineVar(Global, Adaptive::Layout, AdaptiveLayout);
|
||||
DefineVar(Global, bool, AdaptiveForWide);
|
||||
|
@ -24,7 +24,7 @@ class LayeredWidget;
|
||||
|
||||
namespace App {
|
||||
|
||||
void sendBotCommand(PeerData *peer, const QString &cmd, MsgId replyTo = 0);
|
||||
void sendBotCommand(PeerData *peer, UserData *bot, const QString &cmd, MsgId replyTo = 0);
|
||||
bool insertBotCommand(const QString &cmd, bool specialGif = false);
|
||||
void activateBotCommand(const HistoryItem *msg, int row, int col);
|
||||
void searchByHashtag(const QString &tag, PeerData *inPeer);
|
||||
@ -116,6 +116,7 @@ void historyMuteUpdated(History *history);
|
||||
|
||||
// handle pending resize() / paint() on history items
|
||||
void handlePendingHistoryUpdate();
|
||||
void unreadCounterUpdated();
|
||||
|
||||
} // namespace Notify
|
||||
|
||||
@ -184,6 +185,7 @@ void finish();
|
||||
|
||||
DeclareReadOnlyVar(uint64, LaunchId);
|
||||
DeclareRefVar(SingleDelayedCall, HandleHistoryUpdate);
|
||||
DeclareRefVar(SingleDelayedCall, HandleUnreadCounterUpdate);
|
||||
|
||||
DeclareVar(Adaptive::Layout, AdaptiveLayout);
|
||||
DeclareVar(bool, AdaptiveForWide);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -255,7 +255,7 @@ public:
|
||||
int unreadCount() const {
|
||||
return _unreadCount;
|
||||
}
|
||||
void setUnreadCount(int newUnreadCount, bool psUpdate = true);
|
||||
void setUnreadCount(int newUnreadCount);
|
||||
bool mute() const {
|
||||
return _mute;
|
||||
}
|
||||
@ -642,7 +642,7 @@ private:
|
||||
HistoryItem *findPrevItem(HistoryItem *item) const;
|
||||
void switchMode();
|
||||
|
||||
void cleared();
|
||||
void cleared(bool leaveItems);
|
||||
|
||||
bool _onlyImportant;
|
||||
|
||||
@ -729,7 +729,7 @@ protected:
|
||||
|
||||
};
|
||||
|
||||
class HistoryMessage; // dynamic_cast optimize
|
||||
class HistoryMessage;
|
||||
|
||||
enum HistoryCursorState {
|
||||
HistoryDefaultCursorState,
|
||||
@ -738,6 +738,36 @@ enum HistoryCursorState {
|
||||
HistoryInForwardedCursorState,
|
||||
};
|
||||
|
||||
struct HistoryTextState {
|
||||
HistoryTextState() = default;
|
||||
HistoryTextState(const Text::StateResult &state)
|
||||
: cursor(state.uponSymbol ? HistoryInTextCursorState : HistoryDefaultCursorState)
|
||||
, link(state.link)
|
||||
, afterSymbol(state.afterSymbol)
|
||||
, symbol(state.symbol) {
|
||||
}
|
||||
HistoryTextState &operator=(const Text::StateResult &state) {
|
||||
cursor = state.uponSymbol ? HistoryInTextCursorState : HistoryDefaultCursorState;
|
||||
link = state.link;
|
||||
afterSymbol = state.afterSymbol;
|
||||
symbol = state.symbol;
|
||||
return *this;
|
||||
}
|
||||
HistoryCursorState cursor = HistoryDefaultCursorState;
|
||||
ClickHandlerPtr link;
|
||||
bool afterSymbol = false;
|
||||
uint16 symbol = 0;
|
||||
};
|
||||
|
||||
struct HistoryStateRequest {
|
||||
Text::StateRequest::Flags flags = Text::StateRequest::Flag::LookupLink;
|
||||
Text::StateRequest forText() const {
|
||||
Text::StateRequest result;
|
||||
result.flags = flags;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
enum InfoDisplayType {
|
||||
InfoDisplayDefault,
|
||||
InfoDisplayOverImage,
|
||||
@ -936,7 +966,7 @@ public:
|
||||
int naturalHeight() const;
|
||||
|
||||
void paint(Painter &p, const QRect &clip) const;
|
||||
void getState(ClickHandlerPtr &lnk, int x, int y) const;
|
||||
ClickHandlerPtr getState(int x, int y) const;
|
||||
|
||||
void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active);
|
||||
void clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed);
|
||||
@ -1052,6 +1082,14 @@ private:
|
||||
|
||||
};
|
||||
|
||||
|
||||
namespace internal {
|
||||
|
||||
TextSelection unshiftSelection(TextSelection selection, const Text &byText);
|
||||
TextSelection shiftSelection(TextSelection selection, const Text &byText);
|
||||
|
||||
} // namespace internal
|
||||
|
||||
class HistoryItem : public HistoryElem, public Composer, public ClickHandlerHost {
|
||||
public:
|
||||
|
||||
@ -1068,7 +1106,7 @@ public:
|
||||
}
|
||||
return resizeGetHeight_(width);
|
||||
}
|
||||
virtual void draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const = 0;
|
||||
virtual void draw(Painter &p, const QRect &r, TextSelection selection, uint64 ms) const = 0;
|
||||
|
||||
virtual void dependencyItemRemoved(HistoryItem *dependency) {
|
||||
}
|
||||
@ -1216,17 +1254,11 @@ public:
|
||||
virtual bool hasPoint(int x, int y) const {
|
||||
return false;
|
||||
}
|
||||
virtual void getState(ClickHandlerPtr &lnk, HistoryCursorState &state, int x, int y) const {
|
||||
lnk.clear();
|
||||
state = HistoryDefaultCursorState;
|
||||
}
|
||||
virtual void getSymbol(uint16 &symbol, bool &after, bool &upon, int x, int y) const { // from text
|
||||
upon = hasPoint(x, y);
|
||||
symbol = upon ? 0xFFFF : 0;
|
||||
after = false;
|
||||
}
|
||||
virtual uint32 adjustSelection(uint16 from, uint16 to, TextSelectType type) const {
|
||||
return (from << 16) | to;
|
||||
|
||||
virtual HistoryTextState getState(int x, int y, HistoryStateRequest request) const = 0;
|
||||
|
||||
virtual TextSelection adjustSelection(TextSelection selection, TextSelectType type) const {
|
||||
return selection;
|
||||
}
|
||||
|
||||
// ClickHandlerHost interface
|
||||
@ -1251,7 +1283,7 @@ public:
|
||||
}
|
||||
virtual void previousItemChanged();
|
||||
|
||||
virtual QString selectedText(uint32 selection) const {
|
||||
virtual QString selectedText(TextSelection selection) const {
|
||||
return qsl("[-]");
|
||||
}
|
||||
virtual QString inDialogsText() const {
|
||||
@ -1514,6 +1546,13 @@ protected:
|
||||
return const_cast<ReplyKeyboard*>(static_cast<const HistoryItem*>(this)->inlineReplyKeyboard());
|
||||
}
|
||||
|
||||
TextSelection toMediaSelection(TextSelection selection) const {
|
||||
return internal::unshiftSelection(selection, _text);
|
||||
}
|
||||
TextSelection fromMediaSelection(TextSelection selection) const {
|
||||
return internal::shiftSelection(selection, _text);
|
||||
}
|
||||
|
||||
Text _text = { int(st::msgMinWidth) };
|
||||
int32 _textWidth, _textHeight;
|
||||
|
||||
@ -1609,8 +1648,8 @@ public:
|
||||
HistoryMedia &operator=(const HistoryMedia &other) = delete;
|
||||
|
||||
virtual HistoryMediaType type() const = 0;
|
||||
virtual const QString inDialogsText() const = 0;
|
||||
virtual const QString inHistoryText() const = 0;
|
||||
virtual QString inDialogsText() const = 0;
|
||||
virtual QString selectedText(TextSelection selection) const = 0;
|
||||
|
||||
bool hasPoint(int x, int y) const {
|
||||
return (x >= 0 && y >= 0 && x < _width && y < _height);
|
||||
@ -1624,8 +1663,8 @@ public:
|
||||
_width = qMin(width, _maxw);
|
||||
return _height;
|
||||
}
|
||||
virtual void draw(Painter &p, const QRect &r, bool selected, uint64 ms) const = 0;
|
||||
virtual void getState(ClickHandlerPtr &lnk, HistoryCursorState &state, int x, int y) const = 0;
|
||||
virtual void draw(Painter &p, const QRect &r, TextSelection selection, uint64 ms) const = 0;
|
||||
virtual HistoryTextState getState(int x, int y, HistoryStateRequest request) const = 0;
|
||||
|
||||
// if we are in selecting items mode perhaps we want to
|
||||
// toggle selection instead of activating the pressed link
|
||||
@ -1636,6 +1675,10 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual TextSelection adjustSelection(TextSelection selection, TextSelectType type) const {
|
||||
return selection;
|
||||
}
|
||||
|
||||
// if we press and drag this link should we drag the item
|
||||
virtual bool dragItemByHandler(const ClickHandlerPtr &p) const = 0;
|
||||
|
||||
@ -1829,11 +1872,15 @@ public:
|
||||
void initDimensions() override;
|
||||
int resizeGetHeight(int width) override;
|
||||
|
||||
void draw(Painter &p, const QRect &r, bool selected, uint64 ms) const override;
|
||||
void getState(ClickHandlerPtr &lnk, HistoryCursorState &state, int x, int y) const override;
|
||||
void draw(Painter &p, const QRect &r, TextSelection selection, uint64 ms) const override;
|
||||
HistoryTextState getState(int x, int y, HistoryStateRequest request) const override;
|
||||
|
||||
const QString inDialogsText() const override;
|
||||
const QString inHistoryText() const override;
|
||||
TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override {
|
||||
return _caption.adjustSelection(selection, type);
|
||||
}
|
||||
|
||||
QString inDialogsText() const override;
|
||||
QString selectedText(TextSelection selection) const override;
|
||||
|
||||
PhotoData *photo() const {
|
||||
return _data;
|
||||
@ -1902,11 +1949,15 @@ public:
|
||||
void initDimensions() override;
|
||||
int resizeGetHeight(int width) override;
|
||||
|
||||
void draw(Painter &p, const QRect &r, bool selected, uint64 ms) const override;
|
||||
void getState(ClickHandlerPtr &lnk, HistoryCursorState &state, int x, int y) const override;
|
||||
void draw(Painter &p, const QRect &r, TextSelection selection, uint64 ms) const override;
|
||||
HistoryTextState getState(int x, int y, HistoryStateRequest request) const override;
|
||||
|
||||
const QString inDialogsText() const override;
|
||||
const QString inHistoryText() const override;
|
||||
TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override {
|
||||
return _caption.adjustSelection(selection, type);
|
||||
}
|
||||
|
||||
QString inDialogsText() const override;
|
||||
QString selectedText(TextSelection selection) const override;
|
||||
|
||||
DocumentData *getDocument() override {
|
||||
return _data;
|
||||
@ -2015,11 +2066,18 @@ public:
|
||||
void initDimensions() override;
|
||||
int resizeGetHeight(int width) override;
|
||||
|
||||
void draw(Painter &p, const QRect &r, bool selected, uint64 ms) const override;
|
||||
void getState(ClickHandlerPtr &lnk, HistoryCursorState &state, int x, int y) const override;
|
||||
void draw(Painter &p, const QRect &r, TextSelection selection, uint64 ms) const override;
|
||||
HistoryTextState getState(int x, int y, HistoryStateRequest request) const override;
|
||||
|
||||
const QString inDialogsText() const override;
|
||||
const QString inHistoryText() const override;
|
||||
TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override {
|
||||
if (auto captioned = Get<HistoryDocumentCaptioned>()) {
|
||||
return captioned->_caption.adjustSelection(selection, type);
|
||||
}
|
||||
return selection;
|
||||
}
|
||||
|
||||
QString inDialogsText() const override;
|
||||
QString selectedText(TextSelection selection) const override;
|
||||
|
||||
bool uploading() const override {
|
||||
return _data->uploading();
|
||||
@ -2095,11 +2153,15 @@ public:
|
||||
void initDimensions() override;
|
||||
int resizeGetHeight(int width) override;
|
||||
|
||||
void draw(Painter &p, const QRect &r, bool selected, uint64 ms) const override;
|
||||
void getState(ClickHandlerPtr &lnk, HistoryCursorState &state, int x, int y) const override;
|
||||
void draw(Painter &p, const QRect &r, TextSelection selection, uint64 ms) const override;
|
||||
HistoryTextState getState(int x, int y, HistoryStateRequest request) const override;
|
||||
|
||||
const QString inDialogsText() const override;
|
||||
const QString inHistoryText() const override;
|
||||
TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override {
|
||||
return _caption.adjustSelection(selection, type);
|
||||
}
|
||||
|
||||
QString inDialogsText() const override;
|
||||
QString selectedText(TextSelection selection) const override;
|
||||
|
||||
bool uploading() const override {
|
||||
return _data->uploading();
|
||||
@ -2183,8 +2245,8 @@ public:
|
||||
void initDimensions() override;
|
||||
int resizeGetHeight(int width) override;
|
||||
|
||||
void draw(Painter &p, const QRect &r, bool selected, uint64 ms) const override;
|
||||
void getState(ClickHandlerPtr &lnk, HistoryCursorState &state, int x, int y) const override;
|
||||
void draw(Painter &p, const QRect &r, TextSelection selection, uint64 ms) const override;
|
||||
HistoryTextState getState(int x, int y, HistoryStateRequest request) const override;
|
||||
|
||||
bool toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const override {
|
||||
return true;
|
||||
@ -2196,8 +2258,8 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
const QString inDialogsText() const override;
|
||||
const QString inHistoryText() const override;
|
||||
QString inDialogsText() const override;
|
||||
QString selectedText(TextSelection selection) const override;
|
||||
|
||||
DocumentData *getDocument() override {
|
||||
return _data;
|
||||
@ -2255,8 +2317,8 @@ public:
|
||||
|
||||
void initDimensions() override;
|
||||
|
||||
void draw(Painter &p, const QRect &r, bool selected, uint64 ms) const override;
|
||||
void getState(ClickHandlerPtr &lnk, HistoryCursorState &state, int x, int y) const override;
|
||||
void draw(Painter &p, const QRect &r, TextSelection selection, uint64 ms) const override;
|
||||
HistoryTextState getState(int x, int y, HistoryStateRequest request) const override;
|
||||
|
||||
bool toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const override {
|
||||
return true;
|
||||
@ -2265,8 +2327,8 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
const QString inDialogsText() const override;
|
||||
const QString inHistoryText() const override;
|
||||
QString inDialogsText() const override;
|
||||
QString selectedText(TextSelection selection) const override;
|
||||
|
||||
void attachToParent() override;
|
||||
void detachFromParent() override;
|
||||
@ -2318,8 +2380,10 @@ public:
|
||||
void initDimensions() override;
|
||||
int resizeGetHeight(int width) override;
|
||||
|
||||
void draw(Painter &p, const QRect &r, bool selected, uint64 ms) const override;
|
||||
void getState(ClickHandlerPtr &lnk, HistoryCursorState &state, int x, int y) const override;
|
||||
void draw(Painter &p, const QRect &r, TextSelection selection, uint64 ms) const override;
|
||||
HistoryTextState getState(int x, int y, HistoryStateRequest request) const override;
|
||||
|
||||
TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override;
|
||||
|
||||
bool toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const override {
|
||||
return _attach && _attach->toggleSelectionByHandlerClick(p);
|
||||
@ -2328,8 +2392,8 @@ public:
|
||||
return _attach && _attach->dragItemByHandler(p);
|
||||
}
|
||||
|
||||
const QString inDialogsText() const override;
|
||||
const QString inHistoryText() const override;
|
||||
QString inDialogsText() const override;
|
||||
QString selectedText(TextSelection selection) const override;
|
||||
|
||||
void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override;
|
||||
void clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) override;
|
||||
@ -2376,6 +2440,13 @@ public:
|
||||
~HistoryWebPage();
|
||||
|
||||
private:
|
||||
TextSelection toDescriptionSelection(TextSelection selection) const {
|
||||
return internal::unshiftSelection(selection, _title);
|
||||
}
|
||||
TextSelection fromDescriptionSelection(TextSelection selection) const {
|
||||
return internal::shiftSelection(selection, _title);
|
||||
}
|
||||
|
||||
WebPageData *_data;
|
||||
ClickHandlerPtr _openl;
|
||||
HistoryMedia *_attach;
|
||||
@ -2396,17 +2467,8 @@ void initImageLinkManager();
|
||||
void reinitImageLinkManager();
|
||||
void deinitImageLinkManager();
|
||||
|
||||
struct LocationData {
|
||||
LocationData(const LocationCoords &coords) : coords(coords), loading(false) {
|
||||
}
|
||||
|
||||
LocationCoords coords;
|
||||
ImagePtr thumb;
|
||||
bool loading;
|
||||
|
||||
void load();
|
||||
};
|
||||
|
||||
struct LocationCoords;
|
||||
struct LocationData;
|
||||
class LocationManager : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
@ -2449,8 +2511,10 @@ public:
|
||||
void initDimensions() override;
|
||||
int resizeGetHeight(int32 width) override;
|
||||
|
||||
void draw(Painter &p, const QRect &r, bool selected, uint64 ms) const override;
|
||||
void getState(ClickHandlerPtr &lnk, HistoryCursorState &state, int x, int y) const override;
|
||||
void draw(Painter &p, const QRect &r, TextSelection selection, uint64 ms) const override;
|
||||
HistoryTextState getState(int x, int y, HistoryStateRequest request) const override;
|
||||
|
||||
TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override;
|
||||
|
||||
bool toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const override {
|
||||
return p == _link;
|
||||
@ -2459,8 +2523,8 @@ public:
|
||||
return p == _link;
|
||||
}
|
||||
|
||||
const QString inDialogsText() const override;
|
||||
const QString inHistoryText() const override;
|
||||
QString inDialogsText() const override;
|
||||
QString selectedText(TextSelection selection) const override;
|
||||
|
||||
bool needsBubble() const override {
|
||||
if (!_title.isEmpty() || !_description.isEmpty()) {
|
||||
@ -2476,6 +2540,13 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
TextSelection toDescriptionSelection(TextSelection selection) const {
|
||||
return internal::unshiftSelection(selection, _title);
|
||||
}
|
||||
TextSelection fromDescriptionSelection(TextSelection selection) const {
|
||||
return internal::shiftSelection(selection, _title);
|
||||
}
|
||||
|
||||
LocationData *_data;
|
||||
Text _title, _description;
|
||||
ClickHandlerPtr _link;
|
||||
@ -2547,7 +2618,7 @@ public:
|
||||
void drawInfo(Painter &p, int32 right, int32 bottom, int32 width, bool selected, InfoDisplayType type) const override;
|
||||
void setViewsCount(int32 count) override;
|
||||
void setId(MsgId newId) override;
|
||||
void draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const override;
|
||||
void draw(Painter &p, const QRect &r, TextSelection selection, uint64 ms) const override;
|
||||
|
||||
void dependencyItemRemoved(HistoryItem *dependency) override;
|
||||
|
||||
@ -2556,12 +2627,9 @@ public:
|
||||
bool hasPoint(int x, int y) const override;
|
||||
bool pointInTime(int32 right, int32 bottom, int x, int y, InfoDisplayType type) const override;
|
||||
|
||||
void getState(ClickHandlerPtr &lnk, HistoryCursorState &state, int x, int y) const override;
|
||||
HistoryTextState getState(int x, int y, HistoryStateRequest request) const override;
|
||||
|
||||
void getSymbol(uint16 &symbol, bool &after, bool &upon, int x, int y) const override;
|
||||
uint32 adjustSelection(uint16 from, uint16 to, TextSelectType type) const override {
|
||||
return _text.adjustSelection(from, to, type);
|
||||
}
|
||||
TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override;
|
||||
|
||||
// ClickHandlerHost interface
|
||||
void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override {
|
||||
@ -2569,7 +2637,7 @@ public:
|
||||
HistoryItem::clickHandlerActiveChanged(p, active);
|
||||
}
|
||||
void clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) override {
|
||||
if (_media) _media->clickHandlerActiveChanged(p, pressed);
|
||||
if (_media) _media->clickHandlerPressedChanged(p, pressed);
|
||||
HistoryItem::clickHandlerPressedChanged(p, pressed);
|
||||
}
|
||||
|
||||
@ -2582,7 +2650,7 @@ public:
|
||||
int32 addToOverview(AddToOverviewMethod method) override;
|
||||
void eraseFromOverview();
|
||||
|
||||
QString selectedText(uint32 selection) const override;
|
||||
QString selectedText(TextSelection selection) const override;
|
||||
QString inDialogsText() const override;
|
||||
HistoryMedia *getMedia() const override;
|
||||
void setText(const QString &text, const EntitiesInText &entities) override;
|
||||
@ -2772,12 +2840,12 @@ public:
|
||||
|
||||
void countPositionAndSize(int32 &left, int32 &width) const;
|
||||
|
||||
void draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const override;
|
||||
void draw(Painter &p, const QRect &r, TextSelection selection, uint64 ms) const override;
|
||||
bool hasPoint(int x, int y) const override;
|
||||
void getState(ClickHandlerPtr &lnk, HistoryCursorState &state, int x, int y) const override;
|
||||
void getSymbol(uint16 &symbol, bool &after, bool &upon, int x, int y) const override;
|
||||
uint32 adjustSelection(uint16 from, uint16 to, TextSelectType type) const override {
|
||||
return _text.adjustSelection(from, to, type);
|
||||
HistoryTextState getState(int x, int y, HistoryStateRequest request) const override;
|
||||
|
||||
TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override {
|
||||
return _text.adjustSelection(selection, type);
|
||||
}
|
||||
|
||||
void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override {
|
||||
@ -2798,7 +2866,7 @@ public:
|
||||
bool serviceMsg() const override {
|
||||
return true;
|
||||
}
|
||||
QString selectedText(uint32 selection) const override;
|
||||
QString selectedText(TextSelection selection) const override;
|
||||
QString inDialogsText() const override;
|
||||
QString inReplyText() const override;
|
||||
|
||||
@ -2833,16 +2901,12 @@ public:
|
||||
return _create(history, newItem, date);
|
||||
}
|
||||
|
||||
void getState(ClickHandlerPtr &lnk, HistoryCursorState &state, int x, int y) const;
|
||||
void getSymbol(uint16 &symbol, bool &after, bool &upon, int x, int y) const {
|
||||
symbol = 0xFFFF;
|
||||
after = false;
|
||||
upon = false;
|
||||
}
|
||||
QString selectedText(uint32 selection) const {
|
||||
HistoryTextState getState(int x, int y, HistoryStateRequest request) const override;
|
||||
|
||||
QString selectedText(TextSelection selection) const override {
|
||||
return QString();
|
||||
}
|
||||
HistoryItemType type() const {
|
||||
HistoryItemType type() const override {
|
||||
return HistoryItemGroup;
|
||||
}
|
||||
void uniteWith(MsgId minId, MsgId maxId, int32 count);
|
||||
@ -2886,17 +2950,13 @@ public:
|
||||
return _create(history, wasMinId, date);
|
||||
}
|
||||
|
||||
void draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const;
|
||||
void getState(ClickHandlerPtr &lnk, HistoryCursorState &state, int x, int y) const;
|
||||
void getSymbol(uint16 &symbol, bool &after, bool &upon, int x, int y) const {
|
||||
symbol = 0xFFFF;
|
||||
after = false;
|
||||
upon = false;
|
||||
}
|
||||
QString selectedText(uint32 selection) const {
|
||||
void draw(Painter &p, const QRect &r, TextSelection selection, uint64 ms) const override;
|
||||
HistoryTextState getState(int x, int y, HistoryStateRequest request) const override;
|
||||
|
||||
QString selectedText(TextSelection selection) const override {
|
||||
return QString();
|
||||
}
|
||||
HistoryItemType type() const {
|
||||
HistoryItemType type() const override {
|
||||
return HistoryItemCollapse;
|
||||
}
|
||||
MsgId wasMinId() const {
|
||||
|
28
Telegram/SourceFiles/history/history_common.h
Normal file
28
Telegram/SourceFiles/history/history_common.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
enum DragState {
|
||||
DragStateNone = 0x00,
|
||||
DragStateFiles = 0x01,
|
||||
DragStatePhotoFiles = 0x02,
|
||||
DragStateImage = 0x03,
|
||||
};
|
@ -30,12 +30,15 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
#include "lang.h"
|
||||
#include "application.h"
|
||||
#include "mainwidget.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
#include "passcodewidget.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
#include "fileuploader.h"
|
||||
#include "audio.h"
|
||||
#include "localstorage.h"
|
||||
#include "apiwrap.h"
|
||||
#include "window/top_bar_widget.h"
|
||||
#include "playerwidget.h"
|
||||
|
||||
// flick scroll taken from http://qt-project.org/doc/qt-4.8/demos-embedded-anomaly-src-flickcharm-cpp.html
|
||||
|
||||
@ -249,11 +252,13 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
|
||||
p.save();
|
||||
p.translate(0, y);
|
||||
if (r.y() < y + item->height()) while (y < drawToY) {
|
||||
uint32 sel = 0;
|
||||
TextSelection sel;
|
||||
if (y >= selfromy && y < seltoy) {
|
||||
sel = (_dragSelecting && !item->serviceMsg() && item->id > 0) ? FullSelection : 0;
|
||||
if (_dragSelecting && !item->serviceMsg() && item->id > 0) {
|
||||
sel = FullSelection;
|
||||
}
|
||||
} else if (hasSel) {
|
||||
SelectedItems::const_iterator i = _selected.constFind(item);
|
||||
auto i = _selected.constFind(item);
|
||||
if (i != selEnd) {
|
||||
sel = i.value();
|
||||
}
|
||||
@ -294,11 +299,13 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
|
||||
while (y < drawToY) {
|
||||
int32 h = item->height();
|
||||
if (historyRect.y() < y + h && hdrawtop < y + h) {
|
||||
uint32 sel = 0;
|
||||
TextSelection sel;
|
||||
if (y >= selfromy && y < seltoy) {
|
||||
sel = (_dragSelecting && !item->serviceMsg() && item->id > 0) ? FullSelection : 0;
|
||||
if (_dragSelecting && !item->serviceMsg() && item->id > 0) {
|
||||
sel = FullSelection;
|
||||
}
|
||||
} else if (hasSel) {
|
||||
SelectedItems::const_iterator i = _selected.constFind(item);
|
||||
auto i = _selected.constFind(item);
|
||||
if (i != selEnd) {
|
||||
sel = i.value();
|
||||
}
|
||||
@ -585,19 +592,20 @@ void HistoryInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton butt
|
||||
}
|
||||
}
|
||||
if (_dragAction == NoDrag && _dragItem) {
|
||||
bool afterDragSymbol, uponSymbol;
|
||||
uint16 symbol;
|
||||
HistoryTextState dragState;
|
||||
if (_trippleClickTimer.isActive() && (screenPos - _trippleClickPoint).manhattanLength() < QApplication::startDragDistance()) {
|
||||
_dragItem->getSymbol(symbol, afterDragSymbol, uponSymbol, _dragStartPos.x(), _dragStartPos.y());
|
||||
if (uponSymbol) {
|
||||
uint32 selStatus = (symbol << 16) | symbol;
|
||||
HistoryStateRequest request;
|
||||
request.flags = Text::StateRequest::Flag::LookupSymbol;
|
||||
dragState = _dragItem->getState(_dragStartPos.x(), _dragStartPos.y(), request);
|
||||
if (dragState.cursor == HistoryInTextCursorState) {
|
||||
TextSelection selStatus = { dragState.symbol, dragState.symbol };
|
||||
if (selStatus != FullSelection && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection)) {
|
||||
if (!_selected.isEmpty()) {
|
||||
repaintItem(_selected.cbegin().key());
|
||||
_selected.clear();
|
||||
}
|
||||
_selected.insert(_dragItem, selStatus);
|
||||
_dragSymbol = symbol;
|
||||
_dragSymbol = dragState.symbol;
|
||||
_dragAction = Selecting;
|
||||
_dragSelType = TextSelectParagraphs;
|
||||
dragActionUpdate(_dragPos);
|
||||
@ -605,12 +613,14 @@ void HistoryInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton butt
|
||||
}
|
||||
}
|
||||
} else if (App::pressedItem()) {
|
||||
_dragItem->getSymbol(symbol, afterDragSymbol, uponSymbol, _dragStartPos.x(), _dragStartPos.y());
|
||||
HistoryStateRequest request;
|
||||
request.flags = Text::StateRequest::Flag::LookupSymbol;
|
||||
dragState = _dragItem->getState(_dragStartPos.x(), _dragStartPos.y(), request);
|
||||
}
|
||||
if (_dragSelType != TextSelectParagraphs) {
|
||||
if (App::pressedItem()) {
|
||||
_dragSymbol = symbol;
|
||||
bool uponSelected = uponSymbol;
|
||||
_dragSymbol = dragState.symbol;
|
||||
bool uponSelected = (dragState.cursor == HistoryInTextCursorState);
|
||||
if (uponSelected) {
|
||||
if (_selected.isEmpty() ||
|
||||
_selected.cbegin().value() == FullSelection ||
|
||||
@ -618,7 +628,7 @@ void HistoryInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton butt
|
||||
) {
|
||||
uponSelected = false;
|
||||
} else {
|
||||
uint16 selFrom = (_selected.cbegin().value() >> 16) & 0xFFFF, selTo = _selected.cbegin().value() & 0xFFFF;
|
||||
uint16 selFrom = _selected.cbegin().value().from, selTo = _selected.cbegin().value().to;
|
||||
if (_dragSymbol < selFrom || _dragSymbol >= selTo) {
|
||||
uponSelected = false;
|
||||
}
|
||||
@ -630,8 +640,8 @@ void HistoryInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton butt
|
||||
if (dynamic_cast<HistorySticker*>(App::pressedItem()->getMedia()) || _dragCursorState == HistoryInDateCursorState) {
|
||||
_dragAction = PrepareDrag; // start sticker drag or by-date drag
|
||||
} else {
|
||||
if (afterDragSymbol) ++_dragSymbol;
|
||||
uint32 selStatus = (_dragSymbol << 16) | _dragSymbol;
|
||||
if (dragState.afterSymbol) ++_dragSymbol;
|
||||
TextSelection selStatus = { _dragSymbol, _dragSymbol };
|
||||
if (selStatus != FullSelection && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection)) {
|
||||
if (!_selected.isEmpty()) {
|
||||
repaintItem(_selected.cbegin().key());
|
||||
@ -672,12 +682,13 @@ void HistoryInner::onDragExec() {
|
||||
|
||||
bool uponSelected = false;
|
||||
if (_dragItem) {
|
||||
bool afterDragSymbol;
|
||||
uint16 symbol;
|
||||
if (!_selected.isEmpty() && _selected.cbegin().value() == FullSelection) {
|
||||
uponSelected = _selected.contains(_dragItem);
|
||||
} else {
|
||||
_dragItem->getSymbol(symbol, afterDragSymbol, uponSelected, _dragStartPos.x(), _dragStartPos.y());
|
||||
HistoryStateRequest request;
|
||||
request.flags |= Text::StateRequest::Flag::LookupSymbol;
|
||||
auto dragState = _dragItem->getState(_dragStartPos.x(), _dragStartPos.y(), request);
|
||||
uponSelected = (dragState.cursor == HistoryInTextCursorState);
|
||||
if (uponSelected) {
|
||||
if (_selected.isEmpty() ||
|
||||
_selected.cbegin().value() == FullSelection ||
|
||||
@ -685,8 +696,8 @@ void HistoryInner::onDragExec() {
|
||||
) {
|
||||
uponSelected = false;
|
||||
} else {
|
||||
uint16 selFrom = (_selected.cbegin().value() >> 16) & 0xFFFF, selTo = _selected.cbegin().value() & 0xFFFF;
|
||||
if (symbol < selFrom || symbol >= selTo) {
|
||||
uint16 selFrom = _selected.cbegin().value().from, selTo = _selected.cbegin().value().to;
|
||||
if (dragState.symbol < selFrom || dragState.symbol >= selTo) {
|
||||
uponSelected = false;
|
||||
}
|
||||
}
|
||||
@ -838,8 +849,8 @@ void HistoryInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton but
|
||||
applyDragSelection();
|
||||
_dragSelFrom = _dragSelTo = 0;
|
||||
} else if (!_selected.isEmpty() && !_dragWasInactive) {
|
||||
uint32 sel = _selected.cbegin().value();
|
||||
if (sel != FullSelection && (sel & 0xFFFF) == ((sel >> 16) & 0xFFFF)) {
|
||||
auto sel = _selected.cbegin().value();
|
||||
if (sel != FullSelection && sel.from == sel.to) {
|
||||
_selected.clear();
|
||||
if (App::wnd()) App::wnd()->setInnerFocus();
|
||||
}
|
||||
@ -864,15 +875,15 @@ void HistoryInner::mouseDoubleClickEvent(QMouseEvent *e) {
|
||||
|
||||
dragActionStart(e->globalPos(), e->button());
|
||||
if (((_dragAction == Selecting && !_selected.isEmpty() && _selected.cbegin().value() != FullSelection) || (_dragAction == NoDrag && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection))) && _dragSelType == TextSelectLetters && _dragItem) {
|
||||
bool afterDragSymbol, uponSelected;
|
||||
uint16 symbol;
|
||||
_dragItem->getSymbol(symbol, afterDragSymbol, uponSelected, _dragStartPos.x(), _dragStartPos.y());
|
||||
if (uponSelected) {
|
||||
_dragSymbol = symbol;
|
||||
HistoryStateRequest request;
|
||||
request.flags |= Text::StateRequest::Flag::LookupSymbol;
|
||||
auto dragState = _dragItem->getState(_dragStartPos.x(), _dragStartPos.y(), request);
|
||||
if (dragState.cursor == HistoryInTextCursorState) {
|
||||
_dragSymbol = dragState.symbol;
|
||||
_dragSelType = TextSelectWords;
|
||||
if (_dragAction == NoDrag) {
|
||||
_dragAction = Selecting;
|
||||
uint32 selStatus = (symbol << 16) | symbol;
|
||||
TextSelection selStatus = { dragState.symbol, dragState.symbol };
|
||||
if (!_selected.isEmpty()) {
|
||||
repaintItem(_selected.cbegin().key());
|
||||
_selected.clear();
|
||||
@ -912,13 +923,14 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||
isUponSelected = -2;
|
||||
}
|
||||
} else {
|
||||
uint16 symbol, selFrom = (_selected.cbegin().value() >> 16) & 0xFFFF, selTo = _selected.cbegin().value() & 0xFFFF;
|
||||
uint16 selFrom = _selected.cbegin().value().from, selTo = _selected.cbegin().value().to;
|
||||
hasSelected = (selTo > selFrom) ? 1 : 0;
|
||||
if (App::mousedItem() && App::mousedItem() == App::hoveredItem()) {
|
||||
QPoint mousePos(mapMouseToItem(mapFromGlobal(_dragPos), App::mousedItem()));
|
||||
bool afterDragSymbol, uponSymbol;
|
||||
App::mousedItem()->getSymbol(symbol, afterDragSymbol, uponSymbol, mousePos.x(), mousePos.y());
|
||||
if (uponSymbol && symbol >= selFrom && symbol < selTo) {
|
||||
HistoryStateRequest request;
|
||||
request.flags |= Text::StateRequest::Flag::LookupSymbol;
|
||||
auto dragState = App::mousedItem()->getState(mousePos.x(), mousePos.y(), request);
|
||||
if (dragState.cursor == HistoryInTextCursorState && dragState.symbol >= selFrom && dragState.symbol < selTo) {
|
||||
isUponSelected = 1;
|
||||
}
|
||||
}
|
||||
@ -1054,7 +1066,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||
}
|
||||
}
|
||||
QString contextMenuText = item->selectedText(FullSelection);
|
||||
if (!contextMenuText.isEmpty() && (!msg || !msg->getMedia() || (msg->getMedia()->type() != MediaTypeSticker && msg->getMedia()->type() != MediaTypeGif))) {
|
||||
if (!contextMenuText.isEmpty() && msg && !msg->getMedia()) {
|
||||
_menu->addAction(lang(lng_context_copy_text), this, SLOT(copyContextText()))->setEnabled(true);
|
||||
}
|
||||
}
|
||||
@ -1489,7 +1501,7 @@ void HistoryInner::updateSize() {
|
||||
|
||||
void HistoryInner::enterEvent(QEvent *e) {
|
||||
dragActionUpdate(QCursor::pos());
|
||||
return QWidget::enterEvent(e);
|
||||
// return QWidget::enterEvent(e);
|
||||
}
|
||||
|
||||
void HistoryInner::leaveEvent(QEvent *e) {
|
||||
@ -1522,6 +1534,7 @@ void HistoryInner::adjustCurrent(int32 y) const {
|
||||
}
|
||||
|
||||
void HistoryInner::adjustCurrent(int32 y, History *history) const {
|
||||
t_assert(!history->isEmpty());
|
||||
_curHistory = history;
|
||||
if (_curBlock >= history->blocks.size()) {
|
||||
_curBlock = history->blocks.size() - 1;
|
||||
@ -1681,57 +1694,13 @@ void HistoryInner::onUpdateSelected() {
|
||||
dragActionCancel();
|
||||
}
|
||||
|
||||
ClickHandlerPtr lnk;
|
||||
HistoryTextState dragState;
|
||||
ClickHandlerHost *lnkhost = nullptr;
|
||||
HistoryCursorState cursorState = HistoryDefaultCursorState;
|
||||
bool selectingText = (item == _dragItem && item == App::hoveredItem() && !_selected.isEmpty() && _selected.cbegin().value() != FullSelection);
|
||||
if (point.y() < _historyOffset) {
|
||||
if (_botAbout && !_botAbout->info->text.isEmpty() && _botAbout->height > 0) {
|
||||
bool inText = false;
|
||||
_botAbout->info->text.getState(lnk, inText, point.x() - _botAbout->rect.left() - st::msgPadding.left(), point.y() - _botAbout->rect.top() - st::msgPadding.top() - st::botDescSkip - st::msgNameFont->height, _botAbout->width);
|
||||
dragState = _botAbout->info->text.getState(point.x() - _botAbout->rect.left() - st::msgPadding.left(), point.y() - _botAbout->rect.top() - st::msgPadding.top() - st::botDescSkip - st::msgNameFont->height, _botAbout->width);
|
||||
lnkhost = _botAbout.get();
|
||||
cursorState = inText ? HistoryInTextCursorState : HistoryDefaultCursorState;
|
||||
}
|
||||
} else if (item) {
|
||||
item->getState(lnk, cursorState, m.x(), m.y());
|
||||
lnkhost = item;
|
||||
if (!lnk && m.x() >= st::msgMargin.left() && m.x() < st::msgMargin.left() + st::msgPhotoSize) {
|
||||
if (HistoryMessage *msg = item->toHistoryMessage()) {
|
||||
if (msg->hasFromPhoto()) {
|
||||
enumerateUserpics([&lnk, &lnkhost, &point](HistoryMessage *message, int userpicTop) -> bool {
|
||||
// stop enumeration if the userpic is above our point
|
||||
if (userpicTop + st::msgPhotoSize <= point.y()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// stop enumeration if we've found a userpic under the cursor
|
||||
if (point.y() >= userpicTop && point.y() < userpicTop + st::msgPhotoSize) {
|
||||
lnk = message->from()->openLink();
|
||||
lnkhost = message;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bool lnkChanged = ClickHandler::setActive(lnk, lnkhost);
|
||||
if (lnkChanged || cursorState != _dragCursorState) {
|
||||
PopupTooltip::Hide();
|
||||
}
|
||||
if (lnk || cursorState == HistoryInDateCursorState || cursorState == HistoryInForwardedCursorState) {
|
||||
PopupTooltip::Show(1000, this);
|
||||
}
|
||||
|
||||
Qt::CursorShape cur = style::cur_default;
|
||||
if (_dragAction == NoDrag) {
|
||||
_dragCursorState = cursorState;
|
||||
if (lnk) {
|
||||
cur = style::cur_pointer;
|
||||
} else if (_dragCursorState == HistoryInTextCursorState && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection)) {
|
||||
cur = style::cur_text;
|
||||
} else if (_dragCursorState == HistoryInDateCursorState) {
|
||||
// cur = style::cur_cross;
|
||||
}
|
||||
} else if (item) {
|
||||
if (item != _dragItem || (m - _dragStartPos).manhattanLength() >= QApplication::startDragDistance()) {
|
||||
@ -1742,19 +1711,68 @@ void HistoryInner::onUpdateSelected() {
|
||||
_dragAction = Selecting;
|
||||
}
|
||||
}
|
||||
|
||||
HistoryStateRequest request;
|
||||
if (_dragAction == Selecting) {
|
||||
bool canSelectMany = (_history != 0);
|
||||
if (item == _dragItem && item == App::hoveredItem() && !_selected.isEmpty() && _selected.cbegin().value() != FullSelection) {
|
||||
bool afterSymbol, uponSymbol;
|
||||
uint16 second;
|
||||
_dragItem->getSymbol(second, afterSymbol, uponSymbol, m.x(), m.y());
|
||||
if (afterSymbol && _dragSelType == TextSelectLetters) ++second;
|
||||
uint32 selState = _dragItem->adjustSelection(qMin(second, _dragSymbol), qMax(second, _dragSymbol), _dragSelType);
|
||||
request.flags |= Text::StateRequest::Flag::LookupSymbol;
|
||||
} else {
|
||||
selectingText = false;
|
||||
}
|
||||
dragState = item->getState(m.x(), m.y(), request);
|
||||
lnkhost = item;
|
||||
if (!dragState.link && m.x() >= st::msgMargin.left() && m.x() < st::msgMargin.left() + st::msgPhotoSize) {
|
||||
if (HistoryMessage *msg = item->toHistoryMessage()) {
|
||||
if (msg->hasFromPhoto()) {
|
||||
enumerateUserpics([&dragState, &lnkhost, &point](HistoryMessage *message, int userpicTop) -> bool {
|
||||
// stop enumeration if the userpic is above our point
|
||||
if (userpicTop + st::msgPhotoSize <= point.y()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// stop enumeration if we've found a userpic under the cursor
|
||||
if (point.y() >= userpicTop && point.y() < userpicTop + st::msgPhotoSize) {
|
||||
dragState.link = message->from()->openLink();
|
||||
lnkhost = message;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bool lnkChanged = ClickHandler::setActive(dragState.link, lnkhost);
|
||||
if (lnkChanged || dragState.cursor != _dragCursorState) {
|
||||
PopupTooltip::Hide();
|
||||
}
|
||||
if (dragState.link || dragState.cursor == HistoryInDateCursorState || dragState.cursor == HistoryInForwardedCursorState) {
|
||||
PopupTooltip::Show(1000, this);
|
||||
}
|
||||
|
||||
Qt::CursorShape cur = style::cur_default;
|
||||
if (_dragAction == NoDrag) {
|
||||
_dragCursorState = dragState.cursor;
|
||||
if (dragState.link) {
|
||||
cur = style::cur_pointer;
|
||||
} else if (_dragCursorState == HistoryInTextCursorState && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection)) {
|
||||
cur = style::cur_text;
|
||||
} else if (_dragCursorState == HistoryInDateCursorState) {
|
||||
// cur = style::cur_cross;
|
||||
}
|
||||
} else if (item) {
|
||||
if (_dragAction == Selecting) {
|
||||
bool canSelectMany = (_history != nullptr);
|
||||
if (selectingText) {
|
||||
uint16 second = dragState.symbol;
|
||||
if (dragState.afterSymbol && _dragSelType == TextSelectLetters) {
|
||||
++second;
|
||||
}
|
||||
auto selState = _dragItem->adjustSelection({ qMin(second, _dragSymbol), qMax(second, _dragSymbol) }, _dragSelType);
|
||||
if (_selected[_dragItem] != selState) {
|
||||
_selected[_dragItem] = selState;
|
||||
repaintItem(_dragItem);
|
||||
}
|
||||
if (!_wasSelectedText && (selState == FullSelection || (selState & 0xFFFF) != ((selState >> 16) & 0xFFFF))) {
|
||||
if (!_wasSelectedText && (selState == FullSelection || selState.from != selState.to)) {
|
||||
_wasSelectedText = true;
|
||||
setFocus();
|
||||
}
|
||||
@ -2005,7 +2023,7 @@ QString HistoryInner::tooltipText() const {
|
||||
} else if (_dragCursorState == HistoryInForwardedCursorState && _dragAction == NoDrag) {
|
||||
if (App::hoveredItem()) {
|
||||
if (HistoryMessageForwarded *fwd = App::hoveredItem()->Get<HistoryMessageForwarded>()) {
|
||||
return fwd->_text.original(0, 0xFFFF, Text::ExpandLinksNone);
|
||||
return fwd->_text.original(AllTextSelection, Text::ExpandLinksNone);
|
||||
}
|
||||
}
|
||||
} else if (ClickHandlerPtr lnk = ClickHandler::getActive()) {
|
||||
@ -2242,8 +2260,7 @@ void BotKeyboard::enterEvent(QEvent *e) {
|
||||
}
|
||||
|
||||
void BotKeyboard::leaveEvent(QEvent *e) {
|
||||
_lastMousePos = QPoint(-1, -1);
|
||||
updateSelected();
|
||||
clearSelection();
|
||||
}
|
||||
|
||||
void BotKeyboard::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) {
|
||||
@ -2257,44 +2274,43 @@ void BotKeyboard::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pres
|
||||
}
|
||||
|
||||
bool BotKeyboard::updateMarkup(HistoryItem *to, bool force) {
|
||||
if (to && to->definesReplyKeyboard()) {
|
||||
if (_wasForMsgId == FullMsgId(to->channelId(), to->id) && !force) {
|
||||
return false;
|
||||
if (!to || !to->definesReplyKeyboard()) {
|
||||
if (_wasForMsgId.msg) {
|
||||
_maximizeSize = _singleUse = _forceReply = false;
|
||||
_wasForMsgId = FullMsgId();
|
||||
_impl = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
_wasForMsgId = FullMsgId(to->channelId(), to->id);
|
||||
clearSelection();
|
||||
|
||||
auto markupFlags = to->replyKeyboardFlags();
|
||||
_forceReply = markupFlags & MTPDreplyKeyboardMarkup_ClientFlag::f_force_reply;
|
||||
_maximizeSize = !(markupFlags & MTPDreplyKeyboardMarkup::Flag::f_resize);
|
||||
_singleUse = _forceReply || (markupFlags & MTPDreplyKeyboardMarkup::Flag::f_single_use);
|
||||
|
||||
_impl = nullptr;
|
||||
if (auto markup = to->Get<HistoryMessageReplyMarkup>()) {
|
||||
if (!markup->rows.isEmpty()) {
|
||||
_impl.reset(new ReplyKeyboard(to, std_::make_unique<Style>(this, *_st)));
|
||||
}
|
||||
}
|
||||
|
||||
updateStyle();
|
||||
_height = st::botKbScroll.deltat + st::botKbScroll.deltab + (_impl ? _impl->naturalHeight() : 0);
|
||||
if (_maximizeSize) _height = qMax(_height, _maxOuterHeight);
|
||||
if (height() != _height) {
|
||||
resize(width(), _height);
|
||||
} else {
|
||||
resizeEvent(0);
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
if (_wasForMsgId.msg) {
|
||||
_maximizeSize = _singleUse = _forceReply = false;
|
||||
_wasForMsgId = FullMsgId();
|
||||
clearSelection();
|
||||
_impl = nullptr;
|
||||
return true;
|
||||
|
||||
if (_wasForMsgId == FullMsgId(to->channelId(), to->id) && !force) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
|
||||
_wasForMsgId = FullMsgId(to->channelId(), to->id);
|
||||
|
||||
auto markupFlags = to->replyKeyboardFlags();
|
||||
_forceReply = markupFlags & MTPDreplyKeyboardMarkup_ClientFlag::f_force_reply;
|
||||
_maximizeSize = !(markupFlags & MTPDreplyKeyboardMarkup::Flag::f_resize);
|
||||
_singleUse = _forceReply || (markupFlags & MTPDreplyKeyboardMarkup::Flag::f_single_use);
|
||||
|
||||
_impl = nullptr;
|
||||
if (auto markup = to->Get<HistoryMessageReplyMarkup>()) {
|
||||
if (!markup->rows.isEmpty()) {
|
||||
_impl.reset(new ReplyKeyboard(to, std_::make_unique<Style>(this, *_st)));
|
||||
}
|
||||
}
|
||||
|
||||
updateStyle();
|
||||
_height = st::botKbScroll.deltat + st::botKbScroll.deltab + (_impl ? _impl->naturalHeight() : 0);
|
||||
if (_maximizeSize) _height = qMax(_height, _maxOuterHeight);
|
||||
if (height() != _height) {
|
||||
resize(width(), _height);
|
||||
} else {
|
||||
resizeEvent(nullptr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BotKeyboard::hasMarkup() const {
|
||||
@ -2333,7 +2349,10 @@ void BotKeyboard::updateStyle(int32 w) {
|
||||
|
||||
void BotKeyboard::clearSelection() {
|
||||
if (_impl) {
|
||||
_impl->clearSelection();
|
||||
if (ClickHandler::setActive(ClickHandlerPtr(), this)) {
|
||||
PopupTooltip::Hide();
|
||||
setCursor(style::cur_default);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2363,11 +2382,10 @@ void BotKeyboard::updateSelected() {
|
||||
QPoint p(mapFromGlobal(_lastMousePos));
|
||||
int x = rtl() ? st::botKbScroll.width : _st->margin;
|
||||
|
||||
ClickHandlerPtr lnk;
|
||||
_impl->getState(lnk, p.x() - x, p.y() - _st->margin);
|
||||
if (ClickHandler::setActive(lnk, this)) {
|
||||
auto link = _impl->getState(p.x() - x, p.y() - _st->margin);
|
||||
if (ClickHandler::setActive(link, this)) {
|
||||
PopupTooltip::Hide();
|
||||
setCursor(lnk ? style::cur_pointer : style::cur_default);
|
||||
setCursor(link ? style::cur_pointer : style::cur_default);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2891,7 +2909,7 @@ void HistoryWidget::onStickersUpdated() {
|
||||
|
||||
void HistoryWidget::onMentionHashtagOrBotCommandInsert(QString str) {
|
||||
if (str.at(0) == '/') { // bot command
|
||||
App::sendBotCommand(_peer, str);
|
||||
App::sendBotCommand(_peer, nullptr, str);
|
||||
setFieldText(_field.getLastText().mid(_field.textCursor().position()));
|
||||
} else {
|
||||
_field.onMentionHashtagOrBotCommandInsert(str);
|
||||
@ -4835,7 +4853,7 @@ void HistoryWidget::onBotStart() {
|
||||
|
||||
QString token = _peer->asUser()->botInfo->startToken;
|
||||
if (token.isEmpty()) {
|
||||
sendBotCommand(_peer, qsl("/start"), 0);
|
||||
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()));
|
||||
@ -5269,14 +5287,15 @@ void HistoryWidget::stopRecording(bool send) {
|
||||
_a_record.start();
|
||||
}
|
||||
|
||||
void HistoryWidget::sendBotCommand(PeerData *peer, const QString &cmd, MsgId replyTo) { // replyTo != 0 from ReplyKeyboardMarkup, == 0 from cmd links
|
||||
void HistoryWidget::sendBotCommand(PeerData *peer, UserData *bot, const QString &cmd, MsgId replyTo) { // replyTo != 0 from ReplyKeyboardMarkup, == 0 from cmd links
|
||||
if (!_peer || _peer != peer) return;
|
||||
|
||||
bool lastKeyboardUsed = (_keyboard.forMsgId() == FullMsgId(_channel, _history->lastKeyboardId)) && (_keyboard.forMsgId() == FullMsgId(_channel, replyTo));
|
||||
|
||||
QString toSend = cmd;
|
||||
PeerData *bot = _peer->isUser() ? _peer : (App::hoveredLinkItem() ? App::hoveredLinkItem()->fromOriginal() : 0);
|
||||
if (bot && (!bot->isUser() || !bot->asUser()->botInfo)) bot = 0;
|
||||
if (bot && (!bot->isUser() || !bot->asUser()->botInfo)) {
|
||||
bot = nullptr;
|
||||
}
|
||||
QString username = bot ? bot->asUser()->username : QString();
|
||||
int32 botStatus = _peer->isChat() ? _peer->asChat()->botStatus : (_peer->isMegagroup() ? _peer->asChannel()->mgInfo->botStatus : -1);
|
||||
if (!replyTo && toSend.indexOf('@') < 2 && !username.isEmpty() && (botStatus == 0 || botStatus == 2)) {
|
||||
@ -5333,10 +5352,10 @@ void HistoryWidget::botCallbackDone(BotCallbackInfo info, const MTPmessages_BotC
|
||||
if (answerData.has_message()) {
|
||||
if (answerData.is_alert()) {
|
||||
Ui::showLayer(new InformBox(qs(answerData.vmessage)));
|
||||
} else {
|
||||
} else if (App::wnd()) {
|
||||
Ui::Toast::Config toast;
|
||||
toast.text = qs(answerData.vmessage);
|
||||
Ui::Toast::Show(toast);
|
||||
Ui::Toast::Show(App::wnd(), toast);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5923,6 +5942,7 @@ void HistoryWidget::inlineBotChanged() {
|
||||
_inlineBotCancel = std_::make_unique<IconedButton>(this, st::inlineBotCancel);
|
||||
connect(_inlineBotCancel.get(), SIGNAL(clicked()), this, SLOT(onInlineBotCancel()));
|
||||
_inlineBotCancel->setGeometry(_send.geometry());
|
||||
_attachEmoji.raise();
|
||||
updateFieldSubmitSettings();
|
||||
updateControlsVisibility();
|
||||
} else if (!isInlineBot && _inlineBotCancel) {
|
||||
@ -8043,7 +8063,7 @@ void HistoryWidget::drawPinnedBar(Painter &p) {
|
||||
p.drawText(left, st::msgReplyPadding.top() + st::msgServiceNameFont->ascent, lang(lng_pinned_message));
|
||||
|
||||
p.setPen((((_pinnedBar->msg->toHistoryMessage() && _pinnedBar->msg->toHistoryMessage()->emptyText()) || _pinnedBar->msg->serviceMsg()) ? st::msgInDateFg : st::msgColor)->p);
|
||||
_pinnedBar->text.drawElided(p, left, st::msgReplyPadding.top() + st::msgServiceNameFont->height, width() - left -_fieldBarCancel.width() - st::msgReplyPadding.right());
|
||||
_pinnedBar->text.drawElided(p, left, st::msgReplyPadding.top() + st::msgServiceNameFont->height, width() - left - _pinnedBar->cancel.width() - st::msgReplyPadding.right());
|
||||
} else {
|
||||
p.setFont(st::msgDateFont);
|
||||
p.setPen(st::msgInDateFg);
|
||||
|
@ -22,15 +22,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
|
||||
#include "localimageloader.h"
|
||||
#include "ui/boxshadow.h"
|
||||
|
||||
#include "dropdown.h"
|
||||
|
||||
enum DragState {
|
||||
DragStateNone = 0x00,
|
||||
DragStateFiles = 0x01,
|
||||
DragStatePhotoFiles = 0x02,
|
||||
DragStateImage = 0x03,
|
||||
};
|
||||
#include "history/history_common.h"
|
||||
|
||||
class HistoryWidget;
|
||||
class HistoryInner : public TWidget, public AbstractTooltipShower {
|
||||
@ -181,7 +174,7 @@ private:
|
||||
bool _firstLoading = false;
|
||||
|
||||
style::cursor _cursor = style::cur_default;
|
||||
typedef QMap<HistoryItem*, uint32> SelectedItems;
|
||||
using SelectedItems = QMap<HistoryItem*, TextSelection>;
|
||||
SelectedItems _selected;
|
||||
void applyDragSelection();
|
||||
void applyDragSelection(SelectedItems *toItems) const;
|
||||
@ -629,7 +622,7 @@ public:
|
||||
|
||||
void onListEscapePressed();
|
||||
|
||||
void sendBotCommand(PeerData *peer, const QString &cmd, MsgId replyTo);
|
||||
void sendBotCommand(PeerData *peer, UserData *bot, const QString &cmd, MsgId replyTo);
|
||||
bool insertBotCommand(const QString &cmd, bool specialGif);
|
||||
|
||||
bool eventFilter(QObject *obj, QEvent *e) override;
|
||||
|
@ -25,6 +25,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
#include "localstorage.h"
|
||||
#include "mainwidget.h"
|
||||
#include "lang.h"
|
||||
#include "playerwidget.h"
|
||||
|
||||
namespace InlineBots {
|
||||
namespace Layout {
|
||||
@ -124,7 +125,7 @@ void DeleteSavedGifClickHandler::onClickImpl() const {
|
||||
if (App::main()) emit App::main()->savedGifsUpdated();
|
||||
}
|
||||
|
||||
void Gif::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
|
||||
void Gif::paint(Painter &p, const QRect &clip, const PaintContext *context) const {
|
||||
DocumentData *document = getShownDocument();
|
||||
document->automaticLoad(nullptr);
|
||||
|
||||
@ -380,7 +381,7 @@ void Sticker::preload() const {
|
||||
}
|
||||
}
|
||||
|
||||
void Sticker::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
|
||||
void Sticker::paint(Painter &p, const QRect &clip, const PaintContext *context) const {
|
||||
bool loaded = getShownDocument()->loaded();
|
||||
|
||||
float64 over = _a_over.isNull() ? (_active ? 1 : 0) : _a_over.current();
|
||||
@ -472,7 +473,7 @@ void Photo::initDimensions() {
|
||||
_minh = st::inlineMediaHeight + st::inlineResultsSkip;
|
||||
}
|
||||
|
||||
void Photo::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
|
||||
void Photo::paint(Painter &p, const QRect &clip, const PaintContext *context) const {
|
||||
int32 height = st::inlineMediaHeight;
|
||||
QSize frame = countFrameSize();
|
||||
|
||||
@ -590,7 +591,7 @@ void Video::initDimensions() {
|
||||
_minh += st::inlineRowMargin * 2 + st::inlineRowBorder;
|
||||
}
|
||||
|
||||
void Video::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
|
||||
void Video::paint(Painter &p, const QRect &clip, const PaintContext *context) const {
|
||||
int left = st::inlineThumbSize + st::inlineThumbSkip;
|
||||
|
||||
bool withThumb = !content_thumb()->isNull();
|
||||
@ -693,7 +694,7 @@ void File::initDimensions() {
|
||||
_minh += st::inlineRowMargin * 2 + st::inlineRowBorder;
|
||||
}
|
||||
|
||||
void File::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
|
||||
void File::paint(Painter &p, const QRect &clip, const PaintContext *context) const {
|
||||
int32 left = st::msgFileSize + st::inlineThumbSkip;
|
||||
|
||||
DocumentData *document = getShownDocument();
|
||||
@ -941,7 +942,7 @@ int32 Contact::resizeGetHeight(int32 width) {
|
||||
return _height;
|
||||
}
|
||||
|
||||
void Contact::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
|
||||
void Contact::paint(Painter &p, const QRect &clip, const PaintContext *context) const {
|
||||
int32 left = st::emojiPanHeaderLeft - st::inlineResultsLeft;
|
||||
|
||||
left = st::msgFileSize + st::inlineThumbSkip;
|
||||
@ -1050,7 +1051,7 @@ int32 Article::resizeGetHeight(int32 width) {
|
||||
return _height;
|
||||
}
|
||||
|
||||
void Article::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
|
||||
void Article::paint(Painter &p, const QRect &clip, const PaintContext *context) const {
|
||||
int32 left = st::emojiPanHeaderLeft - st::inlineResultsLeft;
|
||||
if (_withThumb) {
|
||||
left = st::inlineThumbSize + st::inlineThumbSkip;
|
||||
|
@ -21,7 +21,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
#pragma once
|
||||
|
||||
#include "inline_bots/inline_bot_layout_item.h"
|
||||
#include "ui/text.h"
|
||||
#include "ui/text/text.h"
|
||||
|
||||
namespace InlineBots {
|
||||
namespace Layout {
|
||||
@ -70,7 +70,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const override;
|
||||
void paint(Painter &p, const QRect &clip, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||
|
||||
// ClickHandlerHost interface
|
||||
@ -135,7 +135,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const override;
|
||||
void paint(Painter &p, const QRect &clip, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||
|
||||
private:
|
||||
@ -165,7 +165,7 @@ public:
|
||||
}
|
||||
void preload() const override;
|
||||
|
||||
void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const override;
|
||||
void paint(Painter &p, const QRect &clip, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||
|
||||
// ClickHandlerHost interface
|
||||
@ -190,7 +190,7 @@ public:
|
||||
|
||||
void initDimensions() override;
|
||||
|
||||
void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const override;
|
||||
void paint(Painter &p, const QRect &clip, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||
|
||||
private:
|
||||
@ -238,7 +238,7 @@ public:
|
||||
|
||||
void initDimensions() override;
|
||||
|
||||
void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const override;
|
||||
void paint(Painter &p, const QRect &clip, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||
|
||||
// ClickHandlerHost interface
|
||||
@ -302,7 +302,7 @@ public:
|
||||
void initDimensions() override;
|
||||
int resizeGetHeight(int width) override;
|
||||
|
||||
void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const override;
|
||||
void paint(Painter &p, const QRect &clip, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||
|
||||
private:
|
||||
@ -321,7 +321,7 @@ public:
|
||||
void initDimensions() override;
|
||||
int resizeGetHeight(int width) override;
|
||||
|
||||
void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const override;
|
||||
void paint(Painter &p, const QRect &clip, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||
|
||||
private:
|
||||
|
@ -21,6 +21,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
#include "stdafx.h"
|
||||
#include "inline_bots/inline_bot_layout_item.h"
|
||||
|
||||
#include "core/click_handler_types.h"
|
||||
#include "inline_bots/inline_bot_result.h"
|
||||
#include "inline_bots/inline_bot_layout_internal.h"
|
||||
#include "localstorage.h"
|
||||
|
@ -22,7 +22,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
|
||||
#include "layout.h"
|
||||
#include "structs.h"
|
||||
#include "ui/text.h"
|
||||
#include "ui/text/text.h"
|
||||
|
||||
namespace InlineBots {
|
||||
class Result;
|
||||
@ -58,7 +58,7 @@ public:
|
||||
//ItemBase(PhotoData *photo) : _photo(photo) {
|
||||
//}
|
||||
|
||||
virtual void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const = 0;
|
||||
virtual void paint(Painter &p, const QRect &clip, const PaintContext *context) const = 0;
|
||||
|
||||
virtual void setPosition(int32 position);
|
||||
int32 position() const;
|
||||
|
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "basic_types.h"
|
||||
#include "core/basic_types.h"
|
||||
#include "structs.h"
|
||||
#include "mtproto/core_types.h"
|
||||
|
||||
|
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "basic_types.h"
|
||||
#include "core/basic_types.h"
|
||||
#include "structs.h"
|
||||
#include "mtproto/core_types.h"
|
||||
|
||||
|
@ -31,49 +31,22 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
#include "intro/introsignup.h"
|
||||
#include "intro/intropwdcheck.h"
|
||||
#include "mainwidget.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
#include "application.h"
|
||||
#include "ui/text.h"
|
||||
|
||||
namespace {
|
||||
IntroWidget *signalEmitOn = 0;
|
||||
QString countryForReg;
|
||||
void gotNearestDC(const MTPNearestDc &result) {
|
||||
const auto &nearest(result.c_nearestDc());
|
||||
DEBUG_LOG(("Got nearest dc, country: %1, nearest: %2, this: %3").arg(nearest.vcountry.c_string().v.c_str()).arg(nearest.vnearest_dc.v).arg(nearest.vthis_dc.v));
|
||||
MTP::setdc(result.c_nearestDc().vnearest_dc.v, true);
|
||||
if (countryForReg != nearest.vcountry.c_string().v.c_str()) {
|
||||
countryForReg = nearest.vcountry.c_string().v.c_str();
|
||||
emit signalEmitOn->countryChanged();
|
||||
}
|
||||
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
||||
Sandbox::startUpdateCheck();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#include "ui/text/text.h"
|
||||
|
||||
IntroWidget::IntroWidget(QWidget *parent) : TWidget(parent)
|
||||
, _langChangeTo(0)
|
||||
, _a_stage(animation(this, &IntroWidget::step_stage))
|
||||
, _cacheHideIndex(0)
|
||||
, _cacheShowIndex(0)
|
||||
, _a_show(animation(this, &IntroWidget::step_show))
|
||||
, _callStatus({ CallDisabled, 0 })
|
||||
, _registered(false)
|
||||
, _hasRecovery(false)
|
||||
, _codeByTelegram(false)
|
||||
, _back(this, st::setClose)
|
||||
, _backFrom(0)
|
||||
, _backTo(0) {
|
||||
, _back(this, st::setClose) {
|
||||
setGeometry(QRect(0, st::titleHeight, App::wnd()->width(), App::wnd()->height() - st::titleHeight));
|
||||
|
||||
connect(&_back, SIGNAL(clicked()), this, SLOT(onBack()));
|
||||
_back.hide();
|
||||
|
||||
countryForReg = psCurrentCountry();
|
||||
_countryForReg = psCurrentCountry();
|
||||
|
||||
MTP::send(MTPhelp_GetNearestDc(), rpcDone(gotNearestDC));
|
||||
signalEmitOn = this;
|
||||
MTP::send(MTPhelp_GetNearestDc(), rpcDone(&IntroWidget::gotNearestDC));
|
||||
|
||||
_stepHistory.push_back(new IntroStart(this));
|
||||
_back.raise();
|
||||
@ -86,6 +59,10 @@ IntroWidget::IntroWidget(QWidget *parent) : TWidget(parent)
|
||||
cSetPasswordRecovered(false);
|
||||
|
||||
_back.move(st::setClosePos.x(), st::setClosePos.y());
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
||||
Sandbox::startUpdateCheck();
|
||||
#endif
|
||||
}
|
||||
|
||||
void IntroWidget::langChangeTo(int32 langId) {
|
||||
@ -173,6 +150,16 @@ void IntroWidget::pushStep(IntroStep *step, MoveType type) {
|
||||
historyMove(type);
|
||||
}
|
||||
|
||||
void IntroWidget::gotNearestDC(const MTPNearestDc &result) {
|
||||
const auto &nearest(result.c_nearestDc());
|
||||
DEBUG_LOG(("Got nearest dc, country: %1, nearest: %2, this: %3").arg(nearest.vcountry.c_string().v.c_str()).arg(nearest.vnearest_dc.v).arg(nearest.vthis_dc.v));
|
||||
MTP::setdc(result.c_nearestDc().vnearest_dc.v, true);
|
||||
if (_countryForReg != nearest.vcountry.c_string().v.c_str()) {
|
||||
_countryForReg = nearest.vcountry.c_string().v.c_str();
|
||||
emit countryChanged();
|
||||
}
|
||||
}
|
||||
|
||||
QPixmap IntroWidget::grabStep(int skip) {
|
||||
return myGrab(step(skip), QRect(st::introSlideShift, 0, st::introSize.width(), st::introSize.height()));
|
||||
}
|
||||
@ -297,7 +284,7 @@ QRect IntroWidget::innerRect() const {
|
||||
}
|
||||
|
||||
QString IntroWidget::currentCountry() const {
|
||||
return countryForReg;
|
||||
return _countryForReg;
|
||||
}
|
||||
|
||||
void IntroWidget::setPhone(const QString &phone, const QString &phone_hash, bool registered) {
|
||||
|
@ -20,8 +20,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "mtproto/rpc_sender.h"
|
||||
|
||||
class IntroStep;
|
||||
class IntroWidget final : public TWidget {
|
||||
class IntroWidget : public TWidget, public RPCSender {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
@ -72,7 +74,7 @@ public:
|
||||
|
||||
void finish(const MTPUser &user, const QImage &photo = QImage());
|
||||
|
||||
void rpcClear();
|
||||
void rpcClear() override;
|
||||
void langChangeTo(int32 langId);
|
||||
|
||||
void nextStep(IntroStep *step) {
|
||||
@ -99,11 +101,12 @@ private:
|
||||
|
||||
QPixmap grabStep(int skip = 0);
|
||||
|
||||
int _langChangeTo;
|
||||
int _langChangeTo = 0;
|
||||
|
||||
Animation _a_stage;
|
||||
QPixmap _cacheHide, _cacheShow;
|
||||
int _cacheHideIndex, _cacheShowIndex;
|
||||
int _cacheHideIndex = 0;
|
||||
int _cacheShowIndex = 0;
|
||||
anim::ivalue a_coordHide, a_coordShow;
|
||||
anim::fvalue a_opacityHide, a_opacityShow;
|
||||
|
||||
@ -125,20 +128,26 @@ private:
|
||||
void historyMove(MoveType type);
|
||||
void pushStep(IntroStep *step, MoveType type);
|
||||
|
||||
void gotNearestDC(const MTPNearestDc &dc);
|
||||
|
||||
QString _countryForReg;
|
||||
|
||||
QString _phone, _phone_hash;
|
||||
CallStatus _callStatus;
|
||||
bool _registered;
|
||||
CallStatus _callStatus = { CallDisabled, 0 };
|
||||
bool _registered = false;
|
||||
|
||||
QString _code;
|
||||
|
||||
QByteArray _pwdSalt;
|
||||
bool _hasRecovery, _codeByTelegram;
|
||||
bool _hasRecovery = false;
|
||||
bool _codeByTelegram = false;
|
||||
QString _pwdHint;
|
||||
|
||||
QString _firstname, _lastname;
|
||||
|
||||
IconedButton _back;
|
||||
float64 _backFrom, _backTo;
|
||||
float64 _backFrom = 0.;
|
||||
float64 _backTo = 0.;
|
||||
|
||||
};
|
||||
|
||||
|
@ -23,7 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
|
||||
#include "layerwidget.h"
|
||||
#include "application.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
#include "mainwidget.h"
|
||||
#include "ui/filedialog.h"
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
static const uint32 FullSelection = 0xFFFFFFFF;
|
||||
static constexpr TextSelection FullSelection = { 0xFFFF, 0xFFFF };
|
||||
|
||||
extern TextParseOptions _textNameOptions, _textDlgOptions;
|
||||
extern TextParseOptions _historyTextOptions, _historyBotOptions, _historyTextNoMonoOptions, _historyBotNoMonoOptions;
|
||||
@ -91,12 +91,13 @@ public:
|
||||
|
||||
};
|
||||
|
||||
class LayoutMediaItemBase;
|
||||
class LayoutItemBase : public Composer, public ClickHandlerHost {
|
||||
public:
|
||||
LayoutItemBase() {
|
||||
}
|
||||
LayoutItemBase &operator=(const LayoutItemBase &) = delete;
|
||||
|
||||
LayoutItemBase(const LayoutItemBase &other) = delete;
|
||||
LayoutItemBase &operator=(const LayoutItemBase &other) = delete;
|
||||
|
||||
int32 maxWidth() const {
|
||||
return _maxw;
|
||||
@ -142,311 +143,3 @@ protected:
|
||||
int _minh = 0;
|
||||
|
||||
};
|
||||
|
||||
class PaintContextOverview : public PaintContextBase {
|
||||
public:
|
||||
PaintContextOverview(uint64 ms, bool selecting) : PaintContextBase(ms, selecting), isAfterDate(false) {
|
||||
}
|
||||
bool isAfterDate;
|
||||
|
||||
};
|
||||
|
||||
class LayoutOverviewItemBase : public LayoutItemBase {
|
||||
public:
|
||||
|
||||
virtual void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContextOverview *context) const = 0;
|
||||
|
||||
virtual LayoutMediaItemBase *toLayoutMediaItem() {
|
||||
return nullptr;
|
||||
}
|
||||
virtual const LayoutMediaItemBase *toLayoutMediaItem() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual HistoryItem *getItem() const {
|
||||
return nullptr;
|
||||
}
|
||||
virtual DocumentData *getDocument() const {
|
||||
return nullptr;
|
||||
}
|
||||
MsgId msgId() const {
|
||||
const HistoryItem *item = getItem();
|
||||
return item ? item->id : 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class LayoutMediaItemBase : public LayoutOverviewItemBase {
|
||||
public:
|
||||
LayoutMediaItemBase(HistoryItem *parent) : _parent(parent) {
|
||||
}
|
||||
|
||||
LayoutMediaItemBase *toLayoutMediaItem() override {
|
||||
return this;
|
||||
}
|
||||
const LayoutMediaItemBase *toLayoutMediaItem() const override {
|
||||
return this;
|
||||
}
|
||||
HistoryItem *getItem() const override {
|
||||
return _parent;
|
||||
}
|
||||
|
||||
void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override;
|
||||
void clickHandlerPressedChanged(const ClickHandlerPtr &p, bool active) override;
|
||||
|
||||
protected:
|
||||
HistoryItem *_parent;
|
||||
|
||||
};
|
||||
|
||||
class LayoutRadialProgressItem : public LayoutMediaItemBase {
|
||||
public:
|
||||
LayoutRadialProgressItem(HistoryItem *parent) : LayoutMediaItemBase(parent)
|
||||
, _radial(0)
|
||||
, a_iconOver(0, 0)
|
||||
, _a_iconOver(animation(this, &LayoutRadialProgressItem::step_iconOver)) {
|
||||
}
|
||||
|
||||
void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override;
|
||||
void clickHandlerPressedChanged(const ClickHandlerPtr &p, bool active) override;
|
||||
|
||||
~LayoutRadialProgressItem();
|
||||
|
||||
protected:
|
||||
ClickHandlerPtr _openl, _savel, _cancell;
|
||||
void setLinks(ClickHandlerPtr &&openl, ClickHandlerPtr &&savel, ClickHandlerPtr &&cancell);
|
||||
void setDocumentLinks(DocumentData *document) {
|
||||
ClickHandlerPtr save;
|
||||
if (document->voice()) {
|
||||
save.reset(new DocumentOpenClickHandler(document));
|
||||
} else {
|
||||
save.reset(new DocumentSaveClickHandler(document));
|
||||
}
|
||||
setLinks(MakeShared<DocumentOpenClickHandler>(document), std_::move(save), MakeShared<DocumentCancelClickHandler>(document));
|
||||
}
|
||||
|
||||
void step_iconOver(float64 ms, bool timer);
|
||||
void step_radial(uint64 ms, bool timer);
|
||||
|
||||
void ensureRadial() const;
|
||||
void checkRadialFinished();
|
||||
|
||||
bool isRadialAnimation(uint64 ms) const {
|
||||
if (!_radial || !_radial->animating()) return false;
|
||||
|
||||
_radial->step(ms);
|
||||
return _radial && _radial->animating();
|
||||
}
|
||||
|
||||
virtual float64 dataProgress() const = 0;
|
||||
virtual bool dataFinished() const = 0;
|
||||
virtual bool dataLoaded() const = 0;
|
||||
virtual bool iconAnimated() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
mutable RadialAnimation *_radial;
|
||||
anim::fvalue a_iconOver;
|
||||
mutable Animation _a_iconOver;
|
||||
|
||||
private:
|
||||
LayoutRadialProgressItem(const LayoutRadialProgressItem &other);
|
||||
|
||||
};
|
||||
|
||||
class LayoutAbstractFileItem : public LayoutRadialProgressItem {
|
||||
public:
|
||||
LayoutAbstractFileItem(HistoryItem *parent) : LayoutRadialProgressItem(parent) {
|
||||
}
|
||||
|
||||
protected:
|
||||
// >= 0 will contain download / upload string, _statusSize = loaded bytes
|
||||
// < 0 will contain played string, _statusSize = -(seconds + 1) played
|
||||
// 0x7FFFFFF0 will contain status for not yet downloaded file
|
||||
// 0x7FFFFFF1 will contain status for already downloaded file
|
||||
// 0x7FFFFFF2 will contain status for failed to download / upload file
|
||||
mutable int32 _statusSize;
|
||||
mutable QString _statusText;
|
||||
|
||||
// duration = -1 - no duration, duration = -2 - "GIF" duration
|
||||
void setStatusSize(int32 newSize, int32 fullSize, int32 duration, qint64 realDuration) const;
|
||||
|
||||
};
|
||||
|
||||
struct OverviewItemInfo : public BaseComponent<OverviewItemInfo> {
|
||||
int top = 0;
|
||||
};
|
||||
|
||||
class LayoutOverviewDate : public LayoutOverviewItemBase {
|
||||
public:
|
||||
LayoutOverviewDate(const QDate &date, bool month);
|
||||
|
||||
void initDimensions() override;
|
||||
void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContextOverview *context) const override;
|
||||
|
||||
private:
|
||||
QDate _date;
|
||||
QString _text;
|
||||
|
||||
};
|
||||
|
||||
class LayoutOverviewPhoto : public LayoutMediaItemBase {
|
||||
public:
|
||||
LayoutOverviewPhoto(PhotoData *photo, HistoryItem *parent);
|
||||
|
||||
void initDimensions() override;
|
||||
int32 resizeGetHeight(int32 width) override;
|
||||
void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContextOverview *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||
|
||||
private:
|
||||
PhotoData *_data;
|
||||
ClickHandlerPtr _link;
|
||||
|
||||
mutable QPixmap _pix;
|
||||
mutable bool _goodLoaded;
|
||||
|
||||
};
|
||||
|
||||
class LayoutOverviewVideo : public LayoutAbstractFileItem {
|
||||
public:
|
||||
LayoutOverviewVideo(DocumentData *video, HistoryItem *parent);
|
||||
|
||||
void initDimensions() override;
|
||||
int32 resizeGetHeight(int32 width) override;
|
||||
void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContextOverview *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||
|
||||
protected:
|
||||
float64 dataProgress() const override {
|
||||
return _data->progress();
|
||||
}
|
||||
bool dataFinished() const override {
|
||||
return !_data->loading();
|
||||
}
|
||||
bool dataLoaded() const override {
|
||||
return _data->loaded();
|
||||
}
|
||||
bool iconAnimated() const override {
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
DocumentData *_data;
|
||||
|
||||
QString _duration;
|
||||
mutable QPixmap _pix;
|
||||
mutable bool _thumbLoaded;
|
||||
|
||||
void updateStatusText() const;
|
||||
|
||||
};
|
||||
|
||||
class LayoutOverviewVoice : public LayoutAbstractFileItem {
|
||||
public:
|
||||
LayoutOverviewVoice(DocumentData *voice, HistoryItem *parent);
|
||||
|
||||
void initDimensions() override;
|
||||
void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContextOverview *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||
|
||||
protected:
|
||||
float64 dataProgress() const override {
|
||||
return _data->progress();
|
||||
}
|
||||
bool dataFinished() const override {
|
||||
return !_data->loading();
|
||||
}
|
||||
bool dataLoaded() const override {
|
||||
return _data->loaded();
|
||||
}
|
||||
bool iconAnimated() const override {
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
DocumentData *_data;
|
||||
ClickHandlerPtr _namel;
|
||||
|
||||
mutable Text _name, _details;
|
||||
mutable int32 _nameVersion;
|
||||
|
||||
void updateName() const;
|
||||
bool updateStatusText() const;
|
||||
|
||||
};
|
||||
|
||||
class LayoutOverviewDocument : public LayoutAbstractFileItem {
|
||||
public:
|
||||
LayoutOverviewDocument(DocumentData *document, HistoryItem *parent);
|
||||
|
||||
void initDimensions() override;
|
||||
void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContextOverview *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||
|
||||
virtual DocumentData *getDocument() const override {
|
||||
return _data;
|
||||
}
|
||||
|
||||
protected:
|
||||
float64 dataProgress() const override {
|
||||
return _data->progress();
|
||||
}
|
||||
bool dataFinished() const override {
|
||||
return !_data->loading();
|
||||
}
|
||||
bool dataLoaded() const override {
|
||||
return _data->loaded();
|
||||
}
|
||||
bool iconAnimated() const override {
|
||||
return _data->song() || !_data->loaded() || (_radial && _radial->animating());
|
||||
}
|
||||
|
||||
private:
|
||||
DocumentData *_data;
|
||||
ClickHandlerPtr _msgl, _namel;
|
||||
|
||||
mutable bool _thumbForLoaded;
|
||||
mutable QPixmap _thumb;
|
||||
|
||||
QString _name, _date, _ext;
|
||||
int32 _namew, _datew, _extw;
|
||||
int32 _thumbw, _colorIndex;
|
||||
|
||||
bool withThumb() const {
|
||||
return !_data->thumb->isNull() && _data->thumb->width() && _data->thumb->height();
|
||||
}
|
||||
bool updateStatusText() const;
|
||||
|
||||
};
|
||||
|
||||
class LayoutOverviewLink : public LayoutMediaItemBase {
|
||||
public:
|
||||
LayoutOverviewLink(HistoryMedia *media, HistoryItem *parent);
|
||||
|
||||
void initDimensions() override;
|
||||
int32 resizeGetHeight(int32 width) override;
|
||||
void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContextOverview *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||
|
||||
private:
|
||||
ClickHandlerPtr _photol;
|
||||
|
||||
QString _title, _letter;
|
||||
int _titlew = 0;
|
||||
WebPageData *_page = nullptr;
|
||||
int _pixw = 0;
|
||||
int _pixh = 0;
|
||||
Text _text = { int(st::msgMinWidth) };
|
||||
|
||||
struct Link {
|
||||
Link() : width(0) {
|
||||
}
|
||||
Link(const QString &url, const QString &text);
|
||||
QString text;
|
||||
int32 width;
|
||||
TextClickHandlerPtr lnk;
|
||||
};
|
||||
QVector<Link> _links;
|
||||
|
||||
};
|
||||
|
@ -25,7 +25,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
|
||||
#include "boxes/photosendbox.h"
|
||||
#include "mainwidget.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
#include "lang.h"
|
||||
#include "boxes/confirmbox.h"
|
||||
|
||||
|
@ -25,10 +25,11 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
|
||||
#include "serialize/serialize_document.h"
|
||||
#include "serialize/serialize_common.h"
|
||||
|
||||
#include "mainwidget.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
#include "lang.h"
|
||||
#include "playerwidget.h"
|
||||
#include "apiwrap.h"
|
||||
|
||||
namespace {
|
||||
typedef quint64 FileKey;
|
||||
|
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "basic_types.h"
|
||||
#include "core/basic_types.h"
|
||||
|
||||
namespace _local_inner {
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -20,107 +20,31 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "apiwrap.h"
|
||||
#include "dialogswidget.h"
|
||||
#include "historywidget.h"
|
||||
#include "profilewidget.h"
|
||||
#include "overviewwidget.h"
|
||||
#include "playerwidget.h"
|
||||
#include "ui/buttons/peer_avatar_button.h"
|
||||
#include "localimageloader.h"
|
||||
#include "history/history_common.h"
|
||||
|
||||
class Window;
|
||||
namespace Dialogs {
|
||||
class Row;
|
||||
} // namespace Dialogs
|
||||
|
||||
namespace Ui {
|
||||
class PeerAvatarButton;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Window {
|
||||
class TopBarWidget;
|
||||
} // namespace Window
|
||||
|
||||
class MainWindow;
|
||||
class ApiWrap;
|
||||
class MainWidget;
|
||||
class ConfirmBox;
|
||||
class DialogsWidget;
|
||||
class HistoryWidget;
|
||||
class ProfileWidget;
|
||||
class OverviewWidget;
|
||||
class PlayerWidget;
|
||||
|
||||
namespace Dialogs {
|
||||
class Row;
|
||||
} // namespace Dialogs
|
||||
|
||||
class TopBarWidget : public TWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
TopBarWidget(MainWidget *w);
|
||||
|
||||
void enterEvent(QEvent *e) override;
|
||||
void enterFromChildEvent(QEvent *e) override;
|
||||
void leaveEvent(QEvent *e) override;
|
||||
void leaveToChildEvent(QEvent *e) override;
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
|
||||
void step_appearance(float64 ms, bool timer);
|
||||
void enableShadow(bool enable = true);
|
||||
|
||||
void startAnim();
|
||||
void stopAnim();
|
||||
void showAll();
|
||||
void showSelected(uint32 selCount, bool canDelete = false);
|
||||
|
||||
void updateAdaptiveLayout();
|
||||
|
||||
FlatButton *mediaTypeButton();
|
||||
|
||||
void grabStart() override {
|
||||
_sideShadow.hide();
|
||||
}
|
||||
void grabFinish() override {
|
||||
_sideShadow.setVisible(!Adaptive::OneColumn());
|
||||
}
|
||||
|
||||
public slots:
|
||||
|
||||
void onForwardSelection();
|
||||
void onDeleteSelection();
|
||||
void onClearSelection();
|
||||
void onInfoClicked();
|
||||
void onAddContact();
|
||||
void onEdit();
|
||||
void onDeleteContact();
|
||||
void onDeleteContactSure();
|
||||
void onDeleteAndExit();
|
||||
void onDeleteAndExitSure();
|
||||
void onSearch();
|
||||
|
||||
signals:
|
||||
|
||||
void clicked();
|
||||
|
||||
private:
|
||||
|
||||
MainWidget *main();
|
||||
anim::fvalue a_over;
|
||||
Animation _a_appearance;
|
||||
|
||||
PeerData *_selPeer;
|
||||
uint32 _selCount;
|
||||
bool _canDelete;
|
||||
QString _selStr;
|
||||
int32 _selStrLeft, _selStrWidth;
|
||||
|
||||
bool _animating;
|
||||
|
||||
FlatButton _clearSelection;
|
||||
FlatButton _forward, _delete;
|
||||
int32 _selectionButtonsWidth, _forwardDeleteWidth;
|
||||
|
||||
PeerAvatarButton _info;
|
||||
FlatButton _edit, _leaveGroup, _addContact, _deleteContact;
|
||||
FlatButton _mediaType;
|
||||
|
||||
IconedButton _search;
|
||||
|
||||
PlainShadow _sideShadow;
|
||||
|
||||
};
|
||||
class HistoryHider;
|
||||
class Dropdown;
|
||||
|
||||
enum StackItemType {
|
||||
HistoryStackItem,
|
||||
@ -220,7 +144,7 @@ class MainWidget : public TWidget, public RPCSender {
|
||||
|
||||
public:
|
||||
|
||||
MainWidget(Window *window);
|
||||
MainWidget(MainWindow *window);
|
||||
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
@ -230,7 +154,7 @@ public:
|
||||
bool needBackButton();
|
||||
|
||||
void paintTopBar(QPainter &p, float64 over, int32 decreaseWidth);
|
||||
TopBarWidget *topBar();
|
||||
Window::TopBarWidget *topBar();
|
||||
|
||||
PlayerWidget *player();
|
||||
int contentScrollAddToY() const;
|
||||
@ -365,7 +289,7 @@ public:
|
||||
uint64 animActiveTimeStart(const HistoryItem *msg) const;
|
||||
void stopAnimActive();
|
||||
|
||||
void sendBotCommand(PeerData *peer, const QString &cmd, MsgId replyTo);
|
||||
void sendBotCommand(PeerData *peer, UserData *bot, const QString &cmd, MsgId replyTo);
|
||||
bool insertBotCommand(const QString &cmd, bool specialGif);
|
||||
|
||||
void searchMessages(const QString &query, PeerData *inPeer);
|
||||
@ -448,6 +372,8 @@ public:
|
||||
|
||||
bool isItemVisible(HistoryItem *item);
|
||||
|
||||
void closePlayer();
|
||||
|
||||
void app_sendBotCallback(const HistoryMessageReplyMarkup::Button *button, const HistoryItem *msg, int row, int col);
|
||||
|
||||
void ui_repaintHistoryItem(const HistoryItem *item);
|
||||
@ -498,7 +424,6 @@ public slots:
|
||||
void documentPlayProgress(const SongMsgId &songId);
|
||||
void inlineResultLoadProgress(FileLoader *loader);
|
||||
void inlineResultLoadFailed(FileLoader *loader, bool started);
|
||||
void hidePlayer();
|
||||
|
||||
void dialogsCancelled();
|
||||
|
||||
@ -623,14 +548,14 @@ private:
|
||||
|
||||
int _dialogsWidth = st::dlgMinWidth;
|
||||
|
||||
DialogsWidget dialogs;
|
||||
HistoryWidget history;
|
||||
ProfileWidget* profile = nullptr;
|
||||
OverviewWidget* overview = nullptr;
|
||||
PlayerWidget _player;
|
||||
TopBarWidget _topBar;
|
||||
ChildWidget<DialogsWidget> _dialogs;
|
||||
ChildWidget<HistoryWidget> _history;
|
||||
ChildWidget<ProfileWidget> _profile = { nullptr };
|
||||
ChildWidget<OverviewWidget> _overview = { nullptr };
|
||||
ChildWidget<PlayerWidget> _player;
|
||||
ChildWidget<Window::TopBarWidget> _topBar;
|
||||
ConfirmBox *_forwardConfirm = nullptr; // for single column layout
|
||||
HistoryHider *_hider = nullptr;
|
||||
ChildWidget<HistoryHider> _hider = { nullptr };
|
||||
StackItems _stack;
|
||||
PeerData *_peerInStack = nullptr;
|
||||
MsgId _msgIdInStack = 0;
|
||||
@ -638,7 +563,7 @@ private:
|
||||
int _playerHeight = 0;
|
||||
int _contentScrollAddToY = 0;
|
||||
|
||||
Dropdown _mediaType;
|
||||
ChildWidget<Dropdown> _mediaType;
|
||||
int32 _mediaTypeMask = 0;
|
||||
|
||||
int32 updDate = 0;
|
||||
@ -711,8 +636,8 @@ private:
|
||||
void viewsIncrementDone(QVector<MTPint> ids, const MTPVector<MTPint> &result, mtpRequestId req);
|
||||
bool viewsIncrementFail(const RPCError &error, mtpRequestId req);
|
||||
|
||||
App::WallPaper *_background = nullptr;
|
||||
std_::unique_ptr<App::WallPaper> _background;
|
||||
|
||||
ApiWrap *_api;
|
||||
std_::unique_ptr<ApiWrap> _api;
|
||||
|
||||
};
|
||||
|
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include "zip.h"
|
||||
|
||||
@ -364,7 +364,7 @@ NotifyWindow::~NotifyWindow() {
|
||||
if (App::wnd()) App::wnd()->notifyShowNext(this);
|
||||
}
|
||||
|
||||
Window::Window(QWidget *parent) : PsMainWindow(parent) {
|
||||
MainWindow::MainWindow(QWidget *parent) : PsMainWindow(parent) {
|
||||
icon16 = icon256.scaledToWidth(16, Qt::SmoothTransformation);
|
||||
icon32 = icon256.scaledToWidth(32, Qt::SmoothTransformation);
|
||||
icon64 = icon256.scaledToWidth(64, Qt::SmoothTransformation);
|
||||
@ -400,7 +400,7 @@ Window::Window(QWidget *parent) : PsMainWindow(parent) {
|
||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
}
|
||||
|
||||
void Window::inactivePress(bool inactive) {
|
||||
void MainWindow::inactivePress(bool inactive) {
|
||||
_inactivePress = inactive;
|
||||
if (_inactivePress) {
|
||||
_inactiveTimer.start(200);
|
||||
@ -409,15 +409,15 @@ void Window::inactivePress(bool inactive) {
|
||||
}
|
||||
}
|
||||
|
||||
bool Window::inactivePress() const {
|
||||
bool MainWindow::inactivePress() const {
|
||||
return _inactivePress;
|
||||
}
|
||||
|
||||
void Window::onInactiveTimer() {
|
||||
void MainWindow::onInactiveTimer() {
|
||||
inactivePress(false);
|
||||
}
|
||||
|
||||
void Window::stateChanged(Qt::WindowState state) {
|
||||
void MainWindow::stateChanged(Qt::WindowState state) {
|
||||
psUserActionDone();
|
||||
|
||||
updateIsActive((state == Qt::WindowMinimized) ? Global::OfflineBlurTimeout() : Global::OnlineFocusTimeout());
|
||||
@ -429,7 +429,7 @@ void Window::stateChanged(Qt::WindowState state) {
|
||||
psSavePosition(state);
|
||||
}
|
||||
|
||||
void Window::init() {
|
||||
void MainWindow::init() {
|
||||
psInitFrameless();
|
||||
setWindowIcon(wndIcon);
|
||||
|
||||
@ -446,7 +446,7 @@ void Window::init() {
|
||||
psInitSize();
|
||||
}
|
||||
|
||||
void Window::firstShow() {
|
||||
void MainWindow::firstShow() {
|
||||
#ifdef Q_OS_WIN
|
||||
trayIconMenu = new PopupMenu();
|
||||
trayIconMenu->deleteOnHide(false);
|
||||
@ -472,11 +472,11 @@ void Window::firstShow() {
|
||||
updateTrayMenu();
|
||||
}
|
||||
|
||||
QWidget *Window::filedialogParent() {
|
||||
QWidget *MainWindow::filedialogParent() {
|
||||
return (_mediaView && _mediaView->isVisible()) ? (QWidget*)_mediaView : (QWidget*)this;
|
||||
}
|
||||
|
||||
void Window::clearWidgets() {
|
||||
void MainWindow::clearWidgets() {
|
||||
Ui::hideLayer(true);
|
||||
if (_passcode) {
|
||||
_passcode->hide();
|
||||
@ -511,7 +511,7 @@ void Window::clearWidgets() {
|
||||
updateGlobalMenu();
|
||||
}
|
||||
|
||||
QPixmap Window::grabInner() {
|
||||
QPixmap MainWindow::grabInner() {
|
||||
QPixmap result;
|
||||
if (settings) {
|
||||
result = myGrab(settings);
|
||||
@ -525,7 +525,7 @@ QPixmap Window::grabInner() {
|
||||
return result;
|
||||
}
|
||||
|
||||
void Window::clearPasscode() {
|
||||
void MainWindow::clearPasscode() {
|
||||
if (!_passcode) return;
|
||||
|
||||
QPixmap bg = grabInner();
|
||||
@ -546,7 +546,7 @@ void Window::clearPasscode() {
|
||||
updateGlobalMenu();
|
||||
}
|
||||
|
||||
void Window::setupPasscode(bool anim) {
|
||||
void MainWindow::setupPasscode(bool anim) {
|
||||
QPixmap bg = grabInner();
|
||||
|
||||
if (_passcode) {
|
||||
@ -570,7 +570,7 @@ void Window::setupPasscode(bool anim) {
|
||||
updateGlobalMenu();
|
||||
}
|
||||
|
||||
void Window::checkAutoLockIn(int msec) {
|
||||
void MainWindow::checkAutoLockIn(int msec) {
|
||||
if (_autoLockTimer.isActive()) {
|
||||
int remain = _autoLockTimer.remainingTime();
|
||||
if (remain > 0 && remain <= msec) return;
|
||||
@ -578,7 +578,7 @@ void Window::checkAutoLockIn(int msec) {
|
||||
_autoLockTimer.start(msec);
|
||||
}
|
||||
|
||||
void Window::checkAutoLock() {
|
||||
void MainWindow::checkAutoLock() {
|
||||
if (!cHasPasscode() || App::passcoded()) return;
|
||||
|
||||
App::app()->checkLocalTime();
|
||||
@ -591,7 +591,7 @@ void Window::checkAutoLock() {
|
||||
}
|
||||
}
|
||||
|
||||
void Window::setupIntro(bool anim) {
|
||||
void MainWindow::setupIntro(bool anim) {
|
||||
cSetContactsReceived(false);
|
||||
cSetDialogsReceived(false);
|
||||
if (intro && !intro->isHidden() && !main) return;
|
||||
@ -616,11 +616,11 @@ void Window::setupIntro(bool anim) {
|
||||
}
|
||||
}
|
||||
|
||||
void Window::getNotifySetting(const MTPInputNotifyPeer &peer, uint32 msWait) {
|
||||
void MainWindow::getNotifySetting(const MTPInputNotifyPeer &peer, uint32 msWait) {
|
||||
MTP::send(MTPaccount_GetNotifySettings(peer), main->rpcDone(&MainWidget::gotNotifySetting, peer), main->rpcFail(&MainWidget::failNotifySetting, peer), 0, msWait);
|
||||
}
|
||||
|
||||
void Window::serviceNotification(const QString &msg, const MTPMessageMedia &media, bool force) {
|
||||
void MainWindow::serviceNotification(const QString &msg, const MTPMessageMedia &media, bool force) {
|
||||
History *h = (main && App::userLoaded(ServiceUserId)) ? App::history(ServiceUserId) : 0;
|
||||
if (!h || (!force && h->isEmpty())) {
|
||||
_delayedServiceMsgs.push_back(DelayedServiceMsg(msg, media));
|
||||
@ -630,7 +630,7 @@ void Window::serviceNotification(const QString &msg, const MTPMessageMedia &medi
|
||||
main->serviceNotification(msg, media);
|
||||
}
|
||||
|
||||
void Window::showDelayedServiceMsgs() {
|
||||
void MainWindow::showDelayedServiceMsgs() {
|
||||
QVector<DelayedServiceMsg> toAdd = _delayedServiceMsgs;
|
||||
_delayedServiceMsgs.clear();
|
||||
for (QVector<DelayedServiceMsg>::const_iterator i = toAdd.cbegin(), e = toAdd.cend(); i != e; ++i) {
|
||||
@ -638,7 +638,7 @@ void Window::showDelayedServiceMsgs() {
|
||||
}
|
||||
}
|
||||
|
||||
void Window::sendServiceHistoryRequest() {
|
||||
void MainWindow::sendServiceHistoryRequest() {
|
||||
if (!main || !main->started() || _delayedServiceMsgs.isEmpty() || _serviceHistoryRequest) return;
|
||||
|
||||
UserData *user = App::userLoaded(ServiceUserId);
|
||||
@ -649,7 +649,7 @@ void Window::sendServiceHistoryRequest() {
|
||||
_serviceHistoryRequest = MTP::send(MTPmessages_GetHistory(user->input, MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(1), MTP_int(0), MTP_int(0)), main->rpcDone(&MainWidget::serviceHistoryDone), main->rpcFail(&MainWidget::serviceHistoryFail));
|
||||
}
|
||||
|
||||
void Window::setupMain(bool anim, const MTPUser *self) {
|
||||
void MainWindow::setupMain(bool anim, const MTPUser *self) {
|
||||
QPixmap bg = anim ? grabInner() : QPixmap();
|
||||
clearWidgets();
|
||||
main = new MainWidget(this);
|
||||
@ -673,14 +673,14 @@ void Window::setupMain(bool anim, const MTPUser *self) {
|
||||
_mediaView = new MediaView();
|
||||
}
|
||||
|
||||
void Window::updateCounter() {
|
||||
void MainWindow::updateUnreadCounter() {
|
||||
if (!Global::started() || App::quitting()) return;
|
||||
|
||||
psUpdateCounter();
|
||||
title->updateCounter();
|
||||
psUpdateCounter();
|
||||
}
|
||||
|
||||
void Window::showSettings() {
|
||||
void MainWindow::showSettings() {
|
||||
if (_passcode) return;
|
||||
|
||||
if (isHidden()) showFromTray();
|
||||
@ -705,7 +705,7 @@ void Window::showSettings() {
|
||||
fixOrder();
|
||||
}
|
||||
|
||||
void Window::hideSettings(bool fast) {
|
||||
void MainWindow::hideSettings(bool fast) {
|
||||
if (!settings || _passcode) return;
|
||||
|
||||
if (fast) {
|
||||
@ -738,14 +738,14 @@ void Window::hideSettings(bool fast) {
|
||||
fixOrder();
|
||||
}
|
||||
|
||||
void Window::mtpStateChanged(int32 dc, int32 state) {
|
||||
void MainWindow::mtpStateChanged(int32 dc, int32 state) {
|
||||
if (dc == MTP::maindc()) {
|
||||
updateTitleStatus();
|
||||
if (settings) settings->updateConnectionType();
|
||||
}
|
||||
}
|
||||
|
||||
void Window::updateTitleStatus() {
|
||||
void MainWindow::updateTitleStatus() {
|
||||
int32 state = MTP::dcstate();
|
||||
if (state == MTP::ConnectingState || state == MTP::DisconnectedState || (state < 0 && state > -600)) {
|
||||
if (main || getms() > 5000 || _connecting) {
|
||||
@ -759,48 +759,48 @@ void Window::updateTitleStatus() {
|
||||
}
|
||||
}
|
||||
|
||||
IntroWidget *Window::introWidget() {
|
||||
IntroWidget *MainWindow::introWidget() {
|
||||
return intro;
|
||||
}
|
||||
|
||||
MainWidget *Window::mainWidget() {
|
||||
MainWidget *MainWindow::mainWidget() {
|
||||
return main;
|
||||
}
|
||||
|
||||
SettingsWidget *Window::settingsWidget() {
|
||||
SettingsWidget *MainWindow::settingsWidget() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
PasscodeWidget *Window::passcodeWidget() {
|
||||
PasscodeWidget *MainWindow::passcodeWidget() {
|
||||
return _passcode;
|
||||
}
|
||||
|
||||
void Window::showPhoto(const PhotoOpenClickHandler *lnk, HistoryItem *item) {
|
||||
void MainWindow::showPhoto(const PhotoOpenClickHandler *lnk, HistoryItem *item) {
|
||||
return lnk->peer() ? showPhoto(lnk->photo(), lnk->peer()) : showPhoto(lnk->photo(), item);
|
||||
}
|
||||
|
||||
void Window::showPhoto(PhotoData *photo, HistoryItem *item) {
|
||||
void MainWindow::showPhoto(PhotoData *photo, HistoryItem *item) {
|
||||
if (_mediaView->isHidden()) Ui::hideLayer(true);
|
||||
_mediaView->showPhoto(photo, item);
|
||||
_mediaView->activateWindow();
|
||||
_mediaView->setFocus();
|
||||
}
|
||||
|
||||
void Window::showPhoto(PhotoData *photo, PeerData *peer) {
|
||||
void MainWindow::showPhoto(PhotoData *photo, PeerData *peer) {
|
||||
if (_mediaView->isHidden()) Ui::hideLayer(true);
|
||||
_mediaView->showPhoto(photo, peer);
|
||||
_mediaView->activateWindow();
|
||||
_mediaView->setFocus();
|
||||
}
|
||||
|
||||
void Window::showDocument(DocumentData *doc, HistoryItem *item) {
|
||||
void MainWindow::showDocument(DocumentData *doc, HistoryItem *item) {
|
||||
if (_mediaView->isHidden()) Ui::hideLayer(true);
|
||||
_mediaView->showDocument(doc, item);
|
||||
_mediaView->activateWindow();
|
||||
_mediaView->setFocus();
|
||||
}
|
||||
|
||||
void Window::ui_showLayer(LayeredWidget *box, ShowLayerOptions options) {
|
||||
void MainWindow::ui_showLayer(LayeredWidget *box, ShowLayerOptions options) {
|
||||
if (box) {
|
||||
bool fast = (options.testFlag(ForceFastShowLayer)) || Ui::isLayerShown();
|
||||
if (layerBg) {
|
||||
@ -837,15 +837,15 @@ void Window::ui_showLayer(LayeredWidget *box, ShowLayerOptions options) {
|
||||
}
|
||||
}
|
||||
|
||||
bool Window::ui_isLayerShown() {
|
||||
bool MainWindow::ui_isLayerShown() {
|
||||
return !!layerBg;
|
||||
}
|
||||
|
||||
bool Window::ui_isMediaViewShown() {
|
||||
bool MainWindow::ui_isMediaViewShown() {
|
||||
return _mediaView && !_mediaView->isHidden();
|
||||
}
|
||||
|
||||
void Window::ui_showMediaPreview(DocumentData *document) {
|
||||
void MainWindow::ui_showMediaPreview(DocumentData *document) {
|
||||
if (!document || ((!document->isAnimation() || !document->loaded()) && !document->sticker())) return;
|
||||
if (!_mediaPreview) {
|
||||
_mediaPreview = std_::make_unique<MediaPreviewWidget>(this);
|
||||
@ -857,7 +857,7 @@ void Window::ui_showMediaPreview(DocumentData *document) {
|
||||
_mediaPreview->showPreview(document);
|
||||
}
|
||||
|
||||
void Window::ui_showMediaPreview(PhotoData *photo) {
|
||||
void MainWindow::ui_showMediaPreview(PhotoData *photo) {
|
||||
if (!photo) return;
|
||||
if (!_mediaPreview) {
|
||||
_mediaPreview = std_::make_unique<MediaPreviewWidget>(this);
|
||||
@ -869,12 +869,12 @@ void Window::ui_showMediaPreview(PhotoData *photo) {
|
||||
_mediaPreview->showPreview(photo);
|
||||
}
|
||||
|
||||
void Window::ui_hideMediaPreview() {
|
||||
void MainWindow::ui_hideMediaPreview() {
|
||||
if (!_mediaPreview) return;
|
||||
_mediaPreview->hidePreview();
|
||||
}
|
||||
|
||||
PeerData *Window::ui_getPeerForMouseAction() {
|
||||
PeerData *MainWindow::ui_getPeerForMouseAction() {
|
||||
if (_mediaView && !_mediaView->isHidden()) {
|
||||
return _mediaView->ui_getPeerForMouseAction();
|
||||
} else if (main) {
|
||||
@ -883,7 +883,7 @@ PeerData *Window::ui_getPeerForMouseAction() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Window::showConnecting(const QString &text, const QString &reconnect) {
|
||||
void MainWindow::showConnecting(const QString &text, const QString &reconnect) {
|
||||
if (_connecting) {
|
||||
_connecting->set(text, reconnect);
|
||||
} else {
|
||||
@ -895,11 +895,11 @@ void Window::showConnecting(const QString &text, const QString &reconnect) {
|
||||
if (settings) settings->update();
|
||||
}
|
||||
|
||||
bool Window::connectingVisible() const {
|
||||
bool MainWindow::connectingVisible() const {
|
||||
return _connecting && !_connecting->isHidden();
|
||||
}
|
||||
|
||||
void Window::hideConnecting() {
|
||||
void MainWindow::hideConnecting() {
|
||||
if (_connecting) {
|
||||
_connecting->deleteLater();
|
||||
_connecting = 0;
|
||||
@ -907,18 +907,18 @@ void Window::hideConnecting() {
|
||||
if (settings) settings->update();
|
||||
}
|
||||
|
||||
bool Window::historyIsActive() const {
|
||||
bool MainWindow::historyIsActive() const {
|
||||
return isActive(false) && main && main->historyIsActive() && (!settings || !settings->isVisible());
|
||||
}
|
||||
|
||||
void Window::checkHistoryActivation() {
|
||||
void MainWindow::checkHistoryActivation() {
|
||||
if (main && MTP::authedId() && historyIsActive()) {
|
||||
main->historyWasRead();
|
||||
}
|
||||
QTimer::singleShot(1, this, SLOT(updateTrayMenu()));
|
||||
}
|
||||
|
||||
void Window::layerHidden() {
|
||||
void MainWindow::layerHidden() {
|
||||
if (layerBg) {
|
||||
layerBg->hide();
|
||||
layerBg->deleteLater();
|
||||
@ -928,7 +928,7 @@ void Window::layerHidden() {
|
||||
setInnerFocus();
|
||||
}
|
||||
|
||||
void Window::hideMediaview() {
|
||||
void MainWindow::hideMediaview() {
|
||||
if (_mediaView && !_mediaView->isHidden()) {
|
||||
_mediaView->hide();
|
||||
#if defined Q_OS_LINUX32 || defined Q_OS_LINUX64
|
||||
@ -939,13 +939,13 @@ void Window::hideMediaview() {
|
||||
}
|
||||
}
|
||||
|
||||
bool Window::contentOverlapped(const QRect &globalRect) {
|
||||
bool MainWindow::contentOverlapped(const QRect &globalRect) {
|
||||
if (main && main->contentOverlapped(globalRect)) return true;
|
||||
if (layerBg && layerBg->contentOverlapped(globalRect)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void Window::setInnerFocus() {
|
||||
void MainWindow::setInnerFocus() {
|
||||
if (layerBg && layerBg->canSetFocus()) {
|
||||
layerBg->setInnerFocus();
|
||||
} else if (_passcode) {
|
||||
@ -957,11 +957,11 @@ void Window::setInnerFocus() {
|
||||
}
|
||||
}
|
||||
|
||||
QRect Window::clientRect() const {
|
||||
QRect MainWindow::clientRect() const {
|
||||
return QRect(0, st::titleHeight, width(), height() - st::titleHeight);
|
||||
}
|
||||
|
||||
QRect Window::photoRect() const {
|
||||
QRect MainWindow::photoRect() const {
|
||||
if (settings) {
|
||||
return settings->geometry();
|
||||
} else if (main) {
|
||||
@ -973,15 +973,15 @@ QRect Window::photoRect() const {
|
||||
return QRect(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void Window::wStartDrag(QMouseEvent *e) {
|
||||
void MainWindow::wStartDrag(QMouseEvent *e) {
|
||||
dragStart = e->globalPos() - frameGeometry().topLeft();
|
||||
dragging = true;
|
||||
}
|
||||
|
||||
void Window::paintEvent(QPaintEvent *e) {
|
||||
void MainWindow::paintEvent(QPaintEvent *e) {
|
||||
}
|
||||
|
||||
HitTestType Window::hitTest(const QPoint &p) const {
|
||||
HitTestType MainWindow::hitTest(const QPoint &p) const {
|
||||
int x(p.x()), y(p.y()), w(width()), h(height());
|
||||
|
||||
const int32 raw = psResizeRowWidth();
|
||||
@ -1015,11 +1015,11 @@ HitTestType Window::hitTest(const QPoint &p) const {
|
||||
return HitTestNone;
|
||||
}
|
||||
|
||||
QRect Window::iconRect() const {
|
||||
QRect MainWindow::iconRect() const {
|
||||
return QRect(st::titleIconPos + title->geometry().topLeft(), st::titleIconImg.pxSize());
|
||||
}
|
||||
|
||||
bool Window::eventFilter(QObject *obj, QEvent *e) {
|
||||
bool MainWindow::eventFilter(QObject *obj, QEvent *e) {
|
||||
switch (e->type()) {
|
||||
case QEvent::MouseButtonPress:
|
||||
case QEvent::KeyPress:
|
||||
@ -1088,7 +1088,7 @@ bool Window::eventFilter(QObject *obj, QEvent *e) {
|
||||
return PsMainWindow::eventFilter(obj, e);
|
||||
}
|
||||
|
||||
void Window::mouseMoveEvent(QMouseEvent *e) {
|
||||
void MainWindow::mouseMoveEvent(QMouseEvent *e) {
|
||||
if (e->buttons() & Qt::LeftButton) {
|
||||
if (dragging) {
|
||||
if (windowState().testFlag(Qt::WindowMaximized)) {
|
||||
@ -1104,11 +1104,11 @@ void Window::mouseMoveEvent(QMouseEvent *e) {
|
||||
}
|
||||
}
|
||||
|
||||
void Window::mouseReleaseEvent(QMouseEvent *e) {
|
||||
void MainWindow::mouseReleaseEvent(QMouseEvent *e) {
|
||||
dragging = false;
|
||||
}
|
||||
|
||||
bool Window::minimizeToTray() {
|
||||
bool MainWindow::minimizeToTray() {
|
||||
if (App::quitting() || !psHasTrayIcon()) return false;
|
||||
|
||||
hide();
|
||||
@ -1123,7 +1123,7 @@ bool Window::minimizeToTray() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Window::updateTrayMenu(bool force) {
|
||||
void MainWindow::updateTrayMenu(bool force) {
|
||||
if (!trayIconMenu || (cPlatform() == dbipWindows && !force)) return;
|
||||
|
||||
bool active = isActive(false);
|
||||
@ -1153,25 +1153,25 @@ void Window::updateTrayMenu(bool force) {
|
||||
psTrayMenuUpdated();
|
||||
}
|
||||
|
||||
void Window::onShowAddContact() {
|
||||
void MainWindow::onShowAddContact() {
|
||||
if (isHidden()) showFromTray();
|
||||
|
||||
if (main) main->showAddContact();
|
||||
}
|
||||
|
||||
void Window::onShowNewGroup() {
|
||||
void MainWindow::onShowNewGroup() {
|
||||
if (isHidden()) showFromTray();
|
||||
|
||||
if (main) Ui::showLayer(new GroupInfoBox(CreatingGroupGroup, false), KeepOtherLayers);
|
||||
}
|
||||
|
||||
void Window::onShowNewChannel() {
|
||||
void MainWindow::onShowNewChannel() {
|
||||
if (isHidden()) showFromTray();
|
||||
|
||||
if (main) Ui::showLayer(new GroupInfoBox(CreatingGroupChannel, false), KeepOtherLayers);
|
||||
}
|
||||
|
||||
void Window::onLogout() {
|
||||
void MainWindow::onLogout() {
|
||||
if (isHidden()) showFromTray();
|
||||
|
||||
ConfirmBox *box = new ConfirmBox(lang(lng_sure_logout), lang(lng_settings_logout), st::attentionBoxButton);
|
||||
@ -1179,25 +1179,21 @@ void Window::onLogout() {
|
||||
Ui::showLayer(box);
|
||||
}
|
||||
|
||||
void Window::onLogoutSure() {
|
||||
if (MTP::authedId()) {
|
||||
App::logOut();
|
||||
} else {
|
||||
setupIntro(true);
|
||||
}
|
||||
void MainWindow::onLogoutSure() {
|
||||
App::logOut();
|
||||
}
|
||||
|
||||
void Window::updateGlobalMenu() {
|
||||
void MainWindow::updateGlobalMenu() {
|
||||
#ifdef Q_OS_MAC
|
||||
psMacUpdateMenu();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Window::quitFromTray() {
|
||||
void MainWindow::quitFromTray() {
|
||||
App::quit();
|
||||
}
|
||||
|
||||
void Window::activate() {
|
||||
void MainWindow::activate() {
|
||||
bool wasHidden = !isVisible();
|
||||
setWindowState(windowState() & ~Qt::WindowMinimized);
|
||||
setVisible(true);
|
||||
@ -1211,54 +1207,54 @@ void Window::activate() {
|
||||
}
|
||||
}
|
||||
|
||||
void Window::noIntro(IntroWidget *was) {
|
||||
void MainWindow::noIntro(IntroWidget *was) {
|
||||
if (was == intro) {
|
||||
intro = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Window::noSettings(SettingsWidget *was) {
|
||||
void MainWindow::noSettings(SettingsWidget *was) {
|
||||
if (was == settings) {
|
||||
settings = 0;
|
||||
}
|
||||
checkHistoryActivation();
|
||||
}
|
||||
|
||||
void Window::noMain(MainWidget *was) {
|
||||
void MainWindow::noMain(MainWidget *was) {
|
||||
if (was == main) {
|
||||
main = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Window::noBox(BackgroundWidget *was) {
|
||||
void MainWindow::noBox(BackgroundWidget *was) {
|
||||
if (was == layerBg) {
|
||||
layerBg = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Window::layerFinishedHide(BackgroundWidget *was) {
|
||||
void MainWindow::layerFinishedHide(BackgroundWidget *was) {
|
||||
if (was == layerBg) {
|
||||
QTimer::singleShot(0, this, SLOT(layerHidden()));
|
||||
}
|
||||
}
|
||||
|
||||
void Window::fixOrder() {
|
||||
void MainWindow::fixOrder() {
|
||||
title->raise();
|
||||
if (layerBg) layerBg->raise();
|
||||
if (_mediaPreview) _mediaPreview->raise();
|
||||
if (_connecting) _connecting->raise();
|
||||
}
|
||||
|
||||
void Window::showFromTray(QSystemTrayIcon::ActivationReason reason) {
|
||||
void MainWindow::showFromTray(QSystemTrayIcon::ActivationReason reason) {
|
||||
if (reason != QSystemTrayIcon::Context) {
|
||||
QTimer::singleShot(1, this, SLOT(updateTrayMenu()));
|
||||
QTimer::singleShot(1, this, SLOT(updateGlobalMenu()));
|
||||
activate();
|
||||
updateCounter();
|
||||
Notify::unreadCounterUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
void Window::toggleTray(QSystemTrayIcon::ActivationReason reason) {
|
||||
void MainWindow::toggleTray(QSystemTrayIcon::ActivationReason reason) {
|
||||
if ((cPlatform() == dbipMac || cPlatform() == dbipMacOld) && isActive(false)) return;
|
||||
if (reason == QSystemTrayIcon::Context) {
|
||||
updateTrayMenu(true);
|
||||
@ -1272,7 +1268,7 @@ void Window::toggleTray(QSystemTrayIcon::ActivationReason reason) {
|
||||
}
|
||||
}
|
||||
|
||||
void Window::toggleDisplayNotifyFromTray() {
|
||||
void MainWindow::toggleDisplayNotifyFromTray() {
|
||||
if (App::passcoded()) {
|
||||
if (!isActive()) showFromTray();
|
||||
Ui::showLayer(new InformBox(lang(lng_passcode_need_unblock)));
|
||||
@ -1290,7 +1286,7 @@ void Window::toggleDisplayNotifyFromTray() {
|
||||
}
|
||||
}
|
||||
|
||||
void Window::closeEvent(QCloseEvent *e) {
|
||||
void MainWindow::closeEvent(QCloseEvent *e) {
|
||||
if (MTP::authedId() && !Sandbox::isSavingSession() && Ui::hideWindowNoQuit()) {
|
||||
e->ignore();
|
||||
} else {
|
||||
@ -1298,11 +1294,11 @@ void Window::closeEvent(QCloseEvent *e) {
|
||||
}
|
||||
}
|
||||
|
||||
TitleWidget *Window::getTitle() {
|
||||
TitleWidget *MainWindow::getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
void Window::resizeEvent(QResizeEvent *e) {
|
||||
void MainWindow::resizeEvent(QResizeEvent *e) {
|
||||
if (!title) return;
|
||||
|
||||
Adaptive::Layout layout = Adaptive::OneColumnLayout;
|
||||
@ -1322,7 +1318,7 @@ void Window::resizeEvent(QResizeEvent *e) {
|
||||
emit resized(QSize(width(), height() - st::titleHeight));
|
||||
}
|
||||
|
||||
void Window::updateAdaptiveLayout() {
|
||||
void MainWindow::updateAdaptiveLayout() {
|
||||
title->updateAdaptiveLayout();
|
||||
if (main) main->updateAdaptiveLayout();
|
||||
if (settings) settings->updateAdaptiveLayout();
|
||||
@ -1330,25 +1326,25 @@ void Window::updateAdaptiveLayout() {
|
||||
if (layerBg) layerBg->updateAdaptiveLayout();
|
||||
}
|
||||
|
||||
bool Window::needBackButton() {
|
||||
bool MainWindow::needBackButton() {
|
||||
return !!settings;
|
||||
}
|
||||
|
||||
Window::TempDirState Window::tempDirState() {
|
||||
MainWindow::TempDirState MainWindow::tempDirState() {
|
||||
if (_clearManager && _clearManager->hasTask(Local::ClearManagerDownloads)) {
|
||||
return TempDirRemoving;
|
||||
}
|
||||
return QDir(cTempDir()).exists() ? TempDirExists : TempDirEmpty;
|
||||
}
|
||||
|
||||
Window::TempDirState Window::localStorageState() {
|
||||
MainWindow::TempDirState MainWindow::localStorageState() {
|
||||
if (_clearManager && _clearManager->hasTask(Local::ClearManagerStorage)) {
|
||||
return TempDirRemoving;
|
||||
}
|
||||
return (Local::hasImages() || Local::hasStickers() || Local::hasWebFiles() || Local::hasAudios()) ? TempDirExists : TempDirEmpty;
|
||||
}
|
||||
|
||||
void Window::tempDirDelete(int task) {
|
||||
void MainWindow::tempDirDelete(int task) {
|
||||
if (_clearManager) {
|
||||
if (_clearManager->addTask(task)) {
|
||||
return;
|
||||
@ -1364,7 +1360,7 @@ void Window::tempDirDelete(int task) {
|
||||
_clearManager->start();
|
||||
}
|
||||
|
||||
void Window::onClearFinished(int task, void *manager) {
|
||||
void MainWindow::onClearFinished(int task, void *manager) {
|
||||
if (manager && manager == _clearManager) {
|
||||
_clearManager->deleteLater();
|
||||
_clearManager = 0;
|
||||
@ -1372,7 +1368,7 @@ void Window::onClearFinished(int task, void *manager) {
|
||||
emit tempDirCleared(task);
|
||||
}
|
||||
|
||||
void Window::onClearFailed(int task, void *manager) {
|
||||
void MainWindow::onClearFailed(int task, void *manager) {
|
||||
if (manager && manager == _clearManager) {
|
||||
_clearManager->deleteLater();
|
||||
_clearManager = 0;
|
||||
@ -1380,7 +1376,7 @@ void Window::onClearFailed(int task, void *manager) {
|
||||
emit tempDirClearFailed(task);
|
||||
}
|
||||
|
||||
void Window::notifySchedule(History *history, HistoryItem *item) {
|
||||
void MainWindow::notifySchedule(History *history, HistoryItem *item) {
|
||||
if (App::quitting() || !history->currentNotification() || !main) return;
|
||||
|
||||
PeerData *notifyByFrom = (!history->peer->isUser() && item->mentionsMe()) ? item->from() : 0;
|
||||
@ -1451,11 +1447,11 @@ void Window::notifySchedule(History *history, HistoryItem *item) {
|
||||
}
|
||||
}
|
||||
|
||||
void Window::notifyFire() {
|
||||
void MainWindow::notifyFire() {
|
||||
notifyShowNext();
|
||||
}
|
||||
|
||||
void Window::notifyClear(History *history) {
|
||||
void MainWindow::notifyClear(History *history) {
|
||||
if (!history) {
|
||||
for (NotifyWindows::const_iterator i = notifyWindows.cbegin(), e = notifyWindows.cend(); i != e; ++i) {
|
||||
(*i)->unlinkHistory();
|
||||
@ -1480,7 +1476,7 @@ void Window::notifyClear(History *history) {
|
||||
notifyShowNext();
|
||||
}
|
||||
|
||||
void Window::notifyClearFast() {
|
||||
void MainWindow::notifyClearFast() {
|
||||
notifyWaiters.clear();
|
||||
notifySettingWaiters.clear();
|
||||
for (NotifyWindows::const_iterator i = notifyWindows.cbegin(), e = notifyWindows.cend(); i != e; ++i) {
|
||||
@ -1492,7 +1488,7 @@ void Window::notifyClearFast() {
|
||||
notifyWhenAlerts.clear();
|
||||
}
|
||||
|
||||
void Window::notifySettingGot() {
|
||||
void MainWindow::notifySettingGot() {
|
||||
int32 t = unixtime();
|
||||
for (NotifyWaiters::iterator i = notifySettingWaiters.begin(); i != notifySettingWaiters.end();) {
|
||||
History *history = i.key();
|
||||
@ -1534,7 +1530,7 @@ void Window::notifySettingGot() {
|
||||
notifyShowNext();
|
||||
}
|
||||
|
||||
void Window::notifyShowNext(NotifyWindow *remove) {
|
||||
void MainWindow::notifyShowNext(NotifyWindow *remove) {
|
||||
if (App::quitting()) return;
|
||||
|
||||
int32 count = NotifyWindowsCount;
|
||||
@ -1711,7 +1707,7 @@ void Window::notifyShowNext(NotifyWindow *remove) {
|
||||
}
|
||||
}
|
||||
|
||||
void Window::notifyItemRemoved(HistoryItem *item) {
|
||||
void MainWindow::notifyItemRemoved(HistoryItem *item) {
|
||||
if (cCustomNotifies()) {
|
||||
for (NotifyWindows::const_iterator i = notifyWindows.cbegin(), e = notifyWindows.cend(); i != e; ++i) {
|
||||
(*i)->itemRemoved(item);
|
||||
@ -1719,7 +1715,7 @@ void Window::notifyItemRemoved(HistoryItem *item) {
|
||||
}
|
||||
}
|
||||
|
||||
void Window::notifyStopHiding() {
|
||||
void MainWindow::notifyStopHiding() {
|
||||
if (cCustomNotifies()) {
|
||||
for (NotifyWindows::const_iterator i = notifyWindows.cbegin(), e = notifyWindows.cend(); i != e; ++i) {
|
||||
(*i)->stopHiding();
|
||||
@ -1727,7 +1723,7 @@ void Window::notifyStopHiding() {
|
||||
}
|
||||
}
|
||||
|
||||
void Window::notifyStartHiding() {
|
||||
void MainWindow::notifyStartHiding() {
|
||||
if (cCustomNotifies()) {
|
||||
for (NotifyWindows::const_iterator i = notifyWindows.cbegin(), e = notifyWindows.cend(); i != e; ++i) {
|
||||
(*i)->startHiding();
|
||||
@ -1735,7 +1731,7 @@ void Window::notifyStartHiding() {
|
||||
}
|
||||
}
|
||||
|
||||
void Window::notifyUpdateAllPhotos() {
|
||||
void MainWindow::notifyUpdateAllPhotos() {
|
||||
if (cCustomNotifies()) {
|
||||
for (NotifyWindows::const_iterator i = notifyWindows.cbegin(), e = notifyWindows.cend(); i != e; ++i) {
|
||||
(*i)->updatePeerPhoto();
|
||||
@ -1744,11 +1740,11 @@ void Window::notifyUpdateAllPhotos() {
|
||||
if (_mediaView && !_mediaView->isHidden()) _mediaView->updateControls();
|
||||
}
|
||||
|
||||
void Window::app_activateClickHandler(ClickHandlerPtr handler, Qt::MouseButton button) {
|
||||
void MainWindow::app_activateClickHandler(ClickHandlerPtr handler, Qt::MouseButton button) {
|
||||
handler->onClick(button);
|
||||
}
|
||||
|
||||
void Window::notifyUpdateAll() {
|
||||
void MainWindow::notifyUpdateAll() {
|
||||
if (cCustomNotifies()) {
|
||||
for (NotifyWindows::const_iterator i = notifyWindows.cbegin(), e = notifyWindows.cend(); i != e; ++i) {
|
||||
(*i)->updateNotifyDisplay();
|
||||
@ -1757,7 +1753,7 @@ void Window::notifyUpdateAll() {
|
||||
psClearNotifies();
|
||||
}
|
||||
|
||||
void Window::notifyActivateAll() {
|
||||
void MainWindow::notifyActivateAll() {
|
||||
if (cCustomNotifies()) {
|
||||
for (NotifyWindows::const_iterator i = notifyWindows.cbegin(), e = notifyWindows.cend(); i != e; ++i) {
|
||||
psActivateNotify(*i);
|
||||
@ -1765,11 +1761,11 @@ void Window::notifyActivateAll() {
|
||||
}
|
||||
}
|
||||
|
||||
QImage Window::iconLarge() const {
|
||||
QImage MainWindow::iconLarge() const {
|
||||
return iconbig256;
|
||||
}
|
||||
|
||||
void Window::placeSmallCounter(QImage &img, int size, int count, style::color bg, const QPoint &shift, style::color color) {
|
||||
void MainWindow::placeSmallCounter(QImage &img, int size, int count, style::color bg, const QPoint &shift, style::color color) {
|
||||
QPainter p(&img);
|
||||
|
||||
QString cnt = (count < 100) ? QString("%1").arg(count) : QString("..%1").arg(count % 10, 1, 10, QChar('0'));
|
||||
@ -1807,7 +1803,7 @@ void Window::placeSmallCounter(QImage &img, int size, int count, style::color bg
|
||||
|
||||
}
|
||||
|
||||
QImage Window::iconWithCounter(int size, int count, style::color bg, bool smallIcon) {
|
||||
QImage MainWindow::iconWithCounter(int size, int count, style::color bg, bool smallIcon) {
|
||||
bool layer = false;
|
||||
if (size < 0) {
|
||||
size = -size;
|
||||
@ -1874,7 +1870,7 @@ QImage Window::iconWithCounter(int size, int count, style::color bg, bool smallI
|
||||
return img;
|
||||
}
|
||||
|
||||
void Window::sendPaths() {
|
||||
void MainWindow::sendPaths() {
|
||||
if (App::passcoded()) return;
|
||||
hideMediaview();
|
||||
if (settings) {
|
||||
@ -1887,35 +1883,35 @@ void Window::sendPaths() {
|
||||
}
|
||||
}
|
||||
|
||||
void Window::mediaOverviewUpdated(PeerData *peer, MediaOverviewType type) {
|
||||
void MainWindow::mediaOverviewUpdated(PeerData *peer, MediaOverviewType type) {
|
||||
if (main) main->mediaOverviewUpdated(peer, type);
|
||||
if (!_mediaView || _mediaView->isHidden()) return;
|
||||
_mediaView->mediaOverviewUpdated(peer, type);
|
||||
}
|
||||
|
||||
void Window::documentUpdated(DocumentData *doc) {
|
||||
void MainWindow::documentUpdated(DocumentData *doc) {
|
||||
if (!_mediaView || _mediaView->isHidden()) return;
|
||||
_mediaView->documentUpdated(doc);
|
||||
}
|
||||
|
||||
void Window::changingMsgId(HistoryItem *row, MsgId newId) {
|
||||
void MainWindow::changingMsgId(HistoryItem *row, MsgId newId) {
|
||||
if (main) main->changingMsgId(row, newId);
|
||||
if (!_mediaView || _mediaView->isHidden()) return;
|
||||
_mediaView->changingMsgId(row, newId);
|
||||
}
|
||||
|
||||
bool Window::isActive(bool cached) const {
|
||||
bool MainWindow::isActive(bool cached) const {
|
||||
if (cached) return _isActive;
|
||||
return isActiveWindow() && isVisible() && !(windowState() & Qt::WindowMinimized);
|
||||
}
|
||||
|
||||
void Window::updateIsActive(int timeout) {
|
||||
void MainWindow::updateIsActive(int timeout) {
|
||||
if (timeout) return _isActiveTimer.start(timeout);
|
||||
_isActive = isActive(false);
|
||||
if (main) main->updateOnline();
|
||||
}
|
||||
|
||||
Window::~Window() {
|
||||
MainWindow::~MainWindow() {
|
||||
notifyClearFast();
|
||||
delete _clearManager;
|
||||
delete _connecting;
|
@ -123,12 +123,12 @@ typedef QList<NotifyWindow*> NotifyWindows;
|
||||
|
||||
class MediaPreviewWidget;
|
||||
|
||||
class Window : public PsMainWindow {
|
||||
class MainWindow : public PsMainWindow {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Window(QWidget *parent = 0);
|
||||
~Window();
|
||||
MainWindow(QWidget *parent = 0);
|
||||
~MainWindow();
|
||||
|
||||
void init();
|
||||
void firstShow();
|
||||
@ -228,6 +228,8 @@ public:
|
||||
bool isActive(bool cached = true) const;
|
||||
void hideMediaview();
|
||||
|
||||
void updateUnreadCounter();
|
||||
|
||||
bool contentOverlapped(const QRect &globalRect);
|
||||
bool contentOverlapped(QWidget *w, QPaintEvent *e) {
|
||||
return contentOverlapped(QRect(w->mapToGlobal(e->rect().topLeft()), e->rect().size()));
|
||||
@ -250,7 +252,6 @@ public slots:
|
||||
void stateChanged(Qt::WindowState state);
|
||||
|
||||
void checkHistoryActivation();
|
||||
void updateCounter();
|
||||
|
||||
void checkAutoLock();
|
||||
|
@ -23,7 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
|
||||
#include "mediaview.h"
|
||||
#include "mainwidget.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
#include "application.h"
|
||||
#include "ui/filedialog.h"
|
||||
|
||||
@ -1781,13 +1781,14 @@ bool MediaView::updateOverState(OverState newState) {
|
||||
void MediaView::updateOver(QPoint pos) {
|
||||
ClickHandlerPtr lnk;
|
||||
ClickHandlerHost *lnkhost = nullptr;
|
||||
bool inText;
|
||||
|
||||
if (_saveMsgStarted && _saveMsg.contains(pos)) {
|
||||
_saveMsgText.getState(lnk, inText, pos.x() - _saveMsg.x() - st::medviewSaveMsgPadding.left(), pos.y() - _saveMsg.y() - st::medviewSaveMsgPadding.top(), _saveMsg.width() - st::medviewSaveMsgPadding.left() - st::medviewSaveMsgPadding.right());
|
||||
auto textState = _saveMsgText.getState(pos.x() - _saveMsg.x() - st::medviewSaveMsgPadding.left(), pos.y() - _saveMsg.y() - st::medviewSaveMsgPadding.top(), _saveMsg.width() - st::medviewSaveMsgPadding.left() - st::medviewSaveMsgPadding.right());
|
||||
lnk = textState.link;
|
||||
lnkhost = this;
|
||||
} else if (_captionRect.contains(pos)) {
|
||||
_caption.getState(lnk, inText, pos.x() - _captionRect.x(), pos.y() - _captionRect.y(), _captionRect.width());
|
||||
auto textState = _caption.getState(pos.x() - _captionRect.x(), pos.y() - _captionRect.y(), _captionRect.width());
|
||||
lnk = textState.link;
|
||||
lnkhost = this;
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "basic_types.h"
|
||||
#include "core/basic_types.h"
|
||||
|
||||
namespace MTP {
|
||||
|
||||
|
@ -23,7 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
#include "mtproto/file_download.h"
|
||||
|
||||
#include "mainwidget.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include "application.h"
|
||||
#include "localstorage.h"
|
||||
|
1143
Telegram/SourceFiles/overview/overview_layout.cpp
Normal file
1143
Telegram/SourceFiles/overview/overview_layout.cpp
Normal file
File diff suppressed because it is too large
Load Diff
337
Telegram/SourceFiles/overview/overview_layout.h
Normal file
337
Telegram/SourceFiles/overview/overview_layout.h
Normal file
@ -0,0 +1,337 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "layout.h"
|
||||
#include "core/click_handler_types.h"
|
||||
|
||||
namespace Overview {
|
||||
namespace Layout {
|
||||
|
||||
class PaintContext : public PaintContextBase {
|
||||
public:
|
||||
PaintContext(uint64 ms, bool selecting) : PaintContextBase(ms, selecting), isAfterDate(false) {
|
||||
}
|
||||
bool isAfterDate;
|
||||
|
||||
};
|
||||
|
||||
class ItemBase;
|
||||
class AbstractItem : public LayoutItemBase {
|
||||
public:
|
||||
|
||||
virtual void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const = 0;
|
||||
|
||||
virtual ItemBase *toMediaItem() {
|
||||
return nullptr;
|
||||
}
|
||||
virtual const ItemBase *toMediaItem() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual HistoryItem *getItem() const {
|
||||
return nullptr;
|
||||
}
|
||||
virtual DocumentData *getDocument() const {
|
||||
return nullptr;
|
||||
}
|
||||
MsgId msgId() const {
|
||||
const HistoryItem *item = getItem();
|
||||
return item ? item->id : 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class ItemBase : public AbstractItem {
|
||||
public:
|
||||
ItemBase(HistoryItem *parent) : _parent(parent) {
|
||||
}
|
||||
|
||||
ItemBase *toMediaItem() override {
|
||||
return this;
|
||||
}
|
||||
const ItemBase *toMediaItem() const override {
|
||||
return this;
|
||||
}
|
||||
HistoryItem *getItem() const override {
|
||||
return _parent;
|
||||
}
|
||||
|
||||
void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override;
|
||||
void clickHandlerPressedChanged(const ClickHandlerPtr &p, bool active) override;
|
||||
|
||||
protected:
|
||||
HistoryItem *_parent;
|
||||
|
||||
};
|
||||
|
||||
class RadialProgressItem : public ItemBase {
|
||||
public:
|
||||
RadialProgressItem(HistoryItem *parent) : ItemBase(parent)
|
||||
, _radial(0)
|
||||
, a_iconOver(0, 0)
|
||||
, _a_iconOver(animation(this, &RadialProgressItem::step_iconOver)) {
|
||||
}
|
||||
RadialProgressItem(const RadialProgressItem &other) = delete;
|
||||
|
||||
void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override;
|
||||
void clickHandlerPressedChanged(const ClickHandlerPtr &p, bool active) override;
|
||||
|
||||
~RadialProgressItem();
|
||||
|
||||
protected:
|
||||
ClickHandlerPtr _openl, _savel, _cancell;
|
||||
void setLinks(ClickHandlerPtr &&openl, ClickHandlerPtr &&savel, ClickHandlerPtr &&cancell);
|
||||
void setDocumentLinks(DocumentData *document) {
|
||||
ClickHandlerPtr save;
|
||||
if (document->voice()) {
|
||||
save.reset(new DocumentOpenClickHandler(document));
|
||||
} else {
|
||||
save.reset(new DocumentSaveClickHandler(document));
|
||||
}
|
||||
setLinks(MakeShared<DocumentOpenClickHandler>(document), std_::move(save), MakeShared<DocumentCancelClickHandler>(document));
|
||||
}
|
||||
|
||||
void step_iconOver(float64 ms, bool timer);
|
||||
void step_radial(uint64 ms, bool timer);
|
||||
|
||||
void ensureRadial() const;
|
||||
void checkRadialFinished();
|
||||
|
||||
bool isRadialAnimation(uint64 ms) const {
|
||||
if (!_radial || !_radial->animating()) return false;
|
||||
|
||||
_radial->step(ms);
|
||||
return _radial && _radial->animating();
|
||||
}
|
||||
|
||||
virtual float64 dataProgress() const = 0;
|
||||
virtual bool dataFinished() const = 0;
|
||||
virtual bool dataLoaded() const = 0;
|
||||
virtual bool iconAnimated() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
mutable RadialAnimation *_radial;
|
||||
anim::fvalue a_iconOver;
|
||||
mutable Animation _a_iconOver;
|
||||
|
||||
};
|
||||
|
||||
class FileBase : public RadialProgressItem {
|
||||
public:
|
||||
FileBase(HistoryItem *parent) : RadialProgressItem(parent) {
|
||||
}
|
||||
|
||||
protected:
|
||||
// >= 0 will contain download / upload string, _statusSize = loaded bytes
|
||||
// < 0 will contain played string, _statusSize = -(seconds + 1) played
|
||||
// 0x7FFFFFF0 will contain status for not yet downloaded file
|
||||
// 0x7FFFFFF1 will contain status for already downloaded file
|
||||
// 0x7FFFFFF2 will contain status for failed to download / upload file
|
||||
mutable int32 _statusSize;
|
||||
mutable QString _statusText;
|
||||
|
||||
// duration = -1 - no duration, duration = -2 - "GIF" duration
|
||||
void setStatusSize(int32 newSize, int32 fullSize, int32 duration, qint64 realDuration) const;
|
||||
|
||||
};
|
||||
|
||||
struct Info : public BaseComponent<Info> {
|
||||
int top = 0;
|
||||
};
|
||||
|
||||
class Date : public AbstractItem {
|
||||
public:
|
||||
Date(const QDate &date, bool month);
|
||||
|
||||
void initDimensions() override;
|
||||
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const override;
|
||||
|
||||
private:
|
||||
QDate _date;
|
||||
QString _text;
|
||||
|
||||
};
|
||||
|
||||
class Photo : public ItemBase {
|
||||
public:
|
||||
Photo(PhotoData *photo, HistoryItem *parent);
|
||||
|
||||
void initDimensions() override;
|
||||
int32 resizeGetHeight(int32 width) override;
|
||||
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||
|
||||
private:
|
||||
PhotoData *_data;
|
||||
ClickHandlerPtr _link;
|
||||
|
||||
mutable QPixmap _pix;
|
||||
mutable bool _goodLoaded;
|
||||
|
||||
};
|
||||
|
||||
class Video : public FileBase {
|
||||
public:
|
||||
Video(DocumentData *video, HistoryItem *parent);
|
||||
|
||||
void initDimensions() override;
|
||||
int32 resizeGetHeight(int32 width) override;
|
||||
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||
|
||||
protected:
|
||||
float64 dataProgress() const override {
|
||||
return _data->progress();
|
||||
}
|
||||
bool dataFinished() const override {
|
||||
return !_data->loading();
|
||||
}
|
||||
bool dataLoaded() const override {
|
||||
return _data->loaded();
|
||||
}
|
||||
bool iconAnimated() const override {
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
DocumentData *_data;
|
||||
|
||||
QString _duration;
|
||||
mutable QPixmap _pix;
|
||||
mutable bool _thumbLoaded;
|
||||
|
||||
void updateStatusText() const;
|
||||
|
||||
};
|
||||
|
||||
class Voice : public FileBase {
|
||||
public:
|
||||
Voice(DocumentData *voice, HistoryItem *parent);
|
||||
|
||||
void initDimensions() override;
|
||||
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||
|
||||
protected:
|
||||
float64 dataProgress() const override {
|
||||
return _data->progress();
|
||||
}
|
||||
bool dataFinished() const override {
|
||||
return !_data->loading();
|
||||
}
|
||||
bool dataLoaded() const override {
|
||||
return _data->loaded();
|
||||
}
|
||||
bool iconAnimated() const override {
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
DocumentData *_data;
|
||||
ClickHandlerPtr _namel;
|
||||
|
||||
mutable Text _name, _details;
|
||||
mutable int32 _nameVersion;
|
||||
|
||||
void updateName() const;
|
||||
bool updateStatusText() const;
|
||||
|
||||
};
|
||||
|
||||
class Document : public FileBase {
|
||||
public:
|
||||
Document(DocumentData *document, HistoryItem *parent);
|
||||
|
||||
void initDimensions() override;
|
||||
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||
|
||||
virtual DocumentData *getDocument() const override {
|
||||
return _data;
|
||||
}
|
||||
|
||||
protected:
|
||||
float64 dataProgress() const override {
|
||||
return _data->progress();
|
||||
}
|
||||
bool dataFinished() const override {
|
||||
return !_data->loading();
|
||||
}
|
||||
bool dataLoaded() const override {
|
||||
return _data->loaded();
|
||||
}
|
||||
bool iconAnimated() const override {
|
||||
return _data->song() || !_data->loaded() || (_radial && _radial->animating());
|
||||
}
|
||||
|
||||
private:
|
||||
DocumentData *_data;
|
||||
ClickHandlerPtr _msgl, _namel;
|
||||
|
||||
mutable bool _thumbForLoaded;
|
||||
mutable QPixmap _thumb;
|
||||
|
||||
QString _name, _date, _ext;
|
||||
int32 _namew, _datew, _extw;
|
||||
int32 _thumbw, _colorIndex;
|
||||
|
||||
bool withThumb() const {
|
||||
return !_data->thumb->isNull() && _data->thumb->width() && _data->thumb->height();
|
||||
}
|
||||
bool updateStatusText() const;
|
||||
|
||||
};
|
||||
|
||||
class Link : public ItemBase {
|
||||
public:
|
||||
Link(HistoryMedia *media, HistoryItem *parent);
|
||||
|
||||
void initDimensions() override;
|
||||
int32 resizeGetHeight(int32 width) override;
|
||||
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||
|
||||
private:
|
||||
ClickHandlerPtr _photol;
|
||||
|
||||
QString _title, _letter;
|
||||
int _titlew = 0;
|
||||
WebPageData *_page = nullptr;
|
||||
int _pixw = 0;
|
||||
int _pixh = 0;
|
||||
Text _text = { int(st::msgMinWidth) };
|
||||
|
||||
struct LinkEntry {
|
||||
LinkEntry() : width(0) {
|
||||
}
|
||||
LinkEntry(const QString &url, const QString &text);
|
||||
QString text;
|
||||
int32 width;
|
||||
TextClickHandlerPtr lnk;
|
||||
};
|
||||
QVector<LinkEntry> _links;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Layout
|
||||
} // namespace Overview
|
@ -21,7 +21,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "lang.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
#include "mainwidget.h"
|
||||
#include "overviewwidget.h"
|
||||
#include "boxes/addcontactbox.h"
|
||||
@ -29,6 +29,9 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
#include "boxes/photocropbox.h"
|
||||
#include "application.h"
|
||||
#include "ui/filedialog.h"
|
||||
#include "playerwidget.h"
|
||||
#include "window/top_bar_widget.h"
|
||||
#include "overview/overview_layout.h"
|
||||
|
||||
// flick scroll taken from http://qt-project.org/doc/qt-4.8/demos-embedded-anomaly-src-flickcharm-cpp.html
|
||||
|
||||
@ -333,7 +336,7 @@ void OverviewInner::moveToNextItem(MsgId &msgId, int32 &index, MsgId upTo, int32
|
||||
}
|
||||
|
||||
index += delta;
|
||||
while (index >= 0 && index < _items.size() && !_items.at(index)->toLayoutMediaItem()) {
|
||||
while (index >= 0 && index < _items.size() && !_items.at(index)->toMediaItem()) {
|
||||
index += (delta > 0) ? 1 : -1;
|
||||
}
|
||||
if (index < 0 || index >= _items.size()) {
|
||||
@ -354,7 +357,7 @@ void OverviewInner::repaintItem(MsgId itemId, int32 itemIndex) {
|
||||
int32 row = (_photosToAdd + shownAtIndex) / _photosInRow, col = (_photosToAdd + shownAtIndex) % _photosInRow;
|
||||
update(int32(col * w), _marginTop + int32(row * vsize), qCeil(w), vsize);
|
||||
} else {
|
||||
int32 top = _items.at(itemIndex)->Get<OverviewItemInfo>()->top;
|
||||
int32 top = _items.at(itemIndex)->Get<Overview::Layout::Info>()->top;
|
||||
if (_reversed) top = _height - top;
|
||||
update(_rowsLeft, _marginTop + top, _rowWidth, _items.at(itemIndex)->height());
|
||||
}
|
||||
@ -563,8 +566,8 @@ void OverviewInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton bu
|
||||
if (_dragSelFrom && _dragSelTo) {
|
||||
applyDragSelection();
|
||||
} else if (!_selected.isEmpty() && !_dragWasInactive) {
|
||||
uint32 sel = _selected.cbegin().value();
|
||||
if (sel != FullSelection && (sel & 0xFFFF) == ((sel >> 16) & 0xFFFF)) {
|
||||
auto sel = _selected.cbegin().value();
|
||||
if (sel != FullSelection && sel.from == sel.to) {
|
||||
_selected.clear();
|
||||
App::main()->activate();
|
||||
}
|
||||
@ -698,7 +701,7 @@ QPoint OverviewInner::mapMouseToItem(QPoint p, MsgId itemId, int32 itemIndex) {
|
||||
p.setX(p.x() - int32(col * w) - st::overviewPhotoSkip);
|
||||
p.setY(p.y() - _marginTop - row * (_rowWidth + st::overviewPhotoSkip) - st::overviewPhotoSkip);
|
||||
} else {
|
||||
int32 top = _items.at(itemIndex)->Get<OverviewItemInfo>()->top;
|
||||
int32 top = _items.at(itemIndex)->Get<Overview::Layout::Info>()->top;
|
||||
if (_reversed) top = _height - top;
|
||||
p.setY(p.y() - _marginTop - top);
|
||||
}
|
||||
@ -734,7 +737,7 @@ int32 OverviewInner::itemTop(const FullMsgId &msgId) const {
|
||||
int32 itemIndex = -1;
|
||||
fixItemIndex(itemIndex, (msgId.channel == _channel) ? msgId.msg : ((_migrated && msgId.channel == _migrated->channelId()) ? -msgId.msg : 0));
|
||||
if (itemIndex >= 0) {
|
||||
int32 top = _items.at(itemIndex)->Get<OverviewItemInfo>()->top;
|
||||
int32 top = _items.at(itemIndex)->Get<Overview::Layout::Info>()->top;
|
||||
if (_reversed) top = _height - top;
|
||||
return _marginTop + top;
|
||||
}
|
||||
@ -779,15 +782,15 @@ bool OverviewInner::preloadLocal() {
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 OverviewInner::itemSelectedValue(int32 index) const {
|
||||
TextSelection OverviewInner::itemSelectedValue(int32 index) const {
|
||||
int32 selfrom = -1, selto = -1;
|
||||
if (_dragSelFromIndex >= 0 && _dragSelToIndex >= 0) {
|
||||
selfrom = _dragSelToIndex;
|
||||
selto = _dragSelFromIndex;
|
||||
}
|
||||
if (_items.at(index)->toLayoutMediaItem()) { // draw item
|
||||
if (_items.at(index)->toMediaItem()) { // draw item
|
||||
if (index >= _dragSelToIndex && index <= _dragSelFromIndex && _dragSelToIndex >= 0) {
|
||||
return (_dragSelecting && _items.at(index)->msgId() > 0) ? FullSelection : 0;
|
||||
return (_dragSelecting && _items.at(index)->msgId() > 0) ? FullSelection : TextSelection{ 0, 0 };
|
||||
} else if (!_selected.isEmpty()) {
|
||||
SelectedItems::const_iterator j = _selected.constFind(complexMsgId(_items.at(index)->getItem()));
|
||||
if (j != _selected.cend()) {
|
||||
@ -795,7 +798,7 @@ uint32 OverviewInner::itemSelectedValue(int32 index) const {
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return { 0, 0 };
|
||||
}
|
||||
|
||||
void OverviewInner::paintEvent(QPaintEvent *e) {
|
||||
@ -809,7 +812,7 @@ void OverviewInner::paintEvent(QPaintEvent *e) {
|
||||
p.setClipRect(r);
|
||||
}
|
||||
uint64 ms = getms();
|
||||
PaintContextOverview context(ms, _selMode);
|
||||
Overview::Layout::PaintContext context(ms, _selMode);
|
||||
|
||||
if (_history->overview[_type].isEmpty() && (!_migrated || !_history->overviewLoaded(_type) || _migrated->overview[_type].isEmpty())) {
|
||||
QPoint dogPos((_width - st::msgDogImg.pxWidth()) / 2, ((height() - st::msgDogImg.pxHeight()) * 4) / 9);
|
||||
@ -854,15 +857,15 @@ void OverviewInner::paintEvent(QPaintEvent *e) {
|
||||
int32 y = 0, w = _rowWidth;
|
||||
for (int32 j = 0, l = _items.size(); j < l; ++j) {
|
||||
int32 i = _reversed ? (l - j - 1) : j, nexti = _reversed ? (i - 1) : (i + 1);
|
||||
int32 nextItemTop = (j + 1 == l) ? (_reversed ? 0 : _height) : _items.at(nexti)->Get<OverviewItemInfo>()->top;
|
||||
int32 nextItemTop = (j + 1 == l) ? (_reversed ? 0 : _height) : _items.at(nexti)->Get<Overview::Layout::Info>()->top;
|
||||
if (_reversed) nextItemTop = _height - nextItemTop;
|
||||
if (_marginTop + nextItemTop > r.top()) {
|
||||
OverviewItemInfo *info = _items.at(i)->Get<OverviewItemInfo>();
|
||||
auto info = _items.at(i)->Get<Overview::Layout::Info>();
|
||||
int32 curY = info->top;
|
||||
if (_reversed) curY = _height - curY;
|
||||
if (_marginTop + curY >= r.y() + r.height()) break;
|
||||
|
||||
context.isAfterDate = (j > 0) ? !_items.at(j - 1)->toLayoutMediaItem() : false;
|
||||
context.isAfterDate = (j > 0) ? !_items.at(j - 1)->toMediaItem() : false;
|
||||
p.translate(0, curY - y);
|
||||
_items.at(i)->paint(p, r.translated(-_rowsLeft, -_marginTop - curY), itemSelectedValue(i), &context);
|
||||
y = curY;
|
||||
@ -908,7 +911,7 @@ void OverviewInner::onUpdateSelected() {
|
||||
upon = false;
|
||||
}
|
||||
if (i >= 0) {
|
||||
if (LayoutMediaItemBase *media = _items.at(i)->toLayoutMediaItem()) {
|
||||
if (auto media = _items.at(i)->toMediaItem()) {
|
||||
item = media->getItem();
|
||||
index = i;
|
||||
if (upon) {
|
||||
@ -921,23 +924,23 @@ void OverviewInner::onUpdateSelected() {
|
||||
for (int32 j = 0, l = _items.size(); j < l; ++j) {
|
||||
bool lastItem = (j + 1 == l);
|
||||
int32 i = _reversed ? (l - j - 1) : j, nexti = _reversed ? (i - 1) : (i + 1);
|
||||
int32 nextItemTop = lastItem ? (_reversed ? 0 : _height) : _items.at(nexti)->Get<OverviewItemInfo>()->top;
|
||||
int32 nextItemTop = lastItem ? (_reversed ? 0 : _height) : _items.at(nexti)->Get<Overview::Layout::Info>()->top;
|
||||
if (_reversed) nextItemTop = _height - nextItemTop;
|
||||
if (_marginTop + nextItemTop > m.y() || lastItem) {
|
||||
int32 top = _items.at(i)->Get<OverviewItemInfo>()->top;
|
||||
int32 top = _items.at(i)->Get<Overview::Layout::Info>()->top;
|
||||
if (_reversed) top = _height - top;
|
||||
if (!_items.at(i)->toLayoutMediaItem()) { // day item
|
||||
if (!_items.at(i)->toMediaItem()) { // day item
|
||||
int32 h = _items.at(i)->height();
|
||||
bool beforeItem = (_marginTop + top + h / 2) >= m.y();
|
||||
if (_reversed) beforeItem = !beforeItem;
|
||||
if (i > 0 && (beforeItem || i == _items.size() - 1)) {
|
||||
--i;
|
||||
if (!_items.at(i)->toLayoutMediaItem()) break; // wtf
|
||||
top = _items.at(i)->Get<OverviewItemInfo>()->top;
|
||||
if (!_items.at(i)->toMediaItem()) break; // wtf
|
||||
top = _items.at(i)->Get<Overview::Layout::Info>()->top;
|
||||
} else if (i < _items.size() - 1 && (!beforeItem || !i)) {
|
||||
++i;
|
||||
if (!_items.at(i)->toLayoutMediaItem()) break; // wtf
|
||||
top = _items.at(i)->Get<OverviewItemInfo>()->top;
|
||||
if (!_items.at(i)->toMediaItem()) break; // wtf
|
||||
top = _items.at(i)->Get<Overview::Layout::Info>()->top;
|
||||
} else {
|
||||
break; // wtf
|
||||
}
|
||||
@ -945,7 +948,7 @@ void OverviewInner::onUpdateSelected() {
|
||||
j = _reversed ? (l - i - 1) : i;
|
||||
}
|
||||
|
||||
if (LayoutMediaItemBase *media = _items.at(i)->toLayoutMediaItem()) {
|
||||
if (auto media = _items.at(i)->toMediaItem()) {
|
||||
item = media->getItem();
|
||||
index = i;
|
||||
media->getState(lnk, cursorState, m.x() - _rowsLeft, m.y() - _marginTop - top);
|
||||
@ -1007,7 +1010,7 @@ void OverviewInner::onUpdateSelected() {
|
||||
if (_mousedItem == _dragItem && lnk && !_selected.isEmpty() && _selected.cbegin().value() != FullSelection) {
|
||||
bool afterSymbol = false, uponSymbol = false;
|
||||
uint16 second = 0;
|
||||
_selected[_dragItem] = 0;
|
||||
_selected[_dragItem] = { 0, 0 };
|
||||
updateDragSelection(0, -1, 0, -1, false);
|
||||
} else if (canSelectMany) {
|
||||
bool selectingDown = (_reversed ? (_mousedItemIndex < _dragItemIndex) : (_mousedItemIndex > _dragItemIndex)) || (_mousedItemIndex == _dragItemIndex && ((_type == OverviewPhotos || _type == OverviewVideos) ? (_dragStartPos.x() < m.x()) : (_dragStartPos.y() < m.y())));
|
||||
@ -1325,7 +1328,7 @@ int32 OverviewInner::resizeToWidth(int32 nwidth, int32 scrollTop, int32 minHeigh
|
||||
for (int32 i = 0, l = _items.size(); i < l; ++i) {
|
||||
int32 h = _items.at(i)->resizeGetHeight(_rowWidth);
|
||||
if (resize) {
|
||||
_items.at(i)->Get<OverviewItemInfo>()->top = _height + (_reversed ? h : 0);
|
||||
_items.at(i)->Get<Overview::Layout::Info>()->top = _height + (_reversed ? h : 0);
|
||||
_height += h;
|
||||
}
|
||||
}
|
||||
@ -1632,7 +1635,7 @@ void OverviewInner::mediaOverviewUpdated() {
|
||||
allGood = false;
|
||||
}
|
||||
HistoryItem *item = App::histItemById(itemChannel(msgid), itemMsgId(msgid));
|
||||
LayoutMediaItemBase *layout = layoutPrepare(item);
|
||||
auto layout = layoutPrepare(item);
|
||||
if (!layout) continue;
|
||||
|
||||
setLayoutItem(index, layout, 0);
|
||||
@ -1658,17 +1661,17 @@ void OverviewInner::mediaOverviewUpdated() {
|
||||
if (allGood) {
|
||||
if (_items.size() > index && complexMsgId(_items.at(index)->getItem()) == msgid) {
|
||||
if (withDates) prevDate = _items.at(index)->getItem()->date.date();
|
||||
top = _items.at(index)->Get<OverviewItemInfo>()->top;
|
||||
top = _items.at(index)->Get<Overview::Layout::Info>()->top;
|
||||
if (!_reversed) {
|
||||
top += _items.at(index)->height();
|
||||
}
|
||||
++index;
|
||||
continue;
|
||||
}
|
||||
if (_items.size() > index + 1 && !_items.at(index)->toLayoutMediaItem() && complexMsgId(_items.at(index + 1)->getItem()) == msgid) { // day item
|
||||
if (_items.size() > index + 1 && !_items.at(index)->toMediaItem() && complexMsgId(_items.at(index + 1)->getItem()) == msgid) { // day item
|
||||
++index;
|
||||
if (withDates) prevDate = _items.at(index)->getItem()->date.date();
|
||||
top = _items.at(index)->Get<OverviewItemInfo>()->top;
|
||||
top = _items.at(index)->Get<Overview::Layout::Info>()->top;
|
||||
if (!_reversed) {
|
||||
top += _items.at(index)->height();
|
||||
}
|
||||
@ -1678,7 +1681,7 @@ void OverviewInner::mediaOverviewUpdated() {
|
||||
allGood = false;
|
||||
}
|
||||
HistoryItem *item = App::histItemById(itemChannel(msgid), itemMsgId(msgid));
|
||||
LayoutMediaItemBase *layout = layoutPrepare(item);
|
||||
auto layout = layoutPrepare(item);
|
||||
if (!layout) continue;
|
||||
|
||||
if (withDates) {
|
||||
@ -1726,7 +1729,7 @@ void OverviewInner::changingMsgId(HistoryItem *row, MsgId newId) {
|
||||
if (_selectedMsgId == oldId) _selectedMsgId = newId;
|
||||
for (SelectedItems::iterator i = _selected.begin(), e = _selected.end(); i != e; ++i) {
|
||||
if (i.key() == oldId) {
|
||||
uint32 sel = i.value();
|
||||
auto sel = i.value();
|
||||
_selected.erase(i);
|
||||
_selected.insert(newId, sel);
|
||||
break;
|
||||
@ -1795,7 +1798,7 @@ void OverviewInner::repaintItem(const HistoryItem *msg) {
|
||||
if (history == _migrated) msgid = -msgid;
|
||||
for (int32 i = 0, l = _items.size(); i != l; ++i) {
|
||||
if (complexMsgId(_items.at(i)->getItem()) == msgid) {
|
||||
int32 top = _items.at(i)->Get<OverviewItemInfo>()->top;
|
||||
int32 top = _items.at(i)->Get<Overview::Layout::Info>()->top;
|
||||
if (_reversed) top = _height - top;
|
||||
update(_rowsLeft, _marginTop + top, _rowWidth, _items.at(i)->height());
|
||||
break;
|
||||
@ -1840,7 +1843,7 @@ void OverviewInner::recountMargins() {
|
||||
}
|
||||
}
|
||||
|
||||
LayoutMediaItemBase *OverviewInner::layoutPrepare(HistoryItem *item) {
|
||||
Overview::Layout::ItemBase *OverviewInner::layoutPrepare(HistoryItem *item) {
|
||||
if (!item) return nullptr;
|
||||
|
||||
LayoutItems::const_iterator i = _layoutItems.cend();
|
||||
@ -1848,59 +1851,59 @@ LayoutMediaItemBase *OverviewInner::layoutPrepare(HistoryItem *item) {
|
||||
if (_type == OverviewPhotos) {
|
||||
if (media && media->type() == MediaTypePhoto) {
|
||||
if ((i = _layoutItems.constFind(item)) == _layoutItems.cend()) {
|
||||
i = _layoutItems.insert(item, new LayoutOverviewPhoto(static_cast<HistoryPhoto*>(media)->photo(), item));
|
||||
i = _layoutItems.insert(item, new Overview::Layout::Photo(static_cast<HistoryPhoto*>(media)->photo(), item));
|
||||
i.value()->initDimensions();
|
||||
}
|
||||
}
|
||||
} else if (_type == OverviewVideos) {
|
||||
if (media && media->type() == MediaTypeVideo) {
|
||||
if ((i = _layoutItems.constFind(item)) == _layoutItems.cend()) {
|
||||
i = _layoutItems.insert(item, new LayoutOverviewVideo(media->getDocument(), item));
|
||||
i = _layoutItems.insert(item, new Overview::Layout::Video(media->getDocument(), item));
|
||||
i.value()->initDimensions();
|
||||
}
|
||||
}
|
||||
} else if (_type == OverviewVoiceFiles) {
|
||||
if (media && (media->type() == MediaTypeVoiceFile)) {
|
||||
if ((i = _layoutItems.constFind(item)) == _layoutItems.cend()) {
|
||||
i = _layoutItems.insert(item, new LayoutOverviewVoice(media->getDocument(), item));
|
||||
i = _layoutItems.insert(item, new Overview::Layout::Voice(media->getDocument(), item));
|
||||
i.value()->initDimensions();
|
||||
}
|
||||
}
|
||||
} else if (_type == OverviewFiles || _type == OverviewMusicFiles) {
|
||||
if (media && (media->type() == MediaTypeFile || media->type() == MediaTypeMusicFile || media->type() == MediaTypeGif)) {
|
||||
if ((i = _layoutItems.constFind(item)) == _layoutItems.cend()) {
|
||||
i = _layoutItems.insert(item, new LayoutOverviewDocument(media->getDocument(), item));
|
||||
i = _layoutItems.insert(item, new Overview::Layout::Document(media->getDocument(), item));
|
||||
i.value()->initDimensions();
|
||||
}
|
||||
}
|
||||
} else if (_type == OverviewLinks) {
|
||||
if ((i = _layoutItems.constFind(item)) == _layoutItems.cend()) {
|
||||
i = _layoutItems.insert(item, new LayoutOverviewLink(media, item));
|
||||
i = _layoutItems.insert(item, new Overview::Layout::Link(media, item));
|
||||
i.value()->initDimensions();
|
||||
}
|
||||
}
|
||||
return (i == _layoutItems.cend()) ? nullptr : i.value();
|
||||
}
|
||||
|
||||
LayoutOverviewItemBase *OverviewInner::layoutPrepare(const QDate &date, bool month) {
|
||||
Overview::Layout::AbstractItem *OverviewInner::layoutPrepare(const QDate &date, bool month) {
|
||||
int32 key = date.year() * 100 + date.month();
|
||||
if (!month) key = key * 100 + date.day();
|
||||
LayoutDates::const_iterator i = _layoutDates.constFind(key);
|
||||
if (i == _layoutDates.cend()) {
|
||||
i = _layoutDates.insert(key, new LayoutOverviewDate(date, month));
|
||||
i = _layoutDates.insert(key, new Overview::Layout::Date(date, month));
|
||||
i.value()->initDimensions();
|
||||
}
|
||||
return i.value();
|
||||
}
|
||||
|
||||
int32 OverviewInner::setLayoutItem(int32 index, LayoutOverviewItemBase *item, int32 top) {
|
||||
int32 OverviewInner::setLayoutItem(int32 index, Overview::Layout::AbstractItem *item, int32 top) {
|
||||
if (_items.size() > index) {
|
||||
_items[index] = item;
|
||||
} else {
|
||||
_items.push_back(item);
|
||||
}
|
||||
int32 h = item->resizeGetHeight(_rowWidth);
|
||||
if (OverviewItemInfo *info = item->Get<OverviewItemInfo>()) {
|
||||
if (auto info = item->Get<Overview::Layout::Info>()) {
|
||||
info->top = top + (_reversed ? h : 0);
|
||||
}
|
||||
return h;
|
||||
|
@ -20,6 +20,16 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
namespace Overview {
|
||||
namespace Layout {
|
||||
|
||||
class AbstractItem;
|
||||
class ItemBase;
|
||||
class Date;
|
||||
|
||||
} // namespace Layout
|
||||
} // namespace Overview
|
||||
|
||||
class OverviewWidget;
|
||||
class OverviewInner : public QWidget, public AbstractTooltipShower, public RPCSender {
|
||||
Q_OBJECT
|
||||
@ -148,19 +158,19 @@ private:
|
||||
ChannelId _channel;
|
||||
|
||||
bool _selMode;
|
||||
uint32 itemSelectedValue(int32 index) const;
|
||||
TextSelection itemSelectedValue(int32 index) const;
|
||||
|
||||
int32 _rowsLeft, _rowWidth;
|
||||
|
||||
typedef QVector<LayoutOverviewItemBase*> Items;
|
||||
typedef QVector<Overview::Layout::AbstractItem*> Items;
|
||||
Items _items;
|
||||
typedef QMap<HistoryItem*, LayoutMediaItemBase*> LayoutItems;
|
||||
typedef QMap<HistoryItem*, Overview::Layout::ItemBase*> LayoutItems;
|
||||
LayoutItems _layoutItems;
|
||||
typedef QMap<int32, LayoutOverviewDate*> LayoutDates;
|
||||
typedef QMap<int32, Overview::Layout::Date*> LayoutDates;
|
||||
LayoutDates _layoutDates;
|
||||
LayoutMediaItemBase *layoutPrepare(HistoryItem *item);
|
||||
LayoutOverviewItemBase *layoutPrepare(const QDate &date, bool month);
|
||||
int32 setLayoutItem(int32 index, LayoutOverviewItemBase *item, int32 top);
|
||||
Overview::Layout::ItemBase *layoutPrepare(HistoryItem *item);
|
||||
Overview::Layout::AbstractItem *layoutPrepare(const QDate &date, bool month);
|
||||
int32 setLayoutItem(int32 index, Overview::Layout::AbstractItem *item, int32 top);
|
||||
|
||||
FlatInput _search;
|
||||
IconedButton _cancelSearch;
|
||||
@ -199,7 +209,7 @@ private:
|
||||
// selection support, like in HistoryWidget
|
||||
Qt::CursorShape _cursor;
|
||||
HistoryCursorState _cursorState;
|
||||
typedef QMap<MsgId, uint32> SelectedItems;
|
||||
using SelectedItems = QMap<MsgId, TextSelection>;
|
||||
SelectedItems _selected;
|
||||
enum DragAction {
|
||||
NoDrag = 0x00,
|
||||
|
@ -25,9 +25,9 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
#include "localstorage.h"
|
||||
|
||||
#include "passcodewidget.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
#include "application.h"
|
||||
#include "ui/text.h"
|
||||
#include "ui/text/text.h"
|
||||
|
||||
PasscodeWidget::PasscodeWidget(QWidget *parent) : TWidget(parent)
|
||||
, _a_show(animation(this, &PasscodeWidget::step_show))
|
||||
|
@ -19,41 +19,21 @@ Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "playerwidget.h"
|
||||
|
||||
#include "shortcuts.h"
|
||||
#include "ui/style.h"
|
||||
#include "lang.h"
|
||||
|
||||
#include "boxes/addcontactbox.h"
|
||||
#include "application.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
#include "playerwidget.h"
|
||||
#include "mainwidget.h"
|
||||
|
||||
#include "localstorage.h"
|
||||
|
||||
#include "audio.h"
|
||||
|
||||
PlayerWidget::PlayerWidget(QWidget *parent) : TWidget(parent)
|
||||
, _prevAvailable(false)
|
||||
, _nextAvailable(false)
|
||||
, _fullAvailable(false)
|
||||
, _over(OverNone)
|
||||
, _down(OverNone)
|
||||
, _downCoord(0)
|
||||
, _downFrequency(AudioVoiceMsgFrequency)
|
||||
, _downProgress(0.)
|
||||
, _a_state(animation(this, &PlayerWidget::step_state))
|
||||
, _msgmigrated(false)
|
||||
, _index(-1)
|
||||
, _migrated(0)
|
||||
, _history(0)
|
||||
, _timeWidth(0)
|
||||
, _repeat(false)
|
||||
, _showPause(false)
|
||||
, _position(0)
|
||||
, _duration(0)
|
||||
, _loaded(0)
|
||||
, a_progress(0., 0.)
|
||||
, a_loadProgress(0., 0.)
|
||||
, _a_progress(animation(this, &PlayerWidget::step_progress))
|
||||
, _sideShadow(this, st::shadowColor) {
|
||||
resize(st::wndMinWidth, st::playerHeight);
|
||||
@ -372,6 +352,29 @@ bool PlayerWidget::seekingSong(const SongMsgId &song) const {
|
||||
return (_down == OverPlayback) && (song == _song);
|
||||
}
|
||||
|
||||
void PlayerWidget::openPlayer() {
|
||||
_playerOpened = true;
|
||||
Shortcuts::enableMediaShortcuts();
|
||||
}
|
||||
|
||||
bool PlayerWidget::isOpened() const {
|
||||
return _playerOpened;
|
||||
}
|
||||
|
||||
void PlayerWidget::closePlayer() {
|
||||
_playerOpened = false;
|
||||
Shortcuts::disableMediaShortcuts();
|
||||
}
|
||||
|
||||
void PlayerWidget::showPlayer() {
|
||||
TWidget::show();
|
||||
}
|
||||
|
||||
void PlayerWidget::hidePlayer() {
|
||||
clearSelection();
|
||||
TWidget::hide();
|
||||
}
|
||||
|
||||
void PlayerWidget::step_state(uint64 ms, bool timer) {
|
||||
for (StateAnimations::iterator i = _stateAnimations.begin(); i != _stateAnimations.cend();) {
|
||||
int32 over = qAbs(i.key());
|
||||
@ -463,7 +466,7 @@ void PlayerWidget::mouseReleaseEvent(QMouseEvent *e) {
|
||||
}
|
||||
update();
|
||||
} else if (_down == OverClose && _over == OverClose) {
|
||||
stopPressed();
|
||||
closePressed();
|
||||
}
|
||||
_down = OverNone;
|
||||
}
|
||||
@ -545,7 +548,11 @@ void PlayerWidget::stopPressed() {
|
||||
if (!_song || isHidden()) return;
|
||||
|
||||
audioPlayer()->stop(OverviewFiles);
|
||||
if (App::main()) App::main()->hidePlayer();
|
||||
}
|
||||
|
||||
void PlayerWidget::closePressed() {
|
||||
stopPressed();
|
||||
if (App::main()) App::main()->closePlayer();
|
||||
}
|
||||
|
||||
void PlayerWidget::resizeEvent(QResizeEvent *e) {
|
||||
|
@ -42,6 +42,7 @@ public:
|
||||
void prevPressed();
|
||||
void nextPressed();
|
||||
void stopPressed();
|
||||
void closePressed();
|
||||
|
||||
void step_progress(float64 ms, bool timer);
|
||||
void step_state(uint64 ms, bool timer);
|
||||
@ -55,12 +56,23 @@ public:
|
||||
|
||||
bool seekingSong(const SongMsgId &song) const;
|
||||
|
||||
void openPlayer();
|
||||
bool isOpened() const;
|
||||
void closePlayer();
|
||||
|
||||
void showPlayer();
|
||||
void hidePlayer();
|
||||
|
||||
signals:
|
||||
|
||||
void playerSongChanged(const FullMsgId &msgId);
|
||||
|
||||
private:
|
||||
|
||||
// Use startPlayer()/stopPlayer() or showPlayer()/hidePlayer() instead.
|
||||
void show();
|
||||
void hide();
|
||||
|
||||
enum OverState {
|
||||
OverNone = 0,
|
||||
OverPrev,
|
||||
@ -87,12 +99,17 @@ private:
|
||||
QPoint _lastMousePos;
|
||||
void updateSelected();
|
||||
|
||||
bool _prevAvailable, _nextAvailable, _fullAvailable;
|
||||
OverState _over, _down;
|
||||
int32 _downCoord;
|
||||
bool _playerOpened = false;
|
||||
|
||||
bool _prevAvailable = false;
|
||||
bool _nextAvailable = false;
|
||||
bool _fullAvailable = false;
|
||||
OverState _over = OverNone;
|
||||
OverState _down = OverNone;
|
||||
int32 _downCoord = 0;
|
||||
int64 _downDuration;
|
||||
int32 _downFrequency;
|
||||
float64 _downProgress;
|
||||
int32 _downFrequency = AudioVoiceMsgFrequency;
|
||||
float64 _downProgress = 0.;
|
||||
|
||||
float64 _stateHovers[OverStateCount];
|
||||
typedef QMap<int32, uint64> StateAnimations;
|
||||
@ -100,20 +117,23 @@ private:
|
||||
Animation _a_state;
|
||||
|
||||
SongMsgId _song;
|
||||
bool _msgmigrated;
|
||||
int32 _index;
|
||||
History *_migrated, *_history;
|
||||
bool _msgmigrated = false;
|
||||
int32 _index = -1;
|
||||
History *_migrated = nullptr;
|
||||
History *_history = nullptr;
|
||||
QRect _playRect, _prevRect, _nextRect, _playbackRect;
|
||||
QRect _closeRect, _volumeRect, _fullRect, _repeatRect, _infoRect;
|
||||
int32 _timeWidth;
|
||||
bool _repeat;
|
||||
int32 _timeWidth = 0;
|
||||
bool _repeat = false;
|
||||
QString _time;
|
||||
Text _name;
|
||||
bool _showPause;
|
||||
int64 _position, _duration;
|
||||
int32 _loaded;
|
||||
bool _showPause = false;
|
||||
int64 _position = 0;
|
||||
int64 _duration = 0;
|
||||
int32 _loaded = 0;
|
||||
|
||||
anim::fvalue a_progress, a_loadProgress;
|
||||
anim::fvalue a_progress = { 0., 0. };
|
||||
anim::fvalue a_loadProgress = { 0., 0. };
|
||||
Animation _a_progress;
|
||||
|
||||
PlainShadow _sideShadow;
|
||||
|
@ -21,7 +21,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "lang.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
#include "mainwidget.h"
|
||||
#include "profilewidget.h"
|
||||
#include "boxes/addcontactbox.h"
|
||||
@ -30,6 +30,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
#include "application.h"
|
||||
#include "boxes/contactsbox.h"
|
||||
#include "ui/filedialog.h"
|
||||
#include "apiwrap.h"
|
||||
#include "window/top_bar_widget.h"
|
||||
|
||||
ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, PeerData *peer) : TWidget(0)
|
||||
, _profile(profile)
|
||||
@ -573,7 +575,7 @@ void ProfileInner::onBotSettings() {
|
||||
QString cmd = _peerUser->botInfo->commands.at(i).command;
|
||||
if (!cmd.compare(qsl("settings"), Qt::CaseInsensitive)) {
|
||||
Ui::showPeerHistory(_peer, ShowAtTheEndMsgId);
|
||||
App::sendBotCommand(_peerUser, '/' + cmd);
|
||||
App::sendBotCommand(_peerUser, _peerUser, '/' + cmd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -587,7 +589,7 @@ void ProfileInner::onBotHelp() {
|
||||
QString cmd = _peerUser->botInfo->commands.at(i).command;
|
||||
if (!cmd.compare(qsl("help"), Qt::CaseInsensitive)) {
|
||||
Ui::showPeerHistory(_peer, ShowAtTheEndMsgId);
|
||||
App::sendBotCommand(_peerUser, '/' + cmd);
|
||||
App::sendBotCommand(_peerUser, _peerUser, '/' + cmd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1118,9 +1120,9 @@ void ProfileInner::updateSelected() {
|
||||
|
||||
ClickHandlerPtr lnk;
|
||||
ClickHandlerHost *lnkhost = nullptr;
|
||||
bool inText = false;
|
||||
if (!_about.isEmpty() && lp.y() >= _aboutTop && lp.y() < _aboutTop + _aboutHeight && lp.x() >= _left && lp.x() < _left + _width) {
|
||||
_about.getState(lnk, inText, lp.x() - _left, lp.y() - _aboutTop, _width);
|
||||
auto textState = _about.getState(lp.x() - _left, lp.y() - _aboutTop, _width);
|
||||
lnk = textState.link;
|
||||
lnkhost = this;
|
||||
}
|
||||
ClickHandler::setActive(lnk, lnkhost);
|
||||
|
@ -488,7 +488,7 @@ namespace {
|
||||
}
|
||||
|
||||
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) {
|
||||
Window *wnd = App::wnd();
|
||||
auto wnd = App::wnd();
|
||||
if (!wnd) return false;
|
||||
|
||||
return false;
|
||||
|
@ -40,7 +40,7 @@ namespace {
|
||||
}
|
||||
|
||||
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) {
|
||||
Window *wnd = AppClass::wnd();
|
||||
auto wnd = AppClass::wnd();
|
||||
if (!wnd) return false;
|
||||
|
||||
return wnd->psFilterNativeEvent(message);
|
||||
@ -57,9 +57,7 @@ void MacPrivate::activeSpaceChanged() {
|
||||
}
|
||||
|
||||
void MacPrivate::darkModeChanged() {
|
||||
if (App::wnd()) {
|
||||
App::wnd()->updateCounter();
|
||||
}
|
||||
Notify::unreadCounterUpdated();
|
||||
}
|
||||
|
||||
void MacPrivate::notifyClicked(unsigned long long peer, int msgid) {
|
||||
|
@ -18,9 +18,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
#include "stdafx.h"
|
||||
#include "pspecific_mac_p.h"
|
||||
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
#include "mainwidget.h"
|
||||
#include "application.h"
|
||||
#include "playerwidget.h"
|
||||
|
||||
#include "lang.h"
|
||||
|
||||
|
@ -802,7 +802,7 @@ namespace {
|
||||
}
|
||||
|
||||
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) {
|
||||
Window *wnd = App::wnd();
|
||||
auto wnd = App::wnd();
|
||||
if (!wnd) return false;
|
||||
|
||||
MSG *msg = (MSG*)message;
|
||||
|
@ -802,7 +802,7 @@ namespace {
|
||||
}
|
||||
|
||||
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) {
|
||||
Window *wnd = App::wnd();
|
||||
auto wnd = App::wnd();
|
||||
if (!wnd) return false;
|
||||
|
||||
MSG *msg = (MSG*)message;
|
||||
|
@ -41,9 +41,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
#include "boxes/stickersetbox.h"
|
||||
#include "langloaderplain.h"
|
||||
#include "ui/filedialog.h"
|
||||
|
||||
#include "apiwrap.h"
|
||||
#include "autoupdater.h"
|
||||
|
||||
#include "localstorage.h"
|
||||
|
||||
Slider::Slider(QWidget *parent, const style::slider &st, int32 count, int32 sel) : QWidget(parent),
|
||||
@ -291,9 +290,9 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : TWidget(parent)
|
||||
connect(&_downloadPathEdit, SIGNAL(clicked()), this, SLOT(onDownloadPathEdit()));
|
||||
connect(&_downloadPathClear, SIGNAL(clicked()), this, SLOT(onDownloadPathClear()));
|
||||
switch (App::wnd()->tempDirState()) {
|
||||
case Window::TempDirEmpty: _tempDirClearState = TempDirEmpty; break;
|
||||
case Window::TempDirExists: _tempDirClearState = TempDirExists; break;
|
||||
case Window::TempDirRemoving: _tempDirClearState = TempDirClearing; break;
|
||||
case MainWindow::TempDirEmpty: _tempDirClearState = TempDirEmpty; break;
|
||||
case MainWindow::TempDirExists: _tempDirClearState = TempDirExists; break;
|
||||
case MainWindow::TempDirRemoving: _tempDirClearState = TempDirClearing; break;
|
||||
}
|
||||
connect(App::wnd(), SIGNAL(tempDirCleared(int)), this, SLOT(onTempDirCleared(int)));
|
||||
connect(App::wnd(), SIGNAL(tempDirClearFailed(int)), this, SLOT(onTempDirClearFailed(int)));
|
||||
@ -302,9 +301,9 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : TWidget(parent)
|
||||
// local storage
|
||||
connect(&_localStorageClear, SIGNAL(clicked()), this, SLOT(onLocalStorageClear()));
|
||||
switch (App::wnd()->localStorageState()) {
|
||||
case Window::TempDirEmpty: _storageClearState = TempDirEmpty; break;
|
||||
case Window::TempDirExists: _storageClearState = TempDirExists; break;
|
||||
case Window::TempDirRemoving: _storageClearState = TempDirClearing; break;
|
||||
case MainWindow::TempDirEmpty: _storageClearState = TempDirEmpty; break;
|
||||
case MainWindow::TempDirExists: _storageClearState = TempDirExists; break;
|
||||
case MainWindow::TempDirRemoving: _storageClearState = TempDirClearing; break;
|
||||
}
|
||||
|
||||
// chat background
|
||||
@ -1516,7 +1515,7 @@ void SettingsInner::onSoundNotify() {
|
||||
|
||||
void SettingsInner::onIncludeMuted() {
|
||||
cSetIncludeMuted(_includeMuted.checked());
|
||||
if (App::wnd()) App::wnd()->updateCounter();
|
||||
Notify::unreadCounterUpdated();
|
||||
Local::writeUserSettings();
|
||||
}
|
||||
|
||||
@ -1836,7 +1835,7 @@ void SettingsInner::onPhotoUpdateDone(PeerId peer) {
|
||||
update();
|
||||
}
|
||||
|
||||
SettingsWidget::SettingsWidget(Window *parent) : TWidget(parent)
|
||||
SettingsWidget::SettingsWidget(MainWindow *parent) : TWidget(parent)
|
||||
, _a_show(animation(this, &SettingsWidget::step_show))
|
||||
, _scroll(this, st::setScroll)
|
||||
, _inner(this)
|
||||
|
@ -26,7 +26,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
|
||||
#include <QtWidgets/QWidget>
|
||||
|
||||
class Window;
|
||||
class MainWindow;
|
||||
class Settings;
|
||||
|
||||
class Slider : public QWidget {
|
||||
@ -313,7 +313,7 @@ class SettingsWidget : public TWidget {
|
||||
|
||||
public:
|
||||
|
||||
SettingsWidget(Window *parent);
|
||||
SettingsWidget(MainWindow *parent);
|
||||
|
||||
void paintEvent(QPaintEvent *e);
|
||||
void resizeEvent(QResizeEvent *e);
|
||||
|
@ -19,421 +19,458 @@ Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "shortcuts.h"
|
||||
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
#include "passcodewidget.h"
|
||||
#include "mainwidget.h"
|
||||
#include "playerwidget.h"
|
||||
|
||||
namespace ShortcutCommands {
|
||||
typedef void(*Handler)();
|
||||
|
||||
void lock_telegram() {
|
||||
if (Window *w = App::wnd()) {
|
||||
if (App::passcoded()) {
|
||||
w->passcodeWidget()->onSubmit();
|
||||
} else if (cHasPasscode()) {
|
||||
w->setupPasscode(true);
|
||||
}
|
||||
typedef void(*Handler)();
|
||||
|
||||
void lock_telegram() {
|
||||
if (auto w = App::wnd()) {
|
||||
if (App::passcoded()) {
|
||||
w->passcodeWidget()->onSubmit();
|
||||
} else if (cHasPasscode()) {
|
||||
w->setupPasscode(true);
|
||||
}
|
||||
}
|
||||
|
||||
void minimize_telegram() {
|
||||
if (Window *w = App::wnd()) {
|
||||
if (cWorkMode() == dbiwmTrayOnly) {
|
||||
w->minimizeToTray();
|
||||
} else {
|
||||
w->setWindowState(Qt::WindowMinimized);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void close_telegram() {
|
||||
if (!Ui::hideWindowNoQuit()) {
|
||||
if (Window *w = App::wnd()) {
|
||||
App::wnd()->close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void quit_telegram() {
|
||||
App::quit();
|
||||
}
|
||||
|
||||
//void start_stop_recording() {
|
||||
|
||||
//}
|
||||
|
||||
//void cancel_recording() {
|
||||
|
||||
//}
|
||||
|
||||
void media_play() {
|
||||
if (MainWidget *m = App::main()) {
|
||||
m->player()->playPressed();
|
||||
}
|
||||
}
|
||||
|
||||
void media_pause() {
|
||||
if (MainWidget *m = App::main()) {
|
||||
m->player()->pausePressed();
|
||||
}
|
||||
}
|
||||
|
||||
void media_playpause() {
|
||||
if (MainWidget *m = App::main()) {
|
||||
m->player()->playPausePressed();
|
||||
}
|
||||
}
|
||||
|
||||
void media_stop() {
|
||||
if (MainWidget *m = App::main()) {
|
||||
m->player()->stopPressed();
|
||||
}
|
||||
}
|
||||
|
||||
void media_previous() {
|
||||
if (MainWidget *m = App::main()) {
|
||||
m->player()->prevPressed();
|
||||
}
|
||||
}
|
||||
|
||||
void media_next() {
|
||||
if (MainWidget *m = App::main()) {
|
||||
m->player()->nextPressed();
|
||||
}
|
||||
}
|
||||
|
||||
void search() {
|
||||
if (MainWidget *m = App::main()) {
|
||||
m->cmd_search();
|
||||
}
|
||||
}
|
||||
|
||||
void previous_chat() {
|
||||
if (MainWidget *m = App::main()) {
|
||||
m->cmd_previous_chat();
|
||||
}
|
||||
}
|
||||
|
||||
void next_chat() {
|
||||
if (MainWidget *m = App::main()) {
|
||||
m->cmd_next_chat();
|
||||
}
|
||||
}
|
||||
|
||||
// other commands here
|
||||
|
||||
}
|
||||
|
||||
void minimize_telegram() {
|
||||
if (auto w = App::wnd()) {
|
||||
if (cWorkMode() == dbiwmTrayOnly) {
|
||||
w->minimizeToTray();
|
||||
} else {
|
||||
w->setWindowState(Qt::WindowMinimized);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void close_telegram() {
|
||||
if (!Ui::hideWindowNoQuit()) {
|
||||
if (auto w = App::wnd()) {
|
||||
w->close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void quit_telegram() {
|
||||
App::quit();
|
||||
}
|
||||
|
||||
//void start_stop_recording() {
|
||||
|
||||
//}
|
||||
|
||||
//void cancel_recording() {
|
||||
|
||||
//}
|
||||
|
||||
void media_play() {
|
||||
if (MainWidget *m = App::main()) {
|
||||
m->player()->playPressed();
|
||||
}
|
||||
}
|
||||
|
||||
void media_pause() {
|
||||
if (MainWidget *m = App::main()) {
|
||||
m->player()->pausePressed();
|
||||
}
|
||||
}
|
||||
|
||||
void media_playpause() {
|
||||
if (MainWidget *m = App::main()) {
|
||||
m->player()->playPausePressed();
|
||||
}
|
||||
}
|
||||
|
||||
void media_stop() {
|
||||
if (MainWidget *m = App::main()) {
|
||||
m->player()->stopPressed();
|
||||
}
|
||||
}
|
||||
|
||||
void media_previous() {
|
||||
if (MainWidget *m = App::main()) {
|
||||
m->player()->prevPressed();
|
||||
}
|
||||
}
|
||||
|
||||
void media_next() {
|
||||
if (MainWidget *m = App::main()) {
|
||||
m->player()->nextPressed();
|
||||
}
|
||||
}
|
||||
|
||||
void search() {
|
||||
if (MainWidget *m = App::main()) {
|
||||
m->cmd_search();
|
||||
}
|
||||
}
|
||||
|
||||
void previous_chat() {
|
||||
if (MainWidget *m = App::main()) {
|
||||
m->cmd_previous_chat();
|
||||
}
|
||||
}
|
||||
|
||||
void next_chat() {
|
||||
if (MainWidget *m = App::main()) {
|
||||
m->cmd_next_chat();
|
||||
}
|
||||
}
|
||||
|
||||
// other commands here
|
||||
|
||||
} // namespace ShortcutCommands
|
||||
|
||||
inline bool qMapLessThanKey(const ShortcutCommands::Handler &a, const ShortcutCommands::Handler &b) {
|
||||
return a < b;
|
||||
}
|
||||
|
||||
namespace Shortcuts {
|
||||
|
||||
// inspired by https://github.com/sindresorhus/strip-json-comments
|
||||
QByteArray _stripJsonComments(const QByteArray &json) {
|
||||
enum InsideComment {
|
||||
InsideCommentNone,
|
||||
InsideCommentSingleLine,
|
||||
InsideCommentMultiLine,
|
||||
};
|
||||
InsideComment insideComment = InsideCommentNone;
|
||||
bool insideString = false;
|
||||
// inspired by https://github.com/sindresorhus/strip-json-comments
|
||||
QByteArray _stripJsonComments(const QByteArray &json) {
|
||||
enum InsideComment {
|
||||
InsideCommentNone,
|
||||
InsideCommentSingleLine,
|
||||
InsideCommentMultiLine,
|
||||
};
|
||||
InsideComment insideComment = InsideCommentNone;
|
||||
bool insideString = false;
|
||||
|
||||
QByteArray result;
|
||||
QByteArray result;
|
||||
|
||||
const char *b = json.cbegin(), *e = json.cend(), *offset = b;
|
||||
for (const char *ch = offset; ch != e; ++ch) {
|
||||
char currentChar = *ch;
|
||||
char nextChar = (ch + 1 == e) ? 0 : *(ch + 1);
|
||||
const char *b = json.cbegin(), *e = json.cend(), *offset = b;
|
||||
for (const char *ch = offset; ch != e; ++ch) {
|
||||
char currentChar = *ch;
|
||||
char nextChar = (ch + 1 == e) ? 0 : *(ch + 1);
|
||||
|
||||
if (insideComment == InsideCommentNone && currentChar == '"') {
|
||||
bool escaped = ((ch > b) && *(ch - 1) == '\\') && ((ch - 1 < b) || *(ch - 2) != '\\');
|
||||
if (!escaped) {
|
||||
insideString = !insideString;
|
||||
}
|
||||
}
|
||||
|
||||
if (insideString) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (insideComment == InsideCommentNone && currentChar == '/' && nextChar == '/') {
|
||||
if (ch > offset) {
|
||||
if (result.isEmpty()) result.reserve(json.size() - 2);
|
||||
result.append(offset, ch - offset);
|
||||
offset = ch;
|
||||
}
|
||||
insideComment = InsideCommentSingleLine;
|
||||
++ch;
|
||||
} else if (insideComment == InsideCommentSingleLine && currentChar == '\r' && nextChar == '\n') {
|
||||
if (ch > offset) {
|
||||
offset = ch;
|
||||
}
|
||||
++ch;
|
||||
insideComment = InsideCommentNone;
|
||||
} else if (insideComment == InsideCommentSingleLine && currentChar == '\n') {
|
||||
if (ch > offset) {
|
||||
offset = ch;
|
||||
}
|
||||
insideComment = InsideCommentNone;
|
||||
} else if (insideComment == InsideCommentNone && currentChar == '/' && nextChar == '*') {
|
||||
if (ch > offset) {
|
||||
if (result.isEmpty()) result.reserve(json.size() - 2);
|
||||
result.append(offset, ch - offset);
|
||||
offset = ch;
|
||||
}
|
||||
insideComment = InsideCommentMultiLine;
|
||||
++ch;
|
||||
} else if (insideComment == InsideCommentMultiLine && currentChar == '*' && nextChar == '/') {
|
||||
if (ch > offset) {
|
||||
offset = ch;
|
||||
}
|
||||
++ch;
|
||||
insideComment = InsideCommentNone;
|
||||
if (insideComment == InsideCommentNone && currentChar == '"') {
|
||||
bool escaped = ((ch > b) && *(ch - 1) == '\\') && ((ch - 1 < b) || *(ch - 2) != '\\');
|
||||
if (!escaped) {
|
||||
insideString = !insideString;
|
||||
}
|
||||
}
|
||||
|
||||
if (insideComment == InsideCommentNone && e > offset && !result.isEmpty()) {
|
||||
result.append(offset, e - offset);
|
||||
if (insideString) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (insideComment == InsideCommentNone && currentChar == '/' && nextChar == '/') {
|
||||
if (ch > offset) {
|
||||
if (result.isEmpty()) result.reserve(json.size() - 2);
|
||||
result.append(offset, ch - offset);
|
||||
offset = ch;
|
||||
}
|
||||
insideComment = InsideCommentSingleLine;
|
||||
++ch;
|
||||
} else if (insideComment == InsideCommentSingleLine && currentChar == '\r' && nextChar == '\n') {
|
||||
if (ch > offset) {
|
||||
offset = ch;
|
||||
}
|
||||
++ch;
|
||||
insideComment = InsideCommentNone;
|
||||
} else if (insideComment == InsideCommentSingleLine && currentChar == '\n') {
|
||||
if (ch > offset) {
|
||||
offset = ch;
|
||||
}
|
||||
insideComment = InsideCommentNone;
|
||||
} else if (insideComment == InsideCommentNone && currentChar == '/' && nextChar == '*') {
|
||||
if (ch > offset) {
|
||||
if (result.isEmpty()) result.reserve(json.size() - 2);
|
||||
result.append(offset, ch - offset);
|
||||
offset = ch;
|
||||
}
|
||||
insideComment = InsideCommentMultiLine;
|
||||
++ch;
|
||||
} else if (insideComment == InsideCommentMultiLine && currentChar == '*' && nextChar == '/') {
|
||||
if (ch > offset) {
|
||||
offset = ch;
|
||||
}
|
||||
++ch;
|
||||
insideComment = InsideCommentNone;
|
||||
}
|
||||
return result.isEmpty() ? json : result;
|
||||
}
|
||||
|
||||
struct DataStruct;
|
||||
DataStruct *DataPtr = nullptr;
|
||||
if (insideComment == InsideCommentNone && e > offset && !result.isEmpty()) {
|
||||
result.append(offset, e - offset);
|
||||
}
|
||||
return result.isEmpty() ? json : result;
|
||||
}
|
||||
|
||||
void _createCommand(const QString &command, ShortcutCommands::Handler handler);
|
||||
QKeySequence _setShortcut(const QString &keys, const QString &command);
|
||||
struct DataStruct {
|
||||
DataStruct() {
|
||||
t_assert(DataPtr == nullptr);
|
||||
DataPtr = this;
|
||||
struct DataStruct;
|
||||
DataStruct *DataPtr = nullptr;
|
||||
|
||||
#define DeclareAlias(keys, command) _setShortcut(qsl(keys), qsl(#command))
|
||||
#define DeclareCommand(keys, command) _createCommand(qsl(#command), ShortcutCommands::command); DeclareAlias(keys, command)
|
||||
namespace {
|
||||
|
||||
DeclareCommand("ctrl+w", close_telegram);
|
||||
DeclareAlias("ctrl+f4", close_telegram);
|
||||
DeclareCommand("ctrl+l", lock_telegram);
|
||||
DeclareCommand("ctrl+m", minimize_telegram);
|
||||
DeclareCommand("ctrl+q", quit_telegram);
|
||||
void createCommand(const QString &command, ShortcutCommands::Handler handler);
|
||||
QKeySequence setShortcut(const QString &keys, const QString &command);
|
||||
void destroyShortcut(QShortcut *shortcut);
|
||||
|
||||
//DeclareCommand("ctrl+r", start_stop_recording);
|
||||
//DeclareCommand("ctrl+shift+r", cancel_recording);
|
||||
//DeclareCommand("media record", start_stop_recording);
|
||||
} // namespace
|
||||
|
||||
DeclareCommand("media play", media_play);
|
||||
DeclareCommand("media pause", media_pause);
|
||||
DeclareCommand("toggle media play/pause", media_playpause);
|
||||
DeclareCommand("media stop", media_stop);
|
||||
DeclareCommand("media previous", media_previous);
|
||||
DeclareCommand("media next", media_next);
|
||||
struct DataStruct {
|
||||
DataStruct() {
|
||||
t_assert(DataPtr == nullptr);
|
||||
DataPtr = this;
|
||||
|
||||
DeclareCommand("ctrl+f", search);
|
||||
DeclareAlias("search", search);
|
||||
DeclareAlias("find", search);
|
||||
#define DeclareAlias(keys, command) setShortcut(qsl(keys), qsl(#command))
|
||||
#define DeclareCommand(keys, command) createCommand(qsl(#command), ShortcutCommands::command); DeclareAlias(keys, command)
|
||||
|
||||
DeclareCommand("ctrl+pgdown", next_chat);
|
||||
DeclareAlias("alt+down", next_chat);
|
||||
DeclareCommand("ctrl+pgup", previous_chat);
|
||||
DeclareAlias("alt+up", previous_chat);
|
||||
if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) {
|
||||
DeclareAlias("meta+tab", next_chat);
|
||||
DeclareAlias("meta+shift+tab", previous_chat);
|
||||
DeclareAlias("meta+backtab", previous_chat);
|
||||
} else {
|
||||
DeclareAlias("ctrl+tab", next_chat);
|
||||
DeclareAlias("ctrl+shift+tab", previous_chat);
|
||||
DeclareAlias("ctrl+backtab", previous_chat);
|
||||
}
|
||||
DeclareCommand("ctrl+w", close_telegram);
|
||||
DeclareAlias("ctrl+f4", close_telegram);
|
||||
DeclareCommand("ctrl+l", lock_telegram);
|
||||
DeclareCommand("ctrl+m", minimize_telegram);
|
||||
DeclareCommand("ctrl+q", quit_telegram);
|
||||
|
||||
// other commands here
|
||||
//DeclareCommand("ctrl+r", start_stop_recording);
|
||||
//DeclareCommand("ctrl+shift+r", cancel_recording);
|
||||
//DeclareCommand("media record", start_stop_recording);
|
||||
|
||||
DeclareCommand("media play", media_play);
|
||||
DeclareCommand("media pause", media_pause);
|
||||
DeclareCommand("toggle media play/pause", media_playpause);
|
||||
DeclareCommand("media stop", media_stop);
|
||||
DeclareCommand("media previous", media_previous);
|
||||
DeclareCommand("media next", media_next);
|
||||
|
||||
DeclareCommand("ctrl+f", search);
|
||||
DeclareAlias("search", search);
|
||||
DeclareAlias("find", search);
|
||||
|
||||
DeclareCommand("ctrl+pgdown", next_chat);
|
||||
DeclareAlias("alt+down", next_chat);
|
||||
DeclareCommand("ctrl+pgup", previous_chat);
|
||||
DeclareAlias("alt+up", previous_chat);
|
||||
if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) {
|
||||
DeclareAlias("meta+tab", next_chat);
|
||||
DeclareAlias("meta+shift+tab", previous_chat);
|
||||
DeclareAlias("meta+backtab", previous_chat);
|
||||
} else {
|
||||
DeclareAlias("ctrl+tab", next_chat);
|
||||
DeclareAlias("ctrl+shift+tab", previous_chat);
|
||||
DeclareAlias("ctrl+backtab", previous_chat);
|
||||
}
|
||||
|
||||
// other commands here
|
||||
|
||||
#undef DeclareCommand
|
||||
#undef DeclareAlias
|
||||
}
|
||||
QStringList errors;
|
||||
}
|
||||
QStringList errors;
|
||||
|
||||
QMap<QString, ShortcutCommands::Handler> commands;
|
||||
QMap<ShortcutCommands::Handler, QString> commandnames;
|
||||
QMap<QString, ShortcutCommands::Handler> commands;
|
||||
QMap<ShortcutCommands::Handler, QString> commandnames;
|
||||
|
||||
QMap<QKeySequence, QShortcut*> sequences;
|
||||
QMap<int, ShortcutCommands::Handler> handlers;
|
||||
QMap<QKeySequence, QShortcut*> sequences;
|
||||
QMap<int, ShortcutCommands::Handler> handlers;
|
||||
|
||||
QSet<QString> autoRepeatCommands = {
|
||||
qsl("media_previous"),
|
||||
qsl("media_next"),
|
||||
qsl("next_chat"),
|
||||
qsl("previous_chat"),
|
||||
};
|
||||
QSet<QShortcut*> mediaShortcuts;
|
||||
|
||||
QSet<QString> autoRepeatCommands = {
|
||||
qsl("media_previous"),
|
||||
qsl("media_next"),
|
||||
qsl("next_chat"),
|
||||
qsl("previous_chat"),
|
||||
};
|
||||
|
||||
void _createCommand(const QString &command, ShortcutCommands::Handler handler) {
|
||||
t_assert(DataPtr != nullptr);
|
||||
t_assert(!command.isEmpty());
|
||||
QSet<QString> mediaCommands = {
|
||||
qsl("media_play"),
|
||||
qsl("media_pause"),
|
||||
qsl("media_playpause"),
|
||||
qsl("media_stop"),
|
||||
qsl("media_previous"),
|
||||
qsl("media_next")
|
||||
};
|
||||
};
|
||||
|
||||
DataPtr->commands.insert(command, handler);
|
||||
DataPtr->commandnames.insert(handler, command);
|
||||
}
|
||||
namespace {
|
||||
|
||||
QKeySequence _setShortcut(const QString &keys, const QString &command) {
|
||||
t_assert(DataPtr != nullptr);
|
||||
t_assert(!command.isEmpty());
|
||||
if (keys.isEmpty()) return QKeySequence();
|
||||
void createCommand(const QString &command, ShortcutCommands::Handler handler) {
|
||||
t_assert(DataPtr != nullptr);
|
||||
t_assert(!command.isEmpty());
|
||||
|
||||
QKeySequence seq(keys, QKeySequence::PortableText);
|
||||
if (seq.isEmpty()) {
|
||||
DataPtr->errors.push_back(qsl("Could not derive key sequence '%1'!").arg(keys));
|
||||
DataPtr->commands.insert(command, handler);
|
||||
DataPtr->commandnames.insert(handler, command);
|
||||
}
|
||||
|
||||
QKeySequence setShortcut(const QString &keys, const QString &command) {
|
||||
t_assert(DataPtr != nullptr);
|
||||
t_assert(!command.isEmpty());
|
||||
if (keys.isEmpty()) return QKeySequence();
|
||||
|
||||
QKeySequence seq(keys, QKeySequence::PortableText);
|
||||
if (seq.isEmpty()) {
|
||||
DataPtr->errors.push_back(qsl("Could not derive key sequence '%1'!").arg(keys));
|
||||
} else {
|
||||
auto it = DataPtr->commands.constFind(command);
|
||||
if (it == DataPtr->commands.cend()) {
|
||||
LOG(("Warning: could not find shortcut command handler '%1'").arg(command));
|
||||
} else {
|
||||
auto it = DataPtr->commands.constFind(command);
|
||||
if (it == DataPtr->commands.cend()) {
|
||||
LOG(("Warning: could not find shortcut command handler '%1'").arg(command));
|
||||
auto shortcut = std_::make_unique<QShortcut>(seq, App::wnd(), nullptr, nullptr, Qt::ApplicationShortcut);
|
||||
if (!DataPtr->autoRepeatCommands.contains(command)) {
|
||||
shortcut->setAutoRepeat(false);
|
||||
}
|
||||
auto isMediaShortcut = DataPtr->mediaCommands.contains(command);
|
||||
if (isMediaShortcut) {
|
||||
shortcut->setEnabled(false);
|
||||
}
|
||||
int shortcutId = shortcut->id();
|
||||
if (!shortcutId) {
|
||||
DataPtr->errors.push_back(qsl("Could not create shortcut '%1'!").arg(keys));
|
||||
} else {
|
||||
QShortcut *shortcut(new QShortcut(seq, App::wnd(), nullptr, nullptr, Qt::ApplicationShortcut));
|
||||
if (!DataPtr->autoRepeatCommands.contains(command)) {
|
||||
shortcut->setAutoRepeat(false);
|
||||
}
|
||||
int shortcutId = shortcut->id();
|
||||
if (!shortcutId) {
|
||||
DataPtr->errors.push_back(qsl("Could not create shortcut '%1'!").arg(keys));
|
||||
auto seqIt = DataPtr->sequences.find(seq);
|
||||
if (seqIt == DataPtr->sequences.cend()) {
|
||||
seqIt = DataPtr->sequences.insert(seq, shortcut.release());
|
||||
} else {
|
||||
QMap<QKeySequence, QShortcut*>::iterator seqIt = DataPtr->sequences.find(seq);
|
||||
if (seqIt == DataPtr->sequences.cend()) {
|
||||
seqIt = DataPtr->sequences.insert(seq, shortcut);
|
||||
} else {
|
||||
DataPtr->handlers.remove(seqIt.value()->id());
|
||||
delete seqIt.value();
|
||||
seqIt.value() = shortcut;
|
||||
}
|
||||
DataPtr->handlers.insert(shortcutId, it.value());
|
||||
auto oldShortcut = seqIt.value();
|
||||
seqIt.value() = shortcut.release();
|
||||
destroyShortcut(oldShortcut);
|
||||
}
|
||||
DataPtr->handlers.insert(shortcutId, it.value());
|
||||
if (isMediaShortcut) {
|
||||
DataPtr->mediaShortcuts.insert(seqIt.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
return seq;
|
||||
}
|
||||
return seq;
|
||||
}
|
||||
|
||||
QKeySequence _removeShortcut(const QString &keys) {
|
||||
t_assert(DataPtr != nullptr);
|
||||
if (keys.isEmpty()) return QKeySequence();
|
||||
QKeySequence removeShortcut(const QString &keys) {
|
||||
t_assert(DataPtr != nullptr);
|
||||
if (keys.isEmpty()) return QKeySequence();
|
||||
|
||||
QKeySequence seq(keys, QKeySequence::PortableText);
|
||||
if (seq.isEmpty()) {
|
||||
DataPtr->errors.push_back(qsl("Could not derive key sequence '%1'!").arg(keys));
|
||||
} else {
|
||||
QMap<QKeySequence, QShortcut*>::iterator seqIt = DataPtr->sequences.find(seq);
|
||||
if (seqIt != DataPtr->sequences.cend()) {
|
||||
DataPtr->handlers.remove(seqIt.value()->id());
|
||||
delete seqIt.value();
|
||||
DataPtr->sequences.erase(seqIt);
|
||||
}
|
||||
QKeySequence seq(keys, QKeySequence::PortableText);
|
||||
if (seq.isEmpty()) {
|
||||
DataPtr->errors.push_back(qsl("Could not derive key sequence '%1'!").arg(keys));
|
||||
} else {
|
||||
auto seqIt = DataPtr->sequences.find(seq);
|
||||
if (seqIt != DataPtr->sequences.cend()) {
|
||||
auto shortcut = seqIt.value();
|
||||
DataPtr->sequences.erase(seqIt);
|
||||
destroyShortcut(shortcut);
|
||||
}
|
||||
return seq;
|
||||
}
|
||||
return seq;
|
||||
}
|
||||
|
||||
void start() {
|
||||
t_assert(Global::started());
|
||||
void destroyShortcut(QShortcut *shortcut) {
|
||||
t_assert(DataPtr != nullptr);
|
||||
|
||||
new DataStruct();
|
||||
DataPtr->handlers.remove(shortcut->id());
|
||||
DataPtr->mediaShortcuts.remove(shortcut);
|
||||
delete shortcut;
|
||||
}
|
||||
|
||||
// write default shortcuts to a file if they are not there already
|
||||
bool defaultValid = false;
|
||||
QFile defaultFile(cWorkingDir() + qsl("tdata/shortcuts-default.json"));
|
||||
if (defaultFile.open(QIODevice::ReadOnly)) {
|
||||
QJsonParseError error = { 0, QJsonParseError::NoError };
|
||||
QJsonDocument doc = QJsonDocument::fromJson(_stripJsonComments(defaultFile.readAll()), &error);
|
||||
defaultFile.close();
|
||||
} // namespace
|
||||
|
||||
if (error.error == QJsonParseError::NoError && doc.isArray()) {
|
||||
QJsonArray shortcuts(doc.array());
|
||||
if (!shortcuts.isEmpty() && (*shortcuts.constBegin()).isObject()) {
|
||||
QJsonObject versionObject((*shortcuts.constBegin()).toObject());
|
||||
QJsonObject::const_iterator version = versionObject.constFind(qsl("version"));
|
||||
if (version != versionObject.constEnd() && (*version).isString() && (*version).toString() == QString::number(AppVersion)) {
|
||||
defaultValid = true;
|
||||
}
|
||||
void start() {
|
||||
t_assert(Global::started());
|
||||
|
||||
new DataStruct();
|
||||
|
||||
// write default shortcuts to a file if they are not there already
|
||||
bool defaultValid = false;
|
||||
QFile defaultFile(cWorkingDir() + qsl("tdata/shortcuts-default.json"));
|
||||
if (defaultFile.open(QIODevice::ReadOnly)) {
|
||||
QJsonParseError error = { 0, QJsonParseError::NoError };
|
||||
QJsonDocument doc = QJsonDocument::fromJson(_stripJsonComments(defaultFile.readAll()), &error);
|
||||
defaultFile.close();
|
||||
|
||||
if (error.error == QJsonParseError::NoError && doc.isArray()) {
|
||||
QJsonArray shortcuts(doc.array());
|
||||
if (!shortcuts.isEmpty() && (*shortcuts.constBegin()).isObject()) {
|
||||
QJsonObject versionObject((*shortcuts.constBegin()).toObject());
|
||||
QJsonObject::const_iterator version = versionObject.constFind(qsl("version"));
|
||||
if (version != versionObject.constEnd() && (*version).isString() && (*version).toString() == QString::number(AppVersion)) {
|
||||
defaultValid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!defaultValid && defaultFile.open(QIODevice::WriteOnly)) {
|
||||
const char *defaultHeader = "\
|
||||
}
|
||||
if (!defaultValid && defaultFile.open(QIODevice::WriteOnly)) {
|
||||
const char *defaultHeader = "\
|
||||
// This is a list of default shortcuts for Telegram Desktop\n\
|
||||
// Please don't modify it, its content is not used in any way\n\
|
||||
// You can place your own shortcuts in the 'shortcuts-custom.json' file\n\n";
|
||||
defaultFile.write(defaultHeader);
|
||||
defaultFile.write(defaultHeader);
|
||||
|
||||
QJsonArray shortcuts;
|
||||
QJsonArray shortcuts;
|
||||
|
||||
QJsonObject version;
|
||||
version.insert(qsl("version"), QString::number(AppVersion));
|
||||
shortcuts.push_back(version);
|
||||
QJsonObject version;
|
||||
version.insert(qsl("version"), QString::number(AppVersion));
|
||||
shortcuts.push_back(version);
|
||||
|
||||
for (QMap<QKeySequence, QShortcut*>::const_iterator i = DataPtr->sequences.cbegin(), e = DataPtr->sequences.cend(); i != e; ++i) {
|
||||
QMap<int, ShortcutCommands::Handler>::const_iterator h = DataPtr->handlers.constFind(i.value()->id());
|
||||
if (h != DataPtr->handlers.cend()) {
|
||||
QMap<ShortcutCommands::Handler, QString>::const_iterator n = DataPtr->commandnames.constFind(h.value());
|
||||
if (n != DataPtr->commandnames.cend()) {
|
||||
QJsonObject entry;
|
||||
entry.insert(qsl("keys"), i.key().toString().toLower());
|
||||
entry.insert(qsl("command"), n.value());
|
||||
shortcuts.append(entry);
|
||||
}
|
||||
for (auto i = DataPtr->sequences.cbegin(), e = DataPtr->sequences.cend(); i != e; ++i) {
|
||||
auto h = DataPtr->handlers.constFind(i.value()->id());
|
||||
if (h != DataPtr->handlers.cend()) {
|
||||
auto n = DataPtr->commandnames.constFind(h.value());
|
||||
if (n != DataPtr->commandnames.cend()) {
|
||||
QJsonObject entry;
|
||||
entry.insert(qsl("keys"), i.key().toString().toLower());
|
||||
entry.insert(qsl("command"), n.value());
|
||||
shortcuts.append(entry);
|
||||
}
|
||||
}
|
||||
|
||||
QJsonDocument doc;
|
||||
doc.setArray(shortcuts);
|
||||
defaultFile.write(doc.toJson(QJsonDocument::Indented));
|
||||
defaultFile.close();
|
||||
}
|
||||
|
||||
// read custom shortcuts from file if it exists or write an empty custom shortcuts file
|
||||
QFile customFile(cWorkingDir() + qsl("tdata/shortcuts-custom.json"));
|
||||
if (customFile.exists()) {
|
||||
if (customFile.open(QIODevice::ReadOnly)) {
|
||||
QJsonParseError error = { 0, QJsonParseError::NoError };
|
||||
QJsonDocument doc = QJsonDocument::fromJson(_stripJsonComments(customFile.readAll()), &error);
|
||||
customFile.close();
|
||||
QJsonDocument doc;
|
||||
doc.setArray(shortcuts);
|
||||
defaultFile.write(doc.toJson(QJsonDocument::Indented));
|
||||
defaultFile.close();
|
||||
}
|
||||
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
DataPtr->errors.push_back(qsl("Failed to parse! Error: %2").arg(error.errorString()));
|
||||
} else if (!doc.isArray()) {
|
||||
DataPtr->errors.push_back(qsl("Failed to parse! Error: array expected"));
|
||||
} else {
|
||||
QJsonArray shortcuts = doc.array();
|
||||
int limit = ShortcutsCountLimit;
|
||||
for (QJsonArray::const_iterator i = shortcuts.constBegin(), e = shortcuts.constEnd(); i != e; ++i) {
|
||||
if (!(*i).isObject()) {
|
||||
DataPtr->errors.push_back(qsl("Bad entry! Error: object expected"));
|
||||
// read custom shortcuts from file if it exists or write an empty custom shortcuts file
|
||||
QFile customFile(cWorkingDir() + qsl("tdata/shortcuts-custom.json"));
|
||||
if (customFile.exists()) {
|
||||
if (customFile.open(QIODevice::ReadOnly)) {
|
||||
QJsonParseError error = { 0, QJsonParseError::NoError };
|
||||
QJsonDocument doc = QJsonDocument::fromJson(_stripJsonComments(customFile.readAll()), &error);
|
||||
customFile.close();
|
||||
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
DataPtr->errors.push_back(qsl("Failed to parse! Error: %2").arg(error.errorString()));
|
||||
} else if (!doc.isArray()) {
|
||||
DataPtr->errors.push_back(qsl("Failed to parse! Error: array expected"));
|
||||
} else {
|
||||
QJsonArray shortcuts = doc.array();
|
||||
int limit = ShortcutsCountLimit;
|
||||
for (QJsonArray::const_iterator i = shortcuts.constBegin(), e = shortcuts.constEnd(); i != e; ++i) {
|
||||
if (!(*i).isObject()) {
|
||||
DataPtr->errors.push_back(qsl("Bad entry! Error: object expected"));
|
||||
} else {
|
||||
QKeySequence seq;
|
||||
QJsonObject entry((*i).toObject());
|
||||
QJsonObject::const_iterator keys = entry.constFind(qsl("keys")), command = entry.constFind(qsl("command"));
|
||||
if (keys == entry.constEnd() || command == entry.constEnd() || !(*keys).isString() || (!(*command).isString() && !(*command).isNull())) {
|
||||
DataPtr->errors.push_back(qsl("Bad entry! {\"keys\": \"...\", \"command\": [ \"...\" | null ]} expected"));
|
||||
} else if ((*command).isNull()) {
|
||||
seq = removeShortcut((*keys).toString());
|
||||
} else {
|
||||
QKeySequence seq;
|
||||
QJsonObject entry((*i).toObject());
|
||||
QJsonObject::const_iterator keys = entry.constFind(qsl("keys")), command = entry.constFind(qsl("command"));
|
||||
if (keys == entry.constEnd() || command == entry.constEnd() || !(*keys).isString() || (!(*command).isString() && !(*command).isNull())) {
|
||||
DataPtr->errors.push_back(qsl("Bad entry! {\"keys\": \"...\", \"command\": [ \"...\" | null ]} expected"));
|
||||
} else if ((*command).isNull()) {
|
||||
seq = _removeShortcut((*keys).toString());
|
||||
} else {
|
||||
seq = _setShortcut((*keys).toString(), (*command).toString());
|
||||
}
|
||||
if (!--limit) {
|
||||
DataPtr->errors.push_back(qsl("Too many entries! Limit is %1").arg(ShortcutsCountLimit));
|
||||
break;
|
||||
}
|
||||
seq = setShortcut((*keys).toString(), (*command).toString());
|
||||
}
|
||||
if (!--limit) {
|
||||
DataPtr->errors.push_back(qsl("Too many entries! Limit is %1").arg(ShortcutsCountLimit));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DataPtr->errors.push_back(qsl("Could not read the file!"));
|
||||
}
|
||||
if (!DataPtr->errors.isEmpty()) {
|
||||
DataPtr->errors.push_front(qsl("While reading file '%1'...").arg(customFile.fileName()));
|
||||
}
|
||||
} else if (customFile.open(QIODevice::WriteOnly)) {
|
||||
const char *customContent = "\
|
||||
} else {
|
||||
DataPtr->errors.push_back(qsl("Could not read the file!"));
|
||||
}
|
||||
if (!DataPtr->errors.isEmpty()) {
|
||||
DataPtr->errors.push_front(qsl("While reading file '%1'...").arg(customFile.fileName()));
|
||||
}
|
||||
} else if (customFile.open(QIODevice::WriteOnly)) {
|
||||
const char *customContent = "\
|
||||
// This is a list of your own shortcuts for Telegram Desktop\n\
|
||||
// You can see full list of commands in the 'shortcuts-default.json' file\n\
|
||||
// Place a null value instead of a command string to switch the shortcut off\n\n\
|
||||
@ -447,41 +484,55 @@ namespace Shortcuts {
|
||||
// \"keys\": \"ctrl+q\"\n\
|
||||
// }\n\
|
||||
]\n";
|
||||
customFile.write(customContent);
|
||||
customFile.close();
|
||||
}
|
||||
customFile.write(customContent);
|
||||
customFile.close();
|
||||
}
|
||||
|
||||
const QStringList &errors() {
|
||||
t_assert(DataPtr != nullptr);
|
||||
return DataPtr->errors;
|
||||
}
|
||||
|
||||
bool launch(int shortcutId) {
|
||||
t_assert(DataPtr != nullptr);
|
||||
|
||||
QMap<int, ShortcutCommands::Handler>::const_iterator it = DataPtr->handlers.constFind(shortcutId);
|
||||
if (it == DataPtr->handlers.cend()) {
|
||||
return false;
|
||||
}
|
||||
(*it.value())();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool launch(const QString &command) {
|
||||
t_assert(DataPtr != nullptr);
|
||||
|
||||
QMap<QString, ShortcutCommands::Handler>::const_iterator it = DataPtr->commands.constFind(command);
|
||||
if (it == DataPtr->commands.cend()) {
|
||||
return false;
|
||||
}
|
||||
(*it.value())();
|
||||
return true;
|
||||
}
|
||||
|
||||
void finish() {
|
||||
delete DataPtr;
|
||||
DataPtr = nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const QStringList &errors() {
|
||||
t_assert(DataPtr != nullptr);
|
||||
return DataPtr->errors;
|
||||
}
|
||||
|
||||
bool launch(int shortcutId) {
|
||||
t_assert(DataPtr != nullptr);
|
||||
|
||||
auto it = DataPtr->handlers.constFind(shortcutId);
|
||||
if (it == DataPtr->handlers.cend()) {
|
||||
return false;
|
||||
}
|
||||
(*it.value())();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool launch(const QString &command) {
|
||||
t_assert(DataPtr != nullptr);
|
||||
|
||||
auto it = DataPtr->commands.constFind(command);
|
||||
if (it == DataPtr->commands.cend()) {
|
||||
return false;
|
||||
}
|
||||
(*it.value())();
|
||||
return true;
|
||||
}
|
||||
|
||||
void enableMediaShortcuts() {
|
||||
if (!DataPtr) return;
|
||||
for_const (auto shortcut, DataPtr->mediaShortcuts) {
|
||||
shortcut->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void disableMediaShortcuts() {
|
||||
if (!DataPtr) return;
|
||||
for_const (auto shortcut, DataPtr->mediaShortcuts) {
|
||||
shortcut->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void finish() {
|
||||
delete DataPtr;
|
||||
DataPtr = nullptr;
|
||||
}
|
||||
|
||||
} // namespace Shortcuts
|
||||
|
@ -28,6 +28,12 @@ namespace Shortcuts {
|
||||
bool launch(int shortcutId);
|
||||
bool launch(const QString &command);
|
||||
|
||||
// Media shortcuts are not enabled by default, because other
|
||||
// applications also use them. They are enabled only when
|
||||
// the in-app player is active and disabled back after.
|
||||
void enableMediaShortcuts();
|
||||
void disableMediaShortcuts();
|
||||
|
||||
void finish();
|
||||
|
||||
}
|
||||
|
@ -21,22 +21,39 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
|
||||
#define NOMINMAX // no min() and max() macro declarations
|
||||
#define __HUGE
|
||||
#define __STDC_FORMAT_MACROS // fix breakpad for mac
|
||||
|
||||
// Fix Google Breakpad build for Mac App Store version
|
||||
#ifdef Q_OS_MAC
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#endif // Q_OS_MAC
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <cmath>
|
||||
|
||||
// False positive warning in clang for QMap member function value:
|
||||
// const T QMap<Key, T>::value(const Key &akey, const T &adefaultValue)
|
||||
// fires with "Returning address of local temporary object" which is not true.
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wreturn-stack-address"
|
||||
#endif // __clang__
|
||||
|
||||
#include <QtCore/QtCore>
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif // __clang__
|
||||
|
||||
#include <QtWidgets/QtWidgets>
|
||||
#include <QtNetwork/QtNetwork>
|
||||
|
||||
#include "basic_types.h"
|
||||
#include "core/basic_types.h"
|
||||
#include "config.h"
|
||||
|
||||
#include "mtproto/facade.h"
|
||||
|
||||
#include "ui/style_core.h"
|
||||
#include "ui/style.h"
|
||||
#include "ui/twidget.h"
|
||||
#include "ui/animation.h"
|
||||
#include "ui/flatinput.h"
|
||||
@ -46,7 +63,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
#include "ui/popupmenu.h"
|
||||
#include "ui/scrollarea.h"
|
||||
#include "ui/images.h"
|
||||
#include "ui/text.h"
|
||||
#include "ui/text/text.h"
|
||||
#include "ui/flatlabel.h"
|
||||
|
||||
#include "app.h"
|
||||
|
@ -28,11 +28,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
#include "mainwidget.h"
|
||||
#include "application.h"
|
||||
#include "fileuploader.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
#include "ui/filedialog.h"
|
||||
|
||||
#include "apiwrap.h"
|
||||
#include "boxes/confirmbox.h"
|
||||
|
||||
#include "audio.h"
|
||||
#include "localstorage.h"
|
||||
|
||||
|
@ -1312,3 +1312,63 @@ struct MessageCursor {
|
||||
inline bool operator==(const MessageCursor &a, const MessageCursor &b) {
|
||||
return (a.position == b.position) && (a.anchor == b.anchor) && (a.scroll == b.scroll);
|
||||
}
|
||||
|
||||
struct LocationCoords {
|
||||
LocationCoords() : lat(0), lon(0) {
|
||||
}
|
||||
LocationCoords(float64 lat, float64 lon) : lat(lat), lon(lon) {
|
||||
}
|
||||
LocationCoords(const MTPDgeoPoint &point) : lat(point.vlat.v), lon(point.vlong.v) {
|
||||
}
|
||||
float64 lat, lon;
|
||||
};
|
||||
inline bool operator==(const LocationCoords &a, const LocationCoords &b) {
|
||||
return (a.lat == b.lat) && (a.lon == b.lon);
|
||||
}
|
||||
inline bool operator<(const LocationCoords &a, const LocationCoords &b) {
|
||||
return (a.lat < b.lat) || ((a.lat == b.lat) && (a.lon < b.lon));
|
||||
}
|
||||
inline uint qHash(const LocationCoords &t, uint seed = 0) {
|
||||
return qHash(QtPrivate::QHashCombine().operator()(qHash(t.lat), t.lon), seed);
|
||||
}
|
||||
|
||||
struct LocationData {
|
||||
LocationData(const LocationCoords &coords) : coords(coords), loading(false) {
|
||||
}
|
||||
|
||||
LocationCoords coords;
|
||||
ImagePtr thumb;
|
||||
bool loading;
|
||||
|
||||
void load();
|
||||
};
|
||||
|
||||
class LocationClickHandler : public ClickHandler {
|
||||
public:
|
||||
LocationClickHandler(const LocationCoords &coords) : _coords(coords) {
|
||||
setup();
|
||||
}
|
||||
QString copyToClipboardContextItem() const override;
|
||||
|
||||
void copyToClipboard() const override {
|
||||
if (!_text.isEmpty()) {
|
||||
QApplication::clipboard()->setText(_text);
|
||||
}
|
||||
}
|
||||
|
||||
QString tooltip() const override {
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString text() const override {
|
||||
return _text;
|
||||
}
|
||||
void onClick(Qt::MouseButton button) const override;
|
||||
|
||||
private:
|
||||
|
||||
void setup();
|
||||
LocationCoords _coords;
|
||||
QString _text;
|
||||
|
||||
};
|
||||
|
@ -111,7 +111,7 @@ void SysBtn::step_color(float64 ms, bool timer) {
|
||||
if (timer) update();
|
||||
}
|
||||
|
||||
MinimizeBtn::MinimizeBtn(QWidget *parent, Window *window) : SysBtn(parent, st::sysMin), wnd(window) {
|
||||
MinimizeBtn::MinimizeBtn(QWidget *parent, MainWindow *window) : SysBtn(parent, st::sysMin), wnd(window) {
|
||||
connect(this, SIGNAL(clicked()), this, SLOT(onClick()));
|
||||
}
|
||||
|
||||
@ -119,7 +119,7 @@ void MinimizeBtn::onClick() {
|
||||
wnd->setWindowState(Qt::WindowMinimized);
|
||||
}
|
||||
|
||||
MaximizeBtn::MaximizeBtn(QWidget *parent, Window *window) : SysBtn(parent, st::sysMax), wnd(window) {
|
||||
MaximizeBtn::MaximizeBtn(QWidget *parent, MainWindow *window) : SysBtn(parent, st::sysMax), wnd(window) {
|
||||
connect(this, SIGNAL(clicked()), this, SLOT(onClick()));
|
||||
}
|
||||
|
||||
@ -127,7 +127,7 @@ void MaximizeBtn::onClick() {
|
||||
wnd->setWindowState(Qt::WindowMaximized);
|
||||
}
|
||||
|
||||
RestoreBtn::RestoreBtn(QWidget *parent, Window *window) : SysBtn(parent, st::sysRes), wnd(window) {
|
||||
RestoreBtn::RestoreBtn(QWidget *parent, MainWindow *window) : SysBtn(parent, st::sysRes), wnd(window) {
|
||||
connect(this, SIGNAL(clicked()), this, SLOT(onClick()));
|
||||
}
|
||||
|
||||
@ -135,7 +135,7 @@ void RestoreBtn::onClick() {
|
||||
wnd->setWindowState(Qt::WindowNoState);
|
||||
}
|
||||
|
||||
CloseBtn::CloseBtn(QWidget *parent, Window *window) : SysBtn(parent, st::sysCls), wnd(window) {
|
||||
CloseBtn::CloseBtn(QWidget *parent, MainWindow *window) : SysBtn(parent, st::sysCls), wnd(window) {
|
||||
connect(this, SIGNAL(clicked()), this, SLOT(onClick()));
|
||||
}
|
||||
|
||||
@ -143,7 +143,7 @@ void CloseBtn::onClick() {
|
||||
wnd->close();
|
||||
}
|
||||
|
||||
UpdateBtn::UpdateBtn(QWidget *parent, Window *window, const QString &text) : SysBtn(parent, st::sysUpd, text), wnd(window) {
|
||||
UpdateBtn::UpdateBtn(QWidget *parent, MainWindow *window, const QString &text) : SysBtn(parent, st::sysUpd, text), wnd(window) {
|
||||
connect(this, SIGNAL(clicked()), this, SLOT(onClick()));
|
||||
}
|
||||
|
||||
@ -161,7 +161,7 @@ void UpdateBtn::onClick() {
|
||||
App::quit();
|
||||
}
|
||||
|
||||
LockBtn::LockBtn(QWidget *parent, Window *window) : SysBtn(parent, st::sysLock), wnd(window) {
|
||||
LockBtn::LockBtn(QWidget *parent, MainWindow *window) : SysBtn(parent, st::sysLock), wnd(window) {
|
||||
connect(this, SIGNAL(clicked()), this, SLOT(onClick()));
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
#include "ui/animation.h"
|
||||
#include "ui/button.h"
|
||||
|
||||
class Window;
|
||||
class MainWindow;
|
||||
|
||||
class SysBtn : public Button {
|
||||
Q_OBJECT
|
||||
@ -62,7 +62,7 @@ class MinimizeBtn : public SysBtn {
|
||||
|
||||
public:
|
||||
|
||||
MinimizeBtn(QWidget *parent, Window *window);
|
||||
MinimizeBtn(QWidget *parent, MainWindow *window);
|
||||
|
||||
public slots:
|
||||
|
||||
@ -70,7 +70,7 @@ public slots:
|
||||
|
||||
private:
|
||||
|
||||
Window *wnd;
|
||||
MainWindow *wnd;
|
||||
};
|
||||
|
||||
class MaximizeBtn : public SysBtn {
|
||||
@ -78,7 +78,7 @@ class MaximizeBtn : public SysBtn {
|
||||
|
||||
public:
|
||||
|
||||
MaximizeBtn(QWidget *parent, Window *window);
|
||||
MaximizeBtn(QWidget *parent, MainWindow *window);
|
||||
|
||||
public slots:
|
||||
|
||||
@ -86,7 +86,7 @@ public slots:
|
||||
|
||||
private:
|
||||
|
||||
Window *wnd;
|
||||
MainWindow *wnd;
|
||||
};
|
||||
|
||||
class RestoreBtn : public SysBtn {
|
||||
@ -94,7 +94,7 @@ class RestoreBtn : public SysBtn {
|
||||
|
||||
public:
|
||||
|
||||
RestoreBtn(QWidget *parent, Window *window);
|
||||
RestoreBtn(QWidget *parent, MainWindow *window);
|
||||
|
||||
public slots:
|
||||
|
||||
@ -102,7 +102,7 @@ public slots:
|
||||
|
||||
private:
|
||||
|
||||
Window *wnd;
|
||||
MainWindow *wnd;
|
||||
};
|
||||
|
||||
class CloseBtn : public SysBtn {
|
||||
@ -110,7 +110,7 @@ class CloseBtn : public SysBtn {
|
||||
|
||||
public:
|
||||
|
||||
CloseBtn(QWidget *parent, Window *window);
|
||||
CloseBtn(QWidget *parent, MainWindow *window);
|
||||
|
||||
public slots:
|
||||
|
||||
@ -118,7 +118,7 @@ public slots:
|
||||
|
||||
private:
|
||||
|
||||
Window *wnd;
|
||||
MainWindow *wnd;
|
||||
};
|
||||
|
||||
class UpdateBtn : public SysBtn {
|
||||
@ -126,7 +126,7 @@ class UpdateBtn : public SysBtn {
|
||||
|
||||
public:
|
||||
|
||||
UpdateBtn(QWidget *parent, Window *window, const QString &text = QString());
|
||||
UpdateBtn(QWidget *parent, MainWindow *window, const QString &text = QString());
|
||||
|
||||
public slots:
|
||||
|
||||
@ -134,7 +134,7 @@ public slots:
|
||||
|
||||
private:
|
||||
|
||||
Window *wnd;
|
||||
MainWindow *wnd;
|
||||
};
|
||||
|
||||
class LockBtn : public SysBtn {
|
||||
@ -142,7 +142,7 @@ class LockBtn : public SysBtn {
|
||||
|
||||
public:
|
||||
|
||||
LockBtn(QWidget *parent, Window *window);
|
||||
LockBtn(QWidget *parent, MainWindow *window);
|
||||
|
||||
public slots:
|
||||
|
||||
@ -150,5 +150,5 @@ public slots:
|
||||
|
||||
private:
|
||||
|
||||
Window *wnd;
|
||||
MainWindow *wnd;
|
||||
};
|
||||
|
@ -24,7 +24,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
|
||||
#include "title.h"
|
||||
#include "mainwidget.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
#include "application.h"
|
||||
#include "boxes/contactsbox.h"
|
||||
#include "boxes/aboutbox.h"
|
||||
@ -49,7 +49,7 @@ void TitleHider::setLevel(float64 level) {
|
||||
update();
|
||||
}
|
||||
|
||||
TitleWidget::TitleWidget(Window *window) : TWidget(window)
|
||||
TitleWidget::TitleWidget(MainWindow *window) : TWidget(window)
|
||||
, wnd(window)
|
||||
, hideLevel(0)
|
||||
, hider(0)
|
||||
|
@ -23,7 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
#include <QtWidgets/QWidget>
|
||||
#include "sysbuttons.h"
|
||||
|
||||
class Window;
|
||||
class MainWindow;
|
||||
|
||||
class TitleHider : public QWidget {
|
||||
public:
|
||||
@ -44,7 +44,7 @@ class TitleWidget : public TWidget {
|
||||
|
||||
public:
|
||||
|
||||
TitleWidget(Window *parent);
|
||||
TitleWidget(MainWindow *parent);
|
||||
void paintEvent(QPaintEvent *e);
|
||||
void resizeEvent(QResizeEvent *e);
|
||||
|
||||
@ -78,7 +78,7 @@ signals:
|
||||
|
||||
private:
|
||||
|
||||
Window *wnd;
|
||||
MainWindow *wnd;
|
||||
|
||||
style::color statusColor;
|
||||
|
||||
|
@ -30,7 +30,7 @@ extern "C" {
|
||||
}
|
||||
|
||||
#include "mainwidget.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
namespace {
|
||||
AnimationManager *_manager = 0;
|
||||
|
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "basic_types.h"
|
||||
#include "core/basic_types.h"
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtGui/QColor>
|
||||
|
||||
|
@ -21,6 +21,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
#include "stdafx.h"
|
||||
#include "ui/buttons/peer_avatar_button.h"
|
||||
|
||||
#include "structs.h"
|
||||
|
||||
namespace Ui {
|
||||
|
||||
PeerAvatarButton::PeerAvatarButton(QWidget *parent, PeerData *peer, const style::PeerAvatarButton &st) : Button(parent)
|
||||
, _peer(peer)
|
||||
, _st(st) {
|
||||
@ -33,3 +37,5 @@ void PeerAvatarButton::paintEvent(QPaintEvent *e) {
|
||||
_peer->paintUserpic(p, _st.photoSize, (_st.size - _st.photoSize) / 2, (_st.size - _st.photoSize) / 2);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Ui
|
||||
|
@ -22,7 +22,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
|
||||
#include "ui/button.h"
|
||||
#include "ui/style.h"
|
||||
#include "structs.h"
|
||||
|
||||
class PeerData;
|
||||
|
||||
namespace Ui {
|
||||
|
||||
class PeerAvatarButton : public Button {
|
||||
public:
|
||||
@ -38,3 +41,5 @@ private:
|
||||
const style::PeerAvatarButton &_st;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Ui
|
||||
|
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "ui/text.h"
|
||||
#include "ui/text/text.h"
|
||||
|
||||
void emojiInit();
|
||||
EmojiPtr emojiGet(uint32 code);
|
||||
|
@ -22,7 +22,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
#include "ui/style.h"
|
||||
|
||||
#include "flatinput.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
#include "countryinput.h"
|
||||
|
||||
#include "lang.h"
|
||||
|
@ -31,14 +31,14 @@ public:
|
||||
|
||||
FlatInput(QWidget *parent, const style::flatInput &st, const QString &ph = QString(), const QString &val = QString());
|
||||
|
||||
bool event(QEvent *e);
|
||||
bool event(QEvent *e) override;
|
||||
void touchEvent(QTouchEvent *e);
|
||||
void paintEvent(QPaintEvent *e);
|
||||
void focusInEvent(QFocusEvent *e);
|
||||
void focusOutEvent(QFocusEvent *e);
|
||||
void keyPressEvent(QKeyEvent *e);
|
||||
void resizeEvent(QResizeEvent *e);
|
||||
void contextMenuEvent(QContextMenuEvent *e);
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void focusInEvent(QFocusEvent *e) override;
|
||||
void focusOutEvent(QFocusEvent *e) override;
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
void contextMenuEvent(QContextMenuEvent *e) override;
|
||||
|
||||
void notaBene();
|
||||
|
||||
@ -52,8 +52,8 @@ public:
|
||||
|
||||
void step_appearance(float64 ms, bool timer);
|
||||
|
||||
QSize sizeHint() const;
|
||||
QSize minimumSizeHint() const;
|
||||
QSize sizeHint() const override;
|
||||
QSize minimumSizeHint() const override;
|
||||
|
||||
void customUpDown(bool isCustom);
|
||||
const QString &getLastText() const {
|
||||
@ -507,14 +507,14 @@ public:
|
||||
|
||||
MaskedInputField(QWidget *parent, const style::InputField &st, const QString &placeholder = QString(), const QString &val = QString());
|
||||
|
||||
bool event(QEvent *e);
|
||||
bool event(QEvent *e) override;
|
||||
void touchEvent(QTouchEvent *e);
|
||||
void paintEvent(QPaintEvent *e);
|
||||
void focusInEvent(QFocusEvent *e);
|
||||
void focusOutEvent(QFocusEvent *e);
|
||||
void keyPressEvent(QKeyEvent *e);
|
||||
void resizeEvent(QResizeEvent *e);
|
||||
void contextMenuEvent(QContextMenuEvent *e);
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void focusInEvent(QFocusEvent *e) override;
|
||||
void focusOutEvent(QFocusEvent *e) override;
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
void contextMenuEvent(QContextMenuEvent *e) override;
|
||||
|
||||
void showError();
|
||||
|
||||
@ -528,8 +528,8 @@ public:
|
||||
void step_placeholderShift(float64 ms, bool timer);
|
||||
void step_border(float64 ms, bool timer);
|
||||
|
||||
QSize sizeHint() const;
|
||||
QSize minimumSizeHint() const;
|
||||
QSize sizeHint() const override;
|
||||
QSize minimumSizeHint() const override;
|
||||
|
||||
void customUpDown(bool isCustom);
|
||||
const QString &getLastText() const {
|
||||
|
@ -110,10 +110,12 @@ void FlatLabel::updateHover() {
|
||||
QPoint m(mapFromGlobal(_lastMousePos));
|
||||
|
||||
textstyleSet(&_tst);
|
||||
ClickHandlerPtr handler = _text.link(m.x(), m.y(), width(), _st.align);
|
||||
Text::StateRequest request;
|
||||
request.align = _st.align;
|
||||
auto state = _text.getState(m.x(), m.y(), width(), request);
|
||||
textstyleRestore();
|
||||
|
||||
ClickHandler::setActive(handler, this);
|
||||
ClickHandler::setActive(state.link, this);
|
||||
}
|
||||
|
||||
void FlatLabel::setOpacity(float64 o) {
|
||||
|
@ -22,7 +22,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
#include "flattextarea.h"
|
||||
|
||||
#include "ui/style.h"
|
||||
#include "window.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
FlatTextarea::FlatTextarea(QWidget *parent, const style::flatTextarea &st, const QString &pholder, const QString &v) : QTextEdit(parent)
|
||||
, _oldtext(v)
|
||||
|
@ -35,16 +35,16 @@ public:
|
||||
|
||||
FlatTextarea(QWidget *parent, const style::flatTextarea &st, const QString &ph = QString(), const QString &val = QString());
|
||||
|
||||
bool viewportEvent(QEvent *e);
|
||||
bool viewportEvent(QEvent *e) override;
|
||||
void touchEvent(QTouchEvent *e);
|
||||
void paintEvent(QPaintEvent *e);
|
||||
void focusInEvent(QFocusEvent *e);
|
||||
void focusOutEvent(QFocusEvent *e);
|
||||
void keyPressEvent(QKeyEvent *e);
|
||||
void resizeEvent(QResizeEvent *e);
|
||||
void mousePressEvent(QMouseEvent *e);
|
||||
void dropEvent(QDropEvent *e);
|
||||
void contextMenuEvent(QContextMenuEvent *e);
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void focusInEvent(QFocusEvent *e) override;
|
||||
void focusOutEvent(QFocusEvent *e) override;
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
void dropEvent(QDropEvent *e) override;
|
||||
void contextMenuEvent(QContextMenuEvent *e) override;
|
||||
|
||||
void setMaxLength(int32 maxLength);
|
||||
void setMinHeight(int32 minHeight);
|
||||
@ -62,8 +62,8 @@ public:
|
||||
|
||||
void step_appearance(float64 ms, bool timer);
|
||||
|
||||
QSize sizeHint() const;
|
||||
QSize minimumSizeHint() const;
|
||||
QSize sizeHint() const override;
|
||||
QSize minimumSizeHint() const override;
|
||||
|
||||
EmojiPtr getSingleEmoji() const;
|
||||
QString getMentionHashtagBotCommandPart(bool &start) const;
|
||||
@ -82,9 +82,9 @@ public:
|
||||
void parseLinks();
|
||||
QStringList linksList() const;
|
||||
|
||||
void insertFromMimeData(const QMimeData *source);
|
||||
void insertFromMimeData(const QMimeData *source) override;
|
||||
|
||||
QMimeData *createMimeDataFromSelection() const;
|
||||
QMimeData *createMimeDataFromSelection() const override;
|
||||
|
||||
enum class SubmitSettings {
|
||||
None,
|
||||
@ -125,7 +125,7 @@ protected:
|
||||
|
||||
void insertEmoji(EmojiPtr emoji, QTextCursor c);
|
||||
|
||||
QVariant loadResource(int type, const QUrl &name);
|
||||
QVariant loadResource(int type, const QUrl &name) override;
|
||||
|
||||
void checkContentHeight();
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "text.h"
|
||||
#include "ui/text/text.h"
|
||||
|
||||
class PopupMenu : public TWidget {
|
||||
Q_OBJECT
|
||||
|
@ -20,5 +20,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../GeneratedFiles/style_classes.h"
|
||||
#include "../GeneratedFiles/style_auto.h"
|
||||
#include "ui/style_core.h"
|
||||
#include "GeneratedFiles/style_classes.h"
|
||||
#include "GeneratedFiles/style_auto.h"
|
||||
|
@ -134,24 +134,13 @@ namespace style {
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Color::set(const QColor &newv) {
|
||||
if (!owner) {
|
||||
ptr = new ColorData(*ptr);
|
||||
owner = true;
|
||||
}
|
||||
ptr->set(newv);
|
||||
namespace {
|
||||
inline uint32 colorKey(uchar r, uchar g, uchar b, uchar a) {
|
||||
return (((((uint32(r) << 8) | uint32(g)) << 8) | uint32(b)) << 8) | uint32(a);
|
||||
}
|
||||
|
||||
void Color::set(uchar r, uchar g, uchar b, uchar a) {
|
||||
if (!owner) {
|
||||
ptr = new ColorData(*ptr);
|
||||
owner = true;
|
||||
}
|
||||
ptr->set(QColor(r, g, b, a));
|
||||
}
|
||||
|
||||
void Color::init(uchar r, uchar g, uchar b, uchar a) {
|
||||
uint32 key = _colorKey(r, g, b, a);
|
||||
uint32 key = colorKey(r, g, b, a);
|
||||
ColorDatas::const_iterator i = _colorsMap.constFind(key);
|
||||
if (i == _colorsMap.cend()) {
|
||||
i = _colorsMap.insert(key, new ColorData(r, g, b, a));
|
||||
|
@ -46,7 +46,7 @@ inline QRect centerrect(const QRect &inRect, const QRect &rect) {
|
||||
}
|
||||
|
||||
namespace style {
|
||||
|
||||
|
||||
class FontData;
|
||||
class Font {
|
||||
public:
|
||||
@ -189,7 +189,7 @@ namespace style {
|
||||
bool owner;
|
||||
|
||||
void init(uchar r, uchar g, uchar b, uchar a);
|
||||
|
||||
|
||||
friend void startManager();
|
||||
|
||||
Color(ColorData *p) : ptr(p) {
|
||||
@ -213,7 +213,7 @@ namespace style {
|
||||
|
||||
ColorData(uchar r, uchar g, uchar b, uchar a);
|
||||
void set(const QColor &c);
|
||||
|
||||
|
||||
friend class Color;
|
||||
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user