New main menu in DialogsWidget.

Also "flip_horizontal" and "flip_vertical" modifiers support added.
Also moving parts of MainWindow to Window::MainWindow.
This commit is contained in:
John Preston 2016-11-04 14:14:47 +03:00
parent 0cbb0014db
commit 3a599e0752
86 changed files with 565 additions and 774 deletions

View file

@ -402,25 +402,12 @@ noContactsHeight: 100px;
noContactsFont: font(fsize); noContactsFont: font(fsize);
noContactsColor: #777777; noContactsColor: #777777;
fieldSearchIcon: icon {{ "box_search", #aaaaaa, point(10px, 9px) }};
dlgFilter: flatInput(inpDefGray) {
font: font(fsize);
bgColor: #f2f2f2;
phColor: #949494;
phFocusColor: #a4a4a4;
icon: fieldSearchIcon;
width: 240px;
height: 34px;
textMrg: margins(34px, 2px, 34px, 4px);
}
topBarHeight: 54px; topBarHeight: 54px;
topBarDuration: 200; topBarDuration: 200;
topBarForward: icon {{ "title_next", #a3a3a3 }}; topBarForward: icon {{ "title_back-flip_horizontal", #a3a3a3 }};
topBarBackward: icon {{ "title_previous", #a3a3a3 }}; topBarBackward: icon {{ "title_back", #a3a3a3 }};
topBarForwardAlpha: 0.6; topBarForwardAlpha: 0.6;
topBarBack: icon {{ "title_previous", #259fd8 }}; topBarBack: icon {{ "title_back", #259fd8 }};
topBarBackAlpha: 0.8; topBarBackAlpha: 0.8;
topBarBackColor: #005faf; topBarBackColor: #005faf;
topBarBackFont: font(16px); topBarBackFont: font(16px);
@ -1104,15 +1091,15 @@ infoButton: PeerAvatarButton {
photoSize: 42px; photoSize: 42px;
} }
// forward declaration for single "title_previous" usage. // forward declaration for single "title_back" usage.
profileTopBarBackIconFg: #0290d7; profileTopBarBackIconFg: #0290d7;
profileTopBarBackIcon: icon {{ "title_previous", profileTopBarBackIconFg }}; profileTopBarBackIcon: icon {{ "title_back", profileTopBarBackIconFg }};
historyReplyCancelIcon: icon {{ "box_button_close-invert", historyReplyBg }}; historyReplyCancelIcon: icon {{ "box_button_close-invert", historyReplyBg }};
boxSearchCancelIcon: icon {{ "box_button_close-invert", boxSearchBg }}; boxSearchCancelIcon: icon {{ "box_button_close-invert", boxSearchBg }};
settingsFixedBarCloseIcon: icon {{ "box_button_close-invert", settingsFixedBarBg }}; settingsFixedBarCloseIcon: icon {{ "box_button_close-invert", settingsFixedBarBg }};
notifyFadeRight: icon {{ "fade_horizontal_right", notificationBg }}; notifyFadeRight: icon {{ "fade_horizontal", notificationBg }};
stickerIconLeft: icon {{ "fade_horizontal_left", emojiPanCategories }}; stickerIconLeft: icon {{ "fade_horizontal-flip_horizontal", emojiPanCategories }};
stickerIconRight: icon {{ "fade_horizontal_right", emojiPanCategories }}; stickerIconRight: icon {{ "fade_horizontal", emojiPanCategories }};

View file

@ -24,7 +24,7 @@ windowBg: #ffffff; // white: fallback for background
windowTextFg: #000000; // black: fallback for text color windowTextFg: #000000; // black: fallback for text color
windowSubTextFg: #8a8a8a; // gray: fallback for subtext color windowSubTextFg: #8a8a8a; // gray: fallback for subtext color
windowActiveFill: #40ace3; // bright blue: fallback for blue filled active areas windowActiveFill: #40ace3; // bright blue: fallback for blue filled active areas
windowOverBg: #edf2f5; // light blue: fallback for over background windowOverBg: #f3f3f3; // light blue: fallback for over background
windowSubTextFgOver: #7c99b2; // gray over light blue: fallback for subtext over color windowSubTextFgOver: #7c99b2; // gray over light blue: fallback for subtext over color
windowActiveTextFg: #1485c2; // online blue: fallback for active color windowActiveTextFg: #1485c2; // online blue: fallback for active color
windowShadowFg: #000000; // black: fallback for shadow color windowShadowFg: #000000; // black: fallback for shadow color
@ -32,22 +32,7 @@ windowShadowFg: #000000; // black: fallback for shadow color
imageBg: #000000; imageBg: #000000;
imageBgTransparent: #ffffff; imageBgTransparent: #ffffff;
// custom title bar for Windows // widgets
titleBg: #f3f3f3;
titleShadow: #00000003;
titleButtonFg: #ababab;
titleButtonBgOver: #e5e5e5;
titleButtonFgOver: #9a9a9a;
titleButtonCloseBgOver: #e81123;
titleButtonCloseFgOver: #ffffff;
// tray icon
trayCounterBg: #f23c34;
trayCounterBgMute: #888888;
trayCounterFg: #ffffff;
trayCounterBgMacInvert: #ffffff;
trayCounterFgMacInvert: #ffffff01;
cancelIconFg: #a2a2a2; cancelIconFg: #a2a2a2;
cancelIconFgOver: #808080; cancelIconFgOver: #808080;
@ -63,6 +48,24 @@ lightButtonBgOver: #f2f7fa | lightButtonBg;
lightButtonFg: #2b99d5; lightButtonFg: #2b99d5;
lightButtonFgOver: lightButtonFg; lightButtonFgOver: lightButtonFg;
menuIconFg: #808080 | windowSubTextFg;
// custom title bar for Windows
titleBg: windowOverBg;
titleShadow: #00000003;
titleButtonFg: #ababab;
titleButtonBgOver: #e5e5e5;
titleButtonFgOver: #9a9a9a;
titleButtonCloseBgOver: #e81123;
titleButtonCloseFgOver: #ffffff;
// tray icon
trayCounterBg: #f23c34;
trayCounterBgMute: #888888;
trayCounterFg: #ffffff;
trayCounterBgMacInvert: #ffffff;
trayCounterFgMacInvert: #ffffff01;
// layers // layers
layerBg: #0000007f; layerBg: #0000007f;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 124 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 163 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 B

View file

Before

Width:  |  Height:  |  Size: 145 B

After

Width:  |  Height:  |  Size: 145 B

View file

Before

Width:  |  Height:  |  Size: 213 B

After

Width:  |  Height:  |  Size: 213 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 236 B

View file

Before

Width:  |  Height:  |  Size: 142 B

After

Width:  |  Height:  |  Size: 142 B

View file

Before

Width:  |  Height:  |  Size: 190 B

After

Width:  |  Height:  |  Size: 190 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 139 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 496 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 661 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 393 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 805 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 559 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 292 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 201 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 325 B

View file

Before

Width:  |  Height:  |  Size: 152 B

After

Width:  |  Height:  |  Size: 152 B

View file

Before

Width:  |  Height:  |  Size: 416 B

After

Width:  |  Height:  |  Size: 416 B

View file

Before

Width:  |  Height:  |  Size: 148 B

After

Width:  |  Height:  |  Size: 148 B

View file

Before

Width:  |  Height:  |  Size: 264 B

After

Width:  |  Height:  |  Size: 264 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 316 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 573 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 314 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 557 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 261 B

View file

@ -519,9 +519,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
"lng_create_group_next" = "Next"; "lng_create_group_next" = "Next";
"lng_create_group_create" = "Create"; "lng_create_group_create" = "Create";
"lng_create_group_title" = "New Group"; "lng_create_group_title" = "New Group";
"lng_create_group_about" = "Groups are ideal for limited communities,\nthey can have up to {count:_not_used|# member|# members}";
"lng_create_channel_title" = "New Channel"; "lng_create_channel_title" = "New Channel";
"lng_create_channel_about" = "Channels are a tool for broadcasting your messages to unlimited audiences";
"lng_create_public_channel_title" = "Public Channel"; "lng_create_public_channel_title" = "Public Channel";
"lng_create_public_channel_about" = "Anyone can find the channel in search and join"; "lng_create_public_channel_about" = "Anyone can find the channel in search and join";
"lng_create_private_channel_title" = "Private Channel"; "lng_create_private_channel_title" = "Private Channel";

View file

@ -25,24 +25,12 @@ windowBg: #ffffff;
windowTextFg: #000000; windowTextFg: #000000;
windowSubTextFg: #8a8a8a; windowSubTextFg: #8a8a8a;
windowActiveFill: #40ace3; windowActiveFill: #40ace3;
windowOverBg: #edf2f5; windowOverBg: #f3f3f3;
windowSubTextFgOver: #7c99b2; windowSubTextFgOver: #7c99b2;
windowActiveTextFg: #1485c2; windowActiveTextFg: #1485c2;
windowShadowFg: #000000; windowShadowFg: #000000;
imageBg: #000000; imageBg: #000000;
imageBgTransparent: #ffffff; imageBgTransparent: #ffffff;
titleBg: #f3f3f3;
titleShadow: #00000003;
titleButtonFg: #ababab;
titleButtonBgOver: #e5e5e5;
titleButtonFgOver: #9a9a9a;
titleButtonCloseBgOver: #e81123;
titleButtonCloseFgOver: #ffffff;
trayCounterBg: #f23c34;
trayCounterBgMute: #888888;
trayCounterFg: #ffffff;
trayCounterBgMacInvert: #ffffff;
trayCounterFgMacInvert: #ffffff01;
cancelIconFg: #a2a2a2; cancelIconFg: #a2a2a2;
cancelIconFgOver: #808080; cancelIconFgOver: #808080;
activeButtonBg: windowActiveFill; activeButtonBg: windowActiveFill;
@ -55,6 +43,19 @@ lightButtonBg: windowBg;
lightButtonBgOver: #f2f7fa; // lightButtonBg; lightButtonBgOver: #f2f7fa; // lightButtonBg;
lightButtonFg: #2b99d5; lightButtonFg: #2b99d5;
lightButtonFgOver: lightButtonFg; lightButtonFgOver: lightButtonFg;
menuIconFg: #808080; // windowSubTextFg;
titleBg: windowOverBg;
titleShadow: #00000003;
titleButtonFg: #ababab;
titleButtonBgOver: #e5e5e5;
titleButtonFgOver: #9a9a9a;
titleButtonCloseBgOver: #e81123;
titleButtonCloseFgOver: #ffffff;
trayCounterBg: #f23c34;
trayCounterBgMute: #888888;
trayCounterFg: #ffffff;
trayCounterBgMacInvert: #ffffff;
trayCounterFgMacInvert: #ffffff01;
layerBg: #0000007f; layerBg: #0000007f;
boxBg: windowBg; boxBg: windowBg;
boxTextFg: windowTextFg; boxTextFg: windowTextFg;

View file

@ -260,64 +260,6 @@ void AddContactBox::onRetry() {
update(); update();
} }
NewGroupBox::NewGroupBox() : AbstractBox(),
_group(this, qsl("group_type"), 0, lang(lng_create_group_title), true),
_channel(this, qsl("group_type"), 1, lang(lng_create_channel_title)),
_aboutGroupWidth(width() - st::boxPadding.left() - st::boxButtonPadding.right() - st::newGroupPadding.left() - st::defaultRadiobutton.textPosition.x()),
_aboutGroup(st::normalFont, lng_create_group_about(lt_count, Global::MegagroupSizeMax()), _defaultOptions, _aboutGroupWidth),
_aboutChannel(st::normalFont, lang(lng_create_channel_about), _defaultOptions, _aboutGroupWidth),
_next(this, lang(lng_create_group_next), st::defaultBoxButton),
_cancel(this, lang(lng_cancel), st::cancelBoxButton) {
_aboutGroupHeight = _aboutGroup.countHeight(_aboutGroupWidth);
setMaxHeight(st::boxPadding.top() + st::newGroupPadding.top() + _group->height() + _aboutGroupHeight + st::newGroupSkip + _channel->height() + _aboutChannel.countHeight(_aboutGroupWidth) + st::newGroupPadding.bottom() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _next->height() + st::boxButtonPadding.bottom());
connect(_next, SIGNAL(clicked()), this, SLOT(onNext()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
prepare();
}
void NewGroupBox::showAll() {
_group->show();
_channel->show();
_cancel->show();
_next->show();
}
void NewGroupBox::keyPressEvent(QKeyEvent *e) {
if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
onNext();
} else {
AbstractBox::keyPressEvent(e);
}
}
void NewGroupBox::paintEvent(QPaintEvent *e) {
Painter p(this);
if (paint(p)) return;
p.setPen(st::newGroupAboutFg->p);
QRect aboutGroup(st::boxPadding.left() + st::newGroupPadding.left() + st::defaultRadiobutton.textPosition.x(), _group->y() + _group->height() + st::lineWidth, _aboutGroupWidth, _aboutGroupHeight);
_aboutGroup.drawLeft(p, aboutGroup.x(), aboutGroup.y(), aboutGroup.width(), width());
QRect aboutChannel(st::boxPadding.left() + st::newGroupPadding.left() + st::defaultRadiobutton.textPosition.x(), _channel->y() + _channel->height() + st::lineWidth, _aboutGroupWidth, _aboutGroupHeight);
_aboutChannel.drawLeft(p, aboutChannel.x(), aboutChannel.y(), aboutChannel.width(), width());
}
void NewGroupBox::resizeEvent(QResizeEvent *e) {
_group->moveToLeft(st::boxPadding.left() + st::newGroupPadding.left(), st::boxPadding.top() + st::newGroupPadding.top());
_channel->moveToLeft(st::boxPadding.left() + st::newGroupPadding.left(), _group->y() + _group->height() + _aboutGroupHeight + st::newGroupSkip);
_next->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _next->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _next->width() + st::boxButtonPadding.left(), _next->y());
AbstractBox::resizeEvent(e);
}
void NewGroupBox::onNext() {
Ui::showLayer(new GroupInfoBox(_group->checked() ? CreatingGroupGroup : CreatingGroupChannel, true), KeepOtherLayers);
}
GroupInfoBox::GroupInfoBox(CreatingGroupType creating, bool fromTypeChoose) : AbstractBox(), GroupInfoBox::GroupInfoBox(CreatingGroupType creating, bool fromTypeChoose) : AbstractBox(),
_creating(creating), _creating(creating),
a_photoOver(0, 0), a_photoOver(0, 0),

View file

@ -78,34 +78,6 @@ private:
QString _sentName; QString _sentName;
}; };
class NewGroupBox : public AbstractBox {
Q_OBJECT
public:
NewGroupBox();
public slots:
void onNext();
protected:
void keyPressEvent(QKeyEvent *e) override;
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void showAll() override;
private:
ChildWidget<Ui::Radiobutton> _group;
ChildWidget<Ui::Radiobutton> _channel;
int32 _aboutGroupWidth, _aboutGroupHeight;
Text _aboutGroup, _aboutChannel;
ChildWidget<BoxButton> _next;
ChildWidget<BoxButton> _cancel;
};
class GroupInfoBox : public AbstractBox, public RPCSender { class GroupInfoBox : public AbstractBox, public RPCSender {
Q_OBJECT Q_OBJECT

View file

@ -19,6 +19,7 @@ Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/ */
using "basic.style"; using "basic.style";
using "ui/widgets/widgets.style"; using "ui/widgets/widgets.style";
using "intro/intro.style"; using "intro/intro.style";
@ -143,7 +144,7 @@ contactsMultiSelect: MultiSelect {
font: normalFont; font: normalFont;
} }
fieldMinWidth: 42px; fieldMinWidth: 42px;
fieldIcon: fieldSearchIcon; fieldIcon: boxFieldSearchIcon;
fieldIconSkip: 36px; fieldIconSkip: 36px;
fieldCancel: MaskButton(defaultMaskButton) { fieldCancel: MaskButton(defaultMaskButton) {

View file

@ -38,8 +38,8 @@ namespace codegen {
namespace style { namespace style {
namespace { namespace {
constexpr int kErrorBadIconSize = 861; constexpr int kErrorBadIconSize = 861;
constexpr int kErrorBadIconFormat = 862; constexpr int kErrorBadIconFormat = 862;
// crc32 hash, taken somewhere from the internet // crc32 hash, taken somewhere from the internet
@ -1017,10 +1017,10 @@ QByteArray iconMaskValueSize(int width, int height) {
QByteArray iconMaskValuePng(QString filepath) { QByteArray iconMaskValuePng(QString filepath) {
QByteArray result; QByteArray result;
auto inverted = filepath.endsWith("-invert"); auto pathAndModifiers = filepath.split('-');
if (inverted) { filepath = pathAndModifiers[0];
filepath.chop(QLatin1String("-invert").size()); auto modifiers = pathAndModifiers.mid(1);
}
QImage png100x(filepath + ".png"); QImage png100x(filepath + ".png");
QImage png200x(filepath + "@2x.png"); QImage png200x(filepath + "@2x.png");
png100x.setDevicePixelRatio(1.); png100x.setDevicePixelRatio(1.);
@ -1041,9 +1041,13 @@ QByteArray iconMaskValuePng(QString filepath) {
common::logError(kErrorBadIconSize, filepath + ".png") << "bad icons size, 1x: " << png100x.width() << "x" << png100x.height() << ", 2x: " << png200x.width() << "x" << png200x.height(); common::logError(kErrorBadIconSize, filepath + ".png") << "bad icons size, 1x: " << png100x.width() << "x" << png100x.height() << ", 2x: " << png200x.width() << "x" << png200x.height();
return result; return result;
} }
if (inverted) { for (auto modifierName : modifiers) {
png100x.invertPixels(); if (auto modifier = GetModifier(modifierName)) {
png200x.invertPixels(); modifier(png100x, png200x);
} else {
common::logError(common::kErrorInternal, filepath) << "modifier should be valid here, name: " << modifierName.toStdString();
return result;
}
} }
QImage png125x = png200x.scaled(structure::data::pxAdjust(png100x.width(), 5), structure::data::pxAdjust(png100x.height(), 5), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); QImage png125x = png200x.scaled(structure::data::pxAdjust(png100x.width(), 5), structure::data::pxAdjust(png100x.height(), 5), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
QImage png150x = png200x.scaled(structure::data::pxAdjust(png100x.width(), 6), structure::data::pxAdjust(png100x.height(), 6), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); QImage png150x = png200x.scaled(structure::data::pxAdjust(png100x.width(), 6), structure::data::pxAdjust(png100x.height(), 6), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);

View file

@ -44,6 +44,7 @@ constexpr int kErrorIdentifierNotFound = 804;
constexpr int kErrorAlreadyDefined = 805; constexpr int kErrorAlreadyDefined = 805;
constexpr int kErrorBadString = 806; constexpr int kErrorBadString = 806;
constexpr int kErrorIconDuplicate = 807; constexpr int kErrorIconDuplicate = 807;
constexpr int kErrorBadIconModifier = 808;
QString findInputFile(const Options &options) { QString findInputFile(const Options &options) {
for (const auto &dir : options.includePaths) { for (const auto &dir : options.includePaths) {
@ -151,6 +152,25 @@ bool validateAlignString(const QString &value) {
} // namespace } // namespace
Modifier GetModifier(const QString &name) {
static QMap<QString, Modifier> modifiers;
if (modifiers.empty()) {
modifiers.insert("invert", [](QImage &png100x, QImage &png200x) {
png100x.invertPixels();
png200x.invertPixels();
});
modifiers.insert("flip_horizontal", [](QImage &png100x, QImage &png200x) {
png100x = png100x.mirrored(true, false);
png200x = png200x.mirrored(true, false);
});
modifiers.insert("flip_vertical", [](QImage &png100x, QImage &png200x) {
png100x = png100x.mirrored(false, true);
png200x = png200x.mirrored(false, true);
});
}
return modifiers.value(name);
}
ParsedFile::ParsedFile(const Options &options) ParsedFile::ParsedFile(const Options &options)
: filePath_(findInputFile(options)) : filePath_(findInputFile(options))
, file_(filePath_) , file_(filePath_)
@ -821,21 +841,26 @@ structure::data::monoicon ParsedFile::readMonoIconFields() {
QString ParsedFile::readMonoIconFilename() { QString ParsedFile::readMonoIconFilename() {
if (auto filename = readValue()) { if (auto filename = readValue()) {
if (filename.type().tag == structure::TypeTag::String) { if (filename.type().tag == structure::TypeTag::String) {
auto filepath = QString::fromStdString(filename.String()); auto fullpath = QString::fromStdString(filename.String());
auto inverted = filepath.endsWith("-invert"); auto pathAndModifiers = fullpath.split('-');
if (inverted) { auto filepath = pathAndModifiers[0];
filepath.chop(QLatin1String("-invert").size()); auto modifiers = pathAndModifiers.mid(1);
} for (auto modifierName : modifiers) {
for (const auto &path : options_.includePaths) { if (!GetModifier(modifierName)) {
QFileInfo fileinfo(path + '/' + filepath + ".png"); logError(kErrorBadIconModifier) << "unknown modifier: " << modifierName.toStdString();
if (fileinfo.exists()) { return QString();
return path + '/' + filepath + (inverted ? "-invert" : "");
} }
} }
for (const auto &path : options_.includePaths) { for (auto &path : options_.includePaths) {
QFileInfo fileinfo(path + '/' + filepath + ".png");
if (fileinfo.exists()) {
return path + '/' + fullpath;
}
}
for (auto &path : options_.includePaths) {
QFileInfo fileinfo(path + "/icons/" + filepath + ".png"); QFileInfo fileinfo(path + "/icons/" + filepath + ".png");
if (fileinfo.exists()) { if (fileinfo.exists()) {
return path + "/icons/" + filepath + (inverted ? "-invert" : ""); return path + "/icons/" + fullpath;
} }
} }
logError(common::kErrorFileNotFound) << "could not open icon file '" << filename.String() << "'"; logError(common::kErrorFileNotFound) << "could not open icon file '" << filename.String() << "'";

View file

@ -22,6 +22,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include <memory> #include <memory>
#include <string> #include <string>
#include <functional>
#include <QImage>
#include "codegen/common/basic_tokenized_file.h" #include "codegen/common/basic_tokenized_file.h"
#include "codegen/style/options.h" #include "codegen/style/options.h"
#include "codegen/style/module.h" #include "codegen/style/module.h"
@ -29,6 +31,9 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace codegen { namespace codegen {
namespace style { namespace style {
using Modifier = std::function<void(QImage &png100x, QImage &png200x)>;
Modifier GetModifier(const QString &name);
// Parses an input file to the internal struct. // Parses an input file to the internal struct.
class ParsedFile { class ParsedFile {
public: public:
@ -44,7 +49,6 @@ public:
} }
private: private:
bool failed() const { bool failed() const {
return failed_ || file_.failed(); return failed_ || file_.failed();
} }

View file

@ -59,6 +59,8 @@ template <typename T>
struct remove_reference<T&&> { struct remove_reference<T&&> {
using type = T; using type = T;
}; };
template <typename T>
using remove_reference_t = typename remove_reference<T>::type;
template <typename T> template <typename T>
struct is_lvalue_reference : false_type { struct is_lvalue_reference : false_type {

View file

@ -25,7 +25,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace base { namespace base {
template <typename T, size_t N> template <typename T, size_t N>
inline constexpr size_t array_size(T(&)[N]) { inline constexpr size_t array_size(const T(&)[N]) {
return N; return N;
} }
@ -35,6 +35,27 @@ inline T take(T &source, T &&new_value = T()) {
return std_::move(new_value); return std_::move(new_value);
} }
namespace internal {
template <typename D, typename T>
inline constexpr D up_cast_helper(std_::true_type, T object) {
return object;
}
template <typename D, typename T>
inline constexpr D up_cast_helper(std_::false_type, T object) {
return nullptr;
}
} // namespace internal
template <typename D, typename T>
inline constexpr D up_cast(T object) {
using DV = std_::decay_simple_t<decltype(*D())>;
using TV = std_::decay_simple_t<decltype(*T())>;
return internal::up_cast_helper<D>(std_::integral_constant<bool, std_::is_base_of<DV, TV>::value || std_::is_same<DV, TV>::value>(), object);
}
} // namespace base } // namespace base
template <typename Enum> template <typename Enum>

View file

@ -48,7 +48,7 @@ dialogsNameFg: #000000;
dialogsNameTop: 2px; dialogsNameTop: 2px;
dialogsRowHeight: 62px; dialogsRowHeight: 62px;
dialogsFilterPadding: 10px; dialogsFilterPadding: point(11px, 11px);
dialogsPhotoSize: 46px; dialogsPhotoSize: 46px;
dialogsPhotoPadding: 12px; dialogsPhotoPadding: 12px;
dialogsPadding: point(10px, 8px); dialogsPadding: point(10px, 8px);
@ -83,24 +83,44 @@ dialogsTextStyleDraftActive: textStyle(dialogsTextStyle) {
linkFgDown: #c6e1f7; linkFgDown: #c6e1f7;
} }
dialogsNewChatIcon: icon {{ "dialogs_new_chat", #b7b7b7 }}; dialogsMenuToggle: IconButton {
dialogsNewChatButton: IconButton { width: 32px;
width: 36px; height: 32px;
height: 36px;
icon: dialogsNewChatIcon; icon: icon {{ "dialogs_menu", #999999 }};
iconPosition: point(9px, 10px); iconPosition: point(6px, 6px);
iconPositionDown: point(9px, 11px); iconPositionDown: point(6px, 6px);
} }
dialogsAddContact: IconButton(dialogsNewChatButton) { dialogsFilter: flatInput(inpDefGray) {
icon: icon {{ "dialogs_add_contact", #a6a6a6 }}; font: font(fsize);
iconPosition: point(8px, 8px); bgColor: #f2f2f2;
iconPositionDown: point(8px, 9px); phColor: #949494;
phFocusColor: #a4a4a4;
icon: fieldSearchIcon;
width: 240px;
height: 32px;
textMrg: margins(32px, 3px, 32px, 3px);
} }
dialogsCancelSearch: IconButton(dialogsAddContact) { dialogsCancelSearch: IconButton(dialogsMenuToggle) {
icon: icon {{ "dialogs_cancel_search", #a6a6a6 }}; icon: icon {{ "dialogs_cancel_search", #a6a6a6, point(0px, 1px) }};
} }
dialogsMenu: DropdownMenu(defaultDropdownMenu) {
menu: Menu(defaultMenu) {
skip: 8px;
itemIconPosition: point(15px, 8px);
itemPadding: margins(56px, 10px, 56px, 12px);
}
}
dialogsMenuPosition: point(-3px, -2px);
dialogsMenuNewGroup: icon {{ "menu_new_group", menuIconFg }};
dialogsMenuNewChannel: icon {{ "menu_new_channel", menuIconFg }};
dialogsMenuContacts: icon {{ "menu_contacts", menuIconFg }};
dialogsMenuSettings: icon {{ "menu_settings", menuIconFg }};
dialogsMenuHelp: icon {{ "menu_help", menuIconFg }};
dialogsChatTypeSkip: 22px; dialogsChatTypeSkip: 22px;
dialogsChatIcon: icon {{ "dialogs_chat", #373737, point(1px, 4px) }}; dialogsChatIcon: icon {{ "dialogs_chat", #373737, point(1px, 4px) }};
dialogsChatActiveIcon: icon {{ "dialogs_chat", #ffffff, point(1px, 4px) }}; dialogsChatActiveIcon: icon {{ "dialogs_chat", #ffffff, point(1px, 4px) }};

View file

@ -36,10 +36,12 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "boxes/addcontactbox.h" #include "boxes/addcontactbox.h"
#include "boxes/contactsbox.h" #include "boxes/contactsbox.h"
#include "boxes/confirmbox.h" #include "boxes/confirmbox.h"
#include "boxes/aboutbox.h"
#include "localstorage.h" #include "localstorage.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "ui/widgets/dropdown_menu.h"
DialogsInner::DialogsInner(QWidget *parent, MainWidget *main) : SplittedWidget(parent) DialogsInner::DialogsInner(QWidget *parent, QWidget *main) : SplittedWidget(parent)
, dialogs(std_::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Date)) , dialogs(std_::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Date))
, contactsNoDialogs(std_::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Name)) , contactsNoDialogs(std_::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Name))
, contacts(std_::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Name)) , contacts(std_::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Name))
@ -1770,28 +1772,13 @@ MsgId DialogsInner::lastSearchMigratedId() const {
return _lastSearchMigratedId; return _lastSearchMigratedId;
} }
DialogsWidget::DialogsWidget(MainWidget *parent) : TWidget(parent) DialogsWidget::DialogsWidget(QWidget *parent) : TWidget(parent)
, _dragInScroll(false) , _mainMenuToggle(this, st::dialogsMenuToggle)
, _dragForward(false) , _filter(this, st::dialogsFilter, lang(lng_dlg_filter))
, _dialogsFull(false)
, _dialogsOffsetDate(0)
, _dialogsOffsetId(0)
, _dialogsOffsetPeer(0)
, _dialogsRequest(0)
, _contactsRequest(0)
, _filter(this, st::dlgFilter, lang(lng_dlg_filter))
, _newGroup(this, st::dialogsNewChatButton)
, _addContact(this, st::dialogsAddContact)
, _cancelSearch(this, st::dialogsCancelSearch) , _cancelSearch(this, st::dialogsCancelSearch)
, _scroll(this, st::dialogsScroll) , _scroll(this, st::dialogsScroll)
, _inner(&_scroll, parent) , _inner(&_scroll, parent)
, _a_show(animation(this, &DialogsWidget::step_show)) , _a_show(animation(this, &DialogsWidget::step_show)) {
, _searchInPeer(0)
, _searchInMigrated(0)
, _searchFull(false)
, _searchFullMigrated(false)
, _peopleFull(false)
{
_scroll.setWidget(&_inner); _scroll.setWidget(&_inner);
_scroll.setFocusPolicy(Qt::NoFocus); _scroll.setFocusPolicy(Qt::NoFocus);
connect(&_inner, SIGNAL(mustScrollTo(int,int)), &_scroll, SLOT(scrollToY(int,int))); connect(&_inner, SIGNAL(mustScrollTo(int,int)), &_scroll, SLOT(scrollToY(int,int)));
@ -1803,14 +1790,13 @@ DialogsWidget::DialogsWidget(MainWidget *parent) : TWidget(parent)
connect(&_inner, SIGNAL(cancelSearchInPeer()), this, SLOT(onCancelSearchInPeer())); connect(&_inner, SIGNAL(cancelSearchInPeer()), this, SLOT(onCancelSearchInPeer()));
connect(&_scroll, SIGNAL(geometryChanged()), &_inner, SLOT(onParentGeometryChanged())); connect(&_scroll, SIGNAL(geometryChanged()), &_inner, SLOT(onParentGeometryChanged()));
connect(&_scroll, SIGNAL(scrolled()), this, SLOT(onListScroll())); connect(&_scroll, SIGNAL(scrolled()), this, SLOT(onListScroll()));
connect(&_filter, SIGNAL(cancelled()), this, SLOT(onCancel())); connect(_filter, SIGNAL(cancelled()), this, SLOT(onCancel()));
connect(&_filter, SIGNAL(changed()), this, SLOT(onFilterUpdate())); connect(_filter, SIGNAL(changed()), this, SLOT(onFilterUpdate()));
connect(&_filter, SIGNAL(cursorPositionChanged(int,int)), this, SLOT(onFilterCursorMoved(int,int))); connect(_filter, SIGNAL(cursorPositionChanged(int,int)), this, SLOT(onFilterCursorMoved(int,int)));
connect(parent, SIGNAL(dialogsUpdated()), this, SLOT(onListScroll()));
connect(_addContact, SIGNAL(clicked()), this, SLOT(onAddContact()));
connect(_newGroup, SIGNAL(clicked()), this, SLOT(onNewGroup()));
connect(_cancelSearch, SIGNAL(clicked()), this, SLOT(onCancelSearch())); connect(_cancelSearch, SIGNAL(clicked()), this, SLOT(onCancelSearch()));
_mainMenuToggle->setClickedCallback([this] { showMainMenu(); });
_chooseByDragTimer.setSingleShot(true); _chooseByDragTimer.setSingleShot(true);
connect(&_chooseByDragTimer, SIGNAL(timeout()), this, SLOT(onChooseByDrag())); connect(&_chooseByDragTimer, SIGNAL(timeout()), this, SLOT(onChooseByDrag()));
@ -1819,21 +1805,13 @@ DialogsWidget::DialogsWidget(MainWidget *parent) : TWidget(parent)
_searchTimer.setSingleShot(true); _searchTimer.setSingleShot(true);
connect(&_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchMessages())); connect(&_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchMessages()));
_scroll.show(); _filter->setFocusPolicy(Qt::StrongFocus);
_filter.show(); _filter->customUpDown(true);
_filter.move(st::dialogsPadding.x(), st::dialogsFilterPadding);
_filter.setFocusPolicy(Qt::StrongFocus);
_filter.customUpDown(true);
_addContact->hide();
_newGroup->show();
_cancelSearch->hide(); _cancelSearch->hide();
_newGroup->move(width() - _newGroup->width() - st::dialogsPadding.x(), 0);
_addContact->move(width() - _addContact->width() - st::dialogsPadding.x(), 0);
_cancelSearch->move(width() - _cancelSearch->width() - st::dialogsPadding.x(), 0);
} }
void DialogsWidget::activate() { void DialogsWidget::activate() {
_filter.setFocus(); _filter->setFocus();
_inner.activate(); _inner.activate();
} }
@ -1858,7 +1836,7 @@ void DialogsWidget::dlgUpdated(History *row, MsgId msgId) {
} }
void DialogsWidget::dialogsToUp() { void DialogsWidget::dialogsToUp() {
if (_filter.getLastText().trimmed().isEmpty()) { if (_filter->getLastText().trimmed().isEmpty()) {
_scroll.scrollToY(0); _scroll.scrollToY(0);
} }
} }
@ -1873,9 +1851,8 @@ void DialogsWidget::showAnimated(Window::SlideDirection direction, const Window:
_a_show.stop(); _a_show.stop();
_scroll.hide(); _scroll.hide();
_filter.hide(); _filter->hide();
_cancelSearch->hide(); _cancelSearch->hide();
_newGroup->hide();
int delta = st::slideShift; int delta = st::slideShift;
if (direction == Window::SlideDirection::FromLeft) { if (direction == Window::SlideDirection::FromLeft) {
@ -1903,7 +1880,7 @@ void DialogsWidget::step_show(float64 ms, bool timer) {
_cacheUnder = _cacheOver = QPixmap(); _cacheUnder = _cacheOver = QPixmap();
_scroll.show(); _scroll.show();
_filter.show(); _filter->show();
_a_show.stop(); _a_show.stop();
onFilterUpdate(); onFilterUpdate();
@ -1930,8 +1907,8 @@ void DialogsWidget::updateNotifySettings(PeerData *peer) {
void DialogsWidget::notify_userIsContactChanged(UserData *user, bool fromThisApp) { void DialogsWidget::notify_userIsContactChanged(UserData *user, bool fromThisApp) {
if (fromThisApp) { if (fromThisApp) {
_filter.setText(QString()); _filter->setText(QString());
_filter.updatePlaceholder(); _filter->updatePlaceholder();
onFilterUpdate(); onFilterUpdate();
} }
_inner.notify_userIsContactChanged(user, fromThisApp); _inner.notify_userIsContactChanged(user, fromThisApp);
@ -2031,7 +2008,7 @@ bool DialogsWidget::dialogsFailed(const RPCError &error, mtpRequestId req) {
} }
bool DialogsWidget::onSearchMessages(bool searchCache) { bool DialogsWidget::onSearchMessages(bool searchCache) {
QString q = _filter.getLastText().trimmed(); QString q = _filter->getLastText().trimmed();
if (q.isEmpty()) { if (q.isEmpty()) {
if (_searchRequest) { if (_searchRequest) {
MTP::cancel(_searchRequest); MTP::cancel(_searchRequest);
@ -2098,16 +2075,39 @@ void DialogsWidget::onChooseByDrag() {
_inner.choosePeer(); _inner.choosePeer();
} }
void DialogsWidget::showMainMenu() {
if (!_mainMenu) {
_mainMenu.create(this, st::dialogsMenu);
_mainMenu->addAction(lang(lng_create_group_title), [] {
App::wnd()->onShowNewGroup();
}, &st::dialogsMenuNewGroup);
_mainMenu->addAction(lang(lng_create_channel_title), [] {
App::wnd()->onShowNewChannel();
}, &st::dialogsMenuNewChannel);
_mainMenu->addAction(lang(lng_menu_contacts), [] {
Ui::showLayer(new ContactsBox());
}, &st::dialogsMenuContacts);
_mainMenu->addAction(lang(lng_menu_settings), [] {
App::wnd()->showSettings();
}, &st::dialogsMenuSettings);
_mainMenu->addAction(lang(lng_settings_faq), [] {
QDesktopServices::openUrl(telegramFaqLink());
}, &st::dialogsMenuHelp);
}
updateMainMenuGeometry();
_mainMenu->showAnimated();
}
void DialogsWidget::searchMessages(const QString &query, PeerData *inPeer) { void DialogsWidget::searchMessages(const QString &query, PeerData *inPeer) {
if ((_filter.getLastText() != query) || (inPeer && inPeer != _searchInPeer && inPeer->migrateTo() != _searchInPeer)) { if ((_filter->getLastText() != query) || (inPeer && inPeer != _searchInPeer && inPeer->migrateTo() != _searchInPeer)) {
if (inPeer) { if (inPeer) {
onCancelSearch(); onCancelSearch();
_searchInPeer = inPeer->migrateTo() ? inPeer->migrateTo() : inPeer; _searchInPeer = inPeer->migrateTo() ? inPeer->migrateTo() : inPeer;
_searchInMigrated = _searchInPeer ? _searchInPeer->migrateFrom() : 0; _searchInMigrated = _searchInPeer ? _searchInPeer->migrateFrom() : 0;
_inner.searchInPeer(_searchInPeer); _inner.searchInPeer(_searchInPeer);
} }
_filter.setText(query); _filter->setText(query);
_filter.updatePlaceholder(); _filter->updatePlaceholder();
onFilterUpdate(true); onFilterUpdate(true);
_searchTimer.stop(); _searchTimer.stop();
onSearchMessages(); onSearchMessages();
@ -2371,17 +2371,15 @@ void DialogsWidget::onListScroll() {
void DialogsWidget::onFilterUpdate(bool force) { void DialogsWidget::onFilterUpdate(bool force) {
if (_a_show.animating() && !force) return; if (_a_show.animating() && !force) return;
QString filterText = _filter.getLastText(); QString filterText = _filter->getLastText();
_inner.onFilterUpdate(filterText, force); _inner.onFilterUpdate(filterText, force);
if (filterText.isEmpty()) { if (filterText.isEmpty()) {
_searchCache.clear(); _searchCache.clear();
_searchQueries.clear(); _searchQueries.clear();
_searchQuery = QString(); _searchQuery = QString();
_cancelSearch->hide(); _cancelSearch->hide();
_newGroup->show();
} else if (_cancelSearch->isHidden()) { } else if (_cancelSearch->isHidden()) {
_cancelSearch->show(); _cancelSearch->show();
_newGroup->hide();
} }
if (filterText.size() < MinUsernameLength) { if (filterText.size() < MinUsernameLength) {
_peopleCache.clear(); _peopleCache.clear();
@ -2399,8 +2397,8 @@ void DialogsWidget::searchInPeer(PeerData *peer) {
} }
void DialogsWidget::onFilterCursorMoved(int from, int to) { void DialogsWidget::onFilterCursorMoved(int from, int to) {
if (to < 0) to = _filter.cursorPosition(); if (to < 0) to = _filter->cursorPosition();
QString t = _filter.getLastText(); QString t = _filter->getLastText();
QStringRef r; QStringRef r;
for (int start = to; start > 0;) { for (int start = to; start > 0;) {
--start; --start;
@ -2415,8 +2413,8 @@ void DialogsWidget::onFilterCursorMoved(int from, int to) {
} }
void DialogsWidget::onCompleteHashtag(QString tag) { void DialogsWidget::onCompleteHashtag(QString tag) {
QString t = _filter.getLastText(), r; QString t = _filter->getLastText(), r;
int cur = _filter.cursorPosition(); int cur = _filter->cursorPosition();
for (int start = cur; start > 0;) { for (int start = cur; start > 0;) {
--start; --start;
if (t.size() <= start) break; if (t.size() <= start) break;
@ -2427,8 +2425,8 @@ void DialogsWidget::onCompleteHashtag(QString tag) {
} }
if (cur - start - 1 == tag.size() && cur < t.size() && t.at(cur) == ' ') ++cur; if (cur - start - 1 == tag.size() && cur < t.size() && t.at(cur) == ' ') ++cur;
r = t.mid(0, start + 1) + tag + ' ' + t.mid(cur); r = t.mid(0, start + 1) + tag + ' ' + t.mid(cur);
_filter.setText(r); _filter->setText(r);
_filter.setCursorPosition(start + 1 + tag.size() + 1); _filter->setCursorPosition(start + 1 + tag.size() + 1);
onFilterUpdate(true); onFilterUpdate(true);
return; return;
} }
@ -2436,22 +2434,23 @@ void DialogsWidget::onCompleteHashtag(QString tag) {
} }
if (!t.at(start).isLetterOrNumber() && t.at(start) != '_') break; if (!t.at(start).isLetterOrNumber() && t.at(start) != '_') break;
} }
_filter.setText(t.mid(0, cur) + '#' + tag + ' ' + t.mid(cur)); _filter->setText(t.mid(0, cur) + '#' + tag + ' ' + t.mid(cur));
_filter.setCursorPosition(cur + 1 + tag.size() + 1); _filter->setCursorPosition(cur + 1 + tag.size() + 1);
onFilterUpdate(true); onFilterUpdate(true);
} }
void DialogsWidget::resizeEvent(QResizeEvent *e) { void DialogsWidget::resizeEvent(QResizeEvent *e) {
int32 w = width(); int32 w = width();
_filter.setGeometry(st::dialogsPadding.x(), st::dialogsFilterPadding, w - 2 * st::dialogsPadding.x(), _filter.height()); _filter->setGeometryToLeft(st::dialogsFilterPadding.x() * 2 + _mainMenuToggle->width(), st::dialogsFilterPadding.y(), w - 3 * st::dialogsFilterPadding.x() - _mainMenuToggle->width(), _filter->height());
_newGroup->move(w - _newGroup->width() - st::dialogsPadding.x(), _filter.y()); _mainMenuToggle->moveToLeft(st::dialogsFilterPadding.x(), _filter->y());
_addContact->move(w - _addContact->width() - st::dialogsPadding.x(), _filter.y()); _cancelSearch->moveToRight(st::dialogsFilterPadding.x(), _filter->y());
_cancelSearch->move(w - _cancelSearch->width() - st::dialogsPadding.x(), _filter.y()); _scroll.move(0, _filter->height() + 2 * st::dialogsFilterPadding.y());
_scroll.move(0, _filter.height() + 2 * st::dialogsFilterPadding);
updateMainMenuGeometry();
int32 addToY = App::main() ? App::main()->contentScrollAddToY() : 0; int32 addToY = App::main() ? App::main()->contentScrollAddToY() : 0;
int32 newScrollY = _scroll.scrollTop() + addToY; int32 newScrollY = _scroll.scrollTop() + addToY;
_scroll.resize(w, height() - _filter.y() - _filter.height() - st::dialogsFilterPadding - st::dialogsPadding.y()); _scroll.resize(w, height() - _filter->y() - _filter->height() - st::dialogsFilterPadding.y() - st::dialogsPadding.y());
if (addToY) { if (addToY) {
_scroll.scrollToY(newScrollY); _scroll.scrollToY(newScrollY);
} else { } else {
@ -2459,6 +2458,12 @@ void DialogsWidget::resizeEvent(QResizeEvent *e) {
} }
} }
void DialogsWidget::updateMainMenuGeometry() {
if (!_mainMenu) return;
_mainMenu->moveToLeft(st::dialogsMenuPosition.x(), st::dialogsMenuPosition.y());
}
void DialogsWidget::keyPressEvent(QKeyEvent *e) { void DialogsWidget::keyPressEvent(QKeyEvent *e) {
if (e->key() == Qt::Key_Escape) { if (e->key() == Qt::Key_Escape) {
e->ignore(); e->ignore();
@ -2548,16 +2553,8 @@ Dialogs::IndexedList *DialogsWidget::dialogsList() {
return _inner.dialogsList(); return _inner.dialogsList();
} }
void DialogsWidget::onAddContact() {
Ui::showLayer(new AddContactBox(), KeepOtherLayers);
}
void DialogsWidget::onNewGroup() {
Ui::showLayer(new NewGroupBox());
}
bool DialogsWidget::onCancelSearch() { bool DialogsWidget::onCancelSearch() {
bool clearing = !_filter.getLastText().isEmpty(); bool clearing = !_filter->getLastText().isEmpty();
if (_searchRequest) { if (_searchRequest) {
MTP::cancel(_searchRequest); MTP::cancel(_searchRequest);
_searchRequest = 0; _searchRequest = 0;
@ -2571,8 +2568,8 @@ bool DialogsWidget::onCancelSearch() {
clearing = true; clearing = true;
} }
_inner.clearFilter(); _inner.clearFilter();
_filter.clear(); _filter->clear();
_filter.updatePlaceholder(); _filter->updatePlaceholder();
onFilterUpdate(); onFilterUpdate();
return clearing; return clearing;
} }
@ -2590,8 +2587,8 @@ void DialogsWidget::onCancelSearchInPeer() {
_inner.searchInPeer(0); _inner.searchInPeer(0);
} }
_inner.clearFilter(); _inner.clearFilter();
_filter.clear(); _filter->clear();
_filter.updatePlaceholder(); _filter->updatePlaceholder();
onFilterUpdate(); onFilterUpdate();
if (!Adaptive::OneColumn() && !App::main()->selectingPeer()) { if (!Adaptive::OneColumn() && !App::main()->selectingPeer()) {
emit cancelled(); emit cancelled();

View file

@ -31,10 +31,9 @@ class IndexedList;
namespace Ui { namespace Ui {
class IconButton; class IconButton;
class PopupMenu; class PopupMenu;
class DropdownMenu;
} // namespace Ui } // namespace Ui
class MainWidget;
enum DialogsSearchRequestType { enum DialogsSearchRequestType {
DialogsSearchFromStart, DialogsSearchFromStart,
DialogsSearchFromOffset, DialogsSearchFromOffset,
@ -48,7 +47,7 @@ class DialogsInner : public SplittedWidget, public RPCSender, private base::Subs
Q_OBJECT Q_OBJECT
public: public:
DialogsInner(QWidget *parent, MainWidget *main); DialogsInner(QWidget *parent, QWidget *main);
void dialogsReceived(const QVector<MTPDialog> &dialogs); void dialogsReceived(const QVector<MTPDialog> &dialogs);
void addSavedPeersAfter(const QDateTime &date); void addSavedPeersAfter(const QDateTime &date);
@ -238,7 +237,7 @@ class DialogsWidget : public TWidget, public RPCSender {
Q_OBJECT Q_OBJECT
public: public:
DialogsWidget(MainWidget *parent); DialogsWidget(QWidget *parent);
void dialogsReceived(const MTPmessages_Dialogs &dialogs, mtpRequestId req); void dialogsReceived(const MTPmessages_Dialogs &dialogs, mtpRequestId req);
void contactsReceived(const MTPcontacts_Contacts &contacts); void contactsReceived(const MTPcontacts_Contacts &contacts);
@ -295,17 +294,13 @@ public:
void notify_historyMuteUpdated(History *history); void notify_historyMuteUpdated(History *history);
signals: signals:
void cancelled(); void cancelled();
public slots: public slots:
void onCancel(); void onCancel();
void onListScroll(); void onListScroll();
void activate(); void activate();
void onFilterUpdate(bool force = false); void onFilterUpdate(bool force = false);
void onAddContact();
void onNewGroup();
bool onCancelSearch(); bool onCancelSearch();
void onCancelSearchInPeer(); void onCancelSearchInPeer();
@ -319,8 +314,11 @@ public slots:
void onChooseByDrag(); void onChooseByDrag();
private: private:
void showMainMenu();
void updateMainMenuGeometry();
bool _dragInScroll, _dragForward; bool _dragInScroll = false;
bool _dragForward = false;
QTimer _chooseByDragTimer; QTimer _chooseByDragTimer;
void unreadCountsReceived(const QVector<MTPDialog> &dialogs); void unreadCountsReceived(const QVector<MTPDialog> &dialogs);
@ -329,15 +327,16 @@ private:
bool searchFailed(DialogsSearchRequestType type, const RPCError &error, mtpRequestId req); bool searchFailed(DialogsSearchRequestType type, const RPCError &error, mtpRequestId req);
bool peopleFailed(const RPCError &error, mtpRequestId req); bool peopleFailed(const RPCError &error, mtpRequestId req);
bool _dialogsFull; bool _dialogsFull = false;
int32 _dialogsOffsetDate; int32 _dialogsOffsetDate = 0;
MsgId _dialogsOffsetId; MsgId _dialogsOffsetId = 0;
PeerData *_dialogsOffsetPeer; PeerData *_dialogsOffsetPeer = nullptr;
mtpRequestId _dialogsRequest, _contactsRequest; mtpRequestId _dialogsRequest = 0;
mtpRequestId _contactsRequest = 0;
FlatInput _filter; ChildWidget<Ui::IconButton> _mainMenuToggle;
ChildWidget<Ui::IconButton> _newGroup; ChildWidget<Ui::DropdownMenu> _mainMenu = { nullptr };
ChildWidget<Ui::IconButton> _addContact; ChildWidget<FlatInput> _filter;
ChildWidget<Ui::IconButton> _cancelSearch; ChildWidget<Ui::IconButton> _cancelSearch;
ScrollArea _scroll; ScrollArea _scroll;
DialogsInner _inner; DialogsInner _inner;
@ -347,11 +346,14 @@ private:
anim::ivalue a_coordUnder, a_coordOver; anim::ivalue a_coordUnder, a_coordOver;
anim::fvalue a_progress; anim::fvalue a_progress;
PeerData *_searchInPeer, *_searchInMigrated; PeerData *_searchInPeer = nullptr;
PeerData *_searchInMigrated = nullptr;
QTimer _searchTimer; QTimer _searchTimer;
QString _searchQuery, _peopleQuery; QString _searchQuery, _peopleQuery;
bool _searchFull, _searchFullMigrated, _peopleFull; bool _searchFull = false;
bool _searchFullMigrated = false;
bool _peopleFull = false;
mtpRequestId _searchRequest, _peopleRequest; mtpRequestId _searchRequest, _peopleRequest;
typedef QMap<QString, MTPmessages_Messages> SearchCache; typedef QMap<QString, MTPmessages_Messages> SearchCache;

View file

@ -151,11 +151,11 @@ introBackButton: IconButton {
icon: icon { icon: icon {
{ size(40px, 40px), #f2f2f2 }, { size(40px, 40px), #f2f2f2 },
{ "title_previous", #adadad, point(12px, 12px) }, { "title_back", #adadad, point(12px, 12px) },
}; };
iconOver: icon { iconOver: icon {
{ size(40px, 40px), #eeeeee }, { size(40px, 40px), #eeeeee },
{ "title_previous", #969696, point(12px, 12px) }, { "title_back", #969696, point(12px, 12px) },
}; };
iconPosition: point(0px, 0px); iconPosition: point(0px, 0px);

View file

@ -83,6 +83,7 @@ MainWidget::MainWidget(QWidget *parent) : TWidget(parent)
updateScrollColors(); updateScrollColors();
connect(_dialogs, SIGNAL(cancelled()), this, SLOT(dialogsCancelled())); connect(_dialogs, SIGNAL(cancelled()), this, SLOT(dialogsCancelled()));
connect(this, SIGNAL(dialogsUpdated()), this, SLOT(onListScroll()));
connect(_history, SIGNAL(cancelled()), _dialogs, SLOT(activate())); connect(_history, SIGNAL(cancelled()), _dialogs, SLOT(activate()));
connect(this, SIGNAL(peerPhotoChanged(PeerData*)), this, SIGNAL(dialogsUpdated())); connect(this, SIGNAL(peerPhotoChanged(PeerData*)), this, SIGNAL(dialogsUpdated()));
connect(&noUpdatesTimer, SIGNAL(timeout()), this, SLOT(mtpPing())); connect(&noUpdatesTimer, SIGNAL(timeout()), this, SLOT(mtpPing()));
@ -1448,14 +1449,6 @@ void MainWidget::checkLastUpdate(bool afterSleep) {
} }
} }
void MainWidget::showAddContact() {
_dialogs->onAddContact();
}
void MainWidget::showNewGroup() {
_dialogs->onNewGroup();
}
void MainWidget::overviewLoaded(History *history, const MTPmessages_Messages &result, mtpRequestId req) { void MainWidget::overviewLoaded(History *history, const MTPmessages_Messages &result, mtpRequestId req) {
OverviewsPreload::iterator it; OverviewsPreload::iterator it;
MediaOverviewType type = OverviewCount; MediaOverviewType type = OverviewCount;

View file

@ -312,8 +312,6 @@ public:
void loadMediaBack(PeerData *peer, MediaOverviewType type, bool many = false); void loadMediaBack(PeerData *peer, MediaOverviewType type, bool many = false);
void checkLastUpdate(bool afterSleep); void checkLastUpdate(bool afterSleep);
void showAddContact();
void showNewGroup();
void serviceNotification(const QString &msg, const MTPMessageMedia &media); void serviceNotification(const QString &msg, const MTPMessageMedia &media);
void serviceHistoryDone(const MTPmessages_Messages &msgs); void serviceHistoryDone(const MTPmessages_Messages &msgs);

View file

@ -44,7 +44,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "apiwrap.h" #include "apiwrap.h"
#include "settings/settings_widget.h" #include "settings/settings_widget.h"
#include "platform/platform_notifications_manager.h" #include "platform/platform_notifications_manager.h"
#include "platform/platform_window_title.h"
#include "window/notifications_manager.h" #include "window/notifications_manager.h"
#include "window/window_theme.h" #include "window/window_theme.h"
#include "window/window_theme_warning.h" #include "window/window_theme_warning.h"
@ -86,7 +85,7 @@ void ConnectingWidget::onReconnect() {
MTP::restart(); MTP::restart();
} }
MainWindow::MainWindow() : Platform::MainWindow(), _body(this) { MainWindow::MainWindow() {
icon16 = icon256.scaledToWidth(16, Qt::SmoothTransformation); icon16 = icon256.scaledToWidth(16, Qt::SmoothTransformation);
icon32 = icon256.scaledToWidth(32, Qt::SmoothTransformation); icon32 = icon256.scaledToWidth(32, Qt::SmoothTransformation);
icon64 = icon256.scaledToWidth(64, Qt::SmoothTransformation); icon64 = icon256.scaledToWidth(64, Qt::SmoothTransformation);
@ -105,15 +104,9 @@ MainWindow::MainWindow() : Platform::MainWindow(), _body(this) {
} }
}); });
if (objectName().isEmpty()) { resize(st::windowDefaultWidth, st::windowDefaultHeight);
setObjectName(qsl("MainWindow"));
}
resize(st::windowDefWidth, st::windowDefHeight);
setLocale(QLocale(QLocale::English, QLocale::UnitedStates)); setLocale(QLocale(QLocale::English, QLocale::UnitedStates));
setCentralWidget(_body);
QMetaObject::connectSlotsByName(this);
_inactiveTimer.setSingleShot(true); _inactiveTimer.setSingleShot(true);
connect(&_inactiveTimer, SIGNAL(timeout()), this, SLOT(onInactiveTimer())); connect(&_inactiveTimer, SIGNAL(timeout()), this, SLOT(onInactiveTimer()));
@ -162,26 +155,17 @@ void MainWindow::onStateChanged(Qt::WindowState state) {
if (state == Qt::WindowMinimized && cWorkMode() == dbiwmTrayOnly) { if (state == Qt::WindowMinimized && cWorkMode() == dbiwmTrayOnly) {
App::wnd()->minimizeToTray(); App::wnd()->minimizeToTray();
} }
psSavePosition(state); savePosition(state);
} }
void MainWindow::init() { void MainWindow::init() {
psInitFrameless(); Platform::MainWindow::init();
setWindowIcon(wndIcon);
_title = Platform::CreateTitleWidget(this); setWindowIcon(wndIcon);
Application::instance()->installEventFilter(this); Application::instance()->installEventFilter(this);
connect(windowHandle(), SIGNAL(windowStateChanged(Qt::WindowState)), this, SLOT(onStateChanged(Qt::WindowState))); connect(windowHandle(), SIGNAL(windowStateChanged(Qt::WindowState)), this, SLOT(onStateChanged(Qt::WindowState)));
connect(windowHandle(), SIGNAL(activeChanged()), this, SLOT(onWindowActiveChanged()), Qt::QueuedConnection); connect(windowHandle(), SIGNAL(activeChanged()), this, SLOT(onWindowActiveChanged()), Qt::QueuedConnection);
QPalette p(palette());
p.setColor(QPalette::Window, st::windowBg->c);
setPalette(p);
setMinimumWidth(st::windowMinWidth);
setMinimumHeight(st::windowMinHeight);
psInitSize();
} }
void MainWindow::onWindowActiveChanged() { void MainWindow::onWindowActiveChanged() {
@ -241,9 +225,7 @@ void MainWindow::clearWidgets() {
QPixmap MainWindow::grabInner() { QPixmap MainWindow::grabInner() {
QPixmap result; QPixmap result;
if (_settings) { if (_intro) {
result = myGrab(_settings);
} else if (_intro) {
result = myGrab(_intro); result = myGrab(_intro);
} else if (_main) { } else if (_main) {
result = myGrab(_main); result = myGrab(_main);
@ -274,13 +256,13 @@ void MainWindow::clearPasscode() {
} }
void MainWindow::setupPasscode(bool anim) { void MainWindow::setupPasscode(bool anim) {
QPixmap bg = grabInner(); auto bg = grabInner();
if (_passcode) { if (_passcode) {
_passcode->stop_show(); _passcode->stop_show();
_passcode.destroyDelayed(); _passcode.destroyDelayed();
} }
_passcode.create(_body); _passcode.create(bodyWidget());
updateControlsGeometry(); updateControlsGeometry();
if (_main) _main->hide(); if (_main) _main->hide();
@ -332,7 +314,7 @@ void MainWindow::setupIntro(bool anim) {
QPixmap bg = anim ? grabInner() : QPixmap(); QPixmap bg = anim ? grabInner() : QPixmap();
clearWidgets(); clearWidgets();
_intro.create(_body); _intro.create(bodyWidget());
updateControlsGeometry(); updateControlsGeometry();
if (anim) { if (anim) {
@ -382,7 +364,7 @@ void MainWindow::sendServiceHistoryRequest() {
void MainWindow::setupMain(bool anim, const MTPUser *self) { void MainWindow::setupMain(bool anim, const MTPUser *self) {
QPixmap bg = anim ? grabInner() : QPixmap(); QPixmap bg = anim ? grabInner() : QPixmap();
clearWidgets(); clearWidgets();
_main.create(_body); _main.create(bodyWidget());
updateControlsGeometry(); updateControlsGeometry();
if (anim) { if (anim) {
@ -418,7 +400,7 @@ void MainWindow::showSettings() {
} }
if (!_layerBg) { if (!_layerBg) {
_layerBg.create(_body); _layerBg.create(bodyWidget());
} }
_settings.create(this); _settings.create(this);
connect(_settings, SIGNAL(destroyed(QObject*)), this, SLOT(onSettingsDestroyed(QObject*))); connect(_settings, SIGNAL(destroyed(QObject*)), this, SLOT(onSettingsDestroyed(QObject*)));
@ -492,7 +474,7 @@ void MainWindow::showDocument(DocumentData *doc, HistoryItem *item) {
void MainWindow::ui_showLayer(LayerWidget *box, ShowLayerOptions options) { void MainWindow::ui_showLayer(LayerWidget *box, ShowLayerOptions options) {
if (box) { if (box) {
if (!_layerBg) { if (!_layerBg) {
_layerBg.create(_body); _layerBg.create(bodyWidget());
} }
if (options.testFlag(KeepOtherLayers)) { if (options.testFlag(KeepOtherLayers)) {
if (options.testFlag(ShowAfterOtherLayers)) { if (options.testFlag(ShowAfterOtherLayers)) {
@ -532,7 +514,7 @@ bool MainWindow::ui_isMediaViewShown() {
void MainWindow::ui_showMediaPreview(DocumentData *document) { void MainWindow::ui_showMediaPreview(DocumentData *document) {
if (!document || ((!document->isAnimation() || !document->loaded()) && !document->sticker())) return; if (!document || ((!document->isAnimation() || !document->loaded()) && !document->sticker())) return;
if (!_mediaPreview) { if (!_mediaPreview) {
_mediaPreview.create(_body); _mediaPreview.create(bodyWidget());
updateControlsGeometry(); updateControlsGeometry();
} }
if (_mediaPreview->isHidden()) { if (_mediaPreview->isHidden()) {
@ -544,7 +526,7 @@ void MainWindow::ui_showMediaPreview(DocumentData *document) {
void MainWindow::ui_showMediaPreview(PhotoData *photo) { void MainWindow::ui_showMediaPreview(PhotoData *photo) {
if (!photo) return; if (!photo) return;
if (!_mediaPreview) { if (!_mediaPreview) {
_mediaPreview.create(_body); _mediaPreview.create(bodyWidget());
updateControlsGeometry(); updateControlsGeometry();
} }
if (_mediaPreview->isHidden()) { if (_mediaPreview->isHidden()) {
@ -571,7 +553,7 @@ void MainWindow::showConnecting(const QString &text, const QString &reconnect) {
if (_connecting) { if (_connecting) {
_connecting->set(text, reconnect); _connecting->set(text, reconnect);
} else { } else {
_connecting.create(_body, text, reconnect); _connecting.create(bodyWidget(), text, reconnect);
updateControlsGeometry(); updateControlsGeometry();
fixOrder(); fixOrder();
} }
@ -586,15 +568,13 @@ void MainWindow::hideConnecting() {
void MainWindow::themeUpdated(const Window::Theme::BackgroundUpdate &data) { void MainWindow::themeUpdated(const Window::Theme::BackgroundUpdate &data) {
using Type = Window::Theme::BackgroundUpdate::Type; using Type = Window::Theme::BackgroundUpdate::Type;
if (data.type == Type::TestingTheme) { if (data.type == Type::TestingTheme) {
if (_title) _title->update();
if (!_testingThemeWarning) { if (!_testingThemeWarning) {
_testingThemeWarning.create(_body); _testingThemeWarning.create(bodyWidget());
_testingThemeWarning->setGeometry(rect()); _testingThemeWarning->setGeometry(rect());
_testingThemeWarning->setHiddenCallback([this] { _testingThemeWarning.destroyDelayed(); }); _testingThemeWarning->setHiddenCallback([this] { _testingThemeWarning.destroyDelayed(); });
} }
_testingThemeWarning->showAnimated(); _testingThemeWarning->showAnimated();
} else if (data.type == Type::RevertingTheme || data.type == Type::ApplyingTheme) { } else if (data.type == Type::RevertingTheme || data.type == Type::ApplyingTheme) {
if (_title) _title->update();
_testingThemeWarning->hideAnimated(); _testingThemeWarning->hideAnimated();
} }
} }
@ -659,44 +639,6 @@ void MainWindow::setInnerFocus() {
} }
} }
Window::HitTestResult MainWindow::hitTest(const QPoint &p) const {
int x(p.x()), y(p.y()), w(width()), h(height());
const int32 raw = psResizeRowWidth();
if (!windowState().testFlag(Qt::WindowMaximized)) {
if (y < raw) {
if (x < raw) {
return Window::HitTestResult::TopLeft;
} else if (x > w - raw - 1) {
return Window::HitTestResult::TopRight;
}
return Window::HitTestResult::Top;
} else if (y > h - raw - 1) {
if (x < raw) {
return Window::HitTestResult::BottomLeft;
} else if (x > w - raw - 1) {
return Window::HitTestResult::BottomRight;
}
return Window::HitTestResult::Bottom;
} else if (x < raw) {
return Window::HitTestResult::Left;
} else if (x > w - raw - 1) {
return Window::HitTestResult::Right;
}
}
auto titleTest = _title ? _title->hitTest(p - _title->geometry().topLeft()) : Window::HitTestResult::None;
if (titleTest != Window::HitTestResult::None) {
return titleTest;
} else if (x >= 0 && y >= 0 && x < w && y < h) {
return Window::HitTestResult::Client;
}
return Window::HitTestResult::None;
}
QRect MainWindow::iconRect() const {
return _title ? _title->iconRect() : QRect();
}
bool MainWindow::eventFilter(QObject *obj, QEvent *e) { bool MainWindow::eventFilter(QObject *obj, QEvent *e) {
switch (e->type()) { switch (e->type()) {
case QEvent::MouseButtonPress: case QEvent::MouseButtonPress:
@ -757,7 +699,7 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *e) {
case QEvent::Move: case QEvent::Move:
case QEvent::Resize: case QEvent::Resize:
if (obj == this) { if (obj == this) {
psUpdatedPosition(); positionUpdated();
} }
break; break;
} }
@ -821,13 +763,17 @@ void MainWindow::updateTrayMenu(bool force) {
void MainWindow::onShowAddContact() { void MainWindow::onShowAddContact() {
if (isHidden()) showFromTray(); if (isHidden()) showFromTray();
if (_main) _main->showAddContact(); if (App::self()) {
Ui::showLayer(new AddContactBox(), KeepOtherLayers);
}
} }
void MainWindow::onShowNewGroup() { void MainWindow::onShowNewGroup() {
if (isHidden()) showFromTray(); if (isHidden()) showFromTray();
if (_main) Ui::showLayer(new GroupInfoBox(CreatingGroupGroup, false), KeepOtherLayers); if (App::self()) {
Ui::showLayer(new GroupInfoBox(CreatingGroupGroup, false), KeepOtherLayers);
}
} }
void MainWindow::onShowNewChannel() { void MainWindow::onShowNewChannel() {
@ -906,7 +852,6 @@ void MainWindow::layerFinishedHide(LayerStackWidget *was) {
} }
void MainWindow::fixOrder() { void MainWindow::fixOrder() {
if (_title) _title->raise();
if (_layerBg) _layerBg->raise(); if (_layerBg) _layerBg->raise();
if (_mediaPreview) _mediaPreview->raise(); if (_mediaPreview) _mediaPreview->raise();
if (_connecting) _connecting->raise(); if (_connecting) _connecting->raise();
@ -980,7 +925,7 @@ void MainWindow::closeEvent(QCloseEvent *e) {
} }
void MainWindow::resizeEvent(QResizeEvent *e) { void MainWindow::resizeEvent(QResizeEvent *e) {
if (!_title) return; Platform::MainWindow::resizeEvent(e);
Adaptive::Layout layout = Adaptive::OneColumnLayout; Adaptive::Layout layout = Adaptive::OneColumnLayout;
if (width() > st::adaptiveWideWidth) { if (width() > st::adaptiveWideWidth) {
@ -993,17 +938,11 @@ void MainWindow::resizeEvent(QResizeEvent *e) {
Adaptive::Changed().notify(true); Adaptive::Changed().notify(true);
} }
auto bodyTop = 0;
if (_title) {
_title->setGeometry(0, bodyTop, width(), st::titleHeight);
bodyTop += _title->height();
}
_body->setGeometry(0, bodyTop, width(), height() - bodyTop);
updateControlsGeometry(); updateControlsGeometry();
} }
void MainWindow::updateControlsGeometry() { void MainWindow::updateControlsGeometry() {
auto body = _body->rect(); auto body = bodyWidget()->rect();
if (_passcode) _passcode->setGeometry(body); if (_passcode) _passcode->setGeometry(body);
if (_main) _main->setGeometry(body); if (_main) _main->setGeometry(body);
if (_intro) _intro->setGeometry(body); if (_intro) _intro->setGeometry(body);

View file

@ -23,7 +23,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "pspecific.h" #include "pspecific.h"
#include "ui/effects/rect_shadow.h" #include "ui/effects/rect_shadow.h"
#include "platform/platform_main_window.h" #include "platform/platform_main_window.h"
#include "window/window_title.h"
#include "core/single_timer.h" #include "core/single_timer.h"
class MediaView; class MediaView;
@ -71,7 +70,7 @@ private:
class MediaPreviewWidget; class MediaPreviewWidget;
class MainWindow : public Platform::MainWindow, private base::Subscriber { class MainWindow : public Platform::MainWindow {
Q_OBJECT Q_OBJECT
public: public:
@ -97,9 +96,6 @@ public:
void mtpStateChanged(int32 dc, int32 state); void mtpStateChanged(int32 dc, int32 state);
Window::HitTestResult hitTest(const QPoint &p) const;
QRect iconRect() const;
IntroWidget *introWidget(); IntroWidget *introWidget();
MainWidget *mainWidget(); MainWidget *mainWidget();
PasscodeWidget *passcodeWidget(); PasscodeWidget *passcodeWidget();
@ -233,14 +229,10 @@ private:
void placeSmallCounter(QImage &img, int size, int count, const style::color &bg, const QPoint &shift, const style::color &color); void placeSmallCounter(QImage &img, int size, int count, const style::color &bg, const QPoint &shift, const style::color &color);
QImage icon16, icon32, icon64, iconbig16, iconbig32, iconbig64; QImage icon16, icon32, icon64, iconbig16, iconbig32, iconbig64;
QWidget *centralwidget;
typedef QPair<QString, MTPMessageMedia> DelayedServiceMsg; typedef QPair<QString, MTPMessageMedia> DelayedServiceMsg;
QVector<DelayedServiceMsg> _delayedServiceMsgs; QVector<DelayedServiceMsg> _delayedServiceMsgs;
mtpRequestId _serviceHistoryRequest = 0; mtpRequestId _serviceHistoryRequest = 0;
Window::TitleWidget *_title = nullptr;
ChildWidget<TWidget> _body;
ChildWidget<PasscodeWidget> _passcode = { nullptr }; ChildWidget<PasscodeWidget> _passcode = { nullptr };
ChildWidget<IntroWidget> _intro = { nullptr }; ChildWidget<IntroWidget> _intro = { nullptr };
ChildWidget<MainWidget> _main = { nullptr }; ChildWidget<MainWidget> _main = { nullptr };

View file

@ -125,11 +125,11 @@ mediaPlayerNextDisabledIcon: icon {
}; };
mediaPlayerPreviousButton: IconButton(mediaPlayerNextButton) { mediaPlayerPreviousButton: IconButton(mediaPlayerNextButton) {
icon: icon { icon: icon {
{ "player_previous", mediaPlayerActiveFg, mediaPlayerSkipIconPosition }, { "player_next-flip_horizontal", mediaPlayerActiveFg, mediaPlayerSkipIconPosition },
}; };
} }
mediaPlayerPreviousDisabledIcon: icon { mediaPlayerPreviousDisabledIcon: icon {
{ "player_previous", mediaPlayerInactiveFg, mediaPlayerSkipIconPosition }, { "player_next-flip_horizontal", mediaPlayerInactiveFg, mediaPlayerSkipIconPosition },
}; };
mediaPlayerClose: IconButton(mediaPlayerRepeatButton) { mediaPlayerClose: IconButton(mediaPlayerRepeatButton) {
width: 37px; width: 37px;
@ -178,10 +178,10 @@ mediaPlayerPanelNextDisabledIcon: icon {
{ "player_panel_next", mediaPlayerInactiveFg, point(10px, 10px) }, { "player_panel_next", mediaPlayerInactiveFg, point(10px, 10px) },
}; };
mediaPlayerPanelPreviousButton: IconButton(mediaPlayerPanelNextButton) { mediaPlayerPanelPreviousButton: IconButton(mediaPlayerPanelNextButton) {
icon: icon {{ "player_panel_previous", mediaPlayerActiveFg, point(10px, 10px) }}; icon: icon {{ "player_panel_next-flip_horizontal", mediaPlayerActiveFg, point(10px, 10px) }};
} }
mediaPlayerPanelPreviousDisabledIcon: icon { mediaPlayerPanelPreviousDisabledIcon: icon {
{ "player_panel_previous", mediaPlayerInactiveFg, point(10px, 10px) }, { "player_panel_next-flip_horizontal", mediaPlayerInactiveFg, point(10px, 10px) },
}; };
mediaPlayerPanelPadding: 16px; mediaPlayerPanelPadding: 16px;

View file

@ -81,7 +81,7 @@ mediaviewVolumeOnIconOver: icon {{ "media_volume", mediaviewPlaybackActiveOver,
mediaviewVolumeIconTop: 8px; mediaviewVolumeIconTop: 8px;
mediaviewControllerRadius: 25px; mediaviewControllerRadius: 25px;
mediaviewLeft: icon {{ "mediaview_previous", #ffffff }}; mediaviewLeft: icon {{ "mediaview_next-flip_horizontal", #ffffff }};
mediaviewRight: icon {{ "mediaview_next", #ffffff }}; mediaviewRight: icon {{ "mediaview_next", #ffffff }};
mediaviewClose: icon {{ "mediaview_close", #ffffff }}; mediaviewClose: icon {{ "mediaview_close", #ffffff }};
mediaviewSave: icon {{ "mediaview_download", #ffffff }}; mediaviewSave: icon {{ "mediaview_download", #ffffff }};

View file

@ -54,7 +54,7 @@ OverviewInner::OverviewInner(OverviewWidget *overview, ScrollArea *scroll, PeerD
, _history(App::history(_peer->id)) , _history(App::history(_peer->id))
, _channel(peerToChannel(_peer->id)) , _channel(peerToChannel(_peer->id))
, _rowWidth(st::msgMinWidth) , _rowWidth(st::msgMinWidth)
, _search(this, st::dlgFilter, lang(lng_dlg_filter)) , _search(this, st::dialogsFilter, lang(lng_dlg_filter))
, _cancelSearch(this, st::dialogsCancelSearch) , _cancelSearch(this, st::dialogsCancelSearch)
, _itemsToBeLoaded(LinksOverviewPerPage * 2) , _itemsToBeLoaded(LinksOverviewPerPage * 2)
, _width(st::windowMinWidth) { , _width(st::windowMinWidth) {

View file

@ -431,89 +431,6 @@ void MainWindow::LibsLoaded() {
#endif // !TDESKTOP_DISABLE_UNITY_INTEGRATION #endif // !TDESKTOP_DISABLE_UNITY_INTEGRATION
} }
void MainWindow::psInitSize() {
TWindowPos pos(cWindowPos());
QRect avail(QDesktopWidget().availableGeometry());
bool maximized = false;
QRect geom(avail.x() + (avail.width() - st::windowDefWidth) / 2, avail.y() + (avail.height() - st::windowDefHeight) / 2, st::windowDefWidth, st::windowDefHeight);
if (pos.w && pos.h) {
QList<QScreen*> screens = Application::screens();
for (QList<QScreen*>::const_iterator i = screens.cbegin(), e = screens.cend(); i != e; ++i) {
QByteArray name = (*i)->name().toUtf8();
if (pos.moncrc == hashCrc32(name.constData(), name.size())) {
QRect screen((*i)->geometry());
int32 w = screen.width(), h = screen.height();
if (w >= st::windowMinWidth && h >= st::windowMinHeight) {
if (pos.w > w) pos.w = w;
if (pos.h > h) pos.h = h;
pos.x += screen.x();
pos.y += screen.y();
if (pos.x < screen.x() + screen.width() - 10 && pos.y < screen.y() + screen.height() - 10) {
geom = QRect(pos.x, pos.y, pos.w, pos.h);
}
}
break;
}
}
if (pos.y < 0) pos.y = 0;
maximized = pos.maximized;
}
setGeometry(geom);
}
void MainWindow::psInitFrameless() {
psUpdatedPositionTimer.setSingleShot(true);
connect(&psUpdatedPositionTimer, SIGNAL(timeout()), this, SLOT(psSavePosition()));
}
void MainWindow::psSavePosition(Qt::WindowState state) {
if (state == Qt::WindowActive) state = windowHandle()->windowState();
if (state == Qt::WindowMinimized || !posInited) return;
TWindowPos pos(cWindowPos()), curPos = pos;
if (state == Qt::WindowMaximized) {
curPos.maximized = 1;
} else {
QRect r(geometry());
curPos.x = r.x();
curPos.y = r.y();
curPos.w = r.width();
curPos.h = r.height();
curPos.maximized = 0;
}
int px = curPos.x + curPos.w / 2, py = curPos.y + curPos.h / 2, d = 0;
QScreen *chosen = 0;
QList<QScreen*> screens = Application::screens();
for (QList<QScreen*>::const_iterator i = screens.cbegin(), e = screens.cend(); i != e; ++i) {
int dx = (*i)->geometry().x() + (*i)->geometry().width() / 2 - px; if (dx < 0) dx = -dx;
int dy = (*i)->geometry().y() + (*i)->geometry().height() / 2 - py; if (dy < 0) dy = -dy;
if (!chosen || dx + dy < d) {
d = dx + dy;
chosen = *i;
}
}
if (chosen) {
curPos.x -= chosen->geometry().x();
curPos.y -= chosen->geometry().y();
QByteArray name = chosen->name().toUtf8();
curPos.moncrc = hashCrc32(name.constData(), name.size());
}
if (curPos.w >= st::wndMinWidth && curPos.h >= st::wndMinHeight) {
if (curPos.x != pos.x || curPos.y != pos.y || curPos.w != pos.w || curPos.h != pos.h || curPos.moncrc != pos.moncrc || curPos.maximized != pos.maximized) {
cSetWindowPos(curPos);
Local::writeSettings();
}
}
}
void MainWindow::psUpdatedPosition() {
psUpdatedPositionTimer.start(SaveWindowPositionTimeout);
}
void MainWindow::psCreateTrayIcon() { void MainWindow::psCreateTrayIcon() {
if (!noQtTrayIcon) { if (!noQtTrayIcon) {
cSetSupportTray(QSystemTrayIcon::isSystemTrayAvailable()); cSetSupportTray(QSystemTrayIcon::isSystemTrayAvailable());
@ -641,7 +558,7 @@ void MainWindow::psFirstShow() {
show(); show();
} }
posInited = true; setPositionInited();
} }
void MainWindow::psInitSysMenu() { void MainWindow::psInitSysMenu() {

View file

@ -30,18 +30,10 @@ class MainWindow : public Window::MainWindow {
public: public:
MainWindow(); MainWindow();
int32 psResizeRowWidth() const {
return 0;//st::wndResizeAreaWidth;
}
void psInitFrameless();
void psInitSize();
void psFirstShow(); void psFirstShow();
void psInitSysMenu(); void psInitSysMenu();
void psUpdateSysMenu(Qt::WindowState state); void psUpdateSysMenu(Qt::WindowState state);
void psUpdateMargins(); void psUpdateMargins();
void psUpdatedPosition();
void psFlash(); void psFlash();
void psNotifySettingGot(); void psNotifySettingGot();
@ -51,10 +43,6 @@ public:
void psRefreshTaskbarIcon() { void psRefreshTaskbarIcon() {
} }
bool psPosInited() const {
return posInited;
}
void psUpdateCounter(); void psUpdateCounter();
bool psHasNativeNotifications(); bool psHasNativeNotifications();
@ -66,7 +54,6 @@ public:
~MainWindow(); ~MainWindow();
public slots: public slots:
void psSavePosition(Qt::WindowState state = Qt::WindowActive);
void psShowTrayMenu(); void psShowTrayMenu();
void psStatusIconCheck(); void psStatusIconCheck();
@ -76,7 +63,6 @@ protected:
bool psHasTrayIcon() const; bool psHasTrayIcon() const;
bool posInited = false;
QSystemTrayIcon *trayIcon = nullptr; QSystemTrayIcon *trayIcon = nullptr;
QMenu *trayIconMenu = nullptr; QMenu *trayIconMenu = nullptr;
QImage icon256, iconbig256; QImage icon256, iconbig256;

View file

@ -38,18 +38,10 @@ class MainWindow : public Window::MainWindow {
public: public:
MainWindow(); MainWindow();
int32 psResizeRowWidth() const {
return 0;//st::wndResizeAreaWidth;
}
void psInitFrameless();
void psInitSize();
void psFirstShow(); void psFirstShow();
void psInitSysMenu(); void psInitSysMenu();
void psUpdateSysMenu(Qt::WindowState state); void psUpdateSysMenu(Qt::WindowState state);
void psUpdateMargins(); void psUpdateMargins();
void psUpdatedPosition();
void psFlash(); void psFlash();
@ -58,10 +50,6 @@ public:
void psRefreshTaskbarIcon() { void psRefreshTaskbarIcon() {
} }
bool psPosInited() const {
return posInited;
}
bool psFilterNativeEvent(void *event); bool psFilterNativeEvent(void *event);
bool eventFilter(QObject *obj, QEvent *evt) override; bool eventFilter(QObject *obj, QEvent *evt) override;
@ -79,7 +67,6 @@ public:
~MainWindow(); ~MainWindow();
public slots: public slots:
void psSavePosition(Qt::WindowState state = Qt::WindowActive);
void psShowTrayMenu(); void psShowTrayMenu();
void psMacUndo(); void psMacUndo();
@ -103,7 +90,6 @@ protected:
void psMacUpdateMenu(); void psMacUpdateMenu();
bool posInited;
QSystemTrayIcon *trayIcon = nullptr; QSystemTrayIcon *trayIcon = nullptr;
QMenu *trayIconMenu = nullptr; QMenu *trayIconMenu = nullptr;
QImage icon256, iconbig256; QImage icon256, iconbig256;
@ -118,6 +104,8 @@ protected:
QTimer psUpdatedPositionTimer; QTimer psUpdatedPositionTimer;
private: private:
void createGlobalMenu();
MacPrivate _private; MacPrivate _private;
mutable bool psIdle; mutable bool psIdle;

View file

@ -52,8 +52,7 @@ void MacPrivate::darkModeChanged() {
} }
MainWindow::MainWindow() MainWindow::MainWindow()
: posInited(false) : icon256(qsl(":/gui/art/icon256.png"))
, icon256(qsl(":/gui/art/icon256.png"))
, iconbig256(qsl(":/gui/art/iconbig256.png")) , iconbig256(qsl(":/gui/art/iconbig256.png"))
, wndIcon(QPixmap::fromImage(iconbig256, Qt::ColorOnly)) { , wndIcon(QPixmap::fromImage(iconbig256, Qt::ColorOnly)) {
QImage tray(qsl(":/gui/art/osxtray.png")); QImage tray(qsl(":/gui/art/osxtray.png"));
@ -190,89 +189,11 @@ void MainWindow::psUpdateCounter() {
} }
} }
void MainWindow::psInitSize() {
TWindowPos pos(cWindowPos());
QRect avail(QDesktopWidget().availableGeometry());
bool maximized = false;
QRect geom(avail.x() + (avail.width() - st::windowDefWidth) / 2, avail.y() + (avail.height() - st::windowDefHeight) / 2, st::windowDefWidth, st::windowDefHeight);
if (pos.w && pos.h) {
QList<QScreen*> screens = Application::screens();
for (QList<QScreen*>::const_iterator i = screens.cbegin(), e = screens.cend(); i != e; ++i) {
QByteArray name = (*i)->name().toUtf8();
if (pos.moncrc == hashCrc32(name.constData(), name.size())) {
QRect screen((*i)->geometry());
int32 w = screen.width(), h = screen.height();
if (w >= st::windowMinWidth && h >= st::windowMinHeight) {
if (pos.w > w) pos.w = w;
if (pos.h > h) pos.h = h;
pos.x += screen.x();
pos.y += screen.y();
if (pos.x < screen.x() + screen.width() - 10 && pos.y < screen.y() + screen.height() - 10) {
geom = QRect(pos.x, pos.y, pos.w, pos.h);
}
}
break;
}
}
if (pos.y < 0) pos.y = 0;
maximized = pos.maximized;
}
setGeometry(geom);
}
void MainWindow::psInitFrameless() { void MainWindow::psInitFrameless() {
psUpdatedPositionTimer.setSingleShot(true); psUpdatedPositionTimer.setSingleShot(true);
connect(&psUpdatedPositionTimer, SIGNAL(timeout()), this, SLOT(psSavePosition())); connect(&psUpdatedPositionTimer, SIGNAL(timeout()), this, SLOT(psSavePosition()));
} }
void MainWindow::psSavePosition(Qt::WindowState state) {
if (state == Qt::WindowActive) state = windowHandle()->windowState();
if (state == Qt::WindowMinimized || !posInited) return;
TWindowPos pos(cWindowPos()), curPos = pos;
if (state == Qt::WindowMaximized) {
curPos.maximized = 1;
} else {
QRect r(geometry());
curPos.x = r.x();
curPos.y = r.y();
curPos.w = r.width();
curPos.h = r.height();
curPos.maximized = 0;
}
int px = curPos.x + curPos.w / 2, py = curPos.y + curPos.h / 2, d = 0;
QScreen *chosen = 0;
QList<QScreen*> screens = Application::screens();
for (QList<QScreen*>::const_iterator i = screens.cbegin(), e = screens.cend(); i != e; ++i) {
int dx = (*i)->geometry().x() + (*i)->geometry().width() / 2 - px; if (dx < 0) dx = -dx;
int dy = (*i)->geometry().y() + (*i)->geometry().height() / 2 - py; if (dy < 0) dy = -dy;
if (!chosen || dx + dy < d) {
d = dx + dy;
chosen = *i;
}
}
if (chosen) {
curPos.x -= chosen->geometry().x();
curPos.y -= chosen->geometry().y();
QByteArray name = chosen->name().toUtf8();
curPos.moncrc = hashCrc32(name.constData(), name.size());
}
if (curPos.w >= st::wndMinWidth && curPos.h >= st::wndMinHeight) {
if (curPos.x != pos.x || curPos.y != pos.y || curPos.w != pos.w || curPos.h != pos.h || curPos.moncrc != pos.moncrc || curPos.maximized != pos.maximized) {
cSetWindowPos(curPos);
Local::writeSettings();
}
}
}
void MainWindow::psUpdatedPosition() {
psUpdatedPositionTimer.start(SaveWindowPositionTimeout);
}
void MainWindow::psFirstShow() { void MainWindow::psFirstShow() {
psUpdateMargins(); psUpdateMargins();
@ -296,9 +217,14 @@ void MainWindow::psFirstShow() {
show(); show();
} }
posInited = true; setPositionInited();
// init global menu createGlobalMenu();
psMacUpdateMenu();
}
void MainWindow::createGlobalMenu() {
auto main = psMainMenu.addMenu(qsl("Telegram")); auto main = psMainMenu.addMenu(qsl("Telegram"));
auto about = main->addAction(lng_mac_menu_about_telegram(lt_telegram, qsl("Telegram"))); auto about = main->addAction(lng_mac_menu_about_telegram(lt_telegram, qsl("Telegram")));
connect(about, SIGNAL(triggered()), base::lambda_slot(about, [] { connect(about, SIGNAL(triggered()), base::lambda_slot(about, [] {
@ -339,8 +265,6 @@ void MainWindow::psFirstShow() {
psNewChannel = window->addAction(lang(lng_mac_menu_new_channel), App::wnd(), SLOT(onShowNewChannel())); psNewChannel = window->addAction(lang(lng_mac_menu_new_channel), App::wnd(), SLOT(onShowNewChannel()));
window->addSeparator(); window->addSeparator();
psShowTelegram = window->addAction(lang(lng_mac_menu_show), App::wnd(), SLOT(showFromTray())); psShowTelegram = window->addAction(lang(lng_mac_menu_show), App::wnd(), SLOT(showFromTray()));
psMacUpdateMenu();
} }
namespace { namespace {
@ -398,23 +322,23 @@ void MainWindow::psUpdateMargins() {
} }
void MainWindow::psMacUpdateMenu() { void MainWindow::psMacUpdateMenu() {
if (!posInited) return; if (!positionInited()) return;
QWidget *focused = QApplication::focusWidget(); QWidget *focused = QApplication::focusWidget();
bool isLogged = !!App::self(), canUndo = false, canRedo = false, canCut = false, canCopy = false, canPaste = false, canDelete = false, canSelectAll = false; bool isLogged = !!App::self(), canUndo = false, canRedo = false, canCut = false, canCopy = false, canPaste = false, canDelete = false, canSelectAll = false;
if (QLineEdit *edit = qobject_cast<QLineEdit*>(focused)) { if (auto edit = qobject_cast<QLineEdit*>(focused)) {
canCut = canCopy = canDelete = edit->hasSelectedText(); canCut = canCopy = canDelete = edit->hasSelectedText();
canSelectAll = !edit->text().isEmpty(); canSelectAll = !edit->text().isEmpty();
canUndo = edit->isUndoAvailable(); canUndo = edit->isUndoAvailable();
canRedo = edit->isRedoAvailable(); canRedo = edit->isRedoAvailable();
canPaste = !Application::clipboard()->text().isEmpty(); canPaste = !Application::clipboard()->text().isEmpty();
} else if (FlatTextarea *edit = qobject_cast<FlatTextarea*>(focused)) { } else if (auto edit = qobject_cast<FlatTextarea*>(focused)) {
canCut = canCopy = canDelete = edit->textCursor().hasSelection(); canCut = canCopy = canDelete = edit->textCursor().hasSelection();
canSelectAll = !edit->isEmpty(); canSelectAll = !edit->isEmpty();
canUndo = edit->isUndoAvailable(); canUndo = edit->isUndoAvailable();
canRedo = edit->isRedoAvailable(); canRedo = edit->isRedoAvailable();
canPaste = !Application::clipboard()->text().isEmpty(); canPaste = !Application::clipboard()->text().isEmpty();
} else if (HistoryInner *list = qobject_cast<HistoryInner*>(focused)) { } else if (auto list = qobject_cast<HistoryInner*>(focused)) {
canCopy = list->canCopySelected(); canCopy = list->canCopySelected();
canDelete = list->canDeleteSelected(); canDelete = list->canDeleteSelected();
} }

View file

@ -194,7 +194,7 @@ public:
max_w = avail.width(); max_w = avail.width();
accumulate_max(max_w, st::windowMinWidth); accumulate_max(max_w, st::windowMinWidth);
max_h = avail.height(); max_h = avail.height();
accumulate_max(max_h, st::windowMinHeight); accumulate_max(max_h, st::titleHeight + st::windowMinHeight);
HINSTANCE appinst = (HINSTANCE)GetModuleHandle(0); HINSTANCE appinst = (HINSTANCE)GetModuleHandle(0);
HWND hwnd = App::wnd() ? App::wnd()->psHwnd() : 0; HWND hwnd = App::wnd() ? App::wnd()->psHwnd() : 0;
@ -350,7 +350,7 @@ public:
} }
return; return;
} }
if (!App::wnd()->psPosInited()) return; if (!App::wnd()->positionInited()) return;
int x = _x, y = _y, w = _w, h = _h; int x = _x, y = _y, w = _w, h = _h;
if (pos && (!(pos->flags & SWP_NOMOVE) || !(pos->flags & SWP_NOSIZE) || !(pos->flags & SWP_NOREPOSITION))) { if (pos && (!(pos->flags & SWP_NOMOVE) || !(pos->flags & SWP_NOSIZE) || !(pos->flags & SWP_NOREPOSITION))) {
@ -644,6 +644,17 @@ void MainWindow::psShowTrayMenu() {
trayIconMenu->popup(QCursor::pos()); trayIconMenu->popup(QCursor::pos());
} }
int32 MainWindow::screenNameChecksum(const QString &name) const {
constexpr int DeviceNameSize = base::array_size(MONITORINFOEX().szDevice);
wchar_t buffer[DeviceNameSize] = { 0 };
if (name.size() < DeviceNameSize) {
name.toWCharArray(buffer);
} else {
memcpy(buffer, name.toStdWString().data(), sizeof(buffer));
}
return hashCrc32(buffer, sizeof(buffer));
}
void MainWindow::psRefreshTaskbarIcon() { void MainWindow::psRefreshTaskbarIcon() {
QWidget *w = new QWidget(this); QWidget *w = new QWidget(this);
w->setWindowFlags(static_cast<Qt::WindowFlags>(Qt::Tool) | Qt::FramelessWindowHint); w->setWindowFlags(static_cast<Qt::WindowFlags>(Qt::Tool) | Qt::FramelessWindowHint);
@ -754,58 +765,7 @@ void MainWindow::psUpdateCounter() {
SetWindowPos(ps_hWnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); SetWindowPos(ps_hWnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
} }
namespace { void MainWindow::initHook() {
HMONITOR enumMonitor = 0;
RECT enumMonitorWork;
BOOL CALLBACK _monitorEnumProc(
_In_ HMONITOR hMonitor,
_In_ HDC hdcMonitor,
_In_ LPRECT lprcMonitor,
_In_ LPARAM dwData
) {
MONITORINFOEX info;
info.cbSize = sizeof(info);
GetMonitorInfo(hMonitor, &info);
if (dwData == hashCrc32(info.szDevice, sizeof(info.szDevice))) {
enumMonitor = hMonitor;
enumMonitorWork = info.rcWork;
return FALSE;
}
return TRUE;
}
} // namespace
void MainWindow::psInitSize() {
TWindowPos pos(cWindowPos());
QRect avail(Sandbox::availableGeometry());
bool maximized = false;
QRect geom(avail.x() + (avail.width() - st::windowDefWidth) / 2, avail.y() + (avail.height() - st::windowDefHeight) / 2, st::windowDefWidth, st::windowDefHeight);
if (pos.w && pos.h) {
if (pos.y < 0) pos.y = 0;
enumMonitor = 0;
EnumDisplayMonitors(0, 0, &_monitorEnumProc, pos.moncrc);
if (enumMonitor) {
int32 w = enumMonitorWork.right - enumMonitorWork.left, h = enumMonitorWork.bottom - enumMonitorWork.top;
if (w >= st::windowMinWidth && h >= st::windowMinHeight) {
if (pos.w > w) pos.w = w;
if (pos.h > h) pos.h = h;
pos.x += enumMonitorWork.left;
pos.y += enumMonitorWork.top;
if (pos.x < enumMonitorWork.right - 10 && pos.y < enumMonitorWork.bottom - 10) {
geom = QRect(pos.x, pos.y, pos.w, pos.h);
}
}
}
maximized = pos.maximized;
}
setGeometry(geom);
}
void MainWindow::psInitFrameless() {
psUpdatedPositionTimer.setSingleShot(true);
connect(&psUpdatedPositionTimer, SIGNAL(timeout()), this, SLOT(psSavePosition()));
auto platformInterface = QGuiApplication::platformNativeInterface(); auto platformInterface = QGuiApplication::platformNativeInterface();
ps_hWnd = static_cast<HWND>(platformInterface->nativeResourceForWindow(QByteArrayLiteral("handle"), windowHandle())); ps_hWnd = static_cast<HWND>(platformInterface->nativeResourceForWindow(QByteArrayLiteral("handle"), windowHandle()));
@ -816,53 +776,9 @@ void MainWindow::psInitFrameless() {
Dlls::WTSRegisterSessionNotification(ps_hWnd, NOTIFY_FOR_THIS_SESSION); Dlls::WTSRegisterSessionNotification(ps_hWnd, NOTIFY_FOR_THIS_SESSION);
} }
// RegisterApplicationRestart(NULL, 0);
psInitSysMenu(); psInitSysMenu();
} }
void MainWindow::psSavePosition(Qt::WindowState state) {
if (state == Qt::WindowActive) state = windowHandle()->windowState();
if (state == Qt::WindowMinimized || !posInited) return;
TWindowPos pos(cWindowPos()), curPos = pos;
if (state == Qt::WindowMaximized) {
curPos.maximized = 1;
} else {
RECT w;
GetWindowRect(ps_hWnd, &w);
curPos.x = w.left;
curPos.y = w.top;
curPos.w = w.right - w.left;
curPos.h = w.bottom - w.top;
curPos.maximized = 0;
}
HMONITOR hMonitor = MonitorFromWindow(ps_hWnd, MONITOR_DEFAULTTONEAREST);
if (hMonitor) {
MONITORINFOEX info;
info.cbSize = sizeof(info);
GetMonitorInfo(hMonitor, &info);
if (!curPos.maximized) {
curPos.x -= info.rcWork.left;
curPos.y -= info.rcWork.top;
}
curPos.moncrc = hashCrc32(info.szDevice, sizeof(info.szDevice));
}
if (curPos.w >= st::windowMinWidth && curPos.h >= st::windowMinHeight) {
if (curPos.x != pos.x || curPos.y != pos.y || curPos.w != pos.w || curPos.h != pos.h || curPos.moncrc != pos.moncrc || curPos.maximized != pos.maximized) {
cSetWindowPos(curPos);
Local::writeSettings();
}
}
}
void MainWindow::psUpdatedPosition() {
psUpdatedPositionTimer.start(SaveWindowPositionTimeout);
}
bool MainWindow::psHasNativeNotifications() { bool MainWindow::psHasNativeNotifications() {
return Notifications::supported(); return Notifications::supported();
} }
@ -894,7 +810,7 @@ void MainWindow::psFirstShow() {
show(); show();
} }
posInited = true; setPositionInited();
if (showShadows) { if (showShadows) {
shadowsUpdate(ShadowsChange::Moved | ShadowsChange::Resized | ShadowsChange::Shown); shadowsUpdate(ShadowsChange::Moved | ShadowsChange::Resized | ShadowsChange::Shown);
} }

View file

@ -35,12 +35,6 @@ class MainWindow : public Window::MainWindow {
public: public:
MainWindow(); MainWindow();
int32 psResizeRowWidth() const {
return 0;//st::wndResizeAreaWidth;
}
void psInitFrameless();
void psInitSize();
HWND psHwnd() const; HWND psHwnd() const;
HMENU psMenu() const; HMENU psMenu() const;
@ -48,7 +42,6 @@ public:
void psInitSysMenu(); void psInitSysMenu();
void psUpdateSysMenu(Qt::WindowState state); void psUpdateSysMenu(Qt::WindowState state);
void psUpdateMargins(); void psUpdateMargins();
void psUpdatedPosition();
void psFlash(); void psFlash();
void psNotifySettingGot(); void psNotifySettingGot();
@ -57,10 +50,6 @@ public:
void psRefreshTaskbarIcon(); void psRefreshTaskbarIcon();
bool psPosInited() const {
return posInited;
}
void psUpdateCounter(); void psUpdateCounter();
bool psHasNativeNotifications(); bool psHasNativeNotifications();
@ -99,15 +88,16 @@ public:
~MainWindow(); ~MainWindow();
public slots: public slots:
void psSavePosition(Qt::WindowState state = Qt::WindowActive);
void psShowTrayMenu(); void psShowTrayMenu();
protected: protected:
void initHook() override;
int32 screenNameChecksum(const QString &name) const override;
bool psHasTrayIcon() const { bool psHasTrayIcon() const {
return trayIcon; return trayIcon;
} }
bool posInited = false;
QSystemTrayIcon *trayIcon = nullptr; QSystemTrayIcon *trayIcon = nullptr;
Ui::PopupMenu *trayIconMenu = nullptr; Ui::PopupMenu *trayIconMenu = nullptr;
QImage icon256, iconbig256; QImage icon256, iconbig256;

View file

@ -22,6 +22,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "platform/win/window_title_win.h" #include "platform/win/window_title_win.h"
#include "ui/buttons/icon_button.h" #include "ui/buttons/icon_button.h"
#include "ui/widgets/shadow.h"
#include "styles/style_window.h" #include "styles/style_window.h"
namespace Platform { namespace Platform {
@ -30,7 +31,8 @@ TitleWidget::TitleWidget(QWidget *parent) : Window::TitleWidget(parent)
, _minimize(this, st::titleButtonMinimize) , _minimize(this, st::titleButtonMinimize)
, _maximizeRestore(this, st::titleButtonMaximize) , _maximizeRestore(this, st::titleButtonMaximize)
, _close(this, st::titleButtonClose) , _close(this, st::titleButtonClose)
, _maximized(parent->window()->windowState() & Qt::WindowMaximized) { , _maximized(parent->window()->windowState() & Qt::WindowMaximized)
, _shadow(this, st::titleShadow) {
_minimize->setClickedCallback([this]() { _minimize->setClickedCallback([this]() {
window()->setWindowState(Qt::WindowMinimized); window()->setWindowState(Qt::WindowMinimized);
_minimize->clearState(); _minimize->clearState();
@ -65,6 +67,7 @@ void TitleWidget::updateControlsPosition() {
void TitleWidget::resizeEvent(QResizeEvent *e) { void TitleWidget::resizeEvent(QResizeEvent *e) {
updateControlsPosition(); updateControlsPosition();
_shadow->setGeometry(0, height() - st::lineWidth, width(), st::lineWidth);
} }
void TitleWidget::updateControlsVisibility() { void TitleWidget::updateControlsVisibility() {

View file

@ -24,6 +24,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Ui { namespace Ui {
class IconButton; class IconButton;
class PlainShadow;
} // namespace Ui } // namespace Ui
namespace Platform { namespace Platform {
@ -51,6 +52,7 @@ private:
ChildWidget<Ui::IconButton> _minimize; ChildWidget<Ui::IconButton> _minimize;
ChildWidget<Ui::IconButton> _maximizeRestore; ChildWidget<Ui::IconButton> _maximizeRestore;
ChildWidget<Ui::IconButton> _close; ChildWidget<Ui::IconButton> _close;
ChildWidget<Ui::PlainShadow> _shadow;
bool _maximized = false; bool _maximized = false;

View file

@ -155,7 +155,7 @@ bool EventFilter::mainWindowEvent(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa
} }
emit App::wnd()->windowHandle()->windowStateChanged(state); emit App::wnd()->windowHandle()->windowStateChanged(state);
} else { } else {
App::wnd()->psUpdatedPosition(); App::wnd()->positionUpdated();
} }
App::wnd()->psUpdateMargins(); App::wnd()->psUpdateMargins();
MainWindow::ShadowsChanges changes = (wParam == SIZE_MINIMIZED || wParam == SIZE_MAXIMIZED) ? ShadowsChange::Hidden : (ShadowsChange::Resized | ShadowsChange::Shown); MainWindow::ShadowsChanges changes = (wParam == SIZE_MINIMIZED || wParam == SIZE_MAXIMIZED) ? ShadowsChange::Hidden : (ShadowsChange::Resized | ShadowsChange::Shown);
@ -172,7 +172,7 @@ bool EventFilter::mainWindowEvent(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa
case WM_MOVE: { case WM_MOVE: {
App::wnd()->shadowsUpdate(ShadowsChange::Moved); App::wnd()->shadowsUpdate(ShadowsChange::Moved);
App::wnd()->psUpdatedPosition(); App::wnd()->positionUpdated();
} return false; } return false;
case WM_NCHITTEST: { case WM_NCHITTEST: {
@ -185,7 +185,6 @@ bool EventFilter::mainWindowEvent(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa
switch (res) { switch (res) {
case Window::HitTestResult::Client: case Window::HitTestResult::Client:
case Window::HitTestResult::SysButton: *result = HTCLIENT; break; case Window::HitTestResult::SysButton: *result = HTCLIENT; break;
case Window::HitTestResult::Icon: *result = HTCAPTION; break;
case Window::HitTestResult::Caption: *result = HTCAPTION; break; case Window::HitTestResult::Caption: *result = HTCAPTION; break;
case Window::HitTestResult::Top: *result = HTTOP; break; case Window::HitTestResult::Top: *result = HTTOP; break;
case Window::HitTestResult::TopRight: *result = HTTOPRIGHT; break; case Window::HitTestResult::TopRight: *result = HTTOPRIGHT; break;
@ -204,42 +203,6 @@ bool EventFilter::mainWindowEvent(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa
SendMessage(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam); SendMessage(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam);
} return true; } return true;
case WM_NCLBUTTONDOWN: {
POINTS p = MAKEPOINTS(lParam);
RECT r;
GetWindowRect(hWnd, &r);
auto res = App::wnd()->hitTest(QPoint(p.x - r.left + App::wnd()->deltaLeft(), p.y - r.top + App::wnd()->deltaTop()));
switch (res) {
case Window::HitTestResult::Icon:
if (menuHidden && getms() < menuHidden + 10) {
menuHidden = 0;
if (getms() < menuShown + GetDoubleClickTime()) {
App::wnd()->close();
}
} else {
QRect icon = App::wnd()->iconRect();
p.x = r.left - App::wnd()->deltaLeft() + icon.left();
p.y = r.top - App::wnd()->deltaTop() + icon.top() + icon.height();
App::wnd()->psUpdateSysMenu(App::wnd()->windowHandle()->windowState());
menuShown = getms();
menuHidden = 0;
TrackPopupMenu(App::wnd()->psMenu(), TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON, p.x, p.y, 0, hWnd, 0);
menuHidden = getms();
}
return true;
};
} return false;
case WM_NCLBUTTONDBLCLK: {
POINTS p = MAKEPOINTS(lParam);
RECT r;
GetWindowRect(hWnd, &r);
auto res = App::wnd()->hitTest(QPoint(p.x - r.left + App::wnd()->deltaLeft(), p.y - r.top + App::wnd()->deltaTop()));
switch (res) {
case Window::HitTestResult::Icon: App::wnd()->close(); return true;
};
} return false;
case WM_SYSCOMMAND: { case WM_SYSCOMMAND: {
if (wParam == SC_MOUSEMENU) { if (wParam == SC_MOUSEMENU) {
POINTS p = MAKEPOINTS(lParam); POINTS p = MAKEPOINTS(lParam);

View file

@ -924,7 +924,7 @@ void psUpdateOverlayed(TWidget *widget) {
if (!wv) widget->setAttribute(Qt::WA_WState_Visible, true); if (!wv) widget->setAttribute(Qt::WA_WState_Visible, true);
widget->update(); widget->update();
QEvent e(QEvent::UpdateRequest); QEvent e(QEvent::UpdateRequest);
widget->event(&e); QGuiApplication::sendEvent(widget, &e);
if (!wm) widget->setAttribute(Qt::WA_Mapped, false); if (!wm) widget->setAttribute(Qt::WA_Mapped, false);
if (!wv) widget->setAttribute(Qt::WA_WState_Visible, false); if (!wv) widget->setAttribute(Qt::WA_WState_Visible, false);
} }

View file

@ -74,10 +74,11 @@ settingsButtonTop: 75px;
settingsButtonSkip: 10px; settingsButtonSkip: 10px;
settingsPrimaryButton: defaultActiveButton; settingsPrimaryButton: defaultActiveButton;
settingsSecondaryButton: defaultLightButton; settingsSecondaryButton: defaultLightButton;
settingsEditButton: IconButton(dialogsNewChatButton) { settingsEditButton: IconButton {
width: 24px; width: 24px;
height: 34px; height: 34px;
icon: icon {{ "settings_edit_name", #b7b7b7 }};
iconPosition: point(3px, 9px); iconPosition: point(3px, 9px);
iconPositionDown: point(3px, 10px); iconPositionDown: point(3px, 10px);
} }

View file

@ -136,8 +136,8 @@ emojiColorsSepColor: #d5d5d5;
emojiSwitchSkip: 27px; emojiSwitchSkip: 27px;
emojiSwitchImgSkip: 21px; emojiSwitchImgSkip: 21px;
emojiSwitchColor: #42a8db; emojiSwitchColor: #42a8db;
emojiSwitchStickers: icon {{ "emoji_switch_right", emojiSwitchColor }}; emojiSwitchStickers: icon {{ "emoji_switch", emojiSwitchColor }};
emojiSwitchEmoji: icon {{ "emoji_switch_left", emojiSwitchColor }}; emojiSwitchEmoji: icon {{ "emoji_switch-flip_horizontal", emojiSwitchColor }};
stickerPanSize: size(64px, 64px); stickerPanSize: size(64px, 64px);
stickerPanPadding: 11px; stickerPanPadding: 11px;

View file

@ -138,9 +138,6 @@ class TWidget : public QWidget {
public: public:
TWidget(QWidget *parent = nullptr) : QWidget(parent) { TWidget(QWidget *parent = nullptr) : QWidget(parent) {
} }
bool event(QEvent *e) override {
return QWidget::event(e);
}
virtual void grabStart() { virtual void grabStart() {
} }
virtual void grabFinish() { virtual void grabFinish() {
@ -238,39 +235,39 @@ private:
// A simple wrap around T* to explicitly state ownership // A simple wrap around T* to explicitly state ownership
template <typename T> template <typename T>
class ChildWidget { class ChildObject {
public: public:
ChildWidget(std_::nullptr_t) : _widget(nullptr) { ChildObject(std_::nullptr_t) : _object(nullptr) {
} }
// No default constructor, but constructors with at least // No default constructor, but constructors with at least
// one argument are simply make functions. // one argument are simply make functions.
template <typename Parent, typename... Args> template <typename Parent, typename... Args>
ChildWidget(Parent &&parent, Args&&... args) : _widget(new T(std_::forward<Parent>(parent), std_::forward<Args>(args)...)) { ChildObject(Parent &&parent, Args&&... args) : _object(new T(std_::forward<Parent>(parent), std_::forward<Args>(args)...)) {
} }
ChildWidget(const ChildWidget<T> &other) = delete; ChildObject(const ChildObject<T> &other) = delete;
ChildWidget<T> &operator=(const ChildWidget<T> &other) = delete; ChildObject<T> &operator=(const ChildObject<T> &other) = delete;
ChildWidget<T> &operator=(std_::nullptr_t) { ChildObject<T> &operator=(std_::nullptr_t) {
_widget = nullptr; _object = nullptr;
return *this; return *this;
} }
ChildWidget<T> &operator=(T *widget) { ChildObject<T> &operator=(T *object) {
_widget = widget; _object = object;
return *this; return *this;
} }
T *operator->() const { T *operator->() const {
return _widget; return _object;
} }
T &operator*() const { T &operator*() const {
return *_widget; return *_object;
} }
// So we can pass this pointer to methods like connect(). // So we can pass this pointer to methods like connect().
T *ptr() const { T *ptr() const {
return _widget; return _object;
} }
operator T*() const { operator T*() const {
return ptr(); return ptr();
@ -279,28 +276,30 @@ public:
// Use that instead "= new T(parent, ...)" // Use that instead "= new T(parent, ...)"
template <typename Parent, typename... Args> template <typename Parent, typename... Args>
void create(Parent &&parent, Args&&... args) { void create(Parent &&parent, Args&&... args) {
delete _widget; delete _object;
_widget = new T(std_::forward<Parent>(parent), std_::forward<Args>(args)...); _object = new T(std_::forward<Parent>(parent), std_::forward<Args>(args)...);
} }
void destroy() { void destroy() {
if (_widget) { delete base::take(_object);
delete _widget;
_widget = nullptr;
}
} }
void destroyDelayed() { void destroyDelayed() {
if (_widget) { if (_object) {
_widget->hide(); if (auto widget = base::up_cast<QWidget*>(_object)) {
_widget->deleteLater(); widget->hide();
_widget = nullptr; }
_object->deleteLater();
_object = nullptr;
} }
} }
private: private:
T *_widget; T *_object;
}; };
template <typename T>
using ChildWidget = ChildObject<T>;
void sendSynteticMouseEvent(QWidget *widget, QEvent::Type type, Qt::MouseButton button, const QPoint &globalPoint); void sendSynteticMouseEvent(QWidget *widget, QEvent::Type type, Qt::MouseButton button, const QPoint &globalPoint);
inline void sendSynteticMouseEvent(QWidget *widget, QEvent::Type type, Qt::MouseButton button) { inline void sendSynteticMouseEvent(QWidget *widget, QEvent::Type type, Qt::MouseButton button) {

View file

@ -68,6 +68,10 @@ QAction *DropdownMenu::addAction(const QString &text, const QObject *receiver, c
return _menu->addAction(text, receiver, member, icon, iconOver); return _menu->addAction(text, receiver, member, icon, iconOver);
} }
QAction *DropdownMenu::addAction(const QString &text, base::lambda_unique<void()> callback, const style::icon *icon, const style::icon *iconOver) {
return _menu->addAction(text, std_::move(callback), icon, iconOver);
}
QAction *DropdownMenu::addSeparator() { QAction *DropdownMenu::addSeparator() {
return _menu->addSeparator(); return _menu->addSeparator();
} }

View file

@ -31,6 +31,7 @@ public:
DropdownMenu(QWidget *parent, const style::DropdownMenu &st = st::defaultDropdownMenu); DropdownMenu(QWidget *parent, const style::DropdownMenu &st = st::defaultDropdownMenu);
QAction *addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr); QAction *addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr);
QAction *addAction(const QString &text, base::lambda_unique<void()> callback, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr);
QAction *addSeparator(); QAction *addSeparator();
void clearActions(); void clearActions();

View file

@ -50,9 +50,15 @@ void Menu::init() {
} }
QAction *Menu::addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon, const style::icon *iconOver) { QAction *Menu::addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon, const style::icon *iconOver) {
auto action = new QAction(text, this); auto action = addAction(new QAction(text, this), icon, iconOver);
connect(action, SIGNAL(triggered(bool)), receiver, member, Qt::QueuedConnection); connect(action, SIGNAL(triggered(bool)), receiver, member, Qt::QueuedConnection);
return addAction(action, icon, iconOver); return action;
}
QAction *Menu::addAction(const QString &text, base::lambda_unique<void()> callback, const style::icon *icon, const style::icon *iconOver) {
auto action = addAction(new QAction(text, this), icon, iconOver);
connect(action, SIGNAL(triggered(bool)), base::lambda_slot(action, std_::move(callback)), SLOT(action()), Qt::QueuedConnection);
return action;
} }
QAction *Menu::addAction(QAction *action, const style::icon *icon, const style::icon *iconOver) { QAction *Menu::addAction(QAction *action, const style::icon *icon, const style::icon *iconOver) {

View file

@ -32,6 +32,7 @@ public:
Menu(QWidget *parent, QMenu *menu, const style::Menu &st = st::defaultMenu); Menu(QWidget *parent, QMenu *menu, const style::Menu &st = st::defaultMenu);
QAction *addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr); QAction *addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr);
QAction *addAction(const QString &text, base::lambda_unique<void()> callback, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr);
QAction *addSeparator(); QAction *addSeparator();
void clearActions(); void clearActions();

View file

@ -84,6 +84,10 @@ QAction *PopupMenu::addAction(const QString &text, const QObject *receiver, cons
return _menu->addAction(text, receiver, member, icon, iconOver); return _menu->addAction(text, receiver, member, icon, iconOver);
} }
QAction *PopupMenu::addAction(const QString &text, base::lambda_unique<void()> callback, const style::icon *icon, const style::icon *iconOver) {
return _menu->addAction(text, std_::move(callback), icon, iconOver);
}
QAction *PopupMenu::addSeparator() { QAction *PopupMenu::addSeparator() {
return _menu->addSeparator(); return _menu->addSeparator();
} }

View file

@ -29,6 +29,7 @@ public:
PopupMenu(QMenu *menu, const style::PopupMenu &st = st::defaultPopupMenu); PopupMenu(QMenu *menu, const style::PopupMenu &st = st::defaultPopupMenu);
QAction *addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr); QAction *addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr);
QAction *addAction(const QString &text, base::lambda_unique<void()> callback, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr);
QAction *addSeparator(); QAction *addSeparator();
void clearActions(); void clearActions();

View file

@ -190,6 +190,9 @@ defaultMaskButton: MaskButton {
widgetSlideDuration: 200; widgetSlideDuration: 200;
widgetFadeDuration: 200; widgetFadeDuration: 200;
fieldSearchIcon: icon {{ "box_search", #aaaaaa, point(9px, 8px) }};
boxFieldSearchIcon: icon {{ "box_search", #aaaaaa, point(10px, 9px) }};
discreteSliderHeight: 39px; discreteSliderHeight: 39px;
discreteSliderTop: 5px; discreteSliderTop: 5px;
discreteSliderSkip: 3px; discreteSliderSkip: 3px;

View file

@ -21,9 +21,147 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "stdafx.h" #include "stdafx.h"
#include "window/main_window.h" #include "window/main_window.h"
#include "localstorage.h"
#include "styles/style_window.h"
#include "platform/platform_window_title.h"
#include "window/window_theme.h"
namespace Window { namespace Window {
MainWindow::MainWindow() { MainWindow::MainWindow() : QMainWindow()
, _positionUpdatedTimer(this)
, _body(this) {
setCentralWidget(_body);
subscribe(Theme::Background(), [this](const Theme::BackgroundUpdate &data) {
using Type = Theme::BackgroundUpdate::Type;
if (data.type == Type::TestingTheme || data.type == Type::RevertingTheme || data.type == Type::ApplyingTheme) {
if (_title) {
_title->update();
}
}
});
}
void MainWindow::init() {
_positionUpdatedTimer->setSingleShot(true);
connect(_positionUpdatedTimer, SIGNAL(timeout()), this, SLOT(savePositionByTimer()));
_title = Platform::CreateTitleWidget(this);
auto p = palette();
p.setColor(QPalette::Window, st::windowBg->c);
setPalette(p);
initSize();
initHook();
}
HitTestResult MainWindow::hitTest(const QPoint &p) const {
auto titleResult = _title ? _title->hitTest(p - _title->geometry().topLeft()) : Window::HitTestResult::None;
if (titleResult != Window::HitTestResult::None) {
return titleResult;
} else if (rect().contains(p)) {
return Window::HitTestResult::Client;
}
return Window::HitTestResult::None;
}
void MainWindow::initSize() {
setMinimumWidth(st::windowMinWidth);
setMinimumHeight((_title ? _title->height() : 0) + st::windowMinHeight);
auto pos = cWindowPos();
auto avail = QDesktopWidget().availableGeometry();
bool maximized = false;
auto geom = QRect(avail.x() + (avail.width() - st::windowDefaultWidth) / 2, avail.y() + (avail.height() - st::windowDefaultHeight) / 2, st::windowDefaultWidth, st::windowDefaultHeight);
if (pos.w && pos.h) {
for (auto screen : QGuiApplication::screens()) {
if (pos.moncrc == screenNameChecksum(screen->name())) {
auto screenGeometry = screen->geometry();
auto w = screenGeometry.width(), h = screenGeometry.height();
if (w >= st::windowMinWidth && h >= st::windowMinHeight) {
if (pos.w > w) pos.w = w;
if (pos.h > h) pos.h = h;
pos.x += screenGeometry.x();
pos.y += screenGeometry.y();
if (pos.x + st::windowMinWidth <= screenGeometry.x() + screenGeometry.width() &&
pos.y + st::windowMinHeight <= screenGeometry.y() + screenGeometry.height()) {
geom = QRect(pos.x, pos.y, pos.w, pos.h);
}
}
break;
}
}
if (pos.y < 0) pos.y = 0;
maximized = pos.maximized;
}
setGeometry(geom);
}
void MainWindow::positionUpdated() {
_positionUpdatedTimer->start(SaveWindowPositionTimeout);
}
int32 MainWindow::screenNameChecksum(const QString &name) const {
auto bytes = name.toUtf8();
return hashCrc32(bytes.constData(), bytes.size());
}
void MainWindow::setPositionInited() {
_positionInited = true;
}
void MainWindow::resizeEvent(QResizeEvent *e) {
auto bodyTop = 0;
if (_title) {
_title->setGeometry(0, bodyTop, width(), st::titleHeight);
bodyTop += _title->height();
}
_body->setGeometry(0, bodyTop, width(), height() - bodyTop);
}
void MainWindow::savePosition(Qt::WindowState state) {
if (state == Qt::WindowActive) state = windowHandle()->windowState();
if (state == Qt::WindowMinimized || !positionInited()) return;
TWindowPos pos(cWindowPos()), curPos = pos;
if (state == Qt::WindowMaximized) {
curPos.maximized = 1;
} else {
QRect r(geometry());
curPos.x = r.x();
curPos.y = r.y();
curPos.w = r.width();
curPos.h = r.height();
curPos.maximized = 0;
}
int px = curPos.x + curPos.w / 2, py = curPos.y + curPos.h / 2;
int minDelta = 0;
QScreen *chosen = 0;
auto screens = QGuiApplication::screens();
for (auto screen : QGuiApplication::screens()) {
auto delta = (screen->geometry().center() - QPoint(px, py)).manhattanLength();
if (!chosen || delta < minDelta) {
minDelta = delta;
chosen = screen;
}
}
if (chosen) {
curPos.x -= chosen->geometry().x();
curPos.y -= chosen->geometry().y();
curPos.moncrc = screenNameChecksum(chosen->name());
}
if (curPos.w >= st::windowMinWidth && curPos.h >= st::windowMinHeight) {
if (curPos.x != pos.x || curPos.y != pos.y || curPos.w != pos.w || curPos.h != pos.h || curPos.moncrc != pos.moncrc || curPos.maximized != pos.maximized) {
cSetWindowPos(curPos);
Local::writeSettings();
}
}
} }
MainWindow::~MainWindow() { MainWindow::~MainWindow() {

View file

@ -20,20 +20,63 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/ */
#pragma once #pragma once
#include "window/window_title.h"
namespace Window { namespace Window {
class MainWindow : public QMainWindow { class TitleWidget;
class MainWindow : public QMainWindow, protected base::Subscriber {
Q_OBJECT
public: public:
MainWindow(); MainWindow();
void init();
HitTestResult hitTest(const QPoint &p) const;
bool positionInited() const {
return _positionInited;
}
void positionUpdated();
virtual void closeWithoutDestroy(); virtual void closeWithoutDestroy();
virtual ~MainWindow(); virtual ~MainWindow();
protected: protected:
void resizeEvent(QResizeEvent *e) override;
QWidget *bodyWidget() { // temp
return _body;
}
void savePosition(Qt::WindowState state = Qt::WindowActive);
virtual void initHook() {
}
virtual void stateChangedHook(Qt::WindowState state) { virtual void stateChangedHook(Qt::WindowState state) {
} }
// This one is overriden in Windows for historical reasons.
virtual int32 screenNameChecksum(const QString &name) const;
void setPositionInited();
private slots:
void savePositionByTimer() {
savePosition();
}
private:
void initSize();
ChildObject<QTimer> _positionUpdatedTimer;
bool _positionInited = false;
ChildWidget<TitleWidget> _title = { nullptr };
ChildWidget<QWidget> _body;
}; };
} // namespace Window } // namespace Window

View file

@ -446,6 +446,7 @@ void Widget::addToHeight(int add) {
auto newHeight = height() + add; auto newHeight = height() + add;
auto newPosition = computePosition(newHeight); auto newPosition = computePosition(newHeight);
updateGeometry(newPosition.x(), newPosition.y(), width(), newHeight); updateGeometry(newPosition.x(), newPosition.y(), width(), newHeight);
psUpdateOverlayed(this);
} }
void Widget::updateGeometry(int x, int y, int width, int height) { void Widget::updateGeometry(int x, int y, int width, int height) {

View file

@ -24,8 +24,8 @@ using "ui/widgets/widgets.style";
windowMinWidth: 380px; windowMinWidth: 380px;
windowMinHeight: 480px; windowMinHeight: 480px;
windowDefWidth: 800px; windowDefaultWidth: 800px;
windowDefHeight: 600px; windowDefaultHeight: 600px;
windowShadow: icon {{ "window_shadow", windowShadowFg }}; windowShadow: icon {{ "window_shadow", windowShadowFg }};
windowShadowShift: 1px; windowShadowShift: 1px;

View file

@ -26,7 +26,6 @@ enum class HitTestResult {
None = 0, None = 0,
Client, Client,
SysButton, SysButton,
Icon,
Caption, Caption,
Top, Top,
TopRight, TopRight,