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);
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;
topBarDuration: 200;
topBarForward: icon {{ "title_next", #a3a3a3 }};
topBarBackward: icon {{ "title_previous", #a3a3a3 }};
topBarForward: icon {{ "title_back-flip_horizontal", #a3a3a3 }};
topBarBackward: icon {{ "title_back", #a3a3a3 }};
topBarForwardAlpha: 0.6;
topBarBack: icon {{ "title_previous", #259fd8 }};
topBarBack: icon {{ "title_back", #259fd8 }};
topBarBackAlpha: 0.8;
topBarBackColor: #005faf;
topBarBackFont: font(16px);
@ -1104,15 +1091,15 @@ infoButton: PeerAvatarButton {
photoSize: 42px;
}
// forward declaration for single "title_previous" usage.
// forward declaration for single "title_back" usage.
profileTopBarBackIconFg: #0290d7;
profileTopBarBackIcon: icon {{ "title_previous", profileTopBarBackIconFg }};
profileTopBarBackIcon: icon {{ "title_back", profileTopBarBackIconFg }};
historyReplyCancelIcon: icon {{ "box_button_close-invert", historyReplyBg }};
boxSearchCancelIcon: icon {{ "box_button_close-invert", boxSearchBg }};
settingsFixedBarCloseIcon: icon {{ "box_button_close-invert", settingsFixedBarBg }};
notifyFadeRight: icon {{ "fade_horizontal_right", notificationBg }};
notifyFadeRight: icon {{ "fade_horizontal", notificationBg }};
stickerIconLeft: icon {{ "fade_horizontal_left", emojiPanCategories }};
stickerIconRight: icon {{ "fade_horizontal_right", emojiPanCategories }};
stickerIconLeft: icon {{ "fade_horizontal-flip_horizontal", 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
windowSubTextFg: #8a8a8a; // gray: fallback for subtext color
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
windowActiveTextFg: #1485c2; // online blue: fallback for active color
windowShadowFg: #000000; // black: fallback for shadow color
@ -32,22 +32,7 @@ windowShadowFg: #000000; // black: fallback for shadow color
imageBg: #000000;
imageBgTransparent: #ffffff;
// custom title bar for Windows
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;
// widgets
cancelIconFg: #a2a2a2;
cancelIconFgOver: #808080;
@ -63,6 +48,24 @@ lightButtonBgOver: #f2f7fa | lightButtonBg;
lightButtonFg: #2b99d5;
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
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_create" = "Create";
"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_about" = "Channels are a tool for broadcasting your messages to unlimited audiences";
"lng_create_public_channel_title" = "Public Channel";
"lng_create_public_channel_about" = "Anyone can find the channel in search and join";
"lng_create_private_channel_title" = "Private Channel";

View file

@ -25,24 +25,12 @@ windowBg: #ffffff;
windowTextFg: #000000;
windowSubTextFg: #8a8a8a;
windowActiveFill: #40ace3;
windowOverBg: #edf2f5;
windowOverBg: #f3f3f3;
windowSubTextFgOver: #7c99b2;
windowActiveTextFg: #1485c2;
windowShadowFg: #000000;
imageBg: #000000;
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;
cancelIconFgOver: #808080;
activeButtonBg: windowActiveFill;
@ -55,6 +43,19 @@ lightButtonBg: windowBg;
lightButtonBgOver: #f2f7fa; // lightButtonBg;
lightButtonFg: #2b99d5;
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;
boxBg: windowBg;
boxTextFg: windowTextFg;

View file

@ -260,64 +260,6 @@ void AddContactBox::onRetry() {
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(),
_creating(creating),
a_photoOver(0, 0),

View file

@ -78,34 +78,6 @@ private:
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 {
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
*/
using "basic.style";
using "ui/widgets/widgets.style";
using "intro/intro.style";
@ -143,7 +144,7 @@ contactsMultiSelect: MultiSelect {
font: normalFont;
}
fieldMinWidth: 42px;
fieldIcon: fieldSearchIcon;
fieldIcon: boxFieldSearchIcon;
fieldIconSkip: 36px;
fieldCancel: MaskButton(defaultMaskButton) {

View file

@ -38,8 +38,8 @@ namespace codegen {
namespace style {
namespace {
constexpr int kErrorBadIconSize = 861;
constexpr int kErrorBadIconFormat = 862;
constexpr int kErrorBadIconSize = 861;
constexpr int kErrorBadIconFormat = 862;
// crc32 hash, taken somewhere from the internet
@ -1017,10 +1017,10 @@ QByteArray iconMaskValueSize(int width, int height) {
QByteArray iconMaskValuePng(QString filepath) {
QByteArray result;
auto inverted = filepath.endsWith("-invert");
if (inverted) {
filepath.chop(QLatin1String("-invert").size());
}
auto pathAndModifiers = filepath.split('-');
filepath = pathAndModifiers[0];
auto modifiers = pathAndModifiers.mid(1);
QImage png100x(filepath + ".png");
QImage png200x(filepath + "@2x.png");
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();
return result;
}
if (inverted) {
png100x.invertPixels();
png200x.invertPixels();
for (auto modifierName : modifiers) {
if (auto modifier = GetModifier(modifierName)) {
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 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 kErrorBadString = 806;
constexpr int kErrorIconDuplicate = 807;
constexpr int kErrorBadIconModifier = 808;
QString findInputFile(const Options &options) {
for (const auto &dir : options.includePaths) {
@ -151,6 +152,25 @@ bool validateAlignString(const QString &value) {
} // 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)
: filePath_(findInputFile(options))
, file_(filePath_)
@ -821,21 +841,26 @@ structure::data::monoicon ParsedFile::readMonoIconFields() {
QString ParsedFile::readMonoIconFilename() {
if (auto filename = readValue()) {
if (filename.type().tag == structure::TypeTag::String) {
auto filepath = QString::fromStdString(filename.String());
auto inverted = filepath.endsWith("-invert");
if (inverted) {
filepath.chop(QLatin1String("-invert").size());
}
for (const auto &path : options_.includePaths) {
QFileInfo fileinfo(path + '/' + filepath + ".png");
if (fileinfo.exists()) {
return path + '/' + filepath + (inverted ? "-invert" : "");
auto fullpath = QString::fromStdString(filename.String());
auto pathAndModifiers = fullpath.split('-');
auto filepath = pathAndModifiers[0];
auto modifiers = pathAndModifiers.mid(1);
for (auto modifierName : modifiers) {
if (!GetModifier(modifierName)) {
logError(kErrorBadIconModifier) << "unknown modifier: " << modifierName.toStdString();
return QString();
}
}
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");
if (fileinfo.exists()) {
return path + "/icons/" + filepath + (inverted ? "-invert" : "");
return path + "/icons/" + fullpath;
}
}
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 <string>
#include <functional>
#include <QImage>
#include "codegen/common/basic_tokenized_file.h"
#include "codegen/style/options.h"
#include "codegen/style/module.h"
@ -29,6 +31,9 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace codegen {
namespace style {
using Modifier = std::function<void(QImage &png100x, QImage &png200x)>;
Modifier GetModifier(const QString &name);
// Parses an input file to the internal struct.
class ParsedFile {
public:
@ -44,7 +49,6 @@ public:
}
private:
bool failed() const {
return failed_ || file_.failed();
}

View file

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

View file

@ -25,7 +25,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace base {
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;
}
@ -35,6 +35,27 @@ inline T take(T &source, T &&new_value = T()) {
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
template <typename Enum>

View file

@ -48,7 +48,7 @@ dialogsNameFg: #000000;
dialogsNameTop: 2px;
dialogsRowHeight: 62px;
dialogsFilterPadding: 10px;
dialogsFilterPadding: point(11px, 11px);
dialogsPhotoSize: 46px;
dialogsPhotoPadding: 12px;
dialogsPadding: point(10px, 8px);
@ -83,24 +83,44 @@ dialogsTextStyleDraftActive: textStyle(dialogsTextStyle) {
linkFgDown: #c6e1f7;
}
dialogsNewChatIcon: icon {{ "dialogs_new_chat", #b7b7b7 }};
dialogsNewChatButton: IconButton {
width: 36px;
height: 36px;
dialogsMenuToggle: IconButton {
width: 32px;
height: 32px;
icon: dialogsNewChatIcon;
iconPosition: point(9px, 10px);
iconPositionDown: point(9px, 11px);
icon: icon {{ "dialogs_menu", #999999 }};
iconPosition: point(6px, 6px);
iconPositionDown: point(6px, 6px);
}
dialogsAddContact: IconButton(dialogsNewChatButton) {
icon: icon {{ "dialogs_add_contact", #a6a6a6 }};
iconPosition: point(8px, 8px);
iconPositionDown: point(8px, 9px);
dialogsFilter: flatInput(inpDefGray) {
font: font(fsize);
bgColor: #f2f2f2;
phColor: #949494;
phFocusColor: #a4a4a4;
icon: fieldSearchIcon;
width: 240px;
height: 32px;
textMrg: margins(32px, 3px, 32px, 3px);
}
dialogsCancelSearch: IconButton(dialogsAddContact) {
icon: icon {{ "dialogs_cancel_search", #a6a6a6 }};
dialogsCancelSearch: IconButton(dialogsMenuToggle) {
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;
dialogsChatIcon: icon {{ "dialogs_chat", #373737, 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/contactsbox.h"
#include "boxes/confirmbox.h"
#include "boxes/aboutbox.h"
#include "localstorage.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))
, contactsNoDialogs(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;
}
DialogsWidget::DialogsWidget(MainWidget *parent) : TWidget(parent)
, _dragInScroll(false)
, _dragForward(false)
, _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)
DialogsWidget::DialogsWidget(QWidget *parent) : TWidget(parent)
, _mainMenuToggle(this, st::dialogsMenuToggle)
, _filter(this, st::dialogsFilter, lang(lng_dlg_filter))
, _cancelSearch(this, st::dialogsCancelSearch)
, _scroll(this, st::dialogsScroll)
, _inner(&_scroll, parent)
, _a_show(animation(this, &DialogsWidget::step_show))
, _searchInPeer(0)
, _searchInMigrated(0)
, _searchFull(false)
, _searchFullMigrated(false)
, _peopleFull(false)
{
, _a_show(animation(this, &DialogsWidget::step_show)) {
_scroll.setWidget(&_inner);
_scroll.setFocusPolicy(Qt::NoFocus);
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(&_scroll, SIGNAL(geometryChanged()), &_inner, SLOT(onParentGeometryChanged()));
connect(&_scroll, SIGNAL(scrolled()), this, SLOT(onListScroll()));
connect(&_filter, SIGNAL(cancelled()), this, SLOT(onCancel()));
connect(&_filter, SIGNAL(changed()), this, SLOT(onFilterUpdate()));
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(_filter, SIGNAL(cancelled()), this, SLOT(onCancel()));
connect(_filter, SIGNAL(changed()), this, SLOT(onFilterUpdate()));
connect(_filter, SIGNAL(cursorPositionChanged(int,int)), this, SLOT(onFilterCursorMoved(int,int)));
connect(_cancelSearch, SIGNAL(clicked()), this, SLOT(onCancelSearch()));
_mainMenuToggle->setClickedCallback([this] { showMainMenu(); });
_chooseByDragTimer.setSingleShot(true);
connect(&_chooseByDragTimer, SIGNAL(timeout()), this, SLOT(onChooseByDrag()));
@ -1819,21 +1805,13 @@ DialogsWidget::DialogsWidget(MainWidget *parent) : TWidget(parent)
_searchTimer.setSingleShot(true);
connect(&_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchMessages()));
_scroll.show();
_filter.show();
_filter.move(st::dialogsPadding.x(), st::dialogsFilterPadding);
_filter.setFocusPolicy(Qt::StrongFocus);
_filter.customUpDown(true);
_addContact->hide();
_newGroup->show();
_filter->setFocusPolicy(Qt::StrongFocus);
_filter->customUpDown(true);
_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() {
_filter.setFocus();
_filter->setFocus();
_inner.activate();
}
@ -1858,7 +1836,7 @@ void DialogsWidget::dlgUpdated(History *row, MsgId msgId) {
}
void DialogsWidget::dialogsToUp() {
if (_filter.getLastText().trimmed().isEmpty()) {
if (_filter->getLastText().trimmed().isEmpty()) {
_scroll.scrollToY(0);
}
}
@ -1873,9 +1851,8 @@ void DialogsWidget::showAnimated(Window::SlideDirection direction, const Window:
_a_show.stop();
_scroll.hide();
_filter.hide();
_filter->hide();
_cancelSearch->hide();
_newGroup->hide();
int delta = st::slideShift;
if (direction == Window::SlideDirection::FromLeft) {
@ -1903,7 +1880,7 @@ void DialogsWidget::step_show(float64 ms, bool timer) {
_cacheUnder = _cacheOver = QPixmap();
_scroll.show();
_filter.show();
_filter->show();
_a_show.stop();
onFilterUpdate();
@ -1930,8 +1907,8 @@ void DialogsWidget::updateNotifySettings(PeerData *peer) {
void DialogsWidget::notify_userIsContactChanged(UserData *user, bool fromThisApp) {
if (fromThisApp) {
_filter.setText(QString());
_filter.updatePlaceholder();
_filter->setText(QString());
_filter->updatePlaceholder();
onFilterUpdate();
}
_inner.notify_userIsContactChanged(user, fromThisApp);
@ -2031,7 +2008,7 @@ bool DialogsWidget::dialogsFailed(const RPCError &error, mtpRequestId req) {
}
bool DialogsWidget::onSearchMessages(bool searchCache) {
QString q = _filter.getLastText().trimmed();
QString q = _filter->getLastText().trimmed();
if (q.isEmpty()) {
if (_searchRequest) {
MTP::cancel(_searchRequest);
@ -2098,16 +2075,39 @@ void DialogsWidget::onChooseByDrag() {
_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) {
if ((_filter.getLastText() != query) || (inPeer && inPeer != _searchInPeer && inPeer->migrateTo() != _searchInPeer)) {
if ((_filter->getLastText() != query) || (inPeer && inPeer != _searchInPeer && inPeer->migrateTo() != _searchInPeer)) {
if (inPeer) {
onCancelSearch();
_searchInPeer = inPeer->migrateTo() ? inPeer->migrateTo() : inPeer;
_searchInMigrated = _searchInPeer ? _searchInPeer->migrateFrom() : 0;
_inner.searchInPeer(_searchInPeer);
}
_filter.setText(query);
_filter.updatePlaceholder();
_filter->setText(query);
_filter->updatePlaceholder();
onFilterUpdate(true);
_searchTimer.stop();
onSearchMessages();
@ -2371,17 +2371,15 @@ void DialogsWidget::onListScroll() {
void DialogsWidget::onFilterUpdate(bool force) {
if (_a_show.animating() && !force) return;
QString filterText = _filter.getLastText();
QString filterText = _filter->getLastText();
_inner.onFilterUpdate(filterText, force);
if (filterText.isEmpty()) {
_searchCache.clear();
_searchQueries.clear();
_searchQuery = QString();
_cancelSearch->hide();
_newGroup->show();
} else if (_cancelSearch->isHidden()) {
_cancelSearch->show();
_newGroup->hide();
}
if (filterText.size() < MinUsernameLength) {
_peopleCache.clear();
@ -2399,8 +2397,8 @@ void DialogsWidget::searchInPeer(PeerData *peer) {
}
void DialogsWidget::onFilterCursorMoved(int from, int to) {
if (to < 0) to = _filter.cursorPosition();
QString t = _filter.getLastText();
if (to < 0) to = _filter->cursorPosition();
QString t = _filter->getLastText();
QStringRef r;
for (int start = to; start > 0;) {
--start;
@ -2415,8 +2413,8 @@ void DialogsWidget::onFilterCursorMoved(int from, int to) {
}
void DialogsWidget::onCompleteHashtag(QString tag) {
QString t = _filter.getLastText(), r;
int cur = _filter.cursorPosition();
QString t = _filter->getLastText(), r;
int cur = _filter->cursorPosition();
for (int start = cur; start > 0;) {
--start;
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;
r = t.mid(0, start + 1) + tag + ' ' + t.mid(cur);
_filter.setText(r);
_filter.setCursorPosition(start + 1 + tag.size() + 1);
_filter->setText(r);
_filter->setCursorPosition(start + 1 + tag.size() + 1);
onFilterUpdate(true);
return;
}
@ -2436,22 +2434,23 @@ void DialogsWidget::onCompleteHashtag(QString tag) {
}
if (!t.at(start).isLetterOrNumber() && t.at(start) != '_') break;
}
_filter.setText(t.mid(0, cur) + '#' + tag + ' ' + t.mid(cur));
_filter.setCursorPosition(cur + 1 + tag.size() + 1);
_filter->setText(t.mid(0, cur) + '#' + tag + ' ' + t.mid(cur));
_filter->setCursorPosition(cur + 1 + tag.size() + 1);
onFilterUpdate(true);
}
void DialogsWidget::resizeEvent(QResizeEvent *e) {
int32 w = width();
_filter.setGeometry(st::dialogsPadding.x(), st::dialogsFilterPadding, w - 2 * st::dialogsPadding.x(), _filter.height());
_newGroup->move(w - _newGroup->width() - st::dialogsPadding.x(), _filter.y());
_addContact->move(w - _addContact->width() - st::dialogsPadding.x(), _filter.y());
_cancelSearch->move(w - _cancelSearch->width() - st::dialogsPadding.x(), _filter.y());
_scroll.move(0, _filter.height() + 2 * st::dialogsFilterPadding);
_filter->setGeometryToLeft(st::dialogsFilterPadding.x() * 2 + _mainMenuToggle->width(), st::dialogsFilterPadding.y(), w - 3 * st::dialogsFilterPadding.x() - _mainMenuToggle->width(), _filter->height());
_mainMenuToggle->moveToLeft(st::dialogsFilterPadding.x(), _filter->y());
_cancelSearch->moveToRight(st::dialogsFilterPadding.x(), _filter->y());
_scroll.move(0, _filter->height() + 2 * st::dialogsFilterPadding.y());
updateMainMenuGeometry();
int32 addToY = App::main() ? App::main()->contentScrollAddToY() : 0;
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) {
_scroll.scrollToY(newScrollY);
} 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) {
if (e->key() == Qt::Key_Escape) {
e->ignore();
@ -2548,16 +2553,8 @@ Dialogs::IndexedList *DialogsWidget::dialogsList() {
return _inner.dialogsList();
}
void DialogsWidget::onAddContact() {
Ui::showLayer(new AddContactBox(), KeepOtherLayers);
}
void DialogsWidget::onNewGroup() {
Ui::showLayer(new NewGroupBox());
}
bool DialogsWidget::onCancelSearch() {
bool clearing = !_filter.getLastText().isEmpty();
bool clearing = !_filter->getLastText().isEmpty();
if (_searchRequest) {
MTP::cancel(_searchRequest);
_searchRequest = 0;
@ -2571,8 +2568,8 @@ bool DialogsWidget::onCancelSearch() {
clearing = true;
}
_inner.clearFilter();
_filter.clear();
_filter.updatePlaceholder();
_filter->clear();
_filter->updatePlaceholder();
onFilterUpdate();
return clearing;
}
@ -2590,8 +2587,8 @@ void DialogsWidget::onCancelSearchInPeer() {
_inner.searchInPeer(0);
}
_inner.clearFilter();
_filter.clear();
_filter.updatePlaceholder();
_filter->clear();
_filter->updatePlaceholder();
onFilterUpdate();
if (!Adaptive::OneColumn() && !App::main()->selectingPeer()) {
emit cancelled();

View file

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

View file

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

View file

@ -83,6 +83,7 @@ MainWidget::MainWidget(QWidget *parent) : TWidget(parent)
updateScrollColors();
connect(_dialogs, SIGNAL(cancelled()), this, SLOT(dialogsCancelled()));
connect(this, SIGNAL(dialogsUpdated()), this, SLOT(onListScroll()));
connect(_history, SIGNAL(cancelled()), _dialogs, SLOT(activate()));
connect(this, SIGNAL(peerPhotoChanged(PeerData*)), this, SIGNAL(dialogsUpdated()));
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) {
OverviewsPreload::iterator it;
MediaOverviewType type = OverviewCount;

View file

@ -312,8 +312,6 @@ public:
void loadMediaBack(PeerData *peer, MediaOverviewType type, bool many = false);
void checkLastUpdate(bool afterSleep);
void showAddContact();
void showNewGroup();
void serviceNotification(const QString &msg, const MTPMessageMedia &media);
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 "settings/settings_widget.h"
#include "platform/platform_notifications_manager.h"
#include "platform/platform_window_title.h"
#include "window/notifications_manager.h"
#include "window/window_theme.h"
#include "window/window_theme_warning.h"
@ -86,7 +85,7 @@ void ConnectingWidget::onReconnect() {
MTP::restart();
}
MainWindow::MainWindow() : Platform::MainWindow(), _body(this) {
MainWindow::MainWindow() {
icon16 = icon256.scaledToWidth(16, Qt::SmoothTransformation);
icon32 = icon256.scaledToWidth(32, Qt::SmoothTransformation);
icon64 = icon256.scaledToWidth(64, Qt::SmoothTransformation);
@ -105,15 +104,9 @@ MainWindow::MainWindow() : Platform::MainWindow(), _body(this) {
}
});
if (objectName().isEmpty()) {
setObjectName(qsl("MainWindow"));
}
resize(st::windowDefWidth, st::windowDefHeight);
resize(st::windowDefaultWidth, st::windowDefaultHeight);
setLocale(QLocale(QLocale::English, QLocale::UnitedStates));
setCentralWidget(_body);
QMetaObject::connectSlotsByName(this);
_inactiveTimer.setSingleShot(true);
connect(&_inactiveTimer, SIGNAL(timeout()), this, SLOT(onInactiveTimer()));
@ -162,26 +155,17 @@ void MainWindow::onStateChanged(Qt::WindowState state) {
if (state == Qt::WindowMinimized && cWorkMode() == dbiwmTrayOnly) {
App::wnd()->minimizeToTray();
}
psSavePosition(state);
savePosition(state);
}
void MainWindow::init() {
psInitFrameless();
setWindowIcon(wndIcon);
Platform::MainWindow::init();
_title = Platform::CreateTitleWidget(this);
setWindowIcon(wndIcon);
Application::instance()->installEventFilter(this);
connect(windowHandle(), SIGNAL(windowStateChanged(Qt::WindowState)), this, SLOT(onStateChanged(Qt::WindowState)));
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() {
@ -241,9 +225,7 @@ void MainWindow::clearWidgets() {
QPixmap MainWindow::grabInner() {
QPixmap result;
if (_settings) {
result = myGrab(_settings);
} else if (_intro) {
if (_intro) {
result = myGrab(_intro);
} else if (_main) {
result = myGrab(_main);
@ -274,13 +256,13 @@ void MainWindow::clearPasscode() {
}
void MainWindow::setupPasscode(bool anim) {
QPixmap bg = grabInner();
auto bg = grabInner();
if (_passcode) {
_passcode->stop_show();
_passcode.destroyDelayed();
}
_passcode.create(_body);
_passcode.create(bodyWidget());
updateControlsGeometry();
if (_main) _main->hide();
@ -332,7 +314,7 @@ void MainWindow::setupIntro(bool anim) {
QPixmap bg = anim ? grabInner() : QPixmap();
clearWidgets();
_intro.create(_body);
_intro.create(bodyWidget());
updateControlsGeometry();
if (anim) {
@ -382,7 +364,7 @@ void MainWindow::sendServiceHistoryRequest() {
void MainWindow::setupMain(bool anim, const MTPUser *self) {
QPixmap bg = anim ? grabInner() : QPixmap();
clearWidgets();
_main.create(_body);
_main.create(bodyWidget());
updateControlsGeometry();
if (anim) {
@ -418,7 +400,7 @@ void MainWindow::showSettings() {
}
if (!_layerBg) {
_layerBg.create(_body);
_layerBg.create(bodyWidget());
}
_settings.create(this);
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) {
if (box) {
if (!_layerBg) {
_layerBg.create(_body);
_layerBg.create(bodyWidget());
}
if (options.testFlag(KeepOtherLayers)) {
if (options.testFlag(ShowAfterOtherLayers)) {
@ -532,7 +514,7 @@ bool MainWindow::ui_isMediaViewShown() {
void MainWindow::ui_showMediaPreview(DocumentData *document) {
if (!document || ((!document->isAnimation() || !document->loaded()) && !document->sticker())) return;
if (!_mediaPreview) {
_mediaPreview.create(_body);
_mediaPreview.create(bodyWidget());
updateControlsGeometry();
}
if (_mediaPreview->isHidden()) {
@ -544,7 +526,7 @@ void MainWindow::ui_showMediaPreview(DocumentData *document) {
void MainWindow::ui_showMediaPreview(PhotoData *photo) {
if (!photo) return;
if (!_mediaPreview) {
_mediaPreview.create(_body);
_mediaPreview.create(bodyWidget());
updateControlsGeometry();
}
if (_mediaPreview->isHidden()) {
@ -571,7 +553,7 @@ void MainWindow::showConnecting(const QString &text, const QString &reconnect) {
if (_connecting) {
_connecting->set(text, reconnect);
} else {
_connecting.create(_body, text, reconnect);
_connecting.create(bodyWidget(), text, reconnect);
updateControlsGeometry();
fixOrder();
}
@ -586,15 +568,13 @@ void MainWindow::hideConnecting() {
void MainWindow::themeUpdated(const Window::Theme::BackgroundUpdate &data) {
using Type = Window::Theme::BackgroundUpdate::Type;
if (data.type == Type::TestingTheme) {
if (_title) _title->update();
if (!_testingThemeWarning) {
_testingThemeWarning.create(_body);
_testingThemeWarning.create(bodyWidget());
_testingThemeWarning->setGeometry(rect());
_testingThemeWarning->setHiddenCallback([this] { _testingThemeWarning.destroyDelayed(); });
}
_testingThemeWarning->showAnimated();
} else if (data.type == Type::RevertingTheme || data.type == Type::ApplyingTheme) {
if (_title) _title->update();
_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) {
switch (e->type()) {
case QEvent::MouseButtonPress:
@ -757,7 +699,7 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *e) {
case QEvent::Move:
case QEvent::Resize:
if (obj == this) {
psUpdatedPosition();
positionUpdated();
}
break;
}
@ -821,13 +763,17 @@ void MainWindow::updateTrayMenu(bool force) {
void MainWindow::onShowAddContact() {
if (isHidden()) showFromTray();
if (_main) _main->showAddContact();
if (App::self()) {
Ui::showLayer(new AddContactBox(), KeepOtherLayers);
}
}
void MainWindow::onShowNewGroup() {
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() {
@ -906,7 +852,6 @@ void MainWindow::layerFinishedHide(LayerStackWidget *was) {
}
void MainWindow::fixOrder() {
if (_title) _title->raise();
if (_layerBg) _layerBg->raise();
if (_mediaPreview) _mediaPreview->raise();
if (_connecting) _connecting->raise();
@ -980,7 +925,7 @@ void MainWindow::closeEvent(QCloseEvent *e) {
}
void MainWindow::resizeEvent(QResizeEvent *e) {
if (!_title) return;
Platform::MainWindow::resizeEvent(e);
Adaptive::Layout layout = Adaptive::OneColumnLayout;
if (width() > st::adaptiveWideWidth) {
@ -993,17 +938,11 @@ void MainWindow::resizeEvent(QResizeEvent *e) {
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();
}
void MainWindow::updateControlsGeometry() {
auto body = _body->rect();
auto body = bodyWidget()->rect();
if (_passcode) _passcode->setGeometry(body);
if (_main) _main->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 "ui/effects/rect_shadow.h"
#include "platform/platform_main_window.h"
#include "window/window_title.h"
#include "core/single_timer.h"
class MediaView;
@ -71,7 +70,7 @@ private:
class MediaPreviewWidget;
class MainWindow : public Platform::MainWindow, private base::Subscriber {
class MainWindow : public Platform::MainWindow {
Q_OBJECT
public:
@ -97,9 +96,6 @@ public:
void mtpStateChanged(int32 dc, int32 state);
Window::HitTestResult hitTest(const QPoint &p) const;
QRect iconRect() const;
IntroWidget *introWidget();
MainWidget *mainWidget();
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);
QImage icon16, icon32, icon64, iconbig16, iconbig32, iconbig64;
QWidget *centralwidget;
typedef QPair<QString, MTPMessageMedia> DelayedServiceMsg;
QVector<DelayedServiceMsg> _delayedServiceMsgs;
mtpRequestId _serviceHistoryRequest = 0;
Window::TitleWidget *_title = nullptr;
ChildWidget<TWidget> _body;
ChildWidget<PasscodeWidget> _passcode = { nullptr };
ChildWidget<IntroWidget> _intro = { nullptr };
ChildWidget<MainWidget> _main = { nullptr };

View file

@ -125,11 +125,11 @@ mediaPlayerNextDisabledIcon: icon {
};
mediaPlayerPreviousButton: IconButton(mediaPlayerNextButton) {
icon: icon {
{ "player_previous", mediaPlayerActiveFg, mediaPlayerSkipIconPosition },
{ "player_next-flip_horizontal", mediaPlayerActiveFg, mediaPlayerSkipIconPosition },
};
}
mediaPlayerPreviousDisabledIcon: icon {
{ "player_previous", mediaPlayerInactiveFg, mediaPlayerSkipIconPosition },
{ "player_next-flip_horizontal", mediaPlayerInactiveFg, mediaPlayerSkipIconPosition },
};
mediaPlayerClose: IconButton(mediaPlayerRepeatButton) {
width: 37px;
@ -178,10 +178,10 @@ mediaPlayerPanelNextDisabledIcon: icon {
{ "player_panel_next", mediaPlayerInactiveFg, point(10px, 10px) },
};
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 {
{ "player_panel_previous", mediaPlayerInactiveFg, point(10px, 10px) },
{ "player_panel_next-flip_horizontal", mediaPlayerInactiveFg, point(10px, 10px) },
};
mediaPlayerPanelPadding: 16px;

View file

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

View file

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

View file

@ -431,89 +431,6 @@ void MainWindow::LibsLoaded() {
#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() {
if (!noQtTrayIcon) {
cSetSupportTray(QSystemTrayIcon::isSystemTrayAvailable());
@ -641,7 +558,7 @@ void MainWindow::psFirstShow() {
show();
}
posInited = true;
setPositionInited();
}
void MainWindow::psInitSysMenu() {

View file

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

View file

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

View file

@ -52,8 +52,7 @@ void MacPrivate::darkModeChanged() {
}
MainWindow::MainWindow()
: posInited(false)
, icon256(qsl(":/gui/art/icon256.png"))
: icon256(qsl(":/gui/art/icon256.png"))
, iconbig256(qsl(":/gui/art/iconbig256.png"))
, wndIcon(QPixmap::fromImage(iconbig256, Qt::ColorOnly)) {
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() {
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::psFirstShow() {
psUpdateMargins();
@ -296,9 +217,14 @@ void MainWindow::psFirstShow() {
show();
}
posInited = true;
setPositionInited();
// init global menu
createGlobalMenu();
psMacUpdateMenu();
}
void MainWindow::createGlobalMenu() {
auto main = psMainMenu.addMenu(qsl("Telegram"));
auto about = main->addAction(lng_mac_menu_about_telegram(lt_telegram, qsl("Telegram")));
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()));
window->addSeparator();
psShowTelegram = window->addAction(lang(lng_mac_menu_show), App::wnd(), SLOT(showFromTray()));
psMacUpdateMenu();
}
namespace {
@ -398,23 +322,23 @@ void MainWindow::psUpdateMargins() {
}
void MainWindow::psMacUpdateMenu() {
if (!posInited) return;
if (!positionInited()) return;
QWidget *focused = QApplication::focusWidget();
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();
canSelectAll = !edit->text().isEmpty();
canUndo = edit->isUndoAvailable();
canRedo = edit->isRedoAvailable();
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();
canSelectAll = !edit->isEmpty();
canUndo = edit->isUndoAvailable();
canRedo = edit->isRedoAvailable();
canPaste = !Application::clipboard()->text().isEmpty();
} else if (HistoryInner *list = qobject_cast<HistoryInner*>(focused)) {
} else if (auto list = qobject_cast<HistoryInner*>(focused)) {
canCopy = list->canCopySelected();
canDelete = list->canDeleteSelected();
}

View file

@ -194,7 +194,7 @@ public:
max_w = avail.width();
accumulate_max(max_w, st::windowMinWidth);
max_h = avail.height();
accumulate_max(max_h, st::windowMinHeight);
accumulate_max(max_h, st::titleHeight + st::windowMinHeight);
HINSTANCE appinst = (HINSTANCE)GetModuleHandle(0);
HWND hwnd = App::wnd() ? App::wnd()->psHwnd() : 0;
@ -350,7 +350,7 @@ public:
}
return;
}
if (!App::wnd()->psPosInited()) return;
if (!App::wnd()->positionInited()) return;
int x = _x, y = _y, w = _w, h = _h;
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());
}
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() {
QWidget *w = new QWidget(this);
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);
}
namespace {
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()));
void MainWindow::initHook() {
auto platformInterface = QGuiApplication::platformNativeInterface();
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);
}
// RegisterApplicationRestart(NULL, 0);
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() {
return Notifications::supported();
}
@ -894,7 +810,7 @@ void MainWindow::psFirstShow() {
show();
}
posInited = true;
setPositionInited();
if (showShadows) {
shadowsUpdate(ShadowsChange::Moved | ShadowsChange::Resized | ShadowsChange::Shown);
}

View file

@ -35,12 +35,6 @@ class MainWindow : public Window::MainWindow {
public:
MainWindow();
int32 psResizeRowWidth() const {
return 0;//st::wndResizeAreaWidth;
}
void psInitFrameless();
void psInitSize();
HWND psHwnd() const;
HMENU psMenu() const;
@ -48,7 +42,6 @@ public:
void psInitSysMenu();
void psUpdateSysMenu(Qt::WindowState state);
void psUpdateMargins();
void psUpdatedPosition();
void psFlash();
void psNotifySettingGot();
@ -57,10 +50,6 @@ public:
void psRefreshTaskbarIcon();
bool psPosInited() const {
return posInited;
}
void psUpdateCounter();
bool psHasNativeNotifications();
@ -99,15 +88,16 @@ public:
~MainWindow();
public slots:
void psSavePosition(Qt::WindowState state = Qt::WindowActive);
void psShowTrayMenu();
protected:
void initHook() override;
int32 screenNameChecksum(const QString &name) const override;
bool psHasTrayIcon() const {
return trayIcon;
}
bool posInited = false;
QSystemTrayIcon *trayIcon = nullptr;
Ui::PopupMenu *trayIconMenu = nullptr;
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 "ui/buttons/icon_button.h"
#include "ui/widgets/shadow.h"
#include "styles/style_window.h"
namespace Platform {
@ -30,7 +31,8 @@ TitleWidget::TitleWidget(QWidget *parent) : Window::TitleWidget(parent)
, _minimize(this, st::titleButtonMinimize)
, _maximizeRestore(this, st::titleButtonMaximize)
, _close(this, st::titleButtonClose)
, _maximized(parent->window()->windowState() & Qt::WindowMaximized) {
, _maximized(parent->window()->windowState() & Qt::WindowMaximized)
, _shadow(this, st::titleShadow) {
_minimize->setClickedCallback([this]() {
window()->setWindowState(Qt::WindowMinimized);
_minimize->clearState();
@ -65,6 +67,7 @@ void TitleWidget::updateControlsPosition() {
void TitleWidget::resizeEvent(QResizeEvent *e) {
updateControlsPosition();
_shadow->setGeometry(0, height() - st::lineWidth, width(), st::lineWidth);
}
void TitleWidget::updateControlsVisibility() {

View file

@ -24,6 +24,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Ui {
class IconButton;
class PlainShadow;
} // namespace Ui
namespace Platform {
@ -51,6 +52,7 @@ private:
ChildWidget<Ui::IconButton> _minimize;
ChildWidget<Ui::IconButton> _maximizeRestore;
ChildWidget<Ui::IconButton> _close;
ChildWidget<Ui::PlainShadow> _shadow;
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);
} else {
App::wnd()->psUpdatedPosition();
App::wnd()->positionUpdated();
}
App::wnd()->psUpdateMargins();
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: {
App::wnd()->shadowsUpdate(ShadowsChange::Moved);
App::wnd()->psUpdatedPosition();
App::wnd()->positionUpdated();
} return false;
case WM_NCHITTEST: {
@ -185,7 +185,6 @@ bool EventFilter::mainWindowEvent(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa
switch (res) {
case Window::HitTestResult::Client:
case Window::HitTestResult::SysButton: *result = HTCLIENT; break;
case Window::HitTestResult::Icon: *result = HTCAPTION; break;
case Window::HitTestResult::Caption: *result = HTCAPTION; break;
case Window::HitTestResult::Top: *result = HTTOP; 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);
} 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: {
if (wParam == SC_MOUSEMENU) {
POINTS p = MAKEPOINTS(lParam);

View file

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

View file

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

View file

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

View file

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

View file

@ -31,6 +31,7 @@ public:
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, base::lambda_unique<void()> callback, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr);
QAction *addSeparator();
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) {
auto action = new QAction(text, this);
auto action = addAction(new QAction(text, this), icon, iconOver);
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) {

View file

@ -32,6 +32,7 @@ public:
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, base::lambda_unique<void()> callback, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr);
QAction *addSeparator();
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);
}
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() {
return _menu->addSeparator();
}

View file

@ -29,6 +29,7 @@ public:
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, base::lambda_unique<void()> callback, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr);
QAction *addSeparator();
void clearActions();

View file

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

View file

@ -21,9 +21,147 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "stdafx.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 {
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() {

View file

@ -20,20 +20,63 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "window/window_title.h"
namespace Window {
class MainWindow : public QMainWindow {
class TitleWidget;
class MainWindow : public QMainWindow, protected base::Subscriber {
Q_OBJECT
public:
MainWindow();
void init();
HitTestResult hitTest(const QPoint &p) const;
bool positionInited() const {
return _positionInited;
}
void positionUpdated();
virtual void closeWithoutDestroy();
virtual ~MainWindow();
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) {
}
// 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

View file

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

View file

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

View file

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