From 2436ad74bdf491ca36e0b6ea6f1677379ae2dbb7 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 13 Dec 2016 20:07:56 +0300 Subject: [PATCH] Boxes redesigned. Common groups moved to Shared Media. Also transparent images sending fixed. --- Telegram/Resources/basic.style | 11 +- Telegram/Resources/colors.palette | 12 +- Telegram/Resources/icons/box_shadow.png | Bin 190 -> 0 bytes Telegram/Resources/icons/box_shadow@2x.png | Bin 294 -> 0 bytes Telegram/Resources/icons/box_title_shadow.png | Bin 85 -> 0 bytes .../Resources/icons/box_title_shadow@2x.png | Bin 107 -> 0 bytes Telegram/Resources/icons/dropdown_shadow.png | Bin 168 -> 0 bytes .../Resources/icons/dropdown_shadow@2x.png | Bin 240 -> 0 bytes .../icons/round_shadow_box_bottom.png | Bin 0 -> 98 bytes .../icons/round_shadow_box_bottom@2x.png | Bin 0 -> 111 bytes .../icons/round_shadow_box_bottom_left.png | Bin 0 -> 292 bytes .../icons/round_shadow_box_bottom_left@2x.png | Bin 0 -> 539 bytes .../Resources/icons/round_shadow_box_left.png | Bin 0 -> 93 bytes .../icons/round_shadow_box_left@2x.png | Bin 0 -> 98 bytes .../Resources/icons/round_shadow_box_top.png | Bin 0 -> 93 bytes .../icons/round_shadow_box_top@2x.png | Bin 0 -> 102 bytes .../icons/round_shadow_box_top_left.png | Bin 0 -> 219 bytes .../icons/round_shadow_box_top_left@2x.png | Bin 0 -> 423 bytes Telegram/Resources/langs/lang.strings | 2 +- Telegram/Resources/sample.tdesktop-theme | 12 +- Telegram/Resources/winrc/Telegram.rc | 8 +- Telegram/Resources/winrc/Updater.rc | 8 +- Telegram/SourceFiles/apiwrap.cpp | 2 +- Telegram/SourceFiles/app.cpp | 2 + Telegram/SourceFiles/boxes/aboutbox.cpp | 37 +- Telegram/SourceFiles/boxes/aboutbox.h | 23 +- Telegram/SourceFiles/boxes/abstractbox.cpp | 414 ++++++++++++------ Telegram/SourceFiles/boxes/abstractbox.h | 251 ++++++++--- Telegram/SourceFiles/boxes/addcontactbox.cpp | 397 ++++++++--------- Telegram/SourceFiles/boxes/addcontactbox.h | 181 ++++---- Telegram/SourceFiles/boxes/autolockbox.cpp | 27 +- Telegram/SourceFiles/boxes/autolockbox.h | 12 +- Telegram/SourceFiles/boxes/backgroundbox.cpp | 34 +- Telegram/SourceFiles/boxes/backgroundbox.h | 28 +- Telegram/SourceFiles/boxes/boxes.style | 127 +++--- Telegram/SourceFiles/boxes/confirmbox.cpp | 337 +++++++------- Telegram/SourceFiles/boxes/confirmbox.h | 211 +++------ .../SourceFiles/boxes/confirmphonebox.cpp | 73 +-- Telegram/SourceFiles/boxes/confirmphonebox.h | 21 +- Telegram/SourceFiles/boxes/connectionbox.cpp | 92 ++-- Telegram/SourceFiles/boxes/connectionbox.h | 69 ++- Telegram/SourceFiles/boxes/contactsbox.cpp | 407 ++++++++--------- Telegram/SourceFiles/boxes/contactsbox.h | 112 ++--- .../SourceFiles/boxes/downloadpathbox.cpp | 49 ++- Telegram/SourceFiles/boxes/downloadpathbox.h | 28 +- Telegram/SourceFiles/boxes/emojibox.cpp | 21 +- Telegram/SourceFiles/boxes/emojibox.h | 8 +- Telegram/SourceFiles/boxes/languagebox.cpp | 55 ++- Telegram/SourceFiles/boxes/languagebox.h | 20 +- .../SourceFiles/boxes/localstoragebox.cpp | 28 +- Telegram/SourceFiles/boxes/localstoragebox.h | 12 +- Telegram/SourceFiles/boxes/members_box.cpp | 125 +++--- Telegram/SourceFiles/boxes/members_box.h | 28 +- .../SourceFiles/boxes/notifications_box.cpp | 21 +- .../SourceFiles/boxes/notifications_box.h | 10 +- Telegram/SourceFiles/boxes/passcodebox.cpp | 154 +++---- Telegram/SourceFiles/boxes/passcodebox.h | 46 +- Telegram/SourceFiles/boxes/photocropbox.cpp | 65 ++- Telegram/SourceFiles/boxes/photocropbox.h | 28 +- Telegram/SourceFiles/boxes/report_box.cpp | 40 +- Telegram/SourceFiles/boxes/report_box.h | 22 +- Telegram/SourceFiles/boxes/send_files_box.cpp | 162 ++++--- Telegram/SourceFiles/boxes/send_files_box.h | 63 +-- Telegram/SourceFiles/boxes/sessionsbox.cpp | 100 ++--- Telegram/SourceFiles/boxes/sessionsbox.h | 35 +- Telegram/SourceFiles/boxes/sharebox.cpp | 144 +++--- Telegram/SourceFiles/boxes/sharebox.h | 39 +- Telegram/SourceFiles/boxes/stickers_box.cpp | 343 ++++++++------- Telegram/SourceFiles/boxes/stickers_box.h | 88 ++-- Telegram/SourceFiles/boxes/stickersetbox.cpp | 99 ++--- Telegram/SourceFiles/boxes/stickersetbox.h | 38 +- Telegram/SourceFiles/boxes/usernamebox.cpp | 61 ++- Telegram/SourceFiles/boxes/usernamebox.h | 28 +- .../SourceFiles/core/click_handler_types.cpp | 25 +- Telegram/SourceFiles/core/single_timer.cpp | 2 +- Telegram/SourceFiles/core/single_timer.h | 2 +- Telegram/SourceFiles/core/version.h | 2 +- Telegram/SourceFiles/dialogs/dialogs.style | 2 +- Telegram/SourceFiles/dialogswidget.cpp | 5 +- Telegram/SourceFiles/dialogswidget.h | 20 +- Telegram/SourceFiles/facades.cpp | 33 +- Telegram/SourceFiles/facades.h | 14 +- .../history/field_autocomplete.cpp | 24 +- .../SourceFiles/history/field_autocomplete.h | 5 +- Telegram/SourceFiles/history/history.style | 6 +- .../SourceFiles/history/history_drag_area.cpp | 48 +- .../SourceFiles/history/history_drag_area.h | 22 +- .../history/history_media_types.cpp | 4 +- .../SourceFiles/history/history_message.cpp | 1 + Telegram/SourceFiles/historywidget.cpp | 189 ++++---- Telegram/SourceFiles/historywidget.h | 73 ++- Telegram/SourceFiles/intro/introcode.h | 10 +- Telegram/SourceFiles/intro/introphone.cpp | 8 +- Telegram/SourceFiles/intro/introphone.h | 10 +- Telegram/SourceFiles/intro/intropwdcheck.cpp | 10 +- Telegram/SourceFiles/intro/intropwdcheck.h | 15 +- Telegram/SourceFiles/intro/introsignup.cpp | 5 +- Telegram/SourceFiles/intro/introsignup.h | 8 +- Telegram/SourceFiles/intro/introwidget.cpp | 61 ++- Telegram/SourceFiles/intro/introwidget.h | 19 +- Telegram/SourceFiles/layerwidget.cpp | 188 ++++++-- Telegram/SourceFiles/layerwidget.h | 62 ++- Telegram/SourceFiles/layout.h | 1 + Telegram/SourceFiles/localimageloader.cpp | 43 +- Telegram/SourceFiles/mainwidget.cpp | 258 ++++++----- Telegram/SourceFiles/mainwidget.h | 43 +- Telegram/SourceFiles/mainwindow.cpp | 76 ++-- Telegram/SourceFiles/mainwindow.h | 31 +- .../media/player/media_player.style | 7 +- .../media/player/media_player_cover.cpp | 2 +- .../media/player/media_player_cover.h | 22 +- .../media/player/media_player_list.cpp | 2 +- .../media/player/media_player_list.h | 2 +- .../media/player/media_player_panel.cpp | 22 +- .../media/player/media_player_panel.h | 11 +- .../player/media_player_volume_controller.cpp | 9 +- .../player/media_player_volume_controller.h | 8 +- .../media/player/media_player_widget.cpp | 4 +- .../media/player/media_player_widget.h | 22 +- .../media/view/media_clip_controller.cpp | 5 +- .../media/view/media_clip_controller.h | 12 +- Telegram/SourceFiles/mediaview.cpp | 3 +- Telegram/SourceFiles/mediaview.h | 10 +- Telegram/SourceFiles/overviewwidget.cpp | 3 +- Telegram/SourceFiles/overviewwidget.h | 10 +- Telegram/SourceFiles/passcodewidget.h | 6 +- .../platform/mac/main_window_mac.mm | 4 +- .../platform/mac/window_title_mac.h | 4 +- .../platform/mac/window_title_mac.mm | 6 +- .../platform/platform_window_title.h | 4 +- .../platform/win/window_title_win.h | 12 +- .../profile/profile_block_actions.cpp | 76 ++-- .../profile/profile_block_actions.h | 4 - .../profile/profile_block_channel_members.cpp | 8 +- .../profile/profile_block_channel_members.h | 6 +- .../profile/profile_block_group_members.cpp | 14 +- .../profile/profile_block_group_members.h | 2 +- .../profile/profile_block_info.cpp | 81 +--- .../SourceFiles/profile/profile_block_info.h | 35 +- .../profile/profile_block_invite_link.h | 2 +- .../profile/profile_block_settings.cpp | 17 +- .../profile/profile_block_settings.h | 7 +- .../profile/profile_block_shared_media.cpp | 52 ++- .../profile/profile_block_shared_media.h | 7 + .../profile/profile_common_groups_section.cpp | 9 +- .../profile/profile_common_groups_section.h | 12 +- .../SourceFiles/profile/profile_cover.cpp | 17 +- Telegram/SourceFiles/profile/profile_cover.h | 8 +- .../SourceFiles/profile/profile_fixed_bar.cpp | 38 +- .../SourceFiles/profile/profile_fixed_bar.h | 4 +- .../profile/profile_inner_widget.h | 2 +- .../profile/profile_section_memento.cpp | 6 +- .../profile/profile_section_memento.h | 2 +- .../SourceFiles/profile/profile_widget.cpp | 38 +- Telegram/SourceFiles/profile/profile_widget.h | 13 +- Telegram/SourceFiles/settings/settings.style | 13 +- .../settings/settings_advanced_widget.cpp | 43 +- .../settings/settings_advanced_widget.h | 10 +- .../settings/settings_background_widget.cpp | 2 +- .../settings/settings_background_widget.h | 10 +- .../settings/settings_block_widget.cpp | 6 +- .../settings/settings_block_widget.h | 22 +- .../settings_chat_settings_widget.cpp | 28 +- .../settings/settings_chat_settings_widget.h | 29 +- .../SourceFiles/settings/settings_cover.cpp | 11 +- .../SourceFiles/settings/settings_cover.h | 16 +- .../settings/settings_fixed_bar.cpp | 17 +- .../SourceFiles/settings/settings_fixed_bar.h | 4 - .../settings/settings_general_widget.cpp | 22 +- .../settings/settings_general_widget.h | 21 +- .../settings/settings_info_widget.cpp | 18 +- .../settings/settings_info_widget.h | 24 +- .../settings/settings_inner_widget.cpp | 2 +- .../settings/settings_inner_widget.h | 2 +- .../settings_notifications_widget.cpp | 2 +- .../settings/settings_notifications_widget.h | 14 +- .../settings/settings_privacy_widget.cpp | 14 +- .../settings/settings_privacy_widget.h | 16 +- .../settings/settings_scale_widget.cpp | 23 +- .../settings/settings_scale_widget.h | 6 +- .../SourceFiles/settings/settings_widget.cpp | 95 ++-- .../SourceFiles/settings/settings_widget.h | 17 +- Telegram/SourceFiles/stickers/emoji_pan.cpp | 174 ++++---- Telegram/SourceFiles/stickers/emoji_pan.h | 66 ++- Telegram/SourceFiles/stickers/stickers.cpp | 4 +- Telegram/SourceFiles/stickers/stickers.style | 16 +- Telegram/SourceFiles/structs.cpp | 2 +- Telegram/SourceFiles/ui/countryinput.cpp | 54 +-- Telegram/SourceFiles/ui/countryinput.h | 25 +- .../SourceFiles/ui/effects/rect_shadow.cpp | 99 ----- Telegram/SourceFiles/ui/effects/rect_shadow.h | 51 --- .../ui/effects/widget_fade_wrap.cpp | 8 +- .../SourceFiles/ui/effects/widget_fade_wrap.h | 42 +- .../ui/effects/widget_slide_wrap.cpp | 4 +- .../ui/effects/widget_slide_wrap.h | 14 +- Telegram/SourceFiles/ui/images.cpp | 3 +- Telegram/SourceFiles/ui/toast/toast.cpp | 2 +- Telegram/SourceFiles/ui/toast/toast.h | 2 +- .../SourceFiles/ui/toast/toast_manager.cpp | 8 +- Telegram/SourceFiles/ui/twidget.cpp | 14 +- Telegram/SourceFiles/ui/twidget.h | 103 +++-- .../ui/widgets/discrete_sliders.cpp | 26 +- .../SourceFiles/ui/widgets/discrete_sliders.h | 5 +- .../SourceFiles/ui/widgets/dropdown_menu.h | 3 +- .../SourceFiles/ui/widgets/inner_dropdown.cpp | 3 +- .../SourceFiles/ui/widgets/inner_dropdown.h | 2 +- .../SourceFiles/ui/widgets/input_fields.cpp | 76 ++-- .../SourceFiles/ui/widgets/input_fields.h | 11 +- Telegram/SourceFiles/ui/widgets/labels.cpp | 5 +- .../SourceFiles/ui/widgets/multi_select.cpp | 7 +- .../SourceFiles/ui/widgets/multi_select.h | 8 +- Telegram/SourceFiles/ui/widgets/popup_menu.h | 2 +- .../SourceFiles/ui/widgets/scroll_area.cpp | 54 +-- Telegram/SourceFiles/ui/widgets/scroll_area.h | 42 +- Telegram/SourceFiles/ui/widgets/shadow.cpp | 53 +-- Telegram/SourceFiles/ui/widgets/shadow.h | 49 +-- Telegram/SourceFiles/ui/widgets/widgets.style | 13 +- Telegram/SourceFiles/window/main_window.h | 8 +- .../window/notifications_manager_default.cpp | 2 +- .../window/notifications_manager_default.h | 12 +- .../SourceFiles/window/player_wrap_widget.cpp | 2 +- Telegram/SourceFiles/window/section_memento.h | 2 +- .../SourceFiles/window/top_bar_widget.cpp | 8 +- Telegram/SourceFiles/window/top_bar_widget.h | 16 +- Telegram/SourceFiles/window/window.style | 3 + .../SourceFiles/window/window_main_menu.cpp | 4 +- .../SourceFiles/window/window_main_menu.h | 10 +- .../window/window_theme_warning.cpp | 8 +- .../SourceFiles/window/window_theme_warning.h | 7 +- Telegram/build/version | 2 +- Telegram/gyp/Telegram.gyp | 2 - 231 files changed, 4233 insertions(+), 4235 deletions(-) delete mode 100644 Telegram/Resources/icons/box_shadow.png delete mode 100644 Telegram/Resources/icons/box_shadow@2x.png delete mode 100644 Telegram/Resources/icons/box_title_shadow.png delete mode 100644 Telegram/Resources/icons/box_title_shadow@2x.png delete mode 100644 Telegram/Resources/icons/dropdown_shadow.png delete mode 100644 Telegram/Resources/icons/dropdown_shadow@2x.png create mode 100644 Telegram/Resources/icons/round_shadow_box_bottom.png create mode 100644 Telegram/Resources/icons/round_shadow_box_bottom@2x.png create mode 100644 Telegram/Resources/icons/round_shadow_box_bottom_left.png create mode 100644 Telegram/Resources/icons/round_shadow_box_bottom_left@2x.png create mode 100644 Telegram/Resources/icons/round_shadow_box_left.png create mode 100644 Telegram/Resources/icons/round_shadow_box_left@2x.png create mode 100644 Telegram/Resources/icons/round_shadow_box_top.png create mode 100644 Telegram/Resources/icons/round_shadow_box_top@2x.png create mode 100644 Telegram/Resources/icons/round_shadow_box_top_left.png create mode 100644 Telegram/Resources/icons/round_shadow_box_top_left@2x.png delete mode 100644 Telegram/SourceFiles/ui/effects/rect_shadow.cpp delete mode 100644 Telegram/SourceFiles/ui/effects/rect_shadow.h diff --git a/Telegram/Resources/basic.style b/Telegram/Resources/basic.style index 3aefbf874..48d2ec1ad 100644 --- a/Telegram/Resources/basic.style +++ b/Telegram/Resources/basic.style @@ -36,11 +36,6 @@ emojiPadding: 1px; lineWidth: 1px; -defaultDropdownDuration: 150; -defaultDropdownPadding: margins(10px, 10px, 10px, 10px); -defaultDropdownShadow: icon {{ "dropdown_shadow", windowShadowFg }}; -defaultDropdownShadowShift: 1px; - defaultTooltip: Tooltip { textBg: #eef2f5; textFg: #5d6c80; @@ -309,8 +304,6 @@ simpleCloseIcon: icon {{ "simple_close", #c7c7c7 }}; simpleCloseIconOver: icon {{ "simple_close", #a3a3a3 }}; dialogsForwardCancelIcon: icon {{ "simple_close", dialogsForwardFg }}; -membersPadding: margins(0px, 10px, 0px, 10px); - forwardMargins: margins(30px, 10px, 30px, 10px); forwardFont: font(16px); forwardBg: #0000004c; @@ -450,8 +443,8 @@ historyReplyCancelIcon: icon {{ "box_button_close", historyReplyCancelFg }}; historyReplyCancelIconOver: icon {{ "box_button_close", historyReplyCancelFgOver }}; boxSearchCancelIcon: icon {{ "box_button_close", boxSearchCancelIconFg }}; boxSearchCancelIconOver: icon {{ "box_button_close", boxSearchCancelIconFgOver }}; -boxBlockTitleCloseIcon: icon {{ "box_button_close", boxBlockTitleCloseFg }}; -boxBlockTitleCloseIconOver: icon {{ "box_button_close", boxBlockTitleCloseFgOver }}; +boxTitleCloseIcon: icon {{ "box_button_close", boxTitleCloseFg }}; +boxTitleCloseIconOver: icon {{ "box_button_close", boxTitleCloseFgOver }}; notifyFadeRight: icon {{ "fade_horizontal", notificationBg }}; diff --git a/Telegram/Resources/colors.palette b/Telegram/Resources/colors.palette index 96214c422..cb6817f4c 100644 --- a/Telegram/Resources/colors.palette +++ b/Telegram/Resources/colors.palette @@ -86,8 +86,8 @@ trayCounterFgMacInvert: #ffffff01; // layers layerBg: #0000007f; -cancelIconFg: #a2a2a2; -cancelIconFgOver: #808080; +cancelIconFg: menuIconFg; +cancelIconFgOver: menuIconFgOver; // boxes boxBg: windowBg; @@ -99,11 +99,9 @@ boxSearchBg: boxBg; boxSearchCancelIconFg: cancelIconFg; boxSearchCancelIconFgOver: cancelIconFgOver; -boxBlockTitleBg: boxBg; -boxBlockTitleFg: boxTitleFg; -boxBlockTitleAdditionalFg: #808080; -boxBlockTitleCloseFg: cancelIconFg; -boxBlockTitleCloseFgOver: cancelIconFgOver; +boxTitleAdditionalFg: #808080; +boxTitleCloseFg: cancelIconFg; +boxTitleCloseFgOver: cancelIconFgOver; membersAboutLimitFg: windowSubTextFgOver; diff --git a/Telegram/Resources/icons/box_shadow.png b/Telegram/Resources/icons/box_shadow.png deleted file mode 100644 index 44d17254e6c61802ba83dd7da40e7a09facd35d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 190 zcmeAS@N?(olHy`uVBq!ia0vp^{2PguW?_TPoa>zI3z&Akv+K-#$Tgv5 zcmMa?bWa7#Z`KD_7Bfu}5S*~3B%IY)&C`V?DqGpLH2#=hgpkU@?{ViDa=e0s-=sCY oHeY%|w_@spHHqtY{pGS__-xG@slQU}9?(Gyp00i_>zopr0GNA7B>(^b diff --git a/Telegram/Resources/icons/box_shadow@2x.png b/Telegram/Resources/icons/box_shadow@2x.png deleted file mode 100644 index 06293b7405db47e11a8762cee0a235b89b118545..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 294 zcmV+>0oneEP) z7{RInN{(%EcD)4LC%w+my{w27*a9pV31M&wM#(ehk$4J5ol&#Tys;(65l}>$s=7iv z_aPWLK|p)-Tu(W+&Q)~)X5ndYRN@}mx2WtC>~%!2<2b&+*Rjtvy|}UhY{^TGky3AA zA=jC?PQAz3`905*6>o_2j{sX})kuv%^K6~p0!Le&w?+2%r@<&ZG3W!a6wIJV+;VUv s;t??0{D12BZu}p3*fQA*_fHDI-r8#}JO0y2m#19#G(6Fi?Lq z_0Rv9BTWHT0seifq$0k@ZTNOi|L)(SbBq&bGB-AU`OUD^m0$1OV_QC;ZU#?RKbLh* G2~7a(5hA<* diff --git a/Telegram/Resources/icons/dropdown_shadow.png b/Telegram/Resources/icons/dropdown_shadow.png deleted file mode 100644 index 343a871527f2ba7f571d66b1b3c6bbd6994699e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 168 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V8<6ZZI=>f4<$Jm~hDc29oe;=%*nr15Rnv^^ z`M>3-V{ff*DZ6=%>yKiE*fib)jpAA1$!Xck?mJ8}F!pFtnIY+M@8HZ!QO+(0?kZ;L z-gofq;P`ScF!aQkse2mV^{qN2k*vMBZ$?2{UG7=Vi7cKTzj*8RJs145T=>FwR_&WT S?=*l`GkCiCxvX^-_)k!%{J6$3$#_BpXt5xM1H@$G}EdJa_82RJ)m3i=lew7s}4 z!3fz3Kma@vNAwTO5?Gf~1i-)}yiDlZ5RxOM?JdFV&H#*LB&C!xO*$PpV%D|R6pbm< zkv&FINJ{TrdhgO&8}M}GcyAsx?7FUac3Q~NS$ptpA=`{&x7PMRKWt>gy)pj z&H95jCJin@g;P`S2V7+lC}(##({tU$#n86aF-^=ObJKNub6xgE6Q3(TE*=7!z~JfX K=d#Wzp$Pyf-XWs^ literal 0 HcmV?d00001 diff --git a/Telegram/Resources/icons/round_shadow_box_bottom_left.png b/Telegram/Resources/icons/round_shadow_box_bottom_left.png new file mode 100644 index 0000000000000000000000000000000000000000..3bb8de35632d70c6025be26dc8b874732a14aad5 GIT binary patch literal 292 zcmV+<0o(qGP)=DSWm(oS5kakWcO%B2Pmf~X z=O!p3E3`c`@S*cwC=)QV)$tJA-9a)9t_4bR2aeGG`>^LxG;`X6GUo)av6?No1KiAy q@NCf;@a!r`;iJy3>Ju$p!424g~-v5!~{TZ3-8s7pqK= zKid)YG5N(Ac)yWaXr?#R2mICgfWKP*8=Qz{43pB|a@=z84tF(`9DfIR6I=pnz;^{v z&hfil|B7}bqNhzyhbN-*@?>qCGIAaFVD550>^Rpb*S#QSxeXM+d&+Q7dDk=(8c|k>i=g=!#NHzE=M3fCh?nT;3({$`t8x_v0fcHSps&7UTY^>^N_C=+>HBR%gkr zD!iI-^_mXg0lK@+kJX6i;W$qoyH$?hLXKNoTK?PvIF929tdEfaxAXum9hNJlRV^em zZ%2X4;Fcl*c+ebJgB^iu?^CHF%bgcMCN&}fguzD@f(PIoWsDroIId~K&%yq~%fZ*J z-K`Xe0B0&m89W<=*0#pX1P}txz(-)C>0$n+foI^Ofp}v?flJ^~h?T%+Ukt!A6GQ>4 zAEL?t1Kb-t3s%i%wLcv2%7j-_;Zly52Ak-pI~RiB6@aU-rE++6;MM=X1U?faJr^c| dhbNs7;5Y0phJ{}GN3H+>002ovPDHLkV1iP0_>lkr literal 0 HcmV?d00001 diff --git a/Telegram/Resources/icons/round_shadow_box_left.png b/Telegram/Resources/icons/round_shadow_box_left.png new file mode 100644 index 0000000000000000000000000000000000000000..7f5e183c9902c54fccb225c6df948c4fbccb5c51 GIT binary patch literal 93 zcmeAS@N?(olHy`uVBq!ia0vp^AT}ch8<2ed)xHi$sd&0LhH%VeJ=n;|V8GFAu;J=| q`+Gu-%NH3Lt0;2jW}bdmR9>U`j4|Ti#kM}6dInEdKbLh*2~7a}3>wY= literal 0 HcmV?d00001 diff --git a/Telegram/Resources/icons/round_shadow_box_left@2x.png b/Telegram/Resources/icons/round_shadow_box_left@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1e28073414f034c5cc32b4a23db4487bf87d548d GIT binary patch literal 98 zcmeAS@N?(olHy`uVBq!ia0vp^B0$WA4$1cCB`|25eEARC4*rOecv1u0dH-VZMJYD@<);T3K0RY`;A87yp literal 0 HcmV?d00001 diff --git a/Telegram/Resources/icons/round_shadow_box_top.png b/Telegram/Resources/icons/round_shadow_box_top.png new file mode 100644 index 0000000000000000000000000000000000000000..f2ff11208bc527027f58ab6d23d1f2f9e6ddc9f1 GIT binary patch literal 93 zcmeAS@N?(olHy`uVBq!ia0vp^j6lrA!3HEtFPV4&DHTr_#}JO0x<@uLG8ph2GH`zI sfAVcsUZx7R4NFp`@89*>bn6qN@m7P$Pq+inf{YjGMOM+L1-?T-7Z2^tZ5t_f@|?1J!o}MD+*H)@w(nt+nYkmV&PU zLNx_G3p(?>8{E^`odbix5eTi$YBz$wy+BfZ6dtK(f_tF7X|#-!3XWQCOiTAj+9MGh zfwu0^0a^K+Tu}uDm9E;o)Q=<<+?sF*s0NL|TV?L3g2JMMkN_>Khg?Mi)Y94&1s1`j zhEV9}06fqvxHgC}--5OVqCqcNfX0T#PBrM>yZa4jz+8T4uVMjb=;I3r30)PSi6%B# z5`326$*KA4=+jvWeMop*eE z&DPYRXQ|1FYL}%?so>VKFXd$@WbxhBCKA9kunN#b5B^=a1boL^_-%{t&>M3D3igpo R#8?0T002ovPDHLkV1kPm!KnZM literal 0 HcmV?d00001 diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index cb6d50f70..20d08b33c 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -296,7 +296,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_backgrounds_header" = "Choose your new chat background"; "lng_theme_sure_keep" = "Keep this color theme?"; -"lng_theme_reverting" = "Reverting to previous color theme in {count:_not_used_|# second|# seconds}."; +"lng_theme_reverting" = "Reverting to the old color theme in {count:_not_used_|# second|# seconds}."; "lng_theme_keep_changes" = "Keep changes"; "lng_theme_revert" = "Revert"; diff --git a/Telegram/Resources/sample.tdesktop-theme b/Telegram/Resources/sample.tdesktop-theme index ce33f6904..a0c0a3342 100644 --- a/Telegram/Resources/sample.tdesktop-theme +++ b/Telegram/Resources/sample.tdesktop-theme @@ -74,8 +74,8 @@ trayCounterFg: #ffffff; trayCounterBgMacInvert: #ffffff; trayCounterFgMacInvert: #ffffff01; layerBg: #0000007f; -cancelIconFg: #a2a2a2; -cancelIconFgOver: #808080; +cancelIconFg: menuIconFg; +cancelIconFgOver: menuIconFgOver; boxBg: windowBg; boxTextFg: windowFg; boxTextFgGood: #4ab44a; @@ -84,11 +84,9 @@ boxTitleFg: #404040; boxSearchBg: boxBg; boxSearchCancelIconFg: cancelIconFg; boxSearchCancelIconFgOver: cancelIconFgOver; -boxBlockTitleBg: boxBg; -boxBlockTitleFg: boxTitleFg; -boxBlockTitleAdditionalFg: #808080; -boxBlockTitleCloseFg: cancelIconFg; -boxBlockTitleCloseFgOver: cancelIconFgOver; +boxTitleAdditionalFg: #808080; +boxTitleCloseFg: cancelIconFg; +boxTitleCloseFgOver: cancelIconFgOver; membersAboutLimitFg: windowSubTextFgOver; contactsBg: windowBg; contactsBgOver: windowBgOver; diff --git a/Telegram/Resources/winrc/Telegram.rc b/Telegram/Resources/winrc/Telegram.rc index c04a8c9e5..5f2d01a9b 100644 --- a/Telegram/Resources/winrc/Telegram.rc +++ b/Telegram/Resources/winrc/Telegram.rc @@ -34,8 +34,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,10,19,14 - PRODUCTVERSION 0,10,19,14 + FILEVERSION 0,10,20,1 + PRODUCTVERSION 0,10,20,1 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -51,10 +51,10 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "CompanyName", "Telegram Messenger LLP" - VALUE "FileVersion", "0.10.19.14" + VALUE "FileVersion", "0.10.20.1" VALUE "LegalCopyright", "Copyright (C) 2014-2016" VALUE "ProductName", "Telegram Desktop" - VALUE "ProductVersion", "0.10.19.14" + VALUE "ProductVersion", "0.10.20.1" END END BLOCK "VarFileInfo" diff --git a/Telegram/Resources/winrc/Updater.rc b/Telegram/Resources/winrc/Updater.rc index 6bd1cf42f..839431d7f 100644 --- a/Telegram/Resources/winrc/Updater.rc +++ b/Telegram/Resources/winrc/Updater.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,10,19,14 - PRODUCTVERSION 0,10,19,14 + FILEVERSION 0,10,20,1 + PRODUCTVERSION 0,10,20,1 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,10 +43,10 @@ BEGIN BEGIN VALUE "CompanyName", "Telegram Messenger LLP" VALUE "FileDescription", "Telegram Updater" - VALUE "FileVersion", "0.10.19.14" + VALUE "FileVersion", "0.10.20.1" VALUE "LegalCopyright", "Copyright (C) 2014-2016" VALUE "ProductName", "Telegram Desktop" - VALUE "ProductVersion", "0.10.19.14" + VALUE "ProductVersion", "0.10.20.1" END END BLOCK "VarFileInfo" diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index d6241e6e5..a646ae8c6 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -830,7 +830,7 @@ bool ApiWrap::channelAmInFail(ChannelData *channel, const RPCError &error) { if (MTP::isDefaultHandledError(error)) return false; if (error.type() == qstr("CHANNELS_TOO_MUCH")) { - Ui::showLayer(new InformBox(lang(lng_join_channel_error))); + Ui::show(Box(lang(lng_join_channel_error))); } _channelAmInRequests.remove(channel); return true; diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index c0033e1c4..f793fd904 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -29,6 +29,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "styles/style_mediaview.h" #include "styles/style_stickers.h" #include "styles/style_history.h" +#include "styles/style_boxes.h" #include "lang.h" #include "data/data_abstract_structure.h" #include "history/history_service_layout.h" @@ -2243,6 +2244,7 @@ namespace { ::cornersMaskSmall[i]->setDevicePixelRatio(cRetinaFactor()); } prepareCorners(MenuCorners, st::buttonRadius, st::menuBg); + prepareCorners(BoxCorners, st::boxRadius, st::boxBg); prepareCorners(BotKbOverCorners, st::dateRadius, st::msgBotKbOverBg); prepareCorners(StickerCorners, st::dateRadius, st::msgServiceBg); prepareCorners(StickerSelectedCorners, st::dateRadius, st::msgServiceSelectBg); diff --git a/Telegram/SourceFiles/boxes/aboutbox.cpp b/Telegram/SourceFiles/boxes/aboutbox.cpp index f085cd0ae..1c59b885f 100644 --- a/Telegram/SourceFiles/boxes/aboutbox.cpp +++ b/Telegram/SourceFiles/boxes/aboutbox.cpp @@ -32,32 +32,35 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "styles/style_boxes.h" #include "platform/platform_file_dialog.h" -AboutBox::AboutBox() : AbstractBox(st::aboutWidth, qsl("Telegram Desktop")) -, _version(this, lng_about_version(lt_version, QString::fromLatin1(AppVersionStr.c_str()) + (cAlphaVersion() ? " alpha" : "") + (cBetaVersion() ? qsl(" beta %1").arg(cBetaVersion()) : QString())), st::aboutVersionLink) +AboutBox::AboutBox(QWidget *parent) +: _version(this, lng_about_version(lt_version, QString::fromLatin1(AppVersionStr.c_str()) + (cAlphaVersion() ? " alpha" : "") + (cBetaVersion() ? qsl(" beta %1").arg(cBetaVersion()) : QString())), st::aboutVersionLink) , _text1(this, lang(lng_about_text_1), Ui::FlatLabel::InitType::Rich, st::aboutLabel, st::aboutTextStyle) , _text2(this, lang(lng_about_text_2), Ui::FlatLabel::InitType::Rich, st::aboutLabel, st::aboutTextStyle) -, _text3(this,st::aboutLabel, st::aboutTextStyle) -, _done(this, lang(lng_close), st::defaultBoxButton) { +, _text3(this, st::aboutLabel, st::aboutTextStyle) { +} + +void AboutBox::prepare() { + setTitle(qsl("Telegram Desktop")); + + addButton(lang(lng_close), [this] { closeBox(); }); + _text3->setRichText(lng_about_text_3(lt_faq_open, qsl("[a href=\"%1\"]").arg(telegramFaqLink()), lt_faq_close, qsl("[/a]"))); - setMaxHeight(titleHeight() + st::aboutTextTop + _text1->height() + st::aboutSkip + _text2->height() + st::aboutSkip + _text3->height() + st::boxButtonPadding.top() + _done->height() + st::boxButtonPadding.bottom()); + _version->setClickedCallback([this] { showVersionHistory(); }); - connect(_version, SIGNAL(clicked()), this, SLOT(onVersion())); - connect(_done, SIGNAL(clicked()), this, SLOT(onClose())); - - setAcceptDrops(true); + setDimensions(st::aboutWidth, st::aboutTextTop + _text1->height() + st::aboutSkip + _text2->height() + st::aboutSkip + _text3->height()); } void AboutBox::resizeEvent(QResizeEvent *e) { - _version->moveToLeft(st::boxPadding.left(), titleHeight() + st::aboutVersionTop); - _text1->moveToLeft(st::boxPadding.left(), titleHeight() + st::aboutTextTop); + BoxContent::resizeEvent(e); + + _version->moveToLeft(st::boxPadding.left(), st::aboutVersionTop); + _text1->moveToLeft(st::boxPadding.left(), st::aboutTextTop); _text2->moveToLeft(st::boxPadding.left(), _text1->y() + _text1->height() + st::aboutSkip); _text3->moveToLeft(st::boxPadding.left(), _text2->y() + _text2->height() + st::aboutSkip); - _done->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _done->height()); - AbstractBox::resizeEvent(e); } -void AboutBox::onVersion() { +void AboutBox::showVersionHistory() { if (cRealBetaVersion()) { auto url = qsl("https://tdesktop.com/"); switch (cPlatform()) { @@ -71,7 +74,7 @@ void AboutBox::onVersion() { Application::clipboard()->setText(url); - Ui::showLayer(new InformBox("The link to the current private beta version of Telegram Desktop was copied to the clipboard.")); + Ui::show(Box("The link to the current private beta version of Telegram Desktop was copied to the clipboard.")); } else { QDesktopServices::openUrl(qsl("https://desktop.telegram.org/?_hash=changelog")); } @@ -79,9 +82,9 @@ void AboutBox::onVersion() { void AboutBox::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { - onClose(); + closeBox(); } else { - AbstractBox::keyPressEvent(e); + BoxContent::keyPressEvent(e); } } diff --git a/Telegram/SourceFiles/boxes/aboutbox.h b/Telegram/SourceFiles/boxes/aboutbox.h index c6a52ce33..5c6518b02 100644 --- a/Telegram/SourceFiles/boxes/aboutbox.h +++ b/Telegram/SourceFiles/boxes/aboutbox.h @@ -23,32 +23,29 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "boxes/abstractbox.h" namespace Ui { -class RoundButton; class LinkButton; class FlatLabel; } // namespace Ui -class AboutBox : public AbstractBox { - Q_OBJECT - +class AboutBox : public BoxContent { public: - AboutBox(); - -public slots: - void onVersion(); + AboutBox(QWidget*); protected: + void prepare() override; + void resizeEvent(QResizeEvent *e) override; void keyPressEvent(QKeyEvent *e) override; void dragEnterEvent(QDragEnterEvent *e) override; void dropEvent(QDropEvent *e) override; private: - ChildWidget _version; - ChildWidget _text1; - ChildWidget _text2; - ChildWidget _text3; - ChildWidget _done; + void showVersionHistory(); + + object_ptr _version; + object_ptr _text1; + object_ptr _text2; + object_ptr _text3; }; diff --git a/Telegram/SourceFiles/boxes/abstractbox.cpp b/Telegram/SourceFiles/boxes/abstractbox.cpp index 31fe4264d..126f75cfd 100644 --- a/Telegram/SourceFiles/boxes/abstractbox.cpp +++ b/Telegram/SourceFiles/boxes/abstractbox.cpp @@ -24,187 +24,341 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "styles/style_boxes.h" #include "localstorage.h" #include "lang.h" +#include "ui/effects/widget_fade_wrap.h" #include "ui/widgets/buttons.h" #include "ui/widgets/scroll_area.h" #include "mainwidget.h" #include "mainwindow.h" -AbstractBox::AbstractBox(int w, const QString &title) : LayerWidget(App::wnd()->bodyWidget()) -, _title(title) { - setAttribute(Qt::WA_OpaquePaintEvent); - resize((w > 0) ? w : st::boxWideWidth, 0); +BoxLayerTitleShadow::BoxLayerTitleShadow(QWidget *parent) : Ui::PlainShadow(parent, st::boxLayerTitleShadow) { } -void AbstractBox::setTitleText(const QString &title) { - _title = title; - update(); +QPointer BoxContent::addButton(const QString &text, base::lambda &&clickCallback) { + return addButton(text, std_::move(clickCallback), st::defaultBoxButton); } -void AbstractBox::setAdditionalTitle(const QString &additionalTitle) { - _additionalTitle = additionalTitle; - update(); +QPointer BoxContent::addLeftButton(const QString &text, base::lambda &&clickCallback) { + return getDelegate()->addLeftButton(text, std_::move(clickCallback), st::defaultBoxButton); } -void AbstractBox::keyPressEvent(QKeyEvent *e) { - if (e->key() == Qt::Key_Escape) { - onClose(); +void BoxContent::setInner(object_ptr inner) { + setInner(std_::move(inner), st::boxLayerScroll); +} + +void BoxContent::setInner(object_ptr inner, const style::ScrollArea &st) { + if (inner) { + getDelegate()->setLayerType(true); + if (!_scroll) { + _scroll.create(this, st); + connect(_scroll, SIGNAL(scrolled()), this, SLOT(onScroll())); + + _topShadow.create(this, object_ptr(this)); + if (_innerTopSkip > 0) { + _topShadow->showFast(); + } else { + _topShadow->hideFast(); + } + + _bottomShadow.create(this); + _bottomShadow->show(); + } else { + _scroll->setGeometryToLeft(0, _innerTopSkip, width(), 0); + } + _scroll->setOwnedWidget(std_::move(inner)); + updateScrollAreaGeometry(); } else { - LayerWidget::keyPressEvent(e); + getDelegate()->setLayerType(false); + _scroll.destroyDelayed(); + _topShadow.destroyDelayed(); + _bottomShadow.destroyDelayed(); } } -void AbstractBox::resizeEvent(QResizeEvent *e) { - updateBlockTitleGeometry(); - LayerWidget::resizeEvent(e); +void BoxContent::onScrollToY(int top, int bottom) { + if (_scroll) { + _scroll->scrollToY(top, bottom); + } } -void AbstractBox::updateBlockTitleGeometry() { - if (_blockClose) { - _blockClose->moveToRight(0, 0); +void BoxContent::onDraggingScrollDelta(int delta) { + _draggingScrollDelta = _scroll ? delta : 0; + if (_draggingScrollDelta) { + if (!_draggingScrollTimer) { + _draggingScrollTimer.create(this); + _draggingScrollTimer->setSingleShot(false); + connect(_draggingScrollTimer, SIGNAL(timeout()), this, SLOT(onDraggingScrollTimer())); + } + _draggingScrollTimer->start(15); + } else { + _draggingScrollTimer.destroy(); } - if (_blockShadow) { - _blockShadow->setGeometry(0, st::boxBlockTitleHeight, width(), st::boxBlockTitleShadow.height()); +} + +void BoxContent::onDraggingScrollTimer() { + auto delta = (_draggingScrollDelta > 0) ? qMin(_draggingScrollDelta * 3 / 20 + 1, int32(MaxScrollSpeed)) : qMax(_draggingScrollDelta * 3 / 20 - 1, -int32(MaxScrollSpeed)); + _scroll->scrollToY(_scroll->scrollTop() + delta); +} + +void BoxContent::onScroll() { + if (_scroll) { + auto top = _scroll->scrollTop(); + if (auto widget = static_cast(_scroll->widget())) { + widget->setVisibleTopBottom(top, top + _scroll->height()); + } + if (top > 0 || _innerTopSkip > 0) { + _topShadow->showAnimated(); + } else { + _topShadow->hideAnimated(); + } + } +} + +void BoxContent::setInnerTopSkip(int innerTopSkip, bool scrollBottomFixed) { + if (_innerTopSkip != innerTopSkip) { + auto delta = innerTopSkip - _innerTopSkip; + _innerTopSkip = innerTopSkip; + if (_scroll) { + auto scrollTopWas = _scroll->scrollTop(); + updateScrollAreaGeometry(); + if (scrollBottomFixed) { + _scroll->scrollToY(scrollTopWas + delta); + } + if (_innerTopSkip > 0) { + _topShadow->showFast(); + } else { + _topShadow->hideFast(); + } + } + } +} + +void BoxContent::setInnerVisible(bool scrollAreaVisible) { + if (_scroll) { + _scroll->setVisible(scrollAreaVisible); + } +} + +QPixmap BoxContent::grabInnerCache() { + auto isTopShadowVisible = !_topShadow->isHidden(); + auto isBottomShadowVisible = !_bottomShadow->isHidden(); + if (isTopShadowVisible) _topShadow->hide(); + if (isBottomShadowVisible) _bottomShadow->hide(); + auto result = myGrab(this, _scroll->geometry()); + if (isTopShadowVisible) _topShadow->show(); + if (isBottomShadowVisible) _bottomShadow->show(); + return std_::move(result); +} + +void BoxContent::resizeEvent(QResizeEvent *e) { + if (_scroll) { + updateScrollAreaGeometry(); + } +} + +void BoxContent::updateScrollAreaGeometry() { + auto newScrollHeight = height() - _innerTopSkip; + auto changed = (_scroll->height() != newScrollHeight); + _scroll->setGeometryToLeft(0, _innerTopSkip, width(), newScrollHeight); + _topShadow->entity()->resize(width(), st::lineWidth); + _topShadow->moveToLeft(0, _innerTopSkip); + _bottomShadow->resize(width(), st::lineWidth); + _bottomShadow->moveToLeft(0, height() - st::lineWidth); + if (changed) { + onScroll(); + } +} + +object_ptr BoxContent::doTakeInnerWidget() { + return _scroll->takeWidget(); +} + +void BoxContent::paintEvent(QPaintEvent *e) { + Painter p(this); + + if (testAttribute(Qt::WA_OpaquePaintEvent)) { + for_const (auto rect, e->region().rects()) { + p.fillRect(rect, st::boxBg); + } + } +} + +AbstractBox::AbstractBox(object_ptr content) +: _content(std_::move(content)) { + _content->setParent(this); + _content->setDelegate(this); +} + +void AbstractBox::setLayerType(bool layerType) { + _layerType = layerType; +} + +int AbstractBox::titleHeight() const { + return _layerType ? st::boxLayerTitleHeight : st::boxTitleHeight; +} + +int AbstractBox::buttonsHeight() const { + auto padding = _layerType ? st::boxLayerButtonPadding : st::boxButtonPadding; + return padding.top() + st::defaultBoxButton.height + padding.bottom(); +} + +int AbstractBox::buttonsTop() const { + auto padding = _layerType ? st::boxLayerButtonPadding : st::boxButtonPadding; + return height() - padding.bottom() - st::defaultBoxButton.height; +} + +void AbstractBox::paintEvent(QPaintEvent *e) { + Painter p(this); + auto clip = e->rect(); + auto paintTopRounded = clip.intersects(QRect(0, 0, width(), st::boxRadius)); + auto paintBottomRounded = clip.intersects(QRect(0, height() - st::boxRadius, width(), st::boxRadius)); + if (paintTopRounded || paintBottomRounded) { + auto parts = qFlags(App::RectPart::None); + if (paintTopRounded) parts |= App::RectPart::TopFull; + if (paintBottomRounded) parts |= App::RectPart::BottomFull; + App::roundRect(p, rect(), st::boxBg, BoxCorners, nullptr, parts); + } + auto other = e->region().intersected(QRect(0, st::boxRadius, width(), height() - 2 * st::boxRadius)); + if (!other.isEmpty()) { + for_const (auto rect, other.rects()) { + p.fillRect(rect, st::boxBg); + } + } + if (!_title.isEmpty() && clip.intersects(QRect(0, 0, width(), titleHeight()))) { + paintTitle(p, _title, _additionalTitle); + } +} + +void AbstractBox::paintTitle(Painter &p, const QString &title, const QString &additional) { + p.setFont(st::boxTitleFont); + p.setPen(st::boxTitleFg); + if (_layerType) { + auto titleWidth = st::boxTitleFont->width(title); + p.drawTextLeft(st::boxLayerTitlePosition.x(), st::boxLayerTitlePosition.y(), width(), title, titleWidth); + if (!additional.isEmpty()) { + p.setFont(st::boxLayerTitleAdditionalFont); + p.setPen(st::boxTitleAdditionalFg); + p.drawTextLeft(st::boxLayerTitlePosition.x() + titleWidth + st::boxLayerTitleAdditionalSkip, st::boxLayerTitlePosition.y() + st::boxTitleFont->ascent - st::boxLayerTitleAdditionalFont->ascent, width(), additional); + } + } else { + p.drawTextLeft(st::boxTitlePosition.x(), st::boxTitlePosition.y(), width(), title); } } void AbstractBox::parentResized() { - auto newHeight = countHeight(); + auto newHeight = countRealHeight(); auto parentSize = parentWidget()->size(); setGeometry((parentSize.width() - width()) / 2, (parentSize.height() - newHeight) / 2, width(), newHeight); update(); } -int AbstractBox::titleHeight() const { - return _blockTitle ? st::boxBlockTitleHeight : st::boxTitleHeight; +void AbstractBox::setTitle(const QString &title, const QString &additional) { + auto wasTitle = hasTitle(); + _title = title; + _additionalTitle = additional; + update(); + if (wasTitle != hasTitle()) { + updateSize(); + } } -void AbstractBox::paintTitle(Painter &p, const QString &title, const QString &additional) { - if (_blockTitle) { - p.fillRect(0, 0, width(), titleHeight(), st::boxBlockTitleBg); +bool AbstractBox::hasTitle() const { + return !_title.isEmpty() || !_additionalTitle.isEmpty(); +} - p.setFont(st::boxBlockTitleFont); - p.setPen(st::boxBlockTitleFg); +void AbstractBox::updateSize() { + setDimensions(width(), _maxContentHeight); +} - auto titleWidth = st::boxBlockTitleFont->width(title); - p.drawTextLeft(st::boxBlockTitlePosition.x(), st::boxBlockTitlePosition.y(), width(), title, titleWidth); - - if (!additional.isEmpty()) { - p.setFont(st::boxBlockTitleAdditionalFont); - p.setPen(st::boxBlockTitleAdditionalFg); - p.drawTextLeft(st::boxBlockTitlePosition.x() + titleWidth + st::boxBlockTitleAdditionalSkip, st::boxBlockTitlePosition.y(), width(), additional); +void AbstractBox::updateButtonsPositions() { + if (!_buttons.isEmpty() || _leftButton) { + auto padding = _layerType ? st::boxLayerButtonPadding : st::boxButtonPadding; + auto right = padding.right(); + auto top = buttonsTop(); + if (_leftButton) { + _leftButton->moveToLeft(right, top); + } + for_const (auto &button, _buttons) { + button->moveToRight(right, top); + right += button->width() + padding.left(); } - } else { - p.setFont(st::boxTitleFont); - p.setPen(st::boxTitleFg); - p.drawTextLeft(st::boxTitlePosition.x(), st::boxTitlePosition.y(), width(), title); } } -void AbstractBox::paintEvent(QPaintEvent *e) { - Painter p(this); - p.fillRect(e->rect(), st::boxBg); - if (!_title.isEmpty()) { - paintTitle(p, _title, _additionalTitle); +void AbstractBox::clearButtons() { + for (auto &button : base::take(_buttons)) { + button.destroy(); } + _leftButton.destroy(); } -void AbstractBox::setMaxHeight(int32 maxHeight) { - resizeMaxHeight(width(), maxHeight); +QPointer AbstractBox::addButton(const QString &text, base::lambda &&clickCallback, const style::RoundButton &st) { + _buttons.push_back(object_ptr(this, text, st)); + auto result = QPointer(_buttons.back()); + result->setClickedCallback(std_::move(clickCallback)); + result->show(); + updateButtonsPositions(); + return result; } -void AbstractBox::resizeMaxHeight(int32 newWidth, int32 maxHeight) { - if (width() != newWidth || _maxHeight != maxHeight) { - QRect g(geometry()); - _maxHeight = maxHeight; - resize(newWidth, countHeight()); +QPointer AbstractBox::addLeftButton(const QString &text, base::lambda &&clickCallback, const style::RoundButton &st) { + _leftButton = object_ptr(this, text, st); + auto result = QPointer(_leftButton); + result->setClickedCallback(std_::move(clickCallback)); + result->show(); + updateButtonsPositions(); + return result; +} + +void AbstractBox::setDimensions(int newWidth, int maxHeight) { + _maxContentHeight = maxHeight; + + auto fullHeight = countFullHeight(); + if (width() != newWidth || _fullHeight != fullHeight) { + _fullHeight = fullHeight; if (parentWidget()) { - QRect r = geometry(); - int32 parenth = parentWidget()->height(); - if (r.top() + r.height() + st::boxVerticalMargin > parenth) { - int32 newTop = qMax(parenth - int(st::boxVerticalMargin) - r.height(), (parenth - r.height()) / 2); - if (newTop != r.top()) { - move(r.left(), newTop); + auto oldGeometry = geometry(); + resize(newWidth, countRealHeight()); + auto newGeometry = geometry(); + auto parentHeight = parentWidget()->height(); + if (newGeometry.top() + newGeometry.height() + st::boxVerticalMargin > parentHeight) { + auto newTop = qMax(parentHeight - int(st::boxVerticalMargin) - newGeometry.height(), (parentHeight - newGeometry.height()) / 2); + if (newTop != newGeometry.top()) { + move(newGeometry.left(), newTop); } } - parentWidget()->update(geometry().united(g).marginsAdded(QMargins(st::boxShadow.width(), st::boxShadow.height(), st::boxShadow.width(), st::boxShadow.height()))); + parentWidget()->update(oldGeometry.united(geometry()).marginsAdded(st::boxRoundShadow.extend)); + } else { + resize(newWidth, 0); } } } -int AbstractBox::countHeight() const { - return qMin(_maxHeight, parentWidget()->height() - 2 * st::boxVerticalMargin); +int AbstractBox::countRealHeight() const { + return qMin(_fullHeight, parentWidget()->height() - 2 * st::boxVerticalMargin); } -void AbstractBox::onClose() { - if (!_closed) { - _closed = true; - closePressed(); - } - emit closed(this); +int AbstractBox::countFullHeight() const { + return contentTop() + _maxContentHeight + buttonsHeight(); } -void AbstractBox::setBlockTitle(bool block, bool withClose, bool withShadow) { - _blockTitle = block; - if (withClose) { - _blockClose.create(this, st::boxBlockTitleClose); - _blockClose->setClickedCallback([this] { onClose(); }); - _blockClose->show(); +int AbstractBox::contentTop() const { + return hasTitle() ? titleHeight() : (_noContentMargin ? 0 : st::boxTopMargin); +} + +void AbstractBox::resizeEvent(QResizeEvent *e) { + updateButtonsPositions(); + + auto top = contentTop(); + _content->resize(width(), height() - top - buttonsHeight()); + _content->moveToLeft(0, top); + + LayerWidget::resizeEvent(e); +} + +void AbstractBox::keyPressEvent(QKeyEvent *e) { + if (e->key() == Qt::Key_Escape) { + closeBox(); } else { - _blockClose.destroy(); - } - if (withShadow) { - _blockShadow.create(this, st::boxBlockTitleShadow); - _blockShadow->show(); - } else { - _blockShadow.destroy(); - } - updateBlockTitleGeometry(); -} - -void AbstractBox::raiseShadow() { - if (_blockShadow) { - _blockShadow->raise(); + LayerWidget::keyPressEvent(e); } } - -ScrollableBoxShadow::ScrollableBoxShadow(QWidget *parent) : Ui::PlainShadow(parent, st::boxScrollShadowBg) { -} - -ScrollableBox::ScrollableBox(const style::FlatScroll &scroll, int32 w) : AbstractBox(w) -, _scroll(this, scroll) -, _topSkip(st::boxBlockTitleHeight) -, _bottomSkip(st::boxScrollSkip) { - setBlockTitle(true); -} - -void ScrollableBox::resizeEvent(QResizeEvent *e) { - updateScrollGeometry(); - AbstractBox::resizeEvent(e); -} - -void ScrollableBox::init(TWidget *inner, int bottomSkip, int topSkip) { - if (bottomSkip < 0) bottomSkip = st::boxScrollSkip; - if (topSkip < 0) topSkip = st::boxBlockTitleHeight; - _bottomSkip = bottomSkip; - _topSkip = topSkip; - _scroll->setOwnedWidget(inner); - updateScrollGeometry(); -} - -void ScrollableBox::setScrollSkips(int bottomSkip, int topSkip) { - if (bottomSkip < 0) bottomSkip = st::boxScrollSkip; - if (topSkip < 0) topSkip = st::boxBlockTitleHeight; - if (_topSkip != topSkip || _bottomSkip != bottomSkip) { - _topSkip = topSkip; - _bottomSkip = bottomSkip; - updateScrollGeometry(); - } -} - -void ScrollableBox::updateScrollGeometry() { - _scroll->setGeometry(0, _topSkip, width(), height() - _topSkip - _bottomSkip); -} - -ItemListBox::ItemListBox(const style::FlatScroll &scroll, int32 w) : ScrollableBox(scroll, w) { - setMaxHeight(st::boxMaxListHeight); -} diff --git a/Telegram/SourceFiles/boxes/abstractbox.h b/Telegram/SourceFiles/boxes/abstractbox.h index cdf5f8dea..4135de9eb 100644 --- a/Telegram/SourceFiles/boxes/abstractbox.h +++ b/Telegram/SourceFiles/boxes/abstractbox.h @@ -24,88 +24,229 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "ui/widgets/shadow.h" namespace Ui { +class RoundButton; class IconButton; -class GradientShadow; class ScrollArea; +template +class WidgetFadeWrap; } // namespace Ui -class AbstractBox : public LayerWidget, protected base::Subscriber { +class BoxLayerTitleShadow : public Ui::PlainShadow { +public: + BoxLayerTitleShadow(QWidget *parent); + +}; + +class BoxContentDelegate { +public: + virtual void setLayerType(bool layerType) = 0; + virtual void setTitle(const QString &title, const QString &additional) = 0; + + virtual void clearButtons() = 0; + virtual QPointer addButton(const QString &text, base::lambda &&clickCallback, const style::RoundButton &st) = 0; + virtual QPointer addLeftButton(const QString &text, base::lambda &&clickCallback, const style::RoundButton &st) = 0; + virtual void updateButtonsPositions() = 0; + + virtual void setDimensions(int newWidth, int maxHeight) = 0; + virtual void setNoContentMargin(bool noContentMargin) = 0; + virtual bool isBoxShown() const = 0; + virtual void closeBox() = 0; + +}; + +class BoxContent : public TWidget, protected base::Subscriber { Q_OBJECT public: - AbstractBox(int w = 0, const QString &title = QString()); - void parentResized() override; + BoxContent() { + setAttribute(Qt::WA_OpaquePaintEvent); + } - void setTitleText(const QString &title); - void setAdditionalTitle(const QString &additionalTitle); - void setBlockTitle(bool block, bool withClose = true, bool withShadow = true); + void setDelegate(BoxContentDelegate *newDelegate) { + _delegate = newDelegate; + prepare(); + } + virtual void setInnerFocus() { + setFocus(); + } + virtual void closeHook() { + } + + bool isBoxShown() const { + return getDelegate()->isBoxShown(); + } + void closeBox() { + getDelegate()->closeBox(); + } public slots: - void onClose(); + void onScrollToY(int top, int bottom = -1); + + void onDraggingScrollDelta(int delta); + +protected: + virtual void prepare() = 0; + + void setLayerType(bool layerType) { + getDelegate()->setLayerType(layerType); + } + void setTitle(const QString &title, const QString &additional = QString()) { + getDelegate()->setTitle(title, additional); + } + + void clearButtons() { + getDelegate()->clearButtons(); + } + QPointer addButton(const QString &text, base::lambda &&clickCallback); + QPointer addLeftButton(const QString &text, base::lambda &&clickCallback); + QPointer addButton(const QString &text, base::lambda &&clickCallback, const style::RoundButton &st) { + return getDelegate()->addButton(text, std_::move(clickCallback), st); + } + void updateButtonsGeometry() { + getDelegate()->updateButtonsPositions(); + } + + void setNoContentMargin(bool noContentMargin) { + if (_noContentMargin != noContentMargin) { + _noContentMargin = noContentMargin; + setAttribute(Qt::WA_OpaquePaintEvent, !_noContentMargin); + } + getDelegate()->setNoContentMargin(noContentMargin); + } + void setDimensions(int newWidth, int maxHeight) { + getDelegate()->setDimensions(newWidth, maxHeight); + } + void setInnerTopSkip(int topSkip, bool scrollBottomFixed = false); + + template + QPointer setInnerWidget(object_ptr inner, const style::ScrollArea &st, int topSkip = 0) { + auto result = QPointer(inner.data()); + setInner(std_::move(inner), st); + setInnerTopSkip(topSkip); + return result; + } + + template + QPointer setInnerWidget(object_ptr inner, int topSkip = 0) { + auto result = QPointer(inner.data()); + setInner(std_::move(inner)); + setInnerTopSkip(topSkip); + return result; + } + + template + object_ptr takeInnerWidget() { + return static_object_cast(doTakeInnerWidget()); + } + + void setInnerVisible(bool scrollAreaVisible); + QPixmap grabInnerCache(); + + void resizeEvent(QResizeEvent *e) override; + void paintEvent(QPaintEvent *e) override; + +private slots: + void onScroll(); + + void onDraggingScrollTimer(); + +private: + void setInner(object_ptr inner); + void setInner(object_ptr inner, const style::ScrollArea &st); + void updateScrollAreaGeometry(); + object_ptr doTakeInnerWidget(); + + BoxContentDelegate *getDelegate() const { + t_assert(_delegate != nullptr); + return _delegate; + } + BoxContentDelegate *_delegate = nullptr; + + bool _noContentMargin = false; + int _innerTopSkip = 0; + object_ptr _scroll = { nullptr }; + object_ptr> _topShadow = { nullptr }; + object_ptr _bottomShadow = { nullptr }; + + object_ptr _draggingScrollTimer = { nullptr }; + int _draggingScrollDelta = 0; + +}; + +class AbstractBox : public LayerWidget, public BoxContentDelegate, protected base::Subscriber { +public: + AbstractBox(object_ptr content); + + void parentResized() override; + + void setLayerType(bool layerType) override; + void setTitle(const QString &title, const QString &additional) override; + + void clearButtons() override; + QPointer addButton(const QString &text, base::lambda &&clickCallback, const style::RoundButton &st) override; + QPointer addLeftButton(const QString &text, base::lambda &&clickCallback, const style::RoundButton &st) override; + void updateButtonsPositions() override; + + void setDimensions(int newWidth, int maxHeight) override; + + void setNoContentMargin(bool noContentMargin) override { + if (_noContentMargin != noContentMargin) { + _noContentMargin = noContentMargin; + updateSize(); + } + } + + bool isBoxShown() const override { + return !isHidden(); + } + void closeBox() override { + closeLayer(); + } protected: void keyPressEvent(QKeyEvent *e) override; void resizeEvent(QResizeEvent *e) override; void paintEvent(QPaintEvent *e) override; - void raiseShadow(); - int titleHeight() const; - void paintTitle(Painter &p, const QString &title, const QString &additional = QString()); - void setMaxHeight(int32 maxHeight); - void resizeMaxHeight(int32 newWidth, int32 maxHeight); - - virtual void closePressed() { + void doSetInnerFocus() override { + _content->setInnerFocus(); + } + void closeHook() override { + _content->closeHook(); } private: - void updateBlockTitleGeometry(); - int countHeight() const; + void paintTitle(Painter &p, const QString &title, const QString &additional = QString()); - int _maxHeight = 0; + bool hasTitle() const; + int titleHeight() const; + int buttonsHeight() const; + int buttonsTop() const; + int contentTop() const; + int countFullHeight() const; + int countRealHeight() const; + void updateSize(); - bool _closed = false; + int _fullHeight = 0; + + bool _noContentMargin = false; + int _maxContentHeight = 0; + object_ptr _content; QString _title; QString _additionalTitle; - bool _blockTitle = false; - ChildWidget _blockClose = { nullptr }; - ChildWidget _blockShadow = { nullptr }; + bool _layerType = false; + + std_::vector_of_moveable> _buttons; + object_ptr _leftButton = { nullptr }; }; -class ScrollableBoxShadow : public Ui::PlainShadow { -public: - ScrollableBoxShadow(QWidget *parent); - -}; - -class ScrollableBox : public AbstractBox { -public: - ScrollableBox(const style::FlatScroll &scroll, int w = 0); - -protected: - void init(TWidget *inner, int bottomSkip = -1, int topSkip = -1); - void setScrollSkips(int bottomSkip = -1, int topSkip = -1); - - void resizeEvent(QResizeEvent *e) override; - - Ui::ScrollArea *scrollArea() { - return _scroll; - } - -private: - void updateScrollGeometry(); - - ChildWidget _scroll; - int _topSkip, _bottomSkip; - -}; - -class ItemListBox : public ScrollableBox { -public: - ItemListBox(const style::FlatScroll &scroll, int32 w = 0); - -}; +template +inline object_ptr Box(Args&&... args) { + auto parent = static_cast(nullptr); + return object_ptr(parent, std_::forward(args)...); +} enum CreatingGroupType { CreatingGroupNone, diff --git a/Telegram/SourceFiles/boxes/addcontactbox.cpp b/Telegram/SourceFiles/boxes/addcontactbox.cpp index 54000b93a..e746a7f7a 100644 --- a/Telegram/SourceFiles/boxes/addcontactbox.cpp +++ b/Telegram/SourceFiles/boxes/addcontactbox.cpp @@ -39,57 +39,52 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "apiwrap.h" #include "observer_peer.h" -AddContactBox::AddContactBox(QString fname, QString lname, QString phone) : AbstractBox(st::boxWidth) -, _first(this, st::defaultInputField, lang(lng_signup_firstname), fname) +AddContactBox::AddContactBox(QWidget*, QString fname, QString lname, QString phone) +: _first(this, st::defaultInputField, lang(lng_signup_firstname), fname) , _last(this, st::defaultInputField, lang(lng_signup_lastname), lname) , _phone(this, st::defaultInputField, lang(lng_contact_phone), phone) -, _save(this, lang(lng_add_contact), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) -, _retry(this, lang(lng_try_other_contact), st::defaultBoxButton) , _invertOrder(langFirstNameGoesSecond()) { if (!phone.isEmpty()) { _phone->setDisabled(true); } - - initBox(); } -AddContactBox::AddContactBox(UserData *user) : AbstractBox(st::boxWidth) -, _user(user) +AddContactBox::AddContactBox(QWidget*, UserData *user) +: _user(user) , _first(this, st::defaultInputField, lang(lng_signup_firstname), user->firstName) , _last(this, st::defaultInputField, lang(lng_signup_lastname), user->lastName) , _phone(this, st::defaultInputField, lang(lng_contact_phone), user->phone()) -, _save(this, lang(lng_settings_save), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) -, _retry(this, lang(lng_try_other_contact), st::defaultBoxButton) , _invertOrder(langFirstNameGoesSecond()) { _phone->setDisabled(true); - initBox(); } -void AddContactBox::initBox() { +void AddContactBox::prepare() { if (_invertOrder) { setTabOrder(_last, _first); } if (_user) { - setTitleText(lang(lng_edit_contact_title)); + setTitle(lang(lng_edit_contact_title)); } else { bool readyToAdd = !_phone->getLastText().isEmpty() && (!_first->getLastText().isEmpty() || !_last->getLastText().isEmpty()); - setTitleText(lang(readyToAdd ? lng_confirm_contact_data : lng_enter_contact_data)); + setTitle(lang(readyToAdd ? lng_confirm_contact_data : lng_enter_contact_data)); } - setMaxHeight(titleHeight() + st::contactPadding.top() + _first->height() + st::contactSkip + _last->height() + st::contactPhoneSkip + _phone->height() + st::contactPadding.bottom() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom()); - _retry->hide(); - - connect(_save, SIGNAL(clicked()), this, SLOT(onSave())); - connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); - connect(_retry, SIGNAL(clicked()), this, SLOT(onRetry())); + updateButtons(); connect(_first, SIGNAL(submitted(bool)), this, SLOT(onSubmit())); connect(_last, SIGNAL(submitted(bool)), this, SLOT(onSubmit())); connect(_phone, SIGNAL(submitted(bool)), this, SLOT(onSubmit())); + + if ((_first->getLastText().isEmpty() && _last->getLastText().isEmpty()) || !_phone->isEnabled()) { + (_invertOrder ? _last : _first)->setDisplayFocused(true); + _phone->finishAnimations(); + } else { + _phone->setDisplayFocused(true); + } + + setDimensions(st::boxWideWidth, st::contactPadding.top() + _first->height() + st::contactSkip + _last->height() + st::contactPhoneSkip + _phone->height() + st::contactPadding.bottom() + st::boxPadding.bottom()); } -void AddContactBox::doSetInnerFocus() { +void AddContactBox::setInnerFocus() { if ((_first->getLastText().isEmpty() && _last->getLastText().isEmpty()) || !_phone->isEnabled()) { (_invertOrder ? _last : _first)->setFocus(); } else { @@ -98,38 +93,35 @@ void AddContactBox::doSetInnerFocus() { } void AddContactBox::paintEvent(QPaintEvent *e) { - AbstractBox::paintEvent(e); + BoxContent::paintEvent(e); Painter p(this); - if (_retry->isHidden()) { - st::contactUserIcon.paint(p, st::boxPadding.left(), _first->y() + st::contactIconTop, width()); - st::contactPhoneIcon.paint(p, st::boxPadding.left(), _phone->y() + st::contactIconTop, width()); - } else { + if (_retrying) { p.setPen(st::boxTextFg); p.setFont(st::boxTextFont); - int32 h = height() - titleHeight() - st::contactPadding.top() - st::contactPadding.bottom() - st::boxPadding.bottom() - st::boxButtonPadding.top() - _retry->height() - st::boxButtonPadding.bottom(); - p.drawText(QRect(st::boxPadding.left(), titleHeight() + st::contactPadding.top(), width() - st::boxPadding.left() - st::boxPadding.right(), h), lng_contact_not_joined(lt_name, _sentName), style::al_topleft); + auto textHeight = height() - st::contactPadding.top() - st::contactPadding.bottom() - st::boxPadding.bottom(); + p.drawText(QRect(st::boxPadding.left(), st::contactPadding.top(), width() - st::boxPadding.left() - st::boxPadding.right(), textHeight), lng_contact_not_joined(lt_name, _sentName), style::al_topleft); + } else { + st::contactUserIcon.paint(p, st::boxPadding.left(), _first->y() + st::contactIconTop, width()); + st::contactPhoneIcon.paint(p, st::boxPadding.left(), _phone->y() + st::contactIconTop, width()); } } void AddContactBox::resizeEvent(QResizeEvent *e) { + BoxContent::resizeEvent(e); + _first->resize(width() - st::boxPadding.left() - st::contactPadding.left() - st::boxPadding.right(), _first->height()); _last->resize(_first->width(), _last->height()); _phone->resize(_first->width(), _last->height()); if (_invertOrder) { - _last->moveToLeft(st::boxPadding.left() + st::contactPadding.left(), titleHeight() + st::contactPadding.top()); + _last->moveToLeft(st::boxPadding.left() + st::contactPadding.left(), st::contactPadding.top()); _first->moveToLeft(st::boxPadding.left() + st::contactPadding.left(), _last->y() + _last->height() + st::contactSkip); _phone->moveToLeft(st::boxPadding.left() + st::contactPadding.left(), _first->y() + _first->height() + st::contactPhoneSkip); } else { - _first->moveToLeft(st::boxPadding.left() + st::contactPadding.left(), titleHeight() + st::contactPadding.top()); + _first->moveToLeft(st::boxPadding.left() + st::contactPadding.left(), st::contactPadding.top()); _last->moveToLeft(st::boxPadding.left() + st::contactPadding.left(), _first->y() + _first->height() + st::contactSkip); _phone->moveToLeft(st::boxPadding.left() + st::contactPadding.left(), _last->y() + _last->height() + st::contactPhoneSkip); } - - _save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height()); - _retry->moveToRight(st::boxButtonPadding.right(), _save->y()); - _cancel->moveToRight(st::boxButtonPadding.right() + (_retry->isHidden() ? _save->width() : _retry->width()) + st::boxButtonPadding.left(), _save->y()); - AbstractBox::resizeEvent(e); } void AddContactBox::onSubmit() { @@ -190,7 +182,7 @@ bool AddContactBox::onSaveUserFail(const RPCError &error) { QString firstName = _first->getLastText().trimmed(), lastName = _last->getLastText().trimmed(); if (err == "CHAT_TITLE_NOT_MODIFIED") { _user->setName(firstName, lastName, _user->nameOrPhone, _user->username); - onClose(); + closeBox(); return true; } else if (err == "NO_CHAT_TITLE") { _first->setFocus(); @@ -202,12 +194,12 @@ bool AddContactBox::onSaveUserFail(const RPCError &error) { } void AddContactBox::onImportDone(const MTPcontacts_ImportedContacts &res) { - if (isHidden() || !App::main()) return; + if (!isBoxShown() || !App::main()) return; - const auto &d(res.c_contacts_importedContacts()); + auto &d = res.c_contacts_importedContacts(); App::feedUsers(d.vusers); - const auto &v(d.vimported.c_vector().v); + auto &v = d.vimported.c_vector().v; UserData *user = nullptr; if (!v.isEmpty()) { const auto &c(v.front().c_importedContact()); @@ -220,8 +212,8 @@ void AddContactBox::onImportDone(const MTPcontacts_ImportedContacts &res) { Ui::hideLayer(); } else { hideChildren(); - _retry->show(); - resizeEvent(0); + _retrying = true; + updateButtons(); update(); } } @@ -229,15 +221,15 @@ void AddContactBox::onImportDone(const MTPcontacts_ImportedContacts &res) { void AddContactBox::onSaveUserDone(const MTPcontacts_ImportedContacts &res) { auto &d = res.c_contacts_importedContacts(); App::feedUsers(d.vusers); - onClose(); + closeBox(); } void AddContactBox::onRetry() { _addRequest = 0; _contactId = 0; showChildren(); - _retry->hide(); - resizeEvent(0); + _retrying = false; + updateButtons(); _first->setText(QString()); _last->setText(QString()); _phone->clearText(); @@ -246,31 +238,42 @@ void AddContactBox::onRetry() { update(); } -GroupInfoBox::GroupInfoBox(CreatingGroupType creating, bool fromTypeChoose) : AbstractBox() -, _creating(creating) -, _photo(this, st::newGroupPhotoSize, st::newGroupPhotoIconPosition) -, _title(this, st::defaultInputField, lang(_creating == CreatingGroupChannel ? lng_dlg_new_channel_name : lng_dlg_new_group_name)) -, _description(this, st::newGroupDescription, lang(lng_create_group_description)) -, _next(this, lang(_creating == CreatingGroupChannel ? lng_create_group_create : lng_create_group_next), st::defaultBoxButton) -, _cancel(this, lang(fromTypeChoose ? lng_create_group_back : lng_cancel), st::cancelBoxButton) { +void AddContactBox::updateButtons() { + clearButtons(); + if (_retrying) { + addButton(lang(lng_try_other_contact), [this] { onRetry(); }); + } else { + addButton(lang(_user ? lng_settings_save : lng_add_contact), [this] { onSave(); }); + addButton(lang(lng_cancel), [this] { closeBox(); }); + } +} +GroupInfoBox::GroupInfoBox(QWidget*, CreatingGroupType creating, bool fromTypeChoose) +: _creating(creating) +, _fromTypeChoose(fromTypeChoose) +, _photo(this, st::newGroupPhotoSize, st::newGroupPhotoIconPosition) +, _title(this, st::defaultInputField, lang(_creating == CreatingGroupChannel ? lng_dlg_new_channel_name : lng_dlg_new_group_name)) { +} + +void GroupInfoBox::prepare() { setMouseTracking(true); _title->setMaxLength(MaxGroupChannelTitle); - _description->setMaxLength(MaxChannelDescription); - _description->resize(width() - st::boxPadding.left() - st::newGroupInfoPadding.left() - st::boxPadding.right(), _description->height()); - _description->setVisible(_creating == CreatingGroupChannel); + if (_creating == CreatingGroupChannel) { + _description.create(this, st::newGroupDescription, lang(lng_create_group_description)); + _description->show(); + _description->setMaxLength(MaxChannelDescription); - updateMaxHeight(); - connect(_description, SIGNAL(resized()), this, SLOT(onDescriptionResized())); - connect(_description, SIGNAL(submitted(bool)), this, SLOT(onNext())); - connect(_description, SIGNAL(cancelled()), this, SLOT(onClose())); + connect(_description, SIGNAL(resized()), this, SLOT(onDescriptionResized())); + connect(_description, SIGNAL(submitted(bool)), this, SLOT(onNext())); + connect(_description, SIGNAL(cancelled()), this, SLOT(onClose())); + } connect(_title, SIGNAL(submitted(bool)), this, SLOT(onNameSubmit())); - connect(_next, SIGNAL(clicked()), this, SLOT(onNext())); - connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); + addButton(lang(_creating == CreatingGroupChannel ? lng_create_group_create : lng_create_group_next), [this] { onNext(); }); + addButton(lang(_fromTypeChoose ? lng_create_group_back : lng_cancel), [this] { closeBox(); }); _photo->setClickedCallback(App::LambdaDelayed(st::defaultActiveButton.ripple.hideDuration, this, [this] { auto imgExtensions = cImgExtensions(); @@ -280,48 +283,53 @@ GroupInfoBox::GroupInfoBox(CreatingGroupType creating, bool fromTypeChoose) : Ab subscribe(FileDialog::QueryDone(), [this](const FileDialog::QueryUpdate &update) { notifyFileQueryUpdated(update); }); + + _title->setDisplayFocused(true); + + updateMaxHeight(); } -void GroupInfoBox::doSetInnerFocus() { +void GroupInfoBox::setInnerFocus() { _title->setFocus(); } void GroupInfoBox::resizeEvent(QResizeEvent *e) { + BoxContent::resizeEvent(e); + _photo->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), st::boxPadding.top() + st::newGroupInfoPadding.top()); - int32 nameLeft = st::newGroupPhotoSize + st::newGroupNamePosition.x(); + auto nameLeft = st::newGroupPhotoSize + st::newGroupNamePosition.x(); _title->resize(width() - st::boxPadding.left() - st::newGroupInfoPadding.left() - st::boxPadding.right() - nameLeft, _title->height()); _title->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left() + nameLeft, st::boxPadding.top() + st::newGroupInfoPadding.top() + st::newGroupNamePosition.y()); - - _description->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), st::boxPadding.top() + st::newGroupInfoPadding.top() + st::newGroupPhotoSize + st::newGroupDescriptionPadding.top()); - - _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); + if (_description) { + _description->resize(width() - st::boxPadding.left() - st::newGroupInfoPadding.left() - st::boxPadding.right(), _description->height()); + _description->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), st::boxPadding.top() + st::newGroupInfoPadding.top() + st::newGroupPhotoSize + st::newGroupDescriptionPadding.top()); + } } void GroupInfoBox::onNameSubmit() { if (_title->getLastText().trimmed().isEmpty()) { _title->setFocus(); _title->showError(); - } else if (_description->isHidden()) { - onNext(); - } else { + } else if (_description) { _description->setFocus(); + } else { + onNext(); } } void GroupInfoBox::onNext() { if (_creationRequestId) return; - QString title = prepareText(_title->getLastText()), description = prepareText(_description->getLastText(), true); + auto title = prepareText(_title->getLastText()); + auto description = _description ? prepareText(_description->getLastText(), true) : QString(); if (title.isEmpty()) { _title->setFocus(); _title->showError(); return; } if (_creating == CreatingGroupGroup) { - Ui::showLayer(new ContactsBox(title, _photoImage), KeepOtherLayers); + Ui::show(Box(title, _photoImage), KeepOtherLayers); } else { bool mega = false; MTPchannels_CreateChannel::Flags flags = mega ? MTPchannels_CreateChannel::Flag::f_megagroup : MTPchannels_CreateChannel::Flag::f_broadcast; @@ -354,7 +362,7 @@ void GroupInfoBox::creationDone(const MTPUpdates &updates) { LOG(("API Error: channel not found in updates (GroupInfoBox::creationDone)")); } - onClose(); + closeBox(); } bool GroupInfoBox::creationFail(const RPCError &error) { @@ -366,7 +374,7 @@ bool GroupInfoBox::creationFail(const RPCError &error) { _title->showError(); return true; } else if (error.type() == qstr("USER_RESTRICTED")) { - Ui::showLayer(new InformBox(lang(lng_cant_do_this))); + Ui::show(Box(lang(lng_cant_do_this))); return true; } return false; @@ -377,7 +385,7 @@ void GroupInfoBox::exportDone(const MTPExportedChatInvite &result) { if (result.type() == mtpc_chatInviteExported) { _createdChannel->setInviteLink(qs(result.c_chatInviteExported().vlink)); } - Ui::showLayer(new SetupChannelBox(_createdChannel)); + Ui::show(Box(_createdChannel)); } void GroupInfoBox::onDescriptionResized() { @@ -386,11 +394,11 @@ void GroupInfoBox::onDescriptionResized() { } void GroupInfoBox::updateMaxHeight() { - int32 h = st::boxPadding.top() + st::newGroupInfoPadding.top() + st::newGroupPhotoSize + st::boxPadding.bottom() + st::newGroupInfoPadding.bottom() + st::boxButtonPadding.top() + _next->height() + st::boxButtonPadding.bottom(); - if (_creating == CreatingGroupChannel) { - h += st::newGroupDescriptionPadding.top() + _description->height() + st::newGroupDescriptionPadding.bottom(); + auto newHeight = st::boxPadding.top() + st::newGroupInfoPadding.top() + st::newGroupPhotoSize + st::boxPadding.bottom() + st::newGroupInfoPadding.bottom(); + if (_description) { + newHeight += st::newGroupDescriptionPadding.top() + _description->height() + st::newGroupDescriptionPadding.bottom(); } - setMaxHeight(h); + setDimensions(st::boxWideWidth, newHeight); } void GroupInfoBox::notifyFileQueryUpdated(const FileDialog::QueryUpdate &update) { @@ -411,9 +419,8 @@ void GroupInfoBox::notifyFileQueryUpdated(const FileDialog::QueryUpdate &update) if (img.isNull() || img.width() > 10 * img.height() || img.height() > 10 * img.width()) { return; } - auto box = new PhotoCropBox(img, (_creating == CreatingGroupChannel) ? peerFromChannel(0) : peerFromChat(0)); + auto box = Ui::show(Box(img, (_creating == CreatingGroupChannel) ? peerFromChannel(0) : peerFromChat(0)), KeepOtherLayers); connect(box, SIGNAL(ready(const QImage&)), this, SLOT(onPhotoReady(const QImage&))); - Ui::showLayer(box, KeepOtherLayers); } void GroupInfoBox::onPhotoReady(const QImage &img) { @@ -421,27 +428,26 @@ void GroupInfoBox::onPhotoReady(const QImage &img) { _photo->setImage(_photoImage); } -SetupChannelBox::SetupChannelBox(ChannelData *channel, bool existing) : AbstractBox() -, _channel(channel) +SetupChannelBox::SetupChannelBox(QWidget*, ChannelData *channel, bool existing) +: _channel(channel) , _existing(existing) , _public(this, qsl("channel_privacy"), 0, lang(channel->isMegagroup() ? lng_create_public_group_title : lng_create_public_channel_title), true, st::defaultBoxCheckbox) , _private(this, qsl("channel_privacy"), 1, lang(channel->isMegagroup() ? lng_create_private_group_title : lng_create_private_channel_title), false, st::defaultBoxCheckbox) , _aboutPublicWidth(width() - st::boxPadding.left() - st::boxButtonPadding.right() - st::newGroupPadding.left() - st::defaultBoxCheckbox.textPosition.x()) , _aboutPublic(st::normalFont, lang(channel->isMegagroup() ? lng_create_public_group_about : lng_create_public_channel_about), _defaultOptions, _aboutPublicWidth) , _aboutPrivate(st::normalFont, lang(channel->isMegagroup() ? lng_create_private_group_about : lng_create_private_channel_about), _defaultOptions, _aboutPublicWidth) -, _link(this, st::setupChannelLink, QString(), channel->username, true) -, _linkOver(false) -, _save(this, lang(lng_settings_save), st::defaultBoxButton) -, _skip(this, lang(existing ? lng_cancel : lng_create_group_skip), st::cancelBoxButton) { +, _link(this, st::setupChannelLink, QString(), channel->username, true) { +} + +void SetupChannelBox::prepare() { + _aboutPublicHeight = _aboutPublic.countHeight(_aboutPublicWidth); + setMouseTracking(true); _checkRequestId = MTP::send(MTPchannels_CheckUsername(_channel->inputChannel, MTP_string("preston")), RPCDoneHandlerPtr(), rpcFail(&SetupChannelBox::onFirstCheckFail)); - _aboutPublicHeight = _aboutPublic.countHeight(_aboutPublicWidth); - updateMaxHeight(); - - connect(_save, SIGNAL(clicked()), this, SLOT(onSave())); - connect(_skip, SIGNAL(clicked()), this, SLOT(onClose())); + addButton(lang(lng_settings_save), [this] { onSave(); }); + addButton(lang(_existing ? lng_cancel : lng_create_group_skip), [this] { closeBox(); }); connect(_link, SIGNAL(changed()), this, SLOT(onChange())); _link->setVisible(_public->checked()); @@ -451,9 +457,11 @@ SetupChannelBox::SetupChannelBox(ChannelData *channel, bool existing) : Abstract connect(_public, SIGNAL(changed()), this, SLOT(onPrivacyChange())); connect(_private, SIGNAL(changed()), this, SLOT(onPrivacyChange())); + + updateMaxHeight(); } -void SetupChannelBox::doSetInnerFocus() { +void SetupChannelBox::setInnerFocus() { if (_link->isHidden()) { setFocus(); } else { @@ -462,11 +470,11 @@ void SetupChannelBox::doSetInnerFocus() { } void SetupChannelBox::updateMaxHeight() { + auto newHeight = st::boxPadding.top() + st::newGroupPadding.top() + _public->heightNoMargins() + _aboutPublicHeight + st::newGroupSkip + _private->heightNoMargins() + _aboutPrivate.countHeight(_aboutPublicWidth) + st::newGroupSkip + st::newGroupPadding.bottom(); if (!_channel->isMegagroup() || _public->checked()) { - setMaxHeight(st::boxPadding.top() + st::newGroupPadding.top() + _public->heightNoMargins() + _aboutPublicHeight + st::newGroupSkip + _private->heightNoMargins() + _aboutPrivate.countHeight(_aboutPublicWidth) + st::newGroupSkip + st::newGroupPadding.bottom() + st::newGroupLinkPadding.top() + _link->height() + st::newGroupLinkPadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom()); - } else { - setMaxHeight(st::boxPadding.top() + st::newGroupPadding.top() + _public->heightNoMargins() + _aboutPublicHeight + st::newGroupSkip + _private->heightNoMargins() + _aboutPrivate.countHeight(_aboutPublicWidth) + st::newGroupSkip + st::newGroupPadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom()); + newHeight += st::newGroupLinkPadding.top() + _link->height() + st::newGroupLinkPadding.bottom(); } + setDimensions(st::boxWideWidth, newHeight); } void SetupChannelBox::keyPressEvent(QKeyEvent *e) { @@ -480,7 +488,7 @@ void SetupChannelBox::keyPressEvent(QKeyEvent *e) { } } } else { - AbstractBox::keyPressEvent(e); + BoxContent::keyPressEvent(e); } } @@ -534,16 +542,14 @@ void SetupChannelBox::paintEvent(QPaintEvent *e) { } void SetupChannelBox::resizeEvent(QResizeEvent *e) { + BoxContent::resizeEvent(e); + _public->moveToLeft(st::boxPadding.left() + st::newGroupPadding.left(), st::boxPadding.top() + st::newGroupPadding.top()); _private->moveToLeft(st::boxPadding.left() + st::newGroupPadding.left(), _public->bottomNoMargins() + _aboutPublicHeight + st::newGroupSkip); _link->resize(width() - st::boxPadding.left() - st::newGroupLinkPadding.left() - st::boxPadding.right(), _link->height()); _link->moveToLeft(st::boxPadding.left() + st::newGroupLinkPadding.left(), _private->bottomNoMargins() + _aboutPrivate.countHeight(_aboutPublicWidth) + st::newGroupSkip + st::newGroupPadding.bottom() + st::newGroupLinkPadding.top()); _invitationLink = QRect(_link->x(), _link->y() + (_link->height() / 2) - st::boxTextFont->height, _link->width(), 2 * st::boxTextFont->height); - - _save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height()); - _skip->moveToRight(st::boxButtonPadding.right() + _save->width() + st::boxButtonPadding.left(), _save->y()); - AbstractBox::resizeEvent(e); } void SetupChannelBox::mouseMoveEvent(QMouseEvent *e) { @@ -574,9 +580,9 @@ void SetupChannelBox::updateSelected(const QPoint &cursorGlobalPosition) { } } -void SetupChannelBox::closePressed() { +void SetupChannelBox::closeHook() { if (!_existing) { - Ui::showLayer(new ContactsBox(_channel)); + Ui::show(Box(_channel)); } } @@ -586,7 +592,7 @@ void SetupChannelBox::onSave() { _sentUsername = QString(); _saveRequestId = MTP::send(MTPchannels_UpdateUsername(_channel->inputChannel, MTP_string(_sentUsername)), rpcDone(&SetupChannelBox::onUpdateDone), rpcFail(&SetupChannelBox::onUpdateFail)); } else { - onClose(); + closeBox(); } } @@ -655,7 +661,7 @@ void SetupChannelBox::onPrivacyChange() { if (_public->checked()) { if (_tooMuchUsernames) { _private->setChecked(true); - Ui::showLayer(new RevokePublicLinkBox(base::lambda_guarded(this, [this] { + Ui::show(Box(base::lambda_guarded(this, [this] { _tooMuchUsernames = false; _public->setChecked(true); onCheck(); @@ -676,7 +682,7 @@ void SetupChannelBox::onPrivacyChange() { void SetupChannelBox::onUpdateDone(const MTPBool &result) { _channel->setName(textOneLine(_channel->name), _sentUsername); - onClose(); + closeBox(); } bool SetupChannelBox::onUpdateFail(const RPCError &error) { @@ -686,7 +692,7 @@ bool SetupChannelBox::onUpdateFail(const RPCError &error) { QString err(error.type()); if (err == "USERNAME_NOT_MODIFIED" || _sentUsername == _channel->username) { _channel->setName(textOneLine(_channel->name), textOneLine(_sentUsername)); - onClose(); + closeBox(); return true; } else if (err == "USERNAME_INVALID") { _link->setFocus(); @@ -748,9 +754,9 @@ bool SetupChannelBox::onCheckFail(const RPCError &error) { } void SetupChannelBox::showRevokePublicLinkBoxForEdit() { - onClose(); - Ui::showLayer(new RevokePublicLinkBox([channel = _channel, existing = _existing]() { - Ui::showLayer(new SetupChannelBox(channel, existing), KeepOtherLayers); + closeBox(); + Ui::show(Box([channel = _channel, existing = _existing]() { + Ui::show(Box(channel, existing), KeepOtherLayers); }), KeepOtherLayers); } @@ -777,38 +783,40 @@ bool SetupChannelBox::onFirstCheckFail(const RPCError &error) { return true; } -EditNameTitleBox::EditNameTitleBox(PeerData *peer) : -_peer(peer), -_first(this, st::defaultInputField, lang(peer->isUser() ? lng_signup_firstname : lng_dlg_new_group_name), peer->isUser() ? peer->asUser()->firstName : peer->name), -_last(this, st::defaultInputField, lang(lng_signup_lastname), peer->isUser() ? peer->asUser()->lastName : QString()), -_save(this, lang(lng_settings_save), st::defaultBoxButton), -_cancel(this, lang(lng_cancel), st::cancelBoxButton), -_invertOrder(!peer->isChat() && langFirstNameGoesSecond()) { +EditNameTitleBox::EditNameTitleBox(QWidget*, PeerData *peer) +: _peer(peer) +, _first(this, st::defaultInputField, lang(peer->isUser() ? lng_signup_firstname : lng_dlg_new_group_name), peer->isUser() ? peer->asUser()->firstName : peer->name) +, _last(this, st::defaultInputField, lang(lng_signup_lastname), peer->isUser() ? peer->asUser()->lastName : QString()) +, _invertOrder(!peer->isChat() && langFirstNameGoesSecond()) { +} + +void EditNameTitleBox::prepare() { + auto newHeight = st::contactPadding.top() + _first->height(); + if (_peer->isUser()) { + setTitle(lang(_peer == App::self() ? lng_edit_self_title : lng_edit_contact_title)); + newHeight += st::contactSkip + _last->height(); + } else if (_peer->isChat()) { + setTitle(lang(lng_edit_group_title)); + } + newHeight += st::boxPadding.bottom() + st::contactPadding.bottom(); + setDimensions(st::boxWideWidth, newHeight); + + addButton(lang(lng_settings_save), [this] { onSave(); }); + addButton(lang(lng_cancel), [this] { closeBox(); }); if (_invertOrder) { setTabOrder(_last, _first); } _first->setMaxLength(MaxGroupChannelTitle); _last->setMaxLength(MaxGroupChannelTitle); - int32 h = titleHeight() + st::contactPadding.top() + _first->height(); - if (_peer->isUser()) { - setTitleText(lang(_peer == App::self() ? lng_edit_self_title : lng_edit_contact_title)); - h += st::contactSkip + _last->height(); - } else if (_peer->isChat()) { - setTitleText(lang(lng_edit_group_title)); - } - h += st::boxPadding.bottom() + st::contactPadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom(); - setMaxHeight(h); - - connect(_save, SIGNAL(clicked()), this, SLOT(onSave())); - connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); - connect(_first, SIGNAL(submitted(bool)), this, SLOT(onSubmit())); connect(_last, SIGNAL(submitted(bool)), this, SLOT(onSubmit())); _last->setVisible(!_peer->isChat()); + + (_invertOrder ? _last : _first)->setDisplayFocused(true); } -void EditNameTitleBox::doSetInnerFocus() { +void EditNameTitleBox::setInnerFocus() { (_invertOrder ? _last : _first)->setFocus(); } @@ -838,19 +846,17 @@ void EditNameTitleBox::onSubmit() { } void EditNameTitleBox::resizeEvent(QResizeEvent *e) { + BoxContent::resizeEvent(e); + _first->resize(width() - st::boxPadding.left() - st::newGroupInfoPadding.left() - st::boxPadding.right(), _first->height()); _last->resize(_first->size()); if (_invertOrder) { - _last->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), titleHeight() + st::contactPadding.top()); + _last->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), st::contactPadding.top()); _first->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _last->y() + _last->height() + st::contactSkip); } else { - _first->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), titleHeight() + st::contactPadding.top()); + _first->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), st::contactPadding.top()); _last->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _first->y() + _first->height() + st::contactSkip); } - - _save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height()); - _cancel->moveToRight(st::boxButtonPadding.right() + _save->width() + st::boxButtonPadding.left(), _save->y()); - AbstractBox::resizeEvent(e); } void EditNameTitleBox::onSave() { @@ -882,7 +888,7 @@ void EditNameTitleBox::onSave() { void EditNameTitleBox::onSaveSelfDone(const MTPUser &user) { App::feedUsers(MTP_vector(1, user)); - onClose(); + closeBox(); } bool EditNameTitleBox::onSaveSelfFail(const RPCError &error) { @@ -892,7 +898,7 @@ bool EditNameTitleBox::onSaveSelfFail(const RPCError &error) { QString first = textOneLine(_first->getLastText().trimmed()), last = textOneLine(_last->getLastText().trimmed()); if (err == "NAME_NOT_MODIFIED") { App::self()->setName(first, last, QString(), textOneLine(App::self()->username)); - onClose(); + closeBox(); return true; } else if (err == "FIRSTNAME_INVALID") { _first->setFocus(); @@ -916,7 +922,7 @@ bool EditNameTitleBox::onSaveChatFail(const RPCError &error) { if (auto chatData = _peer->asChat()) { chatData->setName(_sentName); } - onClose(); + closeBox(); return true; } else if (err == qstr("NO_CHAT_TITLE")) { _first->setFocus(); @@ -929,42 +935,44 @@ bool EditNameTitleBox::onSaveChatFail(const RPCError &error) { void EditNameTitleBox::onSaveChatDone(const MTPUpdates &updates) { App::main()->sentUpdatesReceived(updates); - onClose(); + closeBox(); } -EditChannelBox::EditChannelBox(ChannelData *channel) : AbstractBox() -, _channel(channel) +EditChannelBox::EditChannelBox(QWidget*, ChannelData *channel) +: _channel(channel) , _title(this, st::defaultInputField, lang(lng_dlg_new_channel_name), _channel->name) , _description(this, st::newGroupDescription, lang(lng_create_group_description), _channel->about()) , _sign(this, lang(lng_edit_sign_messages), channel->addsSignature(), st::defaultBoxCheckbox) -, _publicLink(this, lang(channel->isPublic() ? lng_profile_edit_public_link : lng_profile_create_public_link), st::boxLinkButton) -, _save(this, lang(lng_settings_save), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) { - connect(App::main(), SIGNAL(peerNameChanged(PeerData*,const PeerData::Names&,const PeerData::NameFirstChars&)), this, SLOT(peerUpdated(PeerData*))); +, _publicLink(this, lang(channel->isPublic() ? lng_profile_edit_public_link : lng_profile_create_public_link), st::boxLinkButton) { +} - setTitleText(lang(_channel->isMegagroup() ? lng_edit_group : lng_edit_channel_title)); +void EditChannelBox::prepare() { + setTitle(lang(_channel->isMegagroup() ? lng_edit_group : lng_edit_channel_title)); + + addButton(lang(lng_settings_save), [this] { onSave(); }); + addButton(lang(lng_cancel), [this] { closeBox(); }); + + connect(App::main(), SIGNAL(peerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)), this, SLOT(peerUpdated(PeerData*))); setMouseTracking(true); _title->setMaxLength(MaxGroupChannelTitle); _description->setMaxLength(MaxChannelDescription); - _description->resize(width() - st::boxPadding.left() - st::newGroupInfoPadding.left() - st::boxPadding.right(), _description->height()); - myEnsureResized(_description); - updateMaxHeight(); connect(_description, SIGNAL(resized()), this, SLOT(onDescriptionResized())); connect(_description, SIGNAL(submitted(bool)), this, SLOT(onSave())); connect(_description, SIGNAL(cancelled()), this, SLOT(onClose())); - connect(_save, SIGNAL(clicked()), this, SLOT(onSave())); - connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); - connect(_publicLink, SIGNAL(clicked()), this, SLOT(onPublicLink())); _publicLink->setVisible(_channel->canEditUsername()); _sign->setVisible(!_channel->isMegagroup()); + + _title->setDisplayFocused(true); + + updateMaxHeight(); } -void EditChannelBox::doSetInnerFocus() { +void EditChannelBox::setInnerFocus() { _title->setFocus(); } @@ -974,7 +982,7 @@ void EditChannelBox::keyPressEvent(QKeyEvent *e) { onSave(); } } else { - AbstractBox::keyPressEvent(e); + BoxContent::keyPressEvent(e); } } @@ -991,22 +999,25 @@ void EditChannelBox::onDescriptionResized() { } void EditChannelBox::updateMaxHeight() { - int32 h = titleHeight() + st::newGroupInfoPadding.top() + _title->height(); - h += st::newGroupDescriptionPadding.top() + _description->height() + st::newGroupDescriptionPadding.bottom(); + auto newHeight = st::newGroupInfoPadding.top() + _title->height(); + newHeight += st::newGroupDescriptionPadding.top() + _description->height() + st::newGroupDescriptionPadding.bottom(); if (!_channel->isMegagroup()) { - h += st::newGroupPublicLinkPadding.top() + _sign->heightNoMargins() + st::newGroupPublicLinkPadding.bottom(); + newHeight += st::newGroupPublicLinkPadding.top() + _sign->heightNoMargins() + st::newGroupPublicLinkPadding.bottom(); } if (_channel->canEditUsername()) { - h += st::newGroupPublicLinkPadding.top() + _publicLink->height() + st::newGroupPublicLinkPadding.bottom(); + newHeight += st::newGroupPublicLinkPadding.top() + _publicLink->height() + st::newGroupPublicLinkPadding.bottom(); } - h += st::boxPadding.bottom() + st::newGroupInfoPadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom(); - setMaxHeight(h); + newHeight += st::boxPadding.bottom() + st::newGroupInfoPadding.bottom(); + setDimensions(st::boxWideWidth, newHeight); } void EditChannelBox::resizeEvent(QResizeEvent *e) { - _title->resize(width() - st::boxPadding.left() - st::newGroupInfoPadding.left() - st::boxPadding.right(), _title->height()); - _title->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), titleHeight() + st::newGroupInfoPadding.top() + st::newGroupNamePosition.y()); + BoxContent::resizeEvent(e); + _title->resize(width() - st::boxPadding.left() - st::newGroupInfoPadding.left() - st::boxPadding.right(), _title->height()); + _title->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), st::newGroupInfoPadding.top() + st::newGroupNamePosition.y()); + + _description->resize(width() - st::boxPadding.left() - st::newGroupInfoPadding.left() - st::boxPadding.right(), _description->height()); _description->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _title->y() + _title->height() + st::newGroupDescriptionPadding.top()); _sign->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _description->y() + _description->height() + st::newGroupDescriptionPadding.bottom() + st::newGroupPublicLinkPadding.top()); @@ -1016,10 +1027,6 @@ void EditChannelBox::resizeEvent(QResizeEvent *e) { } else { _publicLink->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _sign->bottomNoMargins() + st::newGroupDescriptionPadding.bottom() + st::newGroupPublicLinkPadding.top()); } - - _save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height()); - _cancel->moveToRight(st::boxButtonPadding.right() + _save->width() + st::boxButtonPadding.left(), _save->y()); - AbstractBox::resizeEvent(e); } void EditChannelBox::onSave() { @@ -1041,7 +1048,7 @@ void EditChannelBox::onSave() { } void EditChannelBox::onPublicLink() { - Ui::showLayer(new SetupChannelBox(_channel, true), KeepOtherLayers); + Ui::show(Box(_channel, true), KeepOtherLayers); } void EditChannelBox::saveDescription() { @@ -1054,7 +1061,7 @@ void EditChannelBox::saveDescription() { void EditChannelBox::saveSign() { if (_channel->isMegagroup() || _channel->addsSignature() == _sign->checked()) { - onClose(); + closeBox(); } else { _saveSignRequestId = MTP::send(MTPchannels_ToggleSignatures(_channel->inputChannel, MTP_bool(_sign->checked())), rpcDone(&EditChannelBox::onSaveSignDone), rpcFail(&EditChannelBox::onSaveFail)); } @@ -1093,7 +1100,7 @@ bool EditChannelBox::onSaveFail(const RPCError &error, mtpRequestId req) { } else if (req == _saveSignRequestId) { _saveSignRequestId = 0; if (err == qstr("CHAT_NOT_MODIFIED")) { - onClose(); + closeBox(); return true; } } @@ -1123,28 +1130,31 @@ void EditChannelBox::onSaveSignDone(const MTPUpdates &updates) { if (App::main()) { App::main()->sentUpdatesReceived(updates); } - onClose(); + closeBox(); } -RevokePublicLinkBox::RevokePublicLinkBox(base::lambda &&revokeCallback) : AbstractBox() -, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom()) +RevokePublicLinkBox::RevokePublicLinkBox(QWidget*, base::lambda &&revokeCallback) +: _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom()) , _revokeWidth(st::normalFont->width(lang(lng_channels_too_much_public_revoke))) , _aboutRevoke(this, lang(lng_channels_too_much_public_about), Ui::FlatLabel::InitType::Simple, st::aboutRevokePublicLabel) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) , _revokeCallback(std_::move(revokeCallback)) { +} + +void RevokePublicLinkBox::prepare() { setMouseTracking(true); MTP::send(MTPchannels_GetAdminedPublicChannels(), rpcDone(&RevokePublicLinkBox::getPublicDone), rpcFail(&RevokePublicLinkBox::getPublicFail)); - updateMaxHeight(); + addButton(lang(lng_cancel), [this] { closeBox(); }); - connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); subscribe(FileDownload::ImageLoaded(), [this] { update(); }); + + updateMaxHeight(); } void RevokePublicLinkBox::updateMaxHeight() { _rowsTop = st::boxPadding.top() + _aboutRevoke->height() + st::boxPadding.top(); - setMaxHeight(_rowsTop + (5 * _rowHeight) + st::boxButtonPadding.top() + _cancel->height() + st::boxButtonPadding.bottom()); + setDimensions(st::boxWideWidth, _rowsTop + (5 * _rowHeight)); } void RevokePublicLinkBox::mouseMoveEvent(QMouseEvent *e) { @@ -1183,23 +1193,16 @@ void RevokePublicLinkBox::mouseReleaseEvent(QMouseEvent *e) { if (pressed && pressed == _selected) { auto text_method = pressed->isMegagroup() ? lng_channels_too_much_public_revoke_confirm_group : lng_channels_too_much_public_revoke_confirm_channel; auto text = text_method(lt_link, qsl("telegram.me/") + pressed->userName(), lt_group, pressed->name); - weakRevokeConfirmBox = new ConfirmBox(text, lang(lng_channels_too_much_public_revoke)); - struct Data { - Data(QPointer &&weakThis, PeerData *pressed) : weakThis(std_::move(weakThis)), pressed(pressed) { - } - QPointer weakThis; - PeerData *pressed; - }; - weakRevokeConfirmBox->setConfirmedCallback(base::lambda_guarded(this, [this, pressed]() { + auto confirmText = lang(lng_channels_too_much_public_revoke); + _weakRevokeConfirmBox = Ui::show(Box(text, confirmText, base::lambda_guarded(this, [this, pressed]() { if (_revokeRequestId) return; _revokeRequestId = MTP::send(MTPchannels_UpdateUsername(pressed->asChannel()->inputChannel, MTP_string("")), rpcDone(&RevokePublicLinkBox::revokeLinkDone), rpcFail(&RevokePublicLinkBox::revokeLinkFail)); - })); - Ui::showLayer(weakRevokeConfirmBox, KeepOtherLayers); + })), KeepOtherLayers); } } void RevokePublicLinkBox::paintEvent(QPaintEvent *e) { - AbstractBox::paintEvent(e); + BoxContent::paintEvent(e); Painter p(this); p.translate(0, _rowsTop); @@ -1210,9 +1213,9 @@ void RevokePublicLinkBox::paintEvent(QPaintEvent *e) { } void RevokePublicLinkBox::resizeEvent(QResizeEvent *e) { + BoxContent::resizeEvent(e); + _aboutRevoke->moveToLeft(st::boxPadding.left(), st::boxPadding.top()); - _cancel->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _cancel->height()); - AbstractBox::resizeEvent(e); } void RevokePublicLinkBox::paintChat(Painter &p, const ChatRow &row, bool selected, bool pressed) const { @@ -1268,10 +1271,10 @@ bool RevokePublicLinkBox::getPublicFail(const RPCError &error) { } void RevokePublicLinkBox::revokeLinkDone(const MTPBool &result) { - if (weakRevokeConfirmBox) { - weakRevokeConfirmBox->onClose(); + if (_weakRevokeConfirmBox) { + _weakRevokeConfirmBox->closeBox(); } - onClose(); + closeBox(); if (_revokeCallback) { _revokeCallback(); } diff --git a/Telegram/SourceFiles/boxes/addcontactbox.h b/Telegram/SourceFiles/boxes/addcontactbox.h index 8cea13eeb..e3f64eb2d 100644 --- a/Telegram/SourceFiles/boxes/addcontactbox.h +++ b/Telegram/SourceFiles/boxes/addcontactbox.h @@ -34,114 +34,110 @@ class UsernameInput; class Checkbox; class Radiobutton; class LinkButton; -class RoundButton; class NewAvatarButton; } // namespace Ui -class AddContactBox : public AbstractBox, public RPCSender { +class AddContactBox : public BoxContent, public RPCSender { Q_OBJECT public: - AddContactBox(QString fname = QString(), QString lname = QString(), QString phone = QString()); - AddContactBox(UserData *user); + AddContactBox(QWidget*, QString fname = QString(), QString lname = QString(), QString phone = QString()); + AddContactBox(QWidget*, UserData *user); -public slots: +protected: + void prepare() override; + + void paintEvent(QPaintEvent *e) override; + void resizeEvent(QResizeEvent *e) override; + + void setInnerFocus() override; + +private slots: void onSubmit(); void onSave(); void onRetry(); -protected: - void paintEvent(QPaintEvent *e) override; - void resizeEvent(QResizeEvent *e) override; - - void doSetInnerFocus() override; - private: + void updateButtons(); void onImportDone(const MTPcontacts_ImportedContacts &res); void onSaveUserDone(const MTPcontacts_ImportedContacts &res); bool onSaveUserFail(const RPCError &e); - void initBox(); - UserData *_user = nullptr; - ChildWidget _first; - ChildWidget _last; - ChildWidget _phone; + object_ptr _first; + object_ptr _last; + object_ptr _phone; - ChildWidget _save; - ChildWidget _cancel; - ChildWidget _retry; - - bool _invertOrder; + bool _retrying = false; + bool _invertOrder = false; uint64 _contactId = 0; mtpRequestId _addRequest = 0; QString _sentName; + }; -class GroupInfoBox : public AbstractBox, public RPCSender { +class GroupInfoBox : public BoxContent, public RPCSender { Q_OBJECT public: - GroupInfoBox(CreatingGroupType creating, bool fromTypeChoose); + GroupInfoBox(QWidget*, CreatingGroupType creating, bool fromTypeChoose); -public slots: +protected: + void prepare() override; + void setInnerFocus() override; + + void resizeEvent(QResizeEvent *e) override; + +private slots: void onPhotoReady(const QImage &img); void onNext(); void onNameSubmit(); void onDescriptionResized(); -protected: - void resizeEvent(QResizeEvent *e) override; - - void doSetInnerFocus() override; - private: void notifyFileQueryUpdated(const FileDialog::QueryUpdate &update); + void creationDone(const MTPUpdates &updates); + bool creationFail(const RPCError &e); + void exportDone(const MTPExportedChatInvite &result); + void updateMaxHeight(); void updateSelected(const QPoint &cursorGlobalPosition); - CreatingGroupType _creating; - ChildWidget _photo; - ChildWidget _title; - ChildWidget _description; + CreatingGroupType _creating; + bool _fromTypeChoose = false; + + object_ptr _photo; + object_ptr _title; + object_ptr _description = { nullptr }; QImage _photoImage; - ChildWidget _next; - ChildWidget _cancel; - // channel creation mtpRequestId _creationRequestId = 0; ChannelData *_createdChannel = nullptr; FileDialog::QueryId _setPhotoFileQueryId = 0; - void creationDone(const MTPUpdates &updates); - bool creationFail(const RPCError &e); - void exportDone(const MTPExportedChatInvite &result); - }; -class SetupChannelBox : public AbstractBox, public RPCSender { +class SetupChannelBox : public BoxContent, public RPCSender { Q_OBJECT public: - SetupChannelBox(ChannelData *channel, bool existing = false); + SetupChannelBox(QWidget*, ChannelData *channel, bool existing = false); -public slots: - void onSave(); - void onChange(); - void onCheck(); - - void onPrivacyChange(); + void setInnerFocus() override; + void closeHook() override; protected: + void prepare() override; + void keyPressEvent(QKeyEvent *e) override; void paintEvent(QPaintEvent *e) override; void resizeEvent(QResizeEvent *e) override; @@ -149,8 +145,12 @@ protected: void mousePressEvent(QMouseEvent *e) override; void leaveEvent(QEvent *e) override; - void closePressed() override; - void doSetInnerFocus() override; +private slots: + void onSave(); + void onChange(); + void onCheck(); + + void onPrivacyChange(); private: void updateSelected(const QPoint &cursorGlobalPosition); @@ -166,22 +166,18 @@ private: void showRevokePublicLinkBoxForEdit(); - ChannelData *_channel; - bool _existing; + ChannelData *_channel = nullptr; + bool _existing = false; - ChildWidget _public; - ChildWidget _private; + object_ptr _public; + object_ptr _private; int32 _aboutPublicWidth, _aboutPublicHeight; Text _aboutPublic, _aboutPrivate; - ChildWidget _link; + object_ptr _link; QRect _invitationLink; - bool _linkOver; - - ChildWidget _save; - ChildWidget _skip; - + bool _linkOver = false; bool _tooMuchUsernames = false; mtpRequestId _saveRequestId = 0; @@ -195,20 +191,21 @@ private: }; -class EditNameTitleBox : public AbstractBox, public RPCSender { +class EditNameTitleBox : public BoxContent, public RPCSender { Q_OBJECT public: - EditNameTitleBox(PeerData *peer); - -public slots: - void onSave(); - void onSubmit(); + EditNameTitleBox(QWidget*, PeerData *peer); protected: + void setInnerFocus() override; + void prepare() override; + void resizeEvent(QResizeEvent *e) override; - void doSetInnerFocus() override; +private slots: + void onSave(); + void onSubmit(); private: void onSaveSelfDone(const MTPUser &user); @@ -219,11 +216,8 @@ private: PeerData *_peer; - ChildWidget _first; - ChildWidget _last; - - ChildWidget _save; - ChildWidget _cancel; + object_ptr _first; + object_ptr _last; bool _invertOrder = false; @@ -232,25 +226,26 @@ private: }; -class EditChannelBox : public AbstractBox, public RPCSender { +class EditChannelBox : public BoxContent, public RPCSender { Q_OBJECT public: - EditChannelBox(ChannelData *channel); + EditChannelBox(QWidget*, ChannelData *channel); -public slots: +protected: + void prepare() override; + void setInnerFocus() override; + + void keyPressEvent(QKeyEvent *e) override; + void resizeEvent(QResizeEvent *e) override; + +private slots: void peerUpdated(PeerData *peer); void onSave(); void onDescriptionResized(); void onPublicLink(); -protected: - void keyPressEvent(QKeyEvent *e) override; - void resizeEvent(QResizeEvent *e) override; - - void doSetInnerFocus() override; - private: void updateMaxHeight(); @@ -264,14 +259,11 @@ private: ChannelData *_channel; - ChildWidget _title; - ChildWidget _description; - ChildWidget _sign; + object_ptr _title; + object_ptr _description; + object_ptr _sign; - ChildWidget _publicLink; - - ChildWidget _save; - ChildWidget _cancel; + object_ptr _publicLink; mtpRequestId _saveTitleRequestId = 0; mtpRequestId _saveDescriptionRequestId = 0; @@ -281,13 +273,13 @@ private: }; -class RevokePublicLinkBox : public AbstractBox, public RPCSender { - Q_OBJECT - +class RevokePublicLinkBox : public BoxContent, public RPCSender { public: - RevokePublicLinkBox(base::lambda &&revokeCallback); + RevokePublicLinkBox(QWidget*, base::lambda &&revokeCallback); protected: + void prepare() override; + void mouseMoveEvent(QMouseEvent *e) override; void mousePressEvent(QMouseEvent *e) override; void mouseReleaseEvent(QMouseEvent *e) override; @@ -319,11 +311,10 @@ private: int _rowHeight = 0; int _revokeWidth = 0; - ChildWidget _aboutRevoke; - ChildWidget _cancel; + object_ptr _aboutRevoke; base::lambda _revokeCallback; mtpRequestId _revokeRequestId = 0; - QPointer weakRevokeConfirmBox; + QPointer _weakRevokeConfirmBox; }; diff --git a/Telegram/SourceFiles/boxes/autolockbox.cpp b/Telegram/SourceFiles/boxes/autolockbox.cpp index 88222a709..223c94423 100644 --- a/Telegram/SourceFiles/boxes/autolockbox.cpp +++ b/Telegram/SourceFiles/boxes/autolockbox.cpp @@ -30,32 +30,27 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "ui/widgets/buttons.h" #include "styles/style_boxes.h" -AutoLockBox::AutoLockBox() : _close(this, lang(lng_box_ok), st::defaultBoxButton) { - setTitleText(lang(lng_passcode_autolock)); +void AutoLockBox::prepare() { + setTitle(lang(lng_passcode_autolock)); - bool haveTestLang = (cLang() == languageTest); + addButton(lang(lng_box_ok), [this] { closeBox(); }); - int32 opts[] = { 60, 300, 3600, 18000 }, cnt = sizeof(opts) / sizeof(opts[0]); - - resizeMaxHeight(st::langsWidth, titleHeight() + cnt * (st::boxOptionListPadding.top() + st::langsButton.height) + st::boxOptionListPadding.bottom() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _close->height() + st::boxButtonPadding.bottom()); - - int32 y = titleHeight() + st::boxOptionListPadding.top(); + int opts[] = { 60, 300, 3600, 18000 }, cnt = sizeof(opts) / sizeof(opts[0]); + auto y = st::boxOptionListPadding.top(); _options.reserve(cnt); - for (int32 i = 0; i < cnt; ++i) { - int32 v = opts[i]; + for (auto i = 0; i != cnt; ++i) { + auto v = opts[i]; _options.push_back(new Ui::Radiobutton(this, qsl("autolock"), v, (v % 3600) ? lng_passcode_autolock_minutes(lt_count, v / 60) : lng_passcode_autolock_hours(lt_count, v / 3600), (Global::AutoLock() == v), st::langsButton)); _options.back()->move(st::boxPadding.left() + st::boxOptionListPadding.left(), y); - y += _options.back()->heightNoMargins() + st::boxOptionListPadding.top(); + y += _options.back()->heightNoMargins() + st::boxOptionListSkip; connect(_options.back(), SIGNAL(changed()), this, SLOT(onChange())); } - connect(_close, SIGNAL(clicked()), this, SLOT(onClose())); - - _close->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _close->height()); + setDimensions(st::langsWidth, st::boxOptionListPadding.top() + cnt * st::langsButton.height + (cnt - 1) * st::boxOptionListSkip + st::boxOptionListPadding.bottom() + st::boxPadding.bottom()); } void AutoLockBox::onChange() { - if (isHidden()) return; + if (!isBoxShown()) return; for (int32 i = 0, l = _options.size(); i < l; ++i) { int32 v = _options[i]->val(); @@ -66,5 +61,5 @@ void AutoLockBox::onChange() { } } App::wnd()->checkAutoLock(); - onClose(); + closeBox(); } diff --git a/Telegram/SourceFiles/boxes/autolockbox.h b/Telegram/SourceFiles/boxes/autolockbox.h index 036cc4bb7..767f23e48 100644 --- a/Telegram/SourceFiles/boxes/autolockbox.h +++ b/Telegram/SourceFiles/boxes/autolockbox.h @@ -24,20 +24,22 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org namespace Ui { class Radiobutton; -class RoundButton; } // namespace Ui -class AutoLockBox : public AbstractBox { +class AutoLockBox : public BoxContent { Q_OBJECT public: - AutoLockBox(); + AutoLockBox(QWidget*) { + } -public slots: +protected: + void prepare() override; + +private slots: void onChange(); private: QVector _options; - ChildWidget _close; }; diff --git a/Telegram/SourceFiles/boxes/backgroundbox.cpp b/Telegram/SourceFiles/boxes/backgroundbox.cpp index 3afed1095..37a082d97 100644 --- a/Telegram/SourceFiles/boxes/backgroundbox.cpp +++ b/Telegram/SourceFiles/boxes/backgroundbox.cpp @@ -29,25 +29,29 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "styles/style_boxes.h" #include "ui/effects/round_checkbox.h" -BackgroundBox::BackgroundBox() : ItemListBox(st::backgroundScroll) -, _inner(this) { - init(_inner); - setTitleText(lang(lng_backgrounds_header)); - - connect(_inner, SIGNAL(backgroundChosen(int)), this, SLOT(onBackgroundChosen(int))); - - raiseShadow(); +BackgroundBox::BackgroundBox(QWidget*) { } -void BackgroundBox::onBackgroundChosen(int index) { +void BackgroundBox::prepare() { + setTitle(lang(lng_backgrounds_header)); + + addButton(lang(lng_close), [this] { closeBox(); }); + + setDimensions(st::boxWideWidth, st::boxMaxListHeight); + + _inner = setInnerWidget(object_ptr(this), st::backgroundScroll); + _inner->setBackgroundChosenCallback([this](int index) { backgroundChosen(index); }); +} + +void BackgroundBox::backgroundChosen(int index) { if (index >= 0 && index < App::cServerBackgrounds().size()) { - const App::WallPaper &paper(App::cServerBackgrounds().at(index)); + auto &paper = App::cServerBackgrounds()[index]; if (App::main()) App::main()->setChatBackground(paper); using Update = Window::Theme::BackgroundUpdate; Window::Theme::Background()->notify(Update(Update::Type::Start, !paper.id)); } - onClose(); + closeBox(); } BackgroundBox::Inner::Inner(QWidget *parent) : TWidget(parent) @@ -163,8 +167,8 @@ void BackgroundBox::Inner::paintEvent(QPaintEvent *e) { } } } else { - p.setFont(st::noContactsFont->f); - p.setPen(st::noContactsColor->p); + p.setFont(st::noContactsFont); + p.setPen(st::noContactsColor); p.drawText(QRect(0, 0, width(), st::noContactsHeight), lang(lng_contacts_loading), style::al_center); } } @@ -191,7 +195,9 @@ void BackgroundBox::Inner::mousePressEvent(QMouseEvent *e) { void BackgroundBox::Inner::mouseReleaseEvent(QMouseEvent *e) { if (_overDown == _over && _over >= 0) { - emit backgroundChosen(_over); + if (_backgroundChosenCallback) { + _backgroundChosenCallback(_over); + } } else if (_over < 0) { setCursor(style::cur_default); } diff --git a/Telegram/SourceFiles/boxes/backgroundbox.h b/Telegram/SourceFiles/boxes/backgroundbox.h index b5136ba9f..49f70522a 100644 --- a/Telegram/SourceFiles/boxes/backgroundbox.h +++ b/Telegram/SourceFiles/boxes/backgroundbox.h @@ -26,31 +26,31 @@ namespace Ui { class RoundCheckbox; } // namespace Ui -class BackgroundBox : public ItemListBox { - Q_OBJECT - +class BackgroundBox : public BoxContent { public: - BackgroundBox(); + BackgroundBox(QWidget*); -public slots: - void onBackgroundChosen(int index); +protected: + void prepare() override; private: + void backgroundChosen(int index); + class Inner; - ChildWidget _inner; + QPointer _inner; }; // This class is hold in header because it requires Qt preprocessing. class BackgroundBox::Inner : public TWidget, public RPCSender, private base::Subscriber { - Q_OBJECT - public: Inner(QWidget *parent); - ~Inner(); -signals: - void backgroundChosen(int index); + void setBackgroundChosenCallback(base::lambda &&callback) { + _backgroundChosenCallback = std_::move(callback); + } + + ~Inner(); protected: void paintEvent(QPaintEvent *e) override; @@ -62,10 +62,12 @@ private: void gotWallpapers(const MTPVector &result); void updateWallpapers(); + base::lambda _backgroundChosenCallback; + int _bgCount = 0; int _rows = 0; int _over = -1; int _overDown = -1; - std_::unique_ptr _check; + std_::unique_ptr _check; // this not a widget }; diff --git a/Telegram/SourceFiles/boxes/boxes.style b/Telegram/SourceFiles/boxes/boxes.style index e45b40eb8..011705afd 100644 --- a/Telegram/SourceFiles/boxes/boxes.style +++ b/Telegram/SourceFiles/boxes/boxes.style @@ -24,16 +24,10 @@ using "ui/widgets/widgets.style"; using "intro/intro.style"; boxDuration: 200; +boxRadius: 3px; boxButtonFont: font(boxFontSize semibold); -defaultBoxButton: RoundButton { - textFg: #2f9fea; - textFgOver: #2f9fea; - secondaryTextFg: #2f9fea; - secondaryTextFgOver: #2f9fea; - textBg: boxBg; - textBgOver: lightButtonBgOver; - +defaultBoxButton: RoundButton(defaultLightButton) { width: -24px; height: 36px; padding: margins(0px, 0px, 0px, 0px); @@ -47,9 +41,7 @@ defaultBoxButton: RoundButton { } } -cancelBoxButton: RoundButton(defaultBoxButton) { - textFg: #aeaeae; -} +cancelBoxButton: defaultBoxButton; attentionBoxButton: RoundButton(defaultBoxButton) { textFg: attentionButtonFg; @@ -67,22 +59,40 @@ defaultBoxCheckbox: Checkbox(defaultCheckbox) { font: boxTextFont; } -boxBlockTitleHeight: 48px; -boxBlockTitlePosition: point(18px, 14px); -boxBlockTitleFont: font(boxFontSize semibold); -boxBlockTitleAdditionalSkip: 6px; -boxBlockTitleAdditionalFont: normalFont; -boxBlockTitleShadow: icon {{ "box_title_shadow", windowShadowFg }}; +boxRoundShadow: Shadow { + left: icon {{ "round_shadow_box_left", windowShadowFg }}; + topLeft: icon {{ "round_shadow_box_top_left", windowShadowFg }}; + top: icon {{ "round_shadow_box_top", windowShadowFg }}; + topRight: icon {{ "round_shadow_box_top_left-flip_horizontal", windowShadowFg }}; + right: icon {{ "round_shadow_box_left-flip_horizontal", windowShadowFg }}; + bottomRight: icon {{ "round_shadow_box_bottom_left-flip_horizontal", windowShadowFg }}; + bottom: icon {{ "round_shadow_box_bottom", windowShadowFg }}; + bottomLeft: icon {{ "round_shadow_box_bottom_left", windowShadowFg }}; + extend: margins(10px, 10px, 10px, 10px); + fallback: windowShadowFgFallback; +} -boxBlockTitleClose: IconButton(defaultIconButton) { - width: boxBlockTitleHeight; - height: boxBlockTitleHeight; +boxTitleFont: font(17px semibold); +boxTitlePosition: point(23px, 20px); +boxTitleHeight: 56px; +boxLayerTitlePosition: point(23px, 16px); +boxLayerTitleHeight: 56px; +boxLayerTitleAdditionalSkip: 9px; +boxLayerTitleAdditionalFont: normalFont; +boxLayerTitleShadow: #0000001a; +boxLayerScroll: defaultSolidScroll; - icon: boxBlockTitleCloseIcon; - iconOver: boxBlockTitleCloseIconOver; +boxTopMargin: 6px; + +boxTitleClose: IconButton(defaultIconButton) { + width: boxTitleHeight; + height: boxTitleHeight; + + icon: boxTitleCloseIcon; + iconOver: boxTitleCloseIconOver; rippleAreaPosition: point(4px, 4px); - rippleAreaSize: 40px; + rippleAreaSize: 48px; ripple: RippleAnimation(defaultRippleAnimation) { color: windowBgOver; } @@ -96,34 +106,25 @@ boxLinkButton: LinkButton { overFont: font(boxFontSize underline); } -boxOptionListPadding: margins(2px, 20px, 2px, 2px); +boxOptionListPadding: margins(0px, 0px, 0px, 0px); +boxOptionListSkip: 20px; boxOptionInputSkip: 6px; boxVerticalMargin: 10px; boxWidth: 320px; boxWideWidth: 364px; -boxPadding: margins(26px, 30px, 34px, 8px); +boxPadding: margins(23px, 30px, 23px, 8px); boxMaxListHeight: 600px; boxLittleSkip: 10px; boxMediumSkip: 20px; -boxTitleFont: font(boxFontSize bold); -boxTitlePosition: point(26px, 28px); -boxTitleHeight: 54px; - -boxButtonPadding: margins(12px, 16px, 22px, 16px); +boxButtonPadding: margins(8px, 12px, 13px, 12px); +boxLayerButtonPadding: margins(8px, 8px, 8px, 8px); boxLabel: FlatLabel(defaultFlatLabel) { font: font(boxFontSize); align: align(topleft); } -boxScroll: defaultSolidScroll; -boxScrollSkip: 6px; -boxScrollShadowBg: #00000012; - -boxShadow: icon {{ "box_shadow", windowShadowFg }}; -boxShadowShift: 2px; - countryRowHeight: 36px; countryRowNameFont: semiboldFont; countryRowNameFg: boxTextFg; @@ -134,7 +135,7 @@ countryRowBgOver: windowBgOver; countryRowCodeFg: windowSubTextFg; countryRowCodeFgOver: windowSubTextFgOver; countriesSkip: 12px; -countriesScroll: FlatScroll(boxScroll) { +countriesScroll: ScrollArea(boxLayerScroll) { deltat: 9px; deltab: 3px; } @@ -145,7 +146,7 @@ boxTextStyle: TextStyle(defaultTextStyle) { boxPhotoTitleFont: font(16px semibold); boxPhotoTitlePosition: point(28px, 26px); -boxPhotoPadding: margins(28px, 28px, 28px, 0px); +boxPhotoPadding: margins(28px, 28px, 28px, 18px); boxPhotoCompressedSkip: 20px; boxPhotoCaptionSkip: 8px; boxPhotoTextFg: #808080; @@ -223,7 +224,7 @@ contactsAdd: TwoIconButton { } contactsAddPosition: point(14px, 8px); -contactPadding: margins(49px, 2px, 0px, 6px); +contactPadding: margins(49px, 2px, 0px, 12px); contactSkip: 6px; contactPhoneSkip: 30px; @@ -240,15 +241,12 @@ contactsAboutFg: windowSubTextFgOver; contactsAboutShadow: #0000001F; contactsAboutTop: 60px; contactsAboutBottom: 19px; -contactsScroll: FlatScroll(boxScroll) { - deltab: 0px; -} contactsMultiSelect: MultiSelect { bg: boxSearchBg; - padding: margins(8px, 8px, 8px, 8px); + padding: margins(8px, 6px, 8px, 6px); maxHeight: 104px; - scroll: FlatScroll(defaultSolidScroll) { + scroll: ScrollArea(defaultSolidScroll) { deltat: 3px; deltab: 3px; round: 1px; @@ -302,17 +300,17 @@ contactsMultiSelect: MultiSelect { fieldIconSkip: 36px; fieldCancel: CrossButton { - width: boxBlockTitleHeight; - height: boxBlockTitleHeight; + width: 44px; + height: 44px; cross: CrossAnimation { - size: 40px; - skip: 14px; + size: 36px; + skip: 12px; stroke: 2px; minScale: 0.3; } - crossFg: boxBlockTitleCloseFg; - crossFgOver: boxBlockTitleCloseFgOver; + crossFg: boxTitleCloseFg; + crossFgOver: boxTitleCloseFgOver; crossPosition: point(4px, 4px); duration: 150; @@ -338,6 +336,11 @@ contactsPhotoDisabledCheckFg: #bbbbbb; contactsNameCheckedFg: #2b88b8; contactsRipple: defaultRippleAnimation; +contactsMarginTop: 4px; +contactsMarginBottom: 4px; +membersMarginTop: 10px; +membersMarginBottom: 10px; + localStorageBoxSkip: 10px; shareRowsTop: 12px; @@ -355,7 +358,7 @@ shareColumnSkip: 6px; shareActivateDuration: 150; shareScrollDuration: 300; -notificationsBoxHeight: 450px; +notificationsBoxHeight: 420px; notificationsBoxMonitorTop: 63px; notificationsBoxMonitor: icon {{ "monitor", notificationsBoxMonitorFg }}; notificationsBoxScreenTop: 10px; @@ -374,8 +377,8 @@ notificationSampleSize: size(64px, 16px); membersAboutLimitPadding: margins(0px, 12px, 0px, 12px); -sessionsScroll: boxScroll; -sessionsHeight: 440px; +sessionsScroll: boxLayerScroll; +sessionsHeight: 350px; sessionHeight: 70px; sessionCurrentPadding: margins(0px, 7px, 0px, 4px); sessionCurrentHeight: 118px; @@ -417,9 +420,10 @@ passcodeSubmit: RoundButton(introNextButton) { width: 225px; } passcodeSubmitSkip: 40px; -passcodePadding: margins(0px, 6px, 0px, 13px); +passcodePadding: margins(0px, 0px, 0px, 12px); passcodeTextLine: 28px; -passcodeSkip: 21px; +passcodeLittleSkip: 5px; +passcodeSkip: 20px; newGroupAboutFg: #808080; newGroupPadding: margins(4px, 6px, 4px, 3px); @@ -453,8 +457,6 @@ newGroupLinkFadeDuration: 5000; themeWarningWidth: boxWideWidth; themeWarningHeight: 150px; -themeWarningShadow: boxShadow; -themeWarningShadowShift: boxShadowShift; themeWarningTextTop: 60px; aboutWidth: 390px; @@ -475,6 +477,9 @@ aboutTextStyle: TextStyle(defaultTextStyle) { lineHeight: 22px; } +autoDownloadTitlePosition: point(23px, 28px); +autoDownloadTitleFont: font(15px semibold); + editTextArea: InputField(defaultInputField) { textMargins: margins(1px, 26px, 1px, 4px); heightMax: 276px; @@ -509,9 +514,11 @@ langsButton: Checkbox(defaultBoxCheckbox) { backgroundPadding: 10px; backgroundSize: size(108px, 193px); -backgroundScroll: FlatScroll(boxScroll) { +backgroundScroll: ScrollArea(boxLayerScroll) { + deltax: 3px; + width: 10px; deltat: 10px; - deltab: 0px; + deltab: 10px; } usernamePadding: margins(23px, 6px, 21px, 12px); diff --git a/Telegram/SourceFiles/boxes/confirmbox.cpp b/Telegram/SourceFiles/boxes/confirmbox.cpp index 1b39928df..9c36714cd 100644 --- a/Telegram/SourceFiles/boxes/confirmbox.cpp +++ b/Telegram/SourceFiles/boxes/confirmbox.cpp @@ -30,6 +30,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "ui/widgets/checkbox.h" #include "ui/widgets/buttons.h" #include "ui/widgets/labels.h" +#include "ui/toast/toast.h" #include "core/click_handler_types.h" #include "localstorage.h" @@ -40,54 +41,103 @@ TextParseOptions _confirmBoxTextOptions = { Qt::LayoutDirectionAuto, // dir }; -ConfirmBox::ConfirmBox(const QString &text, const QString &doneText, const style::RoundButton &doneStyle, const QString &cancelText, const style::RoundButton &cancelStyle) : AbstractBox(st::boxWidth) -, _informative(false) -, _text(100) -, _confirm(this, doneText.isEmpty() ? lang(lng_box_ok) : doneText, doneStyle) -, _cancel(this, cancelText.isEmpty() ? lang(lng_cancel) : cancelText, cancelStyle) { +ConfirmBox::ConfirmBox(QWidget*, const QString &text, base::lambda &&confirmedCallback, base::lambda &&cancelledCallback) +: _confirmText(lang(lng_box_ok)) +, _cancelText(lang(lng_cancel)) +, _confirmStyle(st::defaultBoxButton) +, _text(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()) +, _confirmedCallback(std_::move(confirmedCallback)) +, _cancelledCallback(std_::move(cancelledCallback)) { init(text); } -ConfirmBox::ConfirmBox(const QString &text, const QString &doneText, const style::RoundButton &doneStyle, bool informative) : AbstractBox(st::boxWidth) +ConfirmBox::ConfirmBox(QWidget*, const QString &text, const QString &confirmText, base::lambda &&confirmedCallback, base::lambda &&cancelledCallback) +: _confirmText(confirmText) +, _cancelText(lang(lng_cancel)) +, _confirmStyle(st::defaultBoxButton) +, _text(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()) +, _confirmedCallback(std_::move(confirmedCallback)) +, _cancelledCallback(std_::move(cancelledCallback)) { + init(text); +} + +ConfirmBox::ConfirmBox(QWidget*, const QString &text, const QString &confirmText, const style::RoundButton &confirmStyle, base::lambda &&confirmedCallback, base::lambda &&cancelledCallback) +: _confirmText(confirmText) +, _cancelText(lang(lng_cancel)) +, _confirmStyle(confirmStyle) +, _text(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()) +, _confirmedCallback(std_::move(confirmedCallback)) +, _cancelledCallback(std_::move(cancelledCallback)) { + init(text); +} + +ConfirmBox::ConfirmBox(QWidget*, const QString &text, const QString &confirmText, const QString &cancelText, base::lambda &&confirmedCallback, base::lambda &&cancelledCallback) +: _confirmText(confirmText) +, _cancelText(cancelText) +, _confirmStyle(st::defaultBoxButton) +, _text(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()) +, _confirmedCallback(std_::move(confirmedCallback)) +, _cancelledCallback(std_::move(cancelledCallback)) { + init(text); +} + +ConfirmBox::ConfirmBox(QWidget*, const QString &text, const QString &confirmText, const style::RoundButton &confirmStyle, const QString &cancelText, base::lambda &&confirmedCallback, base::lambda &&cancelledCallback) +: _confirmText(confirmText) +, _cancelText(cancelText) +, _confirmStyle(st::defaultBoxButton) +, _text(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()) +, _confirmedCallback(std_::move(confirmedCallback)) +, _cancelledCallback(std_::move(cancelledCallback)) { + init(text); +} + +ConfirmBox::ConfirmBox(const InformBoxTag &, const QString &text, const QString &doneText, base::lambda_copy &&closedCallback) +: _confirmText(doneText) +, _confirmStyle(st::defaultBoxButton) , _informative(true) -, _text(100) -, _confirm(this, doneText.isEmpty() ? lang(lng_box_ok) : doneText, doneStyle) -, _cancel(this, QString(), st::cancelBoxButton) { +, _text(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()) +, _confirmedCallback(base::lambda_copy(closedCallback)) +, _cancelledCallback(base::lambda_copy(closedCallback)) { init(text); } void ConfirmBox::init(const QString &text) { + textstyleSet(&st::boxTextStyle); _text.setText(st::boxTextFont, text, _informative ? _confirmBoxTextOptions : _textPlainOptions); - - connect(_confirm, SIGNAL(clicked()), this, SLOT(onConfirmPressed())); - connect(_cancel, SIGNAL(clicked()), this, SLOT(onCancel())); - if (_informative) { - _cancel->hide(); - connect(this, SIGNAL(confirmed()), this, SLOT(onCancel())); - } - onTextUpdated(); + textstyleRestore(); } -void ConfirmBox::onConfirmPressed() { - if (_confirmedCallback) { - _confirmedCallback(); +void ConfirmBox::prepare() { + addButton(_confirmText, [this] { confirmed(); }, _confirmStyle); + if (!_informative) { + addButton(_cancelText, [this] { _cancelled = true; closeBox(); }); } - emit confirmed(); + textUpdated(); } -void ConfirmBox::onTextUpdated() { +void ConfirmBox::textUpdated() { textstyleSet(&st::boxTextStyle); _textWidth = st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right(); _textHeight = qMin(_text.countHeight(_textWidth), 16 * int(st::boxTextStyle.lineHeight)); - setMaxHeight(st::boxPadding.top() + _textHeight + st::boxPadding.bottom() + st::boxButtonPadding.top() + _confirm->height() + st::boxButtonPadding.bottom()); + setDimensions(st::boxWidth, st::boxPadding.top() + _textHeight + st::boxPadding.bottom()); textstyleRestore(); setMouseTracking(_text.hasLinks()); } -void ConfirmBox::onCancel() { - emit cancelPressed(); - onClose(); +void ConfirmBox::closeHook() { + if (!_confirmed && (!_strictCancel || _cancelled) && _cancelledCallback) { + _cancelledCallback(); + } +} + +void ConfirmBox::confirmed() { + if (!_confirmed) { + _confirmed = true; + if (_confirmedCallback) { + _confirmedCallback(); + } + } } void ConfirmBox::mouseMoveEvent(QMouseEvent *e) { @@ -99,7 +149,7 @@ void ConfirmBox::mousePressEvent(QMouseEvent *e) { _lastMousePos = e->globalPos(); updateHover(); ClickHandler::pressed(); - return LayerWidget::mousePressEvent(e); + return BoxContent::mousePressEvent(e); } void ConfirmBox::mouseReleaseEvent(QMouseEvent *e) { @@ -109,6 +159,7 @@ void ConfirmBox::mouseReleaseEvent(QMouseEvent *e) { Ui::hideLayer(); App::activateClickHandler(activated, e->button()); } + return BoxContent::mouseReleaseEvent(e); } void ConfirmBox::leaveEvent(QEvent *e) { @@ -139,20 +190,16 @@ void ConfirmBox::updateHover() { ClickHandler::setActive(state.link, this); } -void ConfirmBox::closePressed() { - emit cancelled(); -} - void ConfirmBox::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { - onConfirmPressed(); + confirmed(); } else { - AbstractBox::keyPressEvent(e); + BoxContent::keyPressEvent(e); } } void ConfirmBox::paintEvent(QPaintEvent *e) { - AbstractBox::paintEvent(e); + BoxContent::paintEvent(e); Painter p(this); @@ -163,55 +210,19 @@ void ConfirmBox::paintEvent(QPaintEvent *e) { textstyleRestore(); } -void ConfirmBox::resizeEvent(QResizeEvent *e) { - _confirm->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _confirm->height()); - _cancel->moveToRight(st::boxButtonPadding.right() + _confirm->width() + st::boxButtonPadding.left(), _confirm->y()); - AbstractBox::resizeEvent(e); -} - -SharePhoneConfirmBox::SharePhoneConfirmBox(PeerData *recipient) -: ConfirmBox(lang(lng_bot_share_phone), lang(lng_bot_share_phone_confirm)) -, _recipient(recipient) { - connect(this, SIGNAL(confirmed()), this, SLOT(onConfirm())); -} - -void SharePhoneConfirmBox::onConfirm() { - emit confirmed(_recipient); -} - -ConfirmLinkBox::ConfirmLinkBox(const QString &url) : ConfirmBox(lang(lng_open_this_link) + qsl("\n\n") + url, lang(lng_open_link)) -, _url(url) { - connect(this, SIGNAL(confirmed()), this, SLOT(onOpenLink())); -} - -void ConfirmLinkBox::onOpenLink() { - Ui::hideLayer(); - UrlClickHandler::doOpen(_url); -} - -ConfirmBotGameBox::ConfirmBotGameBox(UserData *bot, const QString &url) : ConfirmBox(lng_allow_bot_pass(lt_bot_name, bot->name), lang(lng_allow_bot)) -, _bot(bot) -, _url(url) { - connect(this, SIGNAL(confirmed()), this, SLOT(onOpenLink())); -} - -void ConfirmBotGameBox::onOpenLink() { - Ui::hideLayer(); - Local::makeBotTrusted(_bot); - UrlClickHandler::doOpen(_url); -} - -MaxInviteBox::MaxInviteBox(const QString &link) : AbstractBox(st::boxWidth) -, _close(this, lang(lng_box_ok), st::defaultBoxButton) -, _text(st::boxTextFont, lng_participant_invite_sorry(lt_count, Global::ChatSizeMax()), _confirmBoxTextOptions, st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()) +MaxInviteBox::MaxInviteBox(QWidget*, const QString &link) +: _text(st::boxTextFont, lng_participant_invite_sorry(lt_count, Global::ChatSizeMax()), _confirmBoxTextOptions, st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()) , _link(link) { +} + +void MaxInviteBox::prepare() { setMouseTracking(true); + addButton(lang(lng_box_ok), [this] { closeBox(); }); + _textWidth = st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right(); _textHeight = qMin(_text.countHeight(_textWidth), 16 * int(st::boxTextStyle.lineHeight)); - setMaxHeight(st::boxPadding.top() + _textHeight + st::boxTextFont->height + st::boxTextFont->height * 2 + st::newGroupLinkPadding.bottom() + st::boxButtonPadding.top() + _close->height() + st::boxButtonPadding.bottom()); - - connect(_close, SIGNAL(clicked()), this, SLOT(onClose())); + setDimensions(st::boxWidth, st::boxPadding.top() + _textHeight + st::boxTextFont->height + st::boxTextFont->height * 2 + st::newGroupLinkPadding.bottom()); } void MaxInviteBox::mouseMoveEvent(QMouseEvent *e) { @@ -222,9 +233,10 @@ void MaxInviteBox::mousePressEvent(QMouseEvent *e) { mouseMoveEvent(e); if (_linkOver) { Application::clipboard()->setText(_link); - _goodTextLink = lang(lng_create_channel_link_copied); - _a_goodOpacity.finish(); - _a_goodOpacity.start([this] { update(); }, 1., 0., st::newGroupLinkFadeDuration); + + Ui::Toast::Config toast; + toast.text = lang(lng_create_channel_link_copied); + Ui::Toast::Show(App::wnd(), toast); } } @@ -244,7 +256,7 @@ void MaxInviteBox::updateSelected(const QPoint &cursorGlobalPosition) { } void MaxInviteBox::paintEvent(QPaintEvent *e) { - AbstractBox::paintEvent(e); + BoxContent::paintEvent(e); Painter p(this); @@ -257,49 +269,41 @@ void MaxInviteBox::paintEvent(QPaintEvent *e) { p.setFont(_linkOver ? st::defaultInputField.font->underline() : st::defaultInputField.font); p.setPen(st::defaultLinkButton.color); p.drawText(_invitationLink, _link, option); - if (!_goodTextLink.isEmpty()) { - auto opacity = _a_goodOpacity.current(getms(), 0.); - if (opacity > 0.) { - p.setOpacity(opacity); - p.setPen(st::boxTextFgGood); - p.setFont(st::boxTextFont); - p.drawTextLeft(st::boxPadding.left(), height() - st::boxButtonPadding.bottom() - _close->height() + st::defaultBoxButton.textTop + st::defaultBoxButton.font->ascent - st::boxTextFont->ascent, width(), _goodTextLink); - p.setOpacity(1); - } - } } void MaxInviteBox::resizeEvent(QResizeEvent *e) { - _close->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _close->height()); + BoxContent::resizeEvent(e); _invitationLink = myrtlrect(st::boxPadding.left(), st::boxPadding.top() + _textHeight + st::boxTextFont->height, width() - st::boxPadding.left() - st::boxPadding.right(), 2 * st::boxTextFont->height); - AbstractBox::resizeEvent(e); } -ConvertToSupergroupBox::ConvertToSupergroupBox(ChatData *chat) : AbstractBox(st::boxWideWidth, lang(lng_profile_convert_title)) -, _chat(chat) +ConvertToSupergroupBox::ConvertToSupergroupBox(QWidget*, ChatData *chat) +: _chat(chat) , _text(100) -, _note(100) -, _convert(this, lang(lng_profile_convert_confirm), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) { +, _note(100) { +} + +void ConvertToSupergroupBox::prepare() { QStringList text; text.push_back(lang(lng_profile_convert_feature1)); text.push_back(lang(lng_profile_convert_feature2)); text.push_back(lang(lng_profile_convert_feature3)); text.push_back(lang(lng_profile_convert_feature4)); + setTitle(lang(lng_profile_convert_title)); + + addButton(lang(lng_profile_convert_confirm), [this] { convertToSupergroup(); }); + addButton(lang(lng_cancel), [this] { closeBox(); }); + textstyleSet(&st::boxTextStyle); _text.setText(st::boxTextFont, text.join('\n'), _confirmBoxTextOptions); _note.setText(st::boxTextFont, lng_profile_convert_warning(lt_bold_start, textcmdStartSemibold(), lt_bold_end, textcmdStopSemibold()), _confirmBoxTextOptions); _textWidth = st::boxWideWidth - st::boxPadding.left() - st::boxButtonPadding.right(); _textHeight = _text.countHeight(_textWidth); - setMaxHeight(titleHeight() + _textHeight + st::boxPadding.bottom() + _note.countHeight(_textWidth) + st::boxButtonPadding.top() + _convert->height() + st::boxButtonPadding.bottom()); + setDimensions(st::boxWideWidth, _textHeight + st::boxPadding.bottom() + _note.countHeight(_textWidth)); textstyleRestore(); - - connect(_convert, SIGNAL(clicked()), this, SLOT(onConvert())); - connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); } -void ConvertToSupergroupBox::onConvert() { +void ConvertToSupergroupBox::convertToSupergroup() { MTP::send(MTPmessages_MigrateChat(_chat->inputChat), rpcDone(&ConvertToSupergroupBox::convertDone), rpcFail(&ConvertToSupergroupBox::convertFail)); } @@ -336,54 +340,48 @@ bool ConvertToSupergroupBox::convertFail(const RPCError &error) { void ConvertToSupergroupBox::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { - onConvert(); + convertToSupergroup(); } else { - AbstractBox::keyPressEvent(e); + BoxContent::keyPressEvent(e); } } void ConvertToSupergroupBox::paintEvent(QPaintEvent *e) { - AbstractBox::paintEvent(e); + BoxContent::paintEvent(e); Painter p(this); // draw box title / text p.setPen(st::boxTextFg); textstyleSet(&st::boxTextStyle); - _text.drawLeft(p, st::boxPadding.left(), titleHeight(), _textWidth, width()); - _note.drawLeft(p, st::boxPadding.left(), titleHeight() + _textHeight + st::boxPadding.bottom(), _textWidth, width()); + _text.drawLeft(p, st::boxPadding.left(), 0, _textWidth, width()); + _note.drawLeft(p, st::boxPadding.left(), _textHeight + st::boxPadding.bottom(), _textWidth, width()); textstyleRestore(); } -void ConvertToSupergroupBox::resizeEvent(QResizeEvent *e) { - _convert->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _convert->height()); - _cancel->moveToRight(st::boxButtonPadding.right() + _convert->width() + st::boxButtonPadding.left(), _convert->y()); - AbstractBox::resizeEvent(e); -} - -PinMessageBox::PinMessageBox(ChannelData *channel, MsgId msgId) : AbstractBox(st::boxWidth) -, _channel(channel) +PinMessageBox::PinMessageBox(QWidget*, ChannelData *channel, MsgId msgId) +: _channel(channel) , _msgId(msgId) , _text(this, lang(lng_pinned_pin_sure), Ui::FlatLabel::InitType::Simple, st::boxLabel) -, _notify(this, lang(lng_pinned_notify), true, st::defaultBoxCheckbox) -, _pin(this, lang(lng_pinned_pin), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) { - _text->resizeToWidth(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()); - setMaxHeight(st::boxPadding.top() + _text->height() + st::boxMediumSkip + _notify->heightNoMargins() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _pin->height() + st::boxButtonPadding.bottom()); +, _notify(this, lang(lng_pinned_notify), true, st::defaultBoxCheckbox) { +} - connect(_pin, SIGNAL(clicked()), this, SLOT(onPin())); - connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); +void PinMessageBox::prepare() { + _text->resizeToWidth(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()); + + addButton(lang(lng_pinned_pin), [this] { pinMessage(); }); + addButton(lang(lng_cancel), [this] { closeBox(); }); + + setDimensions(st::boxWidth, st::boxPadding.top() + _text->height() + st::boxMediumSkip + _notify->heightNoMargins() + st::boxPadding.bottom()); } void PinMessageBox::resizeEvent(QResizeEvent *e) { + BoxContent::resizeEvent(e); _text->moveToLeft(st::boxPadding.left(), st::boxPadding.top()); _notify->moveToLeft(st::boxPadding.left(), _text->y() + _text->height() + st::boxMediumSkip); - _pin->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _pin->height()); - _cancel->moveToRight(st::boxButtonPadding.right() + _pin->width() + st::boxButtonPadding.left(), _pin->y()); - AbstractBox::resizeEvent(e); } -void PinMessageBox::onPin() { +void PinMessageBox::pinMessage() { if (_requestId) return; MTPchannels_UpdatePinnedMessage::Flags flags = 0; @@ -406,36 +404,35 @@ bool PinMessageBox::pinFail(const RPCError &error) { return true; } -RichDeleteMessageBox::RichDeleteMessageBox(ChannelData *channel, UserData *from, MsgId msgId) : AbstractBox(st::boxWidth) -, _channel(channel) +RichDeleteMessageBox::RichDeleteMessageBox(QWidget*, ChannelData *channel, UserData *from, MsgId msgId) +: _channel(channel) , _from(from) , _msgId(msgId) , _text(this, lang(lng_selected_delete_sure_this), Ui::FlatLabel::InitType::Simple, st::boxLabel) , _banUser(this, lang(lng_ban_user), false, st::defaultBoxCheckbox) , _reportSpam(this, lang(lng_report_spam), false, st::defaultBoxCheckbox) -, _deleteAll(this, lang(lng_delete_all_from), false, st::defaultBoxCheckbox) -, _delete(this, lang(lng_box_delete), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) { +, _deleteAll(this, lang(lng_delete_all_from), false, st::defaultBoxCheckbox) { +} + +void RichDeleteMessageBox::prepare() { t_assert(_channel != nullptr); - _text->resizeToWidth(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()); - setMaxHeight(st::boxPadding.top() + _text->height() + st::boxMediumSkip + _banUser->heightNoMargins() + st::boxLittleSkip + _reportSpam->heightNoMargins() + st::boxLittleSkip + _deleteAll->heightNoMargins() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _delete->height() + st::boxButtonPadding.bottom()); + addButton(lang(lng_box_delete), [this] { deleteAndClear(); }); + addButton(lang(lng_cancel), [this] { closeBox(); }); - connect(_delete, SIGNAL(clicked()), this, SLOT(onDelete())); - connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); + _text->resizeToWidth(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()); + setDimensions(st::boxWidth, st::boxPadding.top() + _text->height() + st::boxMediumSkip + _banUser->heightNoMargins() + st::boxLittleSkip + _reportSpam->heightNoMargins() + st::boxLittleSkip + _deleteAll->heightNoMargins() + st::boxPadding.bottom()); } void RichDeleteMessageBox::resizeEvent(QResizeEvent *e) { + BoxContent::resizeEvent(e); _text->moveToLeft(st::boxPadding.left(), st::boxPadding.top()); _banUser->moveToLeft(st::boxPadding.left(), _text->bottomNoMargins() + st::boxMediumSkip); _reportSpam->moveToLeft(st::boxPadding.left(), _banUser->bottomNoMargins() + st::boxLittleSkip); _deleteAll->moveToLeft(st::boxPadding.left(), _reportSpam->bottomNoMargins() + st::boxLittleSkip); - _delete->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _delete->height()); - _cancel->moveToRight(st::boxButtonPadding.right() + _delete->width() + st::boxButtonPadding.left(), _delete->y()); - AbstractBox::resizeEvent(e); } -void RichDeleteMessageBox::onDelete() { +void RichDeleteMessageBox::deleteAndClear() { if (_banUser->checked()) { MTP::send(MTPchannels_KickFromChannel(_channel->inputChannel, _from->inputUser, MTP_boolTrue()), App::main()->rpcDone(&MainWidget::sentUpdatesReceived)); } @@ -445,7 +442,7 @@ void RichDeleteMessageBox::onDelete() { if (_deleteAll->checked()) { App::main()->deleteAllFromUser(_channel, _from); } - if (HistoryItem *item = App::histItemById(_channel ? peerToChannel(_channel->id) : 0, _msgId)) { + if (auto item = App::histItemById(_channel ? peerToChannel(_channel->id) : 0, _msgId)) { bool wasLast = (item->history()->lastMsg == item); item->destroy(); @@ -458,33 +455,11 @@ void RichDeleteMessageBox::onDelete() { Ui::hideLayer(); } -KickMemberBox::KickMemberBox(PeerData *chat, UserData *member) -: ConfirmBox(lng_profile_sure_kick(lt_user, member->firstName), lang(lng_box_remove)) -, _chat(chat) -, _member(member) { - connect(this, SIGNAL(confirmed()), this, SLOT(onConfirm())); -} - -void KickMemberBox::onConfirm() { - Ui::hideLayer(); - if (auto chat = _chat->asChat()) { - App::main()->kickParticipant(chat, _member); - } else if (auto channel = _chat->asChannel()) { - App::api()->kickParticipant(channel, _member); - } -} - -ConfirmInviteBox::ConfirmInviteBox(const QString &title, const MTPChatPhoto &photo, int count, const QVector &participants) : AbstractBox() -, _title(this, st::confirmInviteTitle) +ConfirmInviteBox::ConfirmInviteBox(QWidget*, const QString &title, const MTPChatPhoto &photo, int count, const QVector &participants) +: _title(this, st::confirmInviteTitle) , _status(this, st::confirmInviteStatus) , _photo(chatDefPhoto(0)) -, _participants(participants) -, _join(this, lang(lng_group_invite_join), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) { - if (_participants.size() > 4) { - _participants.resize(4); - } - +, _participants(participants) { _title->setText(title); QString status; if (_participants.isEmpty() || _participants.size() >= count) { @@ -504,8 +479,21 @@ ConfirmInviteBox::ConfirmInviteBox(const QString &title, const MTPChatPhoto &pho } } } +} - int h = st::confirmInviteStatusTop + _status->height() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _join->height() + st::boxButtonPadding.bottom(); +void ConfirmInviteBox::prepare() { + addButton(lang(lng_group_invite_join), [this] { + if (auto main = App::main()) { + main->onInviteImport(); + } + }); + addButton(lang(lng_cancel), [this] { closeBox(); }); + + if (_participants.size() > 4) { + _participants.resize(4); + } + + auto newHeight = st::confirmInviteStatusTop + _status->height() + st::boxPadding.bottom(); if (!_participants.isEmpty()) { int skip = (width() - 4 * st::confirmInviteUserPhotoSize) / 5; int padding = skip / 2; @@ -520,24 +508,19 @@ ConfirmInviteBox::ConfirmInviteBox(const QString &title, const MTPChatPhoto &pho left += _userWidth; } - h += st::confirmInviteUserHeight; + newHeight += st::confirmInviteUserHeight; } - setMaxHeight(h); - - connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); - connect(_join, SIGNAL(clicked()), App::main(), SLOT(onInviteImport())); + setDimensions(st::boxWideWidth, newHeight); } void ConfirmInviteBox::resizeEvent(QResizeEvent *e) { + BoxContent::resizeEvent(e); _title->move((width() - _title->width()) / 2, st::confirmInviteTitleTop); _status->move((width() - _status->width()) / 2, st::confirmInviteStatusTop); - _join->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _join->height()); - _cancel->moveToRight(st::boxButtonPadding.right() + _join->width() + st::boxButtonPadding.left(), _join->y()); - AbstractBox::resizeEvent(e); } void ConfirmInviteBox::paintEvent(QPaintEvent *e) { - AbstractBox::paintEvent(e); + BoxContent::paintEvent(e); Painter p(this); diff --git a/Telegram/SourceFiles/boxes/confirmbox.h b/Telegram/SourceFiles/boxes/confirmbox.h index f926a81aa..52ed7ee73 100644 --- a/Telegram/SourceFiles/boxes/confirmbox.h +++ b/Telegram/SourceFiles/boxes/confirmbox.h @@ -24,138 +24,88 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org namespace Ui { class Checkbox; -class RoundButton; class FlatLabel; } // namespace Ui -namespace st { -extern const style::RoundButton &defaultBoxButton; -extern const style::RoundButton &cancelBoxButton; -} // namespace style - class InformBox; -class ConfirmBox : public AbstractBox, public ClickHandlerHost { - Q_OBJECT - +class ConfirmBox : public BoxContent, public ClickHandlerHost { public: - ConfirmBox(const QString &text, const QString &doneText = QString(), const style::RoundButton &doneStyle = st::defaultBoxButton, const QString &cancelText = QString(), const style::RoundButton &cancelStyle = st::cancelBoxButton); + ConfirmBox(QWidget*, const QString &text, base::lambda &&confirmedCallback = base::lambda(), base::lambda &&cancelledCallback = base::lambda()); + ConfirmBox(QWidget*, const QString &text, const QString &confirmText, base::lambda &&confirmedCallback = base::lambda(), base::lambda &&cancelledCallback = base::lambda()); + ConfirmBox(QWidget*, const QString &text, const QString &confirmText, const style::RoundButton &confirmStyle, base::lambda &&confirmedCallback = base::lambda(), base::lambda &&cancelledCallback = base::lambda()); + ConfirmBox(QWidget*, const QString &text, const QString &confirmText, const QString &cancelText, base::lambda &&confirmedCallback = base::lambda(), base::lambda &&cancelledCallback = base::lambda()); + ConfirmBox(QWidget*, const QString &text, const QString &confirmText, const style::RoundButton &confirmStyle, const QString &cancelText, base::lambda &&confirmedCallback = base::lambda(), base::lambda &&cancelledCallback = base::lambda()); void updateLink(); - // You can use this instead of connecting to "confirmed()" signal. - void setConfirmedCallback(base::lambda &&callback) { - _confirmedCallback = std_::move(callback); + // If strict cancel is set the cancelledCallback is only called if the cancel button was pressed. + void setStrictCancel(bool strictCancel) { + _strictCancel = strictCancel; } // ClickHandlerHost interface void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override; void clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) override; -public slots: - void onCancel(); - -signals: - void confirmed(); - void cancelled(); - void cancelPressed(); + void closeHook() override; protected: + void prepare() override; + void keyPressEvent(QKeyEvent *e) override; void paintEvent(QPaintEvent *e) override; - void resizeEvent(QResizeEvent *e) override; void mouseMoveEvent(QMouseEvent *e) override; void mousePressEvent(QMouseEvent *e) override; void mouseReleaseEvent(QMouseEvent *e) override; void leaveEvent(QEvent *e) override; - void closePressed() override; - -private slots: - void onConfirmPressed(); - private: - ConfirmBox(const QString &text, const QString &doneText, const style::RoundButton &doneStyle, bool informative); + struct InformBoxTag { + }; + ConfirmBox(const InformBoxTag &, const QString &text, const QString &doneText, base::lambda_copy &&closedCallback); friend class InformBox; + void confirmed(); void init(const QString &text); - void onTextUpdated(); + void textUpdated(); - bool _informative; + QString _confirmText; + QString _cancelText; + const style::RoundButton &_confirmStyle; + bool _informative = false; Text _text; - int32 _textWidth, _textHeight; + int _textWidth = 0; + int _textHeight = 0; void updateHover(); QPoint _lastMousePos; - ChildWidget _confirm; - ChildWidget _cancel; - + bool _confirmed = false; + bool _cancelled = false; + bool _strictCancel = false; base::lambda _confirmedCallback; + base::lambda _cancelledCallback; }; class InformBox : public ConfirmBox { public: - InformBox(const QString &text, const QString &doneText = QString(), const style::RoundButton &doneStyle = st::defaultBoxButton) : ConfirmBox(text, doneText, doneStyle, true) { + InformBox(QWidget*, const QString &text, base::lambda_copy &&closedCallback = base::lambda_copy()) : ConfirmBox(ConfirmBox::InformBoxTag(), text, QString(), std_::move(closedCallback)) { + } + InformBox(QWidget*, const QString &text, const QString &doneText, base::lambda_copy &&closedCallback = base::lambda_copy()) : ConfirmBox(ConfirmBox::InformBoxTag(), text, doneText, std_::move(closedCallback)) { } }; -class SharePhoneConfirmBox : public ConfirmBox { - Q_OBJECT - +class MaxInviteBox : public BoxContent { public: - SharePhoneConfirmBox(PeerData *recipient); - -signals: - void confirmed(PeerData *recipient); - -private slots: - void onConfirm(); - -private: - PeerData *_recipient; - -}; - -class ConfirmLinkBox : public ConfirmBox { - Q_OBJECT - -public: - ConfirmLinkBox(const QString &url); - -public slots: - void onOpenLink(); - -private: - QString _url; - -}; - -class ConfirmBotGameBox : public ConfirmBox { - Q_OBJECT - -public: - ConfirmBotGameBox(UserData *bot, const QString &url); - -public slots: - void onOpenLink(); - -private: - UserData *_bot; - QString _url; - -}; - -class MaxInviteBox : public AbstractBox { - Q_OBJECT - -public: - MaxInviteBox(const QString &link); + MaxInviteBox(QWidget*, const QString &link); protected: + void prepare() override; + void paintEvent(QPaintEvent *e) override; void resizeEvent(QResizeEvent *e) override; void mouseMoveEvent(QMouseEvent *e) override; @@ -165,8 +115,6 @@ protected: private: void updateSelected(const QPoint &cursorGlobalPosition); - ChildWidget _close; - Text _text; int32 _textWidth, _textHeight; @@ -176,26 +124,20 @@ private: QPoint _lastMousePos; - QString _goodTextLink; - Animation _a_goodOpacity; - }; -class ConvertToSupergroupBox : public AbstractBox, public RPCSender { - Q_OBJECT - +class ConvertToSupergroupBox : public BoxContent, public RPCSender { public: - ConvertToSupergroupBox(ChatData *chat); - -public slots: - void onConvert(); + ConvertToSupergroupBox(QWidget*, ChatData *chat); protected: + void prepare() override; + void keyPressEvent(QKeyEvent *e) override; void paintEvent(QPaintEvent *e) override; - void resizeEvent(QResizeEvent *e) override; private: + void convertToSupergroup(); void convertDone(const MTPUpdates &updates); bool convertFail(const RPCError &error); @@ -203,100 +145,71 @@ private: Text _text, _note; int32 _textWidth, _textHeight; - ChildWidget _convert; - ChildWidget _cancel; - }; -class PinMessageBox : public AbstractBox, public RPCSender { - Q_OBJECT - +class PinMessageBox : public BoxContent, public RPCSender { public: - PinMessageBox(ChannelData *channel, MsgId msgId); - -public slots: - void onPin(); + PinMessageBox(QWidget*, ChannelData *channel, MsgId msgId); protected: + void prepare() override; + void resizeEvent(QResizeEvent *e) override; private: + void pinMessage(); void pinDone(const MTPUpdates &updates); bool pinFail(const RPCError &error); ChannelData *_channel; MsgId _msgId; - ChildWidget _text; - ChildWidget _notify; - - ChildWidget _pin; - ChildWidget _cancel; + object_ptr _text; + object_ptr _notify; mtpRequestId _requestId = 0; }; -class RichDeleteMessageBox : public AbstractBox, public RPCSender { - Q_OBJECT - +class RichDeleteMessageBox : public BoxContent, public RPCSender { public: - RichDeleteMessageBox(ChannelData *channel, UserData *from, MsgId msgId); - -public slots: - void onDelete(); + RichDeleteMessageBox(QWidget*, ChannelData *channel, UserData *from, MsgId msgId); protected: + void prepare() override; + void resizeEvent(QResizeEvent *e) override; private: + void deleteAndClear(); + ChannelData *_channel; UserData *_from; MsgId _msgId; - ChildWidget _text; - ChildWidget _banUser; - ChildWidget _reportSpam; - ChildWidget _deleteAll; - - ChildWidget _delete; - ChildWidget _cancel; + object_ptr _text; + object_ptr _banUser; + object_ptr _reportSpam; + object_ptr _deleteAll; }; -class KickMemberBox : public ConfirmBox { - Q_OBJECT - +class ConfirmInviteBox : public BoxContent, public RPCSender { public: - KickMemberBox(PeerData *chat, UserData *member); - -private slots: - void onConfirm(); - -private: - PeerData *_chat; - UserData *_member; - -}; - -class ConfirmInviteBox : public AbstractBox, public RPCSender { - Q_OBJECT - -public: - ConfirmInviteBox(const QString &title, const MTPChatPhoto &photo, int count, const QVector &participants); + ConfirmInviteBox(QWidget*, const QString &title, const MTPChatPhoto &photo, int count, const QVector &participants); protected: + void prepare() override; + void resizeEvent(QResizeEvent *e) override; void paintEvent(QPaintEvent *e) override; private: - ChildWidget _title; - ChildWidget _status; + object_ptr _title; + object_ptr _status; ImagePtr _photo; QVector _participants; - ChildWidget _join; - ChildWidget _cancel; int _userWidth = 0; }; diff --git a/Telegram/SourceFiles/boxes/confirmphonebox.cpp b/Telegram/SourceFiles/boxes/confirmphonebox.cpp index 1a636c4e0..16235fd83 100644 --- a/Telegram/SourceFiles/boxes/confirmphonebox.cpp +++ b/Telegram/SourceFiles/boxes/confirmphonebox.cpp @@ -31,24 +31,30 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org namespace { -QPointer CurrentConfirmPhoneBox = nullptr; +object_ptr CurrentConfirmPhoneBox = { nullptr }; } // namespace void ConfirmPhoneBox::start(const QString &phone, const QString &hash) { - if (CurrentConfirmPhoneBox) { - if (CurrentConfirmPhoneBox->getPhone() == phone) return; - delete CurrentConfirmPhoneBox; + if (CurrentConfirmPhoneBox && CurrentConfirmPhoneBox->getPhone() != phone) { + CurrentConfirmPhoneBox.destroyDelayed(); } - if (auto main = App::main()) { - CurrentConfirmPhoneBox = new ConfirmPhoneBox(main, phone, hash); + if (!CurrentConfirmPhoneBox) { + CurrentConfirmPhoneBox = Box(phone, hash); } + CurrentConfirmPhoneBox->checkPhoneAndHash(); } -ConfirmPhoneBox::ConfirmPhoneBox(QWidget *parent, const QString &phone, const QString &hash) : AbstractBox(st::boxWidth, lang(lng_confirm_phone_title)) -, _phone(phone) -, _hash(hash) { - setParent(parent); +ConfirmPhoneBox::ConfirmPhoneBox(QWidget*, const QString &phone, const QString &hash) +: _phone(phone) +, _hash(hash) +, _callTimer(this) { +} + +void ConfirmPhoneBox::checkPhoneAndHash() { + if (_sendCodeRequestId) { + return; + } MTPaccount_SendConfirmPhoneCode::Flags flags = 0; _sendCodeRequestId = MTP::send(MTPaccount_SendConfirmPhoneCode(MTP_flags(flags), MTP_string(_hash), MTPBool()), rpcDone(&ConfirmPhoneBox::sendCodeDone), rpcFail(&ConfirmPhoneBox::sendCodeFail)); @@ -83,20 +89,28 @@ bool ConfirmPhoneBox::sendCodeFail(const RPCError &error) { errorText = lang(lng_confirm_phone_link_invalid); } _sendCodeRequestId = 0; - Ui::showLayer(new InformBox(errorText)); - deleteLater(); + Ui::show(Box(errorText)); + if (this == CurrentConfirmPhoneBox) { + CurrentConfirmPhoneBox.destroyDelayed(); + } else { + deleteLater(); + } return true; } void ConfirmPhoneBox::setCallStatus(const CallStatus &status) { _callStatus = status; if (_callStatus.state == CallState::Waiting) { - _callTimer.start(1000); + _callTimer->start(1000); } } void ConfirmPhoneBox::launch() { - setBlockTitle(true); + if (!CurrentConfirmPhoneBox) return; + Ui::show(std_::move(CurrentConfirmPhoneBox)); +} + +void ConfirmPhoneBox::prepare() { _about.create(this, st::confirmPhoneAboutLabel); TextWithEntities aboutText; @@ -110,30 +124,26 @@ void ConfirmPhoneBox::launch() { _code.create(this, st::confirmPhoneCodeField, lang(lng_code_ph)); - _send.create(this, lang(lng_confirm_phone_send), st::defaultBoxButton); - _cancel.create(this, lang(lng_cancel), st::cancelBoxButton); + setTitle(lang(lng_confirm_phone_title)); - setMaxHeight(titleHeight() + st::usernamePadding.top() + _code->height() + st::usernameSkip + _about->height() + st::usernameSkip + _send->height() + st::boxButtonPadding.bottom()); + addButton(lang(lng_confirm_phone_send), [this] { onSendCode(); }); + addButton(lang(lng_cancel), [this] { closeBox(); }); - connect(_send, SIGNAL(clicked()), this, SLOT(onSendCode())); - connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); + setDimensions(st::boxWidth, st::usernamePadding.top() + _code->height() + st::usernameSkip + _about->height() + st::usernameSkip); connect(_code, SIGNAL(changed()), this, SLOT(onCodeChanged())); connect(_code, SIGNAL(submitted(bool)), this, SLOT(onSendCode())); - connect(&_callTimer, SIGNAL(timeout()), this, SLOT(onCallStatusTimer())); + connect(_callTimer, SIGNAL(timeout()), this, SLOT(onCallStatusTimer())); showChildren(); - raiseShadow(); - - Ui::showLayer(this); } void ConfirmPhoneBox::onCallStatusTimer() { if (_callStatus.state == CallState::Waiting) { if (--_callStatus.timeout <= 0) { _callStatus.state = CallState::Calling; - _callTimer.stop(); + _callTimer->stop(); MTP::send(MTPauth_ResendCode(MTP_string(_phone), MTP_string(_phoneHash)), rpcDone(&ConfirmPhoneBox::callDone)); } } @@ -167,7 +177,7 @@ void ConfirmPhoneBox::onSendCode() { void ConfirmPhoneBox::confirmDone(const MTPBool &result) { _sendCodeRequestId = 0; - Ui::showLayer(new InformBox(lng_confirm_phone_success(lt_phone, App::formatPhone(_phone)))); + Ui::show(Box(lng_confirm_phone_success(lt_phone, App::formatPhone(_phone)))); } bool ConfirmPhoneBox::confirmFail(const RPCError &error) { @@ -248,7 +258,7 @@ void ConfirmPhoneBox::showError(const QString &error) { } void ConfirmPhoneBox::paintEvent(QPaintEvent *e) { - AbstractBox::paintEvent(e); + BoxContent::paintEvent(e); Painter p(this); @@ -291,18 +301,15 @@ QString ConfirmPhoneBox::getCallText() const { } void ConfirmPhoneBox::resizeEvent(QResizeEvent *e) { + BoxContent::resizeEvent(e); + _code->resize(width() - st::usernamePadding.left() - st::usernamePadding.right(), _code->height()); - _code->moveToLeft(st::usernamePadding.left(), titleHeight() + st::usernamePadding.top()); + _code->moveToLeft(st::usernamePadding.left(), st::usernamePadding.top()); _about->moveToLeft(st::usernamePadding.left(), _code->y() + _code->height() + st::usernameSkip); - - _send->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _send->height()); - _cancel->moveToRight(st::boxButtonPadding.right() + _send->width() + st::boxButtonPadding.left(), _send->y()); - - AbstractBox::resizeEvent(e); } -void ConfirmPhoneBox::doSetInnerFocus() { +void ConfirmPhoneBox::setInnerFocus() { _code->setFocus(); } diff --git a/Telegram/SourceFiles/boxes/confirmphonebox.h b/Telegram/SourceFiles/boxes/confirmphonebox.h index 915aa4a5c..87c7803cf 100644 --- a/Telegram/SourceFiles/boxes/confirmphonebox.h +++ b/Telegram/SourceFiles/boxes/confirmphonebox.h @@ -24,11 +24,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org namespace Ui { class InputField; -class RoundButton; class FlatLabel; } // namespace Ui -class ConfirmPhoneBox : public AbstractBox, public RPCSender { +class ConfirmPhoneBox : public BoxContent, public RPCSender { Q_OBJECT public: @@ -42,12 +41,18 @@ private slots: void onCodeChanged(); protected: + void prepare() override; + void setInnerFocus() override; + void paintEvent(QPaintEvent *e) override; void resizeEvent(QResizeEvent *e) override; - void doSetInnerFocus() override; private: - ConfirmPhoneBox(QWidget *parent, const QString &phone, const QString &hash); + ConfirmPhoneBox(QWidget*, const QString &phone, const QString &hash); + friend class object_ptr; + + void checkPhoneAndHash(); + void sendCodeDone(const MTPauth_SentCode &result); bool sendCodeFail(const RPCError &error); @@ -88,16 +93,14 @@ private: mtpRequestId _checkCodeRequestId = 0; - ChildWidget _about = { nullptr }; - ChildWidget _send = { nullptr }; - ChildWidget _cancel = { nullptr }; - ChildWidget _code = { nullptr }; + object_ptr _about = { nullptr }; + object_ptr _code = { nullptr }; // Flag for not calling onTextChanged() recursively. bool _fixing = false; QString _error; CallStatus _callStatus; - QTimer _callTimer; + object_ptr _callTimer; }; diff --git a/Telegram/SourceFiles/boxes/connectionbox.cpp b/Telegram/SourceFiles/boxes/connectionbox.cpp index 6e458050d..e325ee9ac 100644 --- a/Telegram/SourceFiles/boxes/connectionbox.cpp +++ b/Telegram/SourceFiles/boxes/connectionbox.cpp @@ -31,20 +31,22 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "history/history_location_manager.h" #include "styles/style_boxes.h" -ConnectionBox::ConnectionBox() : AbstractBox(st::boxWidth, lang(lng_connection_header)) -, _hostInput(this, st::connectionHostInputField, lang(lng_connection_host_ph), Global::ConnectionProxy().host) +ConnectionBox::ConnectionBox(QWidget *parent) +: _hostInput(this, st::connectionHostInputField, lang(lng_connection_host_ph), Global::ConnectionProxy().host) , _portInput(this, st::connectionPortInputField, lang(lng_connection_port_ph), QString::number(Global::ConnectionProxy().port)) , _userInput(this, st::connectionUserInputField, lang(lng_connection_user_ph), Global::ConnectionProxy().user) , _passwordInput(this, st::connectionPasswordInputField, lang(lng_connection_password_ph), Global::ConnectionProxy().password) , _autoRadio(this, qsl("conn_type"), dbictAuto, lang(lng_connection_auto_rb), (Global::ConnectionType() == dbictAuto), st::defaultBoxCheckbox) , _httpProxyRadio(this, qsl("conn_type"), dbictHttpProxy, lang(lng_connection_http_proxy_rb), (Global::ConnectionType() == dbictHttpProxy), st::defaultBoxCheckbox) , _tcpProxyRadio(this, qsl("conn_type"), dbictTcpProxy, lang(lng_connection_tcp_proxy_rb), (Global::ConnectionType() == dbictTcpProxy), st::defaultBoxCheckbox) -, _tryIPv6(this, lang(lng_connection_try_ipv6), Global::TryIPv6(), st::defaultBoxCheckbox) -, _save(this, lang(lng_connection_save), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) { +, _tryIPv6(this, lang(lng_connection_try_ipv6), Global::TryIPv6(), st::defaultBoxCheckbox) { +} - connect(_save, SIGNAL(clicked()), this, SLOT(onSave())); - connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); +void ConnectionBox::prepare() { + setTitle(lang(lng_connection_header)); + + addButton(lang(lng_connection_save), [this] { onSave(); }); + addButton(lang(lng_cancel), [this] { closeBox(); }); connect(_autoRadio, SIGNAL(changed()), this, SLOT(onChange())); connect(_httpProxyRadio, SIGNAL(changed()), this, SLOT(onChange())); @@ -59,9 +61,9 @@ ConnectionBox::ConnectionBox() : AbstractBox(st::boxWidth, lang(lng_connection_h } void ConnectionBox::updateControlsVisibility() { - int32 h = titleHeight() + st::boxOptionListPadding.top() + _autoRadio->heightNoMargins() + st::boxOptionListPadding.top() + _httpProxyRadio->heightNoMargins() + st::boxOptionListPadding.top() + _tcpProxyRadio->heightNoMargins() + st::boxOptionListPadding.top() + st::connectionIPv6Skip + _tryIPv6->heightNoMargins() + st::boxOptionListPadding.bottom() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom(); + auto newHeight = st::boxOptionListPadding.top() + _autoRadio->heightNoMargins() + st::boxOptionListSkip + _httpProxyRadio->heightNoMargins() + st::boxOptionListSkip + _tcpProxyRadio->heightNoMargins() + st::boxOptionListSkip + st::connectionIPv6Skip + _tryIPv6->heightNoMargins() + st::boxOptionListPadding.bottom() + st::boxPadding.bottom(); if (_httpProxyRadio->checked() || _tcpProxyRadio->checked()) { - h += 2 * st::boxOptionInputSkip + 2 * _hostInput->height(); + newHeight += 2 * st::boxOptionInputSkip + 2 * _hostInput->height(); _hostInput->show(); _portInput->show(); _userInput->show(); @@ -73,26 +75,32 @@ void ConnectionBox::updateControlsVisibility() { _passwordInput->hide(); } - setMaxHeight(h); - resizeEvent(0); + setDimensions(st::boxWidth, newHeight); + updateControlsPosition(); } -void ConnectionBox::doSetInnerFocus() { +void ConnectionBox::setInnerFocus() { if (!_hostInput->isHidden()) { _hostInput->setFocus(); } } void ConnectionBox::resizeEvent(QResizeEvent *e) { - _autoRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), titleHeight() + st::boxOptionListPadding.top()); - _httpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _autoRadio->bottomNoMargins() + st::boxOptionListPadding.top()); + BoxContent::resizeEvent(e); + + updateControlsPosition(); +} + +void ConnectionBox::updateControlsPosition() { + _autoRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), st::boxOptionListPadding.top()); + _httpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _autoRadio->bottomNoMargins() + st::boxOptionListSkip); int32 inputy = 0; if (_httpProxyRadio->checked()) { inputy = _httpProxyRadio->bottomNoMargins() + st::boxOptionInputSkip; - _tcpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), inputy + st::boxOptionInputSkip + 2 * _hostInput->height() + st::boxOptionListPadding.top()); + _tcpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), inputy + st::boxOptionInputSkip + 2 * _hostInput->height() + st::boxOptionListSkip); } else { - _tcpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _httpProxyRadio->bottomNoMargins() + st::boxOptionListPadding.top()); + _tcpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _httpProxyRadio->bottomNoMargins() + st::boxOptionListSkip); if (_tcpProxyRadio->checked()) { inputy = _tcpProxyRadio->bottomNoMargins() + st::boxOptionInputSkip; } @@ -105,13 +113,8 @@ void ConnectionBox::resizeEvent(QResizeEvent *e) { _passwordInput->moveToRight(st::boxPadding.right(), _userInput->y()); } - int32 tryipv6y = (_tcpProxyRadio->checked() ? _userInput->bottomNoMargins() : _tcpProxyRadio->bottomNoMargins()) + st::boxOptionListPadding.top() + st::connectionIPv6Skip; + auto tryipv6y = (_tcpProxyRadio->checked() ? _userInput->bottomNoMargins() : _tcpProxyRadio->bottomNoMargins()) + st::boxOptionListSkip + st::connectionIPv6Skip; _tryIPv6->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), tryipv6y); - - _save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height()); - _cancel->moveToRight(st::boxButtonPadding.right() + _save->width() + st::boxButtonPadding.left(), _save->y()); - - AbstractBox::resizeEvent(e); } void ConnectionBox::onChange() { @@ -195,55 +198,52 @@ void ConnectionBox::onSave() { MTP::restart(); reinitLocationManager(); reinitWebLoadManager(); - onClose(); + closeBox(); } } -AutoDownloadBox::AutoDownloadBox() : AbstractBox(st::boxWidth) -, _photoPrivate(this, lang(lng_media_auto_private_chats), !(cAutoDownloadPhoto() & dbiadNoPrivate), st::defaultBoxCheckbox) +AutoDownloadBox::AutoDownloadBox(QWidget *parent) +: _photoPrivate(this, lang(lng_media_auto_private_chats), !(cAutoDownloadPhoto() & dbiadNoPrivate), st::defaultBoxCheckbox) , _photoGroups(this, lang(lng_media_auto_groups), !(cAutoDownloadPhoto() & dbiadNoGroups), st::defaultBoxCheckbox) , _audioPrivate(this, lang(lng_media_auto_private_chats), !(cAutoDownloadAudio() & dbiadNoPrivate), st::defaultBoxCheckbox) , _audioGroups(this, lang(lng_media_auto_groups), !(cAutoDownloadAudio() & dbiadNoGroups), st::defaultBoxCheckbox) , _gifPrivate(this, lang(lng_media_auto_private_chats), !(cAutoDownloadGif() & dbiadNoPrivate), st::defaultBoxCheckbox) , _gifGroups(this, lang(lng_media_auto_groups), !(cAutoDownloadGif() & dbiadNoGroups), st::defaultBoxCheckbox) , _gifPlay(this, lang(lng_media_auto_play), cAutoPlayGif(), st::defaultBoxCheckbox) -, _sectionHeight(titleHeight() + 2 * (st::defaultBoxCheckbox.height + st::setLittleSkip)) -, _save(this, lang(lng_connection_save), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) { +, _sectionHeight(st::boxTitleHeight + 2 * (st::defaultBoxCheckbox.height + st::setLittleSkip)) { +} - setMaxHeight(3 * _sectionHeight + st::setLittleSkip + _gifPlay->heightNoMargins() + st::setLittleSkip + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom()); +void AutoDownloadBox::prepare() { + addButton(lang(lng_connection_save), [this] { onSave(); }); + addButton(lang(lng_cancel), [this] { closeBox(); }); - connect(_save, SIGNAL(clicked()), this, SLOT(onSave())); - connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); + setDimensions(st::boxWidth, 3 * _sectionHeight + st::setLittleSkip + _gifPlay->heightNoMargins() + st::setLittleSkip); } void AutoDownloadBox::paintEvent(QPaintEvent *e) { - AbstractBox::paintEvent(e); + BoxContent::paintEvent(e); Painter p(this); - p.setPen(st::boxTextFg); - p.setFont(st::semiboldFont); - p.drawTextLeft(st::boxTitlePosition.x(), st::boxTitlePosition.y(), width(), lang(lng_media_auto_photo)); - p.drawTextLeft(st::boxTitlePosition.x(), _sectionHeight + st::boxTitlePosition.y(), width(), lang(lng_media_auto_audio)); - p.drawTextLeft(st::boxTitlePosition.x(), 2 * _sectionHeight + st::boxTitlePosition.y(), width(), lang(lng_media_auto_gif)); + p.setPen(st::boxTitleFg); + p.setFont(st::autoDownloadTitleFont); + p.drawTextLeft(st::autoDownloadTitlePosition.x(), st::autoDownloadTitlePosition.y(), width(), lang(lng_media_auto_photo)); + p.drawTextLeft(st::autoDownloadTitlePosition.x(), _sectionHeight + st::autoDownloadTitlePosition.y(), width(), lang(lng_media_auto_audio)); + p.drawTextLeft(st::autoDownloadTitlePosition.x(), 2 * _sectionHeight + st::autoDownloadTitlePosition.y(), width(), lang(lng_media_auto_gif)); } void AutoDownloadBox::resizeEvent(QResizeEvent *e) { - _photoPrivate->moveToLeft(st::boxTitlePosition.x(), titleHeight() + st::setLittleSkip); + BoxContent::resizeEvent(e); + + _photoPrivate->moveToLeft(st::boxTitlePosition.x(), st::boxTitleHeight + st::setLittleSkip); _photoGroups->moveToLeft(st::boxTitlePosition.x(), _photoPrivate->bottomNoMargins() + st::setLittleSkip); - _audioPrivate->moveToLeft(st::boxTitlePosition.x(), _sectionHeight + titleHeight() + st::setLittleSkip); + _audioPrivate->moveToLeft(st::boxTitlePosition.x(), _sectionHeight + st::boxTitleHeight + st::setLittleSkip); _audioGroups->moveToLeft(st::boxTitlePosition.x(), _audioPrivate->bottomNoMargins() + st::setLittleSkip); - _gifPrivate->moveToLeft(st::boxTitlePosition.x(), 2 * _sectionHeight + titleHeight() + st::setLittleSkip); + _gifPrivate->moveToLeft(st::boxTitlePosition.x(), 2 * _sectionHeight + st::boxTitleHeight + st::setLittleSkip); _gifGroups->moveToLeft(st::boxTitlePosition.x(), _gifPrivate->bottomNoMargins() + st::setLittleSkip); _gifPlay->moveToLeft(st::boxTitlePosition.x(), _gifGroups->bottomNoMargins() + st::setLittleSkip); - - _save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height()); - _cancel->moveToRight(st::boxButtonPadding.right() + _save->width() + st::boxButtonPadding.left(), _save->y()); - - AbstractBox::resizeEvent(e); } void AutoDownloadBox::onSave() { @@ -299,5 +299,5 @@ void AutoDownloadBox::onSave() { changed = true; } if (changed) Local::writeUserSettings(); - onClose(); + closeBox(); } diff --git a/Telegram/SourceFiles/boxes/connectionbox.h b/Telegram/SourceFiles/boxes/connectionbox.h index 546b1f154..e9982ccb8 100644 --- a/Telegram/SourceFiles/boxes/connectionbox.h +++ b/Telegram/SourceFiles/boxes/connectionbox.h @@ -28,67 +28,64 @@ class PortInput; class PasswordInput; class Checkbox; class Radiobutton; -class RoundButton; } // namespace Ui -class ConnectionBox : public AbstractBox { +class ConnectionBox : public BoxContent { Q_OBJECT public: - ConnectionBox(); + ConnectionBox(QWidget *parent); -public slots: +protected: + void prepare() override; + void setInnerFocus() override; + + void resizeEvent(QResizeEvent *e) override; + +private slots: void onChange(); void onSubmit(); void onSave(); -protected: - void resizeEvent(QResizeEvent *e) override; - - void doSetInnerFocus() override; - private: void updateControlsVisibility(); + void updateControlsPosition(); - ChildWidget _hostInput; - ChildWidget _portInput; - ChildWidget _userInput; - ChildWidget _passwordInput; - ChildWidget _autoRadio; - ChildWidget _httpProxyRadio; - ChildWidget _tcpProxyRadio; - ChildWidget _tryIPv6; - - ChildWidget _save; - ChildWidget _cancel; + object_ptr _hostInput; + object_ptr _portInput; + object_ptr _userInput; + object_ptr _passwordInput; + object_ptr _autoRadio; + object_ptr _httpProxyRadio; + object_ptr _tcpProxyRadio; + object_ptr _tryIPv6; }; -class AutoDownloadBox : public AbstractBox { +class AutoDownloadBox : public BoxContent { Q_OBJECT public: - AutoDownloadBox(); - -public slots: - void onSave(); + AutoDownloadBox(QWidget *parent); protected: + void prepare() override; + void paintEvent(QPaintEvent *e) override; void resizeEvent(QResizeEvent *e) override; +private slots: + void onSave(); + private: - ChildWidget _photoPrivate; - ChildWidget _photoGroups; - ChildWidget _audioPrivate; - ChildWidget _audioGroups; - ChildWidget _gifPrivate; - ChildWidget _gifGroups; - ChildWidget _gifPlay; + object_ptr _photoPrivate; + object_ptr _photoGroups; + object_ptr _audioPrivate; + object_ptr _audioGroups; + object_ptr _gifPrivate; + object_ptr _gifGroups; + object_ptr _gifPlay; - int _sectionHeight; - - ChildWidget _save; - ChildWidget _cancel; + int _sectionHeight = 0; }; diff --git a/Telegram/SourceFiles/boxes/contactsbox.cpp b/Telegram/SourceFiles/boxes/contactsbox.cpp index 9d2c00e39..4678340d6 100644 --- a/Telegram/SourceFiles/boxes/contactsbox.cpp +++ b/Telegram/SourceFiles/boxes/contactsbox.cpp @@ -47,76 +47,84 @@ QString cantInviteError() { return lng_cant_invite_not_contact(lt_more_info, textcmdLink(qsl("https://telegram.me/spambot"), lang(lng_cant_more_info))); } -ContactsBox::ContactsBox() : ItemListBox(st::contactsScroll) -, _inner(this, CreatingGroupNone) -, _select(this, new Ui::MultiSelect(this, st::contactsMultiSelect, lang(lng_participant_filter)), QMargins(0, 0, 0, 0), [this] { updateScrollSkips(); }) -, _next(this, lang(lng_create_group_next), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) -, _topShadow(this) { - init(); +ContactsBox::ContactsBox(QWidget*, ChatData *chat, MembersFilter filter) +: _chat(chat) +, _membersFilter(filter) +, _select(createMultiSelect()) +, _searchTimer(this) { } -ContactsBox::ContactsBox(const QString &name, const QImage &photo) : ItemListBox(st::boxScroll) -, _inner(this, CreatingGroupGroup) -, _select(this, new Ui::MultiSelect(this, st::contactsMultiSelect, lang(lng_participant_filter)), QMargins(0, 0, 0, 0), [this] { updateScrollSkips(); }) -, _next(this, lang(lng_create_group_create), st::defaultBoxButton) -, _cancel(this, lang(lng_create_group_back), st::cancelBoxButton) -, _topShadow(this) +ContactsBox::ContactsBox(QWidget*, ChannelData *channel) +: _creating(CreatingGroupChannel) +, _channel(channel) +, _select(createMultiSelect()) +, _searchTimer(this) { +} + +ContactsBox::ContactsBox(QWidget*, ChannelData *channel, MembersFilter filter, const MembersAlreadyIn &already) +: _channel(channel) +, _membersFilter(filter) +, _alreadyIn(already) +, _select(createMultiSelect()) +, _searchTimer(this) { +} + +ContactsBox::ContactsBox(QWidget*, UserData *bot) +: _bot(bot) +, _select(createMultiSelect()) +, _searchTimer(this) { +} + +ContactsBox::ContactsBox(QWidget*, const QString &name, const QImage &photo) +: _creating(CreatingGroupGroup) +, _select(createMultiSelect()) +, _searchTimer(this) , _creationName(name) , _creationPhoto(photo) { - init(); } -ContactsBox::ContactsBox(ChannelData *channel) : ItemListBox(st::boxScroll) -, _inner(this, channel, MembersFilter::Recent, MembersAlreadyIn()) -, _select(this, new Ui::MultiSelect(this, st::contactsMultiSelect, lang(lng_participant_filter)), QMargins(0, 0, 0, 0), [this] { updateScrollSkips(); }) -, _next(this, lang(lng_participant_invite), st::defaultBoxButton) -, _cancel(this, lang(lng_create_group_skip), st::cancelBoxButton) -, _topShadow(this) { - init(); +ContactsBox::ContactsBox(QWidget*) +: _select(createMultiSelect()) +, _searchTimer(this) { } -ContactsBox::ContactsBox(ChannelData *channel, MembersFilter filter, const MembersAlreadyIn &already) : ItemListBox((filter == MembersFilter::Admins) ? st::contactsScroll : st::boxScroll) -, _inner(this, channel, filter, already) -, _select(this, new Ui::MultiSelect(this, st::contactsMultiSelect, lang(lng_participant_filter)), QMargins(0, 0, 0, 0), [this] { updateScrollSkips(); }) -, _next(this, lang(lng_participant_invite), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) -, _topShadow(this) { - init(); -} - -ContactsBox::ContactsBox(ChatData *chat, MembersFilter filter) : ItemListBox(st::boxScroll) -, _inner(this, chat, filter) -, _select(this, new Ui::MultiSelect(this, st::contactsMultiSelect, lang(lng_participant_filter)), QMargins(0, 0, 0, 0), [this] { updateScrollSkips(); }) -, _next(this, lang((filter == MembersFilter::Admins) ? lng_settings_save : lng_participant_invite), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) -, _topShadow(this) { - init(); -} - -ContactsBox::ContactsBox(UserData *bot) : ItemListBox(st::contactsScroll) -, _inner(this, bot) -, _select(this, new Ui::MultiSelect(this, st::contactsMultiSelect, lang(lng_participant_filter)), QMargins(0, 0, 0, 0), [this] { updateScrollSkips(); }) -, _next(this, lang(lng_create_group_next), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) -, _topShadow(this) { - init(); -} - -void ContactsBox::init() { +void ContactsBox::prepare() { _select->resizeToWidth(st::boxWideWidth); myEnsureResized(_select); - auto inviting = (_inner->creating() == CreatingGroupGroup) || (_inner->channel() && _inner->membersFilter() == MembersFilter::Recent) || _inner->chat(); - auto topSkip = getTopScrollSkip(); - auto bottomSkip = inviting ? (st::boxButtonPadding.top() + _next->height() + st::boxButtonPadding.bottom()) : st::boxScrollSkip; - ItemListBox::init(_inner, bottomSkip, topSkip); + auto createInner = [this] { + if (_chat) { + return object_ptr(this, _chat, _membersFilter); + } else if (_channel) { + return object_ptr(this, _channel, _membersFilter, _alreadyIn); + } else if (_bot) { + return object_ptr(this, _bot); + } + return object_ptr(this, _creating); + }; + _inner = setInnerWidget(createInner(), getTopScrollSkip()); - if (_inner->creating() == CreatingGroupNone && !_inner->chat() && !_inner->channel() && !_inner->bot()) { - _add.create(this, st::contactsAdd); - _add->setClickedCallback([] { - App::wnd()->onShowAddContact(); - }); + updateTitle(); + if (_chat) { + if (_membersFilter == MembersFilter::Admins) { + addButton(lang(lng_settings_save), [this] { saveChatAdmins(); }); + } else { + addButton(lang(lng_participant_invite), [this] { inviteParticipants(); }); + } + addButton(lang(lng_cancel), [this] { closeBox(); }); + } else if (_channel) { + if (_membersFilter != MembersFilter::Admins) { + addButton(lang(lng_participant_invite), [this] { inviteParticipants(); }); + } + addButton(lang((_creating == CreatingGroupChannel) ? lng_create_group_skip : lng_cancel), [this] { closeBox(); }); + } else if (_bot) { + addButton(lang(lng_close), [this] { closeBox(); }); + } else if (_creating == CreatingGroupGroup) { + addButton(lang(lng_create_group_create), [this] { createGroup(); }); + addButton(lang(lng_create_group_back), [this] { closeBox(); }); + } else { + addButton(lang(lng_close), [this] { closeBox(); }); + addLeftButton(lang(lng_profile_add_contact), [] { App::wnd()->onShowAddContact(); }); } _inner->setPeerSelectedChangedCallback([this](PeerData *peer, bool checked) { @@ -141,24 +149,6 @@ void ContactsBox::init() { } else { _select->showFast(); } - if (_inner->channel() && _inner->membersFilter() == MembersFilter::Admins) { - _next->hide(); - _cancel->hide(); - } else if (_inner->chat() && _inner->membersFilter() == MembersFilter::Admins) { - connect(_next, SIGNAL(clicked()), this, SLOT(onSaveAdmins())); - _bottomShadow.create(this); - } else if (_inner->chat() || _inner->channel()) { - connect(_next, SIGNAL(clicked()), this, SLOT(onInvite())); - _bottomShadow.create(this); - } else if (_inner->creating() != CreatingGroupNone) { - connect(_next, SIGNAL(clicked()), this, SLOT(onCreate())); - _bottomShadow.create(this); - } else { - _next->hide(); - _cancel->hide(); - } - connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); - connect(scrollArea(), SIGNAL(scrolled()), this, SLOT(onScroll())); _select->entity()->setQueryChangedCallback([this](const QString &query) { onFilterUpdate(query); }); _select->entity()->setItemRemovedCallback([this](uint64 itemId) { if (auto peer = App::peerLoaded(itemId)) { @@ -167,14 +157,16 @@ void ContactsBox::init() { } }); _select->entity()->setSubmittedCallback([this](bool) { onSubmit(); }); - connect(_inner, SIGNAL(mustScrollTo(int, int)), scrollArea(), SLOT(scrollToY(int, int))); + connect(_inner, SIGNAL(mustScrollTo(int, int)), this, SLOT(onScrollToY(int, int))); connect(_inner, SIGNAL(searchByUsername()), this, SLOT(onNeedSearchByUsername())); connect(_inner, SIGNAL(adminAdded()), this, SIGNAL(adminAdded())); - _searchTimer.setSingleShot(true); - connect(&_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchByUsername())); + _searchTimer->setSingleShot(true); + connect(_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchByUsername())); - raiseShadow(); + setDimensions(st::boxWideWidth, st::boxMaxListHeight); + + _select->raise(); } bool ContactsBox::onSearchByUsername(bool searchCache) { @@ -204,9 +196,26 @@ bool ContactsBox::onSearchByUsername(bool searchCache) { return false; } +void ContactsBox::updateTitle() { + if (_chat && _membersFilter == MembersFilter::Admins) { + setTitle(lang(lng_channel_admins)); + } else if (_chat || _creating != CreatingGroupNone) { + auto addingAdmin = _channel && (_membersFilter == MembersFilter::Admins); + auto title = lang(addingAdmin ? lng_channel_add_admin : lng_profile_add_participant); + auto additional = (addingAdmin || (_inner->channel() && !_inner->channel()->isMegagroup())) ? QString() : QString("%1 / %2").arg(_inner->selectedCount()).arg(Global::MegagroupSizeMax()); + setTitle(title, additional); + } else if (_inner->sharingBotGame()) { + setTitle(lang(lng_bot_choose_chat)); + } else if (_inner->bot()) { + setTitle(lang(lng_bot_choose_group)); + } else { + setTitle(lang(lng_contacts_header)); + } +} + void ContactsBox::onNeedSearchByUsername() { if (!onSearchByUsername(true)) { - _searchTimer.start(AutoSearchTimeout); + _searchTimer->start(AutoSearchTimeout); } } @@ -231,7 +240,6 @@ void ContactsBox::peopleReceived(const MTPcontacts_Found &result, mtpRequestId r _peopleRequest = 0; _inner->updateSelection(); - onScroll(); } } @@ -245,7 +253,7 @@ bool ContactsBox::peopleFailed(const RPCError &error, mtpRequestId req) { return true; } -void ContactsBox::doSetInnerFocus() { +void ContactsBox::setInnerFocus() { if (_select->isHidden()) { _inner->setFocus(); } else { @@ -265,40 +273,26 @@ void ContactsBox::keyPressEvent(QKeyEvent *e) { } else if (e->key() == Qt::Key_Up) { _inner->selectSkip(-1); } else if (e->key() == Qt::Key_PageDown) { - _inner->selectSkipPage(scrollArea()->height(), 1); + _inner->selectSkipPage(height() - getTopScrollSkip(), 1); } else if (e->key() == Qt::Key_PageUp) { - _inner->selectSkipPage(scrollArea()->height(), -1); + _inner->selectSkipPage(height() - getTopScrollSkip(), -1); } else { - ItemListBox::keyPressEvent(e); + BoxContent::keyPressEvent(e); } } else { - ItemListBox::keyPressEvent(e); + BoxContent::keyPressEvent(e); } } -void ContactsBox::paintEvent(QPaintEvent *e) { - AbstractBox::paintEvent(e); - - Painter p(this); - - bool addingAdmin = _inner->channel() && _inner->membersFilter() == MembersFilter::Admins; - if (_inner->chat() && _inner->membersFilter() == MembersFilter::Admins) { - paintTitle(p, lang(lng_channel_admins)); - } else if (_inner->chat() || _inner->creating() != CreatingGroupNone) { - QString title(lang(addingAdmin ? lng_channel_add_admin : lng_profile_add_participant)); - QString additional((addingAdmin || (_inner->channel() && !_inner->channel()->isMegagroup())) ? QString() : QString("%1 / %2").arg(_inner->selectedCount()).arg(Global::MegagroupSizeMax())); - paintTitle(p, title, additional); - } else if (_inner->sharingBotGame()) { - paintTitle(p, lang(lng_bot_choose_chat)); - } else if (_inner->bot()) { - paintTitle(p, lang(lng_bot_choose_group)); - } else { - paintTitle(p, lang(lng_contacts_header)); - } +object_ptr> ContactsBox::createMultiSelect() { + auto entity = object_ptr(this, st::contactsMultiSelect, lang(lng_participant_filter)); + auto margins = style::margins(0, 0, 0, 0); + auto callback = [this] { updateScrollSkips(); }; + return object_ptr>(this, std_::move(entity), margins, std_::move(callback)); } int ContactsBox::getTopScrollSkip() const { - auto result = titleHeight(); + auto result = 0; if (!_select->isHidden()) { result += _select->height(); } @@ -306,45 +300,28 @@ int ContactsBox::getTopScrollSkip() const { } void ContactsBox::updateScrollSkips() { - auto oldScrollHeight = scrollArea()->height(); - auto inviting = (_inner->creating() == CreatingGroupGroup) || (_inner->channel() && _inner->membersFilter() == MembersFilter::Recent) || _inner->chat(); - auto topSkip = getTopScrollSkip(); - auto bottomSkip = inviting ? (st::boxButtonPadding.top() + _next->height() + st::boxButtonPadding.bottom()) : st::boxScrollSkip; - setScrollSkips(bottomSkip, topSkip); - auto scrollHeightDelta = scrollArea()->height() - oldScrollHeight; - if (scrollHeightDelta) { - scrollArea()->scrollToY(scrollArea()->scrollTop() - scrollHeightDelta); - } - - _topShadow->setGeometry(0, topSkip, width(), st::lineWidth); + setInnerTopSkip(getTopScrollSkip(), true); } void ContactsBox::resizeEvent(QResizeEvent *e) { - ItemListBox::resizeEvent(e); + BoxContent::resizeEvent(e); _select->resizeToWidth(width()); - _select->moveToLeft(0, titleHeight()); + _select->moveToLeft(0, 0); updateScrollSkips(); - if (_add) { - _add->moveToRight(st::contactsAddPosition.x(), height() - st::contactsAddPosition.y() - _add->height()); - } - _inner->resize(width(), _inner->height()); - _next->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _next->height()); - _cancel->moveToRight(st::boxButtonPadding.right() + _next->width() + st::boxButtonPadding.left(), _next->y()); - if (_bottomShadow) _bottomShadow->setGeometry(0, height() - st::boxButtonPadding.bottom() - _next->height() - st::boxButtonPadding.top() - st::lineWidth, width(), st::lineWidth); } -void ContactsBox::closePressed() { - if (_inner->channel() && !_inner->hasAlreadyMembersInChannel()) { - Ui::showPeerHistory(_inner->channel(), ShowAtTheEndMsgId); +void ContactsBox::closeHook() { + if (_channel && _creating == CreatingGroupChannel) { + Ui::showPeerHistory(_channel, ShowAtTheEndMsgId); } } void ContactsBox::onFilterUpdate(const QString &filter) { - scrollArea()->scrollToY(0); + onScrollToY(0); _inner->updateFilter(filter); } @@ -361,10 +338,10 @@ void ContactsBox::onPeerSelectedChanged(PeerData *peer, bool checked) { } else { _select->entity()->removeItem(peer->id); } - update(); + updateTitle(); } -void ContactsBox::onInvite() { +void ContactsBox::inviteParticipants() { QVector users(_inner->selected()); if (users.isEmpty()) { _select->entity()->setInnerFocus(); @@ -376,11 +353,11 @@ void ContactsBox::onInvite() { Ui::hideLayer(); Ui::showPeerHistory(_inner->chat(), ShowAtTheEndMsgId); } else { - onClose(); + closeBox(); } } -void ContactsBox::onCreate() { +void ContactsBox::createGroup() { if (_saveRequestId) return; auto users = _inner->selectedInputs(); @@ -391,7 +368,7 @@ void ContactsBox::onCreate() { _saveRequestId = MTP::send(MTPmessages_CreateChat(MTP_vector(users), MTP_string(_creationName)), rpcDone(&ContactsBox::creationDone), rpcFail(&ContactsBox::creationFail)); } -void ContactsBox::onSaveAdmins() { +void ContactsBox::saveChatAdmins() { if (_saveRequestId) return; _inner->saving(true); @@ -405,7 +382,7 @@ void ContactsBox::saveAdminsDone(const MTPUpdates &result) { void ContactsBox::saveSelectedAdmins() { if (_inner->allAdmins() && !_inner->chat()->participants.isEmpty()) { - onClose(); + closeBox(); } else { _saveRequestId = MTP::send(MTPmessages_GetFullChat(_inner->chat()->inputChat), rpcDone(&ContactsBox::getAdminsDone), rpcFail(&ContactsBox::saveAdminsFail)); } @@ -414,7 +391,7 @@ void ContactsBox::saveSelectedAdmins() { void ContactsBox::getAdminsDone(const MTPmessages_ChatFull &result) { App::api()->processFullPeer(_inner->chat(), result); if (_inner->allAdmins()) { - onClose(); + closeBox(); return; } ChatData::Admins curadmins = _inner->chat()->admins; @@ -444,7 +421,7 @@ void ContactsBox::getAdminsDone(const MTPmessages_ChatFull &result) { _saveRequestId = curadmins.size() + appoint.size(); if (!_saveRequestId) { - onClose(); + closeBox(); } } @@ -459,7 +436,7 @@ void ContactsBox::setAdminDone(UserData *user, const MTPBool &result) { --_saveRequestId; if (!_saveRequestId) { emit App::main()->peerUpdated(_inner->chat()); - onClose(); + closeBox(); } } @@ -470,7 +447,7 @@ void ContactsBox::removeAdminDone(UserData *user, const MTPBool &result) { --_saveRequestId; if (!_saveRequestId) { emit App::main()->peerUpdated(_inner->chat()); - onClose(); + closeBox(); } } @@ -490,18 +467,14 @@ bool ContactsBox::editAdminFail(const RPCError &error) { _inner->chat()->invalidateParticipants(); if (!_saveRequestId) { if (error.type() == qstr("USER_RESTRICTED")) { - Ui::showLayer(new InformBox(lang(lng_cant_do_this))); + Ui::show(Box(lang(lng_cant_do_this))); return true; } - onClose(); + closeBox(); } return false; } -void ContactsBox::onScroll() { - _inner->loadProfilePhotos(scrollArea()->scrollTop()); -} - void ContactsBox::creationDone(const MTPUpdates &updates) { Ui::hideLayer(); @@ -532,16 +505,16 @@ bool ContactsBox::creationFail(const RPCError &error) { _saveRequestId = 0; if (error.type() == "NO_CHAT_TITLE") { - onClose(); + closeBox(); return true; } else if (error.type() == "USERS_TOO_FEW") { _select->entity()->setInnerFocus(); return true; } else if (error.type() == "PEER_FLOOD") { - Ui::showLayer(new InformBox(cantInviteError()), KeepOtherLayers); + Ui::show(Box(cantInviteError()), KeepOtherLayers); return true; } else if (error.type() == qstr("USER_RESTRICTED")) { - Ui::showLayer(new InformBox(lang(lng_cant_do_this))); + Ui::show(Box(lang(lng_cant_do_this))); return true; } return false; @@ -649,6 +622,7 @@ void ContactsBox::Inner::init() { connect(_addContactLnk, SIGNAL(clicked()), App::wnd(), SLOT(onShowAddContact())); connect(_allAdmins, SIGNAL(changed()), this, SLOT(onAllAdminsChanged())); + _rowsTop = st::contactsMarginTop; setAttribute(Qt::WA_OpaquePaintEvent); for_const (auto row, _contacts->all()) { @@ -706,7 +680,7 @@ void ContactsBox::Inner::onPeerNameChanged(PeerData *peer, const PeerData::Names peerUpdated(peer); } -void ContactsBox::Inner::onAddBot() { +void ContactsBox::Inner::addBot() { if (auto &info = _bot->botInfo) { if (!info->shareGameShortName.isEmpty()) { MTPmessages_SendMedia::Flags sendFlags = 0; @@ -730,17 +704,6 @@ void ContactsBox::Inner::onAddBot() { Ui::showPeerHistory(_addToPeer, ShowAtUnreadMsgId); } -void ContactsBox::Inner::onAddAdmin() { - if (_addAdminRequestId) return; - _addAdminRequestId = MTP::send(MTPchannels_EditAdmin(_channel->inputChannel, _addAdmin->inputUser, MTP_channelRoleEditor()), rpcDone(&Inner::addAdminDone), rpcFail(&Inner::addAdminFail)); -} - -void ContactsBox::Inner::onNoAddAdminBox(QObject *obj) { - if (obj == _addAdminBox) { - _addAdminBox = 0; - } -} - void ContactsBox::Inner::onAllAdminsChanged() { if (_saving && _allAdmins->checked() != _allAdminsChecked) { _allAdmins->setChecked(_allAdminsChecked); @@ -771,7 +734,7 @@ void ContactsBox::Inner::addAdminDone(const MTPUpdates &result, mtpRequestId req } Notify::peerUpdatedDelayed(update); } - if (_addAdminBox) _addAdminBox->onClose(); + if (_addAdminBox) _addAdminBox->closeBox(); emit adminAdded(); } @@ -781,13 +744,13 @@ bool ContactsBox::Inner::addAdminFail(const RPCError &error, mtpRequestId req) { if (req != _addAdminRequestId) return true; _addAdminRequestId = 0; - if (_addAdminBox) _addAdminBox->onClose(); + if (_addAdminBox) _addAdminBox->closeBox(); if (error.type() == "USERS_TOO_MUCH") { - Ui::showLayer(new MaxInviteBox(_channel->inviteLink()), KeepOtherLayers); + Ui::show(Box(_channel->inviteLink()), KeepOtherLayers); } else if (error.type() == "ADMINS_TOO_MUCH") { - Ui::showLayer(new InformBox(lang(lng_channel_admins_too_much)), KeepOtherLayers); + Ui::show(Box(lang(lng_channel_admins_too_much)), KeepOtherLayers); } else if (error.type() == qstr("USER_RESTRICTED")) { - Ui::showLayer(new InformBox(lang(lng_cant_do_this)), KeepOtherLayers); + Ui::show(Box(lang(lng_cant_do_this)), KeepOtherLayers); } else { emit adminAdded(); } @@ -834,14 +797,14 @@ void ContactsBox::Inner::peerUpdated(PeerData *peer) { for_const (auto row, _contacts->all()) { if (row->attached == i.value()) { row->attached = nullptr; - update(0, _aboutHeight + _rowHeight * row->pos(), width(), _rowHeight); + update(0, _rowsTop + _aboutHeight + _rowHeight * row->pos(), width(), _rowHeight); } } if (!_filter.isEmpty()) { for (int32 j = 0, s = _filtered.size(); j < s; ++j) { if (_filtered[j]->attached == i.value()) { _filtered[j]->attached = 0; - update(0, _rowHeight * j, width(), _rowHeight); + update(0, _rowsTop + _rowHeight * j, width(), _rowHeight); } } } @@ -851,9 +814,11 @@ void ContactsBox::Inner::peerUpdated(PeerData *peer) { } } -void ContactsBox::Inner::loadProfilePhotos(int32 yFrom) { - if (!parentWidget()) return; - int32 yTo = yFrom + parentWidget()->height() * 5; +void ContactsBox::Inner::loadProfilePhotos() { + if (_visibleTop >= _visibleBottom) return; + + auto yFrom = _visibleTop - _rowsTop; + auto yTo = yFrom + (_visibleBottom - _visibleTop) * 5; MTP::clearLoaderPriorities(); if (yTo < 0) return; @@ -870,10 +835,10 @@ void ContactsBox::Inner::loadProfilePhotos(int32 yFrom) { } } } else if (!_filtered.isEmpty()) { - int32 from = yFrom / _rowHeight; + auto from = yFrom / _rowHeight; if (from < 0) from = 0; if (from < _filtered.size()) { - int32 to = (yTo / _rowHeight) + 1; + auto to = (yTo / _rowHeight) + 1; if (to > _filtered.size()) to = _filtered.size(); for (; from < to; ++from) { @@ -1047,8 +1012,10 @@ void ContactsBox::Inner::paintEvent(QPaintEvent *e) { p.fillRect(r, st::contactsBg); auto ms = getms(); - int32 yFrom = r.y(), yTo = r.y() + r.height(); + auto yFrom = r.y(), yTo = r.y() + r.height(); + auto skip = _rowsTop; if (_filter.isEmpty()) { + skip += _aboutHeight; if (!_contacts->isEmpty() || !_byUsername.isEmpty()) { if (_aboutHeight) { auto infoTop = _allAdmins->bottomNoMargins() + st::contactsAllAdminsTop - st::lineWidth; @@ -1063,11 +1030,10 @@ void ContactsBox::Inner::paintEvent(QPaintEvent *e) { int aboutw = width() - st::contactsPadding.left() - st::contactsPadding.right(); p.setPen(st::contactsAboutFg); (_allAdmins->checked() ? _aboutAllAdmins : _aboutAdmins).draw(p, st::contactsPadding.left(), st::contactsAboutTop, aboutw); - - yFrom -= _aboutHeight; - yTo -= _aboutHeight; - p.translate(0, _aboutHeight); } + yFrom -= skip; + yTo -= skip; + p.translate(0, skip); if (!_contacts->isEmpty()) { auto i = _contacts->cfind(yFrom, _rowHeight); p.translate(0, (*i)->pos() * _rowHeight); @@ -1103,7 +1069,7 @@ void ContactsBox::Inner::paintEvent(QPaintEvent *e) { } } else { QString text; - int32 skip = 0; + skip = 0; if (bot()) { text = lang((cDialogsReceived() && !_searching) ? (sharingBotGame() ? lng_bot_no_chats : lng_bot_no_groups) : lng_contacts_loading); } else if (_chat && _membersFilter == MembersFilter::Admins) { @@ -1126,8 +1092,8 @@ void ContactsBox::Inner::paintEvent(QPaintEvent *e) { } } else { if (_filtered.isEmpty() && _byUsernameFiltered.isEmpty()) { - p.setFont(st::noContactsFont->f); - p.setPen(st::noContactsColor->p); + p.setFont(st::noContactsFont); + p.setPen(st::noContactsColor); QString text; if (bot()) { text = lang((cDialogsReceived() && !_searching) ? (sharingBotGame() ? lng_bot_chats_not_found : lng_bot_groups_not_found) : lng_contacts_loading); @@ -1138,6 +1104,9 @@ void ContactsBox::Inner::paintEvent(QPaintEvent *e) { } p.drawText(QRect(0, 0, width(), st::noContactsHeight), text, style::al_center); } else { + yFrom -= skip; + yTo -= skip; + p.translate(0, skip); if (!_filtered.isEmpty()) { int32 from = floorclamp(yFrom, _rowHeight, 0, _filtered.size()); int32 to = ceilclamp(yTo, _rowHeight, 0, _filtered.size()); @@ -1177,15 +1146,15 @@ void ContactsBox::Inner::enterEvent(QEvent *e) { int ContactsBox::Inner::getSelectedRowTop() const { if (_filter.isEmpty()) { if (_selected) { - return _aboutHeight + (_selected->pos() * _rowHeight); + return _rowsTop + _aboutHeight + (_selected->pos() * _rowHeight); } else if (_searchedSelected >= 0) { - return _aboutHeight + (_contacts->size() * _rowHeight) + st::searchedBarHeight + (_searchedSelected * _rowHeight); + return _rowsTop + _aboutHeight + (_contacts->size() * _rowHeight) + st::searchedBarHeight + (_searchedSelected * _rowHeight); } } else { if (_filteredSelected >= 0) { - return (_filteredSelected * _rowHeight); + return _rowsTop + (_filteredSelected * _rowHeight); } else if (_searchedSelected >= 0) { - return (_filtered.size() * _rowHeight + st::searchedBarHeight + _searchedSelected * _rowHeight); + return _rowsTop + (_filtered.size() * _rowHeight + st::searchedBarHeight + _searchedSelected * _rowHeight); } } return -1; @@ -1206,23 +1175,23 @@ int ContactsBox::Inner::getRowTopWithPeer(PeerData *peer) const { if (_filter.isEmpty()) { for (auto i = _contacts->cbegin(), end = _contacts->cend(); i != end; ++i) { if ((*i)->history()->peer == peer) { - return _aboutHeight + ((*i)->pos() * _rowHeight); + return _rowsTop + _aboutHeight + ((*i)->pos() * _rowHeight); } } for (auto i = 0, count = _byUsername.size(); i != count; ++i) { if (_byUsername[i] == peer) { - return _aboutHeight + (_contacts->size() * _rowHeight) + st::searchedBarHeight + (i * _rowHeight); + return _rowsTop + _aboutHeight + (_contacts->size() * _rowHeight) + st::searchedBarHeight + (i * _rowHeight); } } } else { for (auto i = 0, count = _filtered.size(); i != count; ++i) { if (_filtered[i]->history()->peer == peer) { - return (i * _rowHeight); + return _rowsTop + (i * _rowHeight); } } for (auto i = 0, count = _byUsernameFiltered.size(); i != count; ++i) { if (_byUsernameFiltered[i] == peer) { - return (_contacts->size() * _rowHeight) + st::searchedBarHeight + (i * _rowHeight); + return _rowsTop + (_contacts->size() * _rowHeight) + st::searchedBarHeight + (i * _rowHeight); } } } @@ -1415,10 +1384,10 @@ void ContactsBox::Inner::chooseParticipant() { _addAdminRequestId = 0; } if (_addAdminBox) _addAdminBox->deleteLater(); - _addAdminBox = new ConfirmBox(lng_channel_admin_sure(lt_user, _addAdmin->firstName)); - connect(_addAdminBox, SIGNAL(confirmed()), this, SLOT(onAddAdmin())); - connect(_addAdminBox, SIGNAL(destroyed(QObject*)), this, SLOT(onNoAddAdminBox(QObject*))); - Ui::showLayer(_addAdminBox, KeepOtherLayers); + _addAdminBox = Ui::show(Box(lng_channel_admin_sure(lt_user, _addAdmin->firstName), base::lambda_guarded(this, [this] { + if (_addAdminRequestId) return; + _addAdminRequestId = MTP::send(MTPchannels_EditAdmin(_channel->inputChannel, _addAdmin->inputUser, MTP_channelRoleEditor()), rpcDone(&Inner::addAdminDone), rpcFail(&Inner::addAdminFail)); + })), KeepOtherLayers); } else if (sharingBotGame()) { _addToPeer = peer; auto confirmText = [peer] { @@ -1427,14 +1396,14 @@ void ContactsBox::Inner::chooseParticipant() { } return lng_bot_sure_share_game_group(lt_group, peer->name); }; - auto box = std_::make_unique(confirmText()); - connect(box.get(), SIGNAL(confirmed()), this, SLOT(onAddBot())); - Ui::showLayer(box.release(), KeepOtherLayers); + Ui::show(Box(confirmText(), base::lambda_guarded(this, [this] { + addBot(); + })), KeepOtherLayers); } else if (bot() && (peer->isChat() || peer->isMegagroup())) { _addToPeer = peer; - auto box = std_::make_unique(lng_bot_sure_invite(lt_group, peer->name)); - connect(box.get(), SIGNAL(confirmed()), this, SLOT(onAddBot())); - Ui::showLayer(box.release(), KeepOtherLayers); + Ui::show(Box(lng_bot_sure_invite(lt_group, peer->name), base::lambda_guarded(this, [this] { + addBot(); + })), KeepOtherLayers); } else { Ui::hideSettingsAndLayer(true); App::main()->choosePeer(peer->id, ShowAtUnreadMsgId); @@ -1457,9 +1426,9 @@ void ContactsBox::Inner::changeCheckState(ContactData *data, PeerData *peer) { } else if (selectedCount() < ((_channel && _channel->isMegagroup()) ? Global::MegagroupSizeMax() : Global::ChatSizeMax())) { changePeerCheckState(data, peer, true); } else if (_channel && !_channel->isMegagroup()) { - Ui::showLayer(new MaxInviteBox(_channel->inviteLink()), KeepOtherLayers); + Ui::show(Box(_channel->inviteLink()), KeepOtherLayers); } else if (!_channel && selectedCount() >= Global::ChatSizeMax() && selectedCount() < Global::MegagroupSizeMax()) { - Ui::showLayer(new InformBox(lng_profile_add_more_after_upgrade(lt_count, Global::MegagroupSizeMax())), KeepOtherLayers); + Ui::show(Box(lng_profile_add_more_after_upgrade(lt_count, Global::MegagroupSizeMax())), KeepOtherLayers); } } @@ -1487,7 +1456,7 @@ void ContactsBox::Inner::changePeerCheckState(ContactData *data, PeerData *peer, } } -int32 ContactsBox::Inner::selectedCount() const { +int ContactsBox::Inner::selectedCount() const { auto result = _checkedContacts.size(); if (_chat) { result += qMax(_chat->count, 1); @@ -1499,11 +1468,18 @@ int32 ContactsBox::Inner::selectedCount() const { return result; } +void ContactsBox::Inner::setVisibleTopBottom(int visibleTop, int visibleBottom) { + _visibleTop = visibleTop; + _visibleBottom = visibleBottom; + loadProfilePhotos(); +} + void ContactsBox::Inner::updateSelection() { if (!_mouseSelection) return; auto p = mapFromGlobal(_lastMousePos); - bool in = parentWidget()->rect().contains(parentWidget()->mapFromGlobal(_lastMousePos)); + auto in = parentWidget()->rect().contains(parentWidget()->mapFromGlobal(_lastMousePos)); + p.setY(p.y() - _rowsTop); if (_filter.isEmpty()) { _filteredSelected = -1; setFilteredPressed(-1); @@ -1511,7 +1487,7 @@ void ContactsBox::Inner::updateSelection() { p.setY(p.y() - _aboutHeight); } auto selected = (in && (p.y() >= 0) && (p.y() < _contacts->size() * _rowHeight)) ? _contacts->rowAtY(p.y(), _rowHeight) : nullptr; - auto searchedSelected = (in && p.y() >= _contacts->size() * _rowHeight + st::searchedBarHeight) ? ((p.y() - _contacts->size() * _rowHeight - st::searchedBarHeight) / _rowHeight) : -1; + auto searchedSelected = (in && (p.y() >= _contacts->size() * _rowHeight + st::searchedBarHeight)) ? ((p.y() - _contacts->size() * _rowHeight - st::searchedBarHeight) / _rowHeight) : -1; if (searchedSelected >= _byUsername.size()) searchedSelected = -1; if (_selected != selected || _searchedSelected != searchedSelected) { updateSelectedRow(); @@ -1522,8 +1498,8 @@ void ContactsBox::Inner::updateSelection() { } else { _selected = nullptr; setPressed(nullptr); - auto filteredSelected = (in && p.y() >= 0 && p.y() < _filtered.size() * _rowHeight) ? (p.y() / _rowHeight) : -1; - auto searchedSelected = (in && p.y() >= _filtered.size() * _rowHeight + st::searchedBarHeight) ? ((p.y() - _filtered.size() * _rowHeight - st::searchedBarHeight) / _rowHeight) : -1; + auto filteredSelected = (in && (p.y() >= 0) && (p.y() < _filtered.size() * _rowHeight)) ? (p.y() / _rowHeight) : -1; + auto searchedSelected = (in && (p.y() >= _filtered.size() * _rowHeight + st::searchedBarHeight)) ? ((p.y() - _filtered.size() * _rowHeight - st::searchedBarHeight) / _rowHeight) : -1; if (searchedSelected >= _byUsernameFiltered.size()) searchedSelected = -1; if (_filteredSelected != filteredSelected || _searchedSelected != searchedSelected) { updateSelectedRow(); @@ -1653,7 +1629,7 @@ void ContactsBox::Inner::updateFilter(QString filter) { } } update(); - loadProfilePhotos(0); + loadProfilePhotos(); } } @@ -1760,10 +1736,10 @@ void ContactsBox::Inner::refresh() { } if (!_contacts->isEmpty() || !_byUsername.isEmpty()) { if (!_addContactLnk->isHidden()) _addContactLnk->hide(); - resize(width(), _aboutHeight + (_contacts->size() * _rowHeight) + (_byUsername.isEmpty() ? 0 : (st::searchedBarHeight + _byUsername.size() * _rowHeight))); + resize(width(), _rowsTop + _aboutHeight + (_contacts->size() * _rowHeight) + (_byUsername.isEmpty() ? 0 : (st::searchedBarHeight + _byUsername.size() * _rowHeight)) + st::contactsMarginBottom); } else if (_chat && _membersFilter == MembersFilter::Admins) { if (!_addContactLnk->isHidden()) _addContactLnk->hide(); - resize(width(), _aboutHeight + st::noContactsHeight); + resize(width(), _rowsTop + _aboutHeight + st::noContactsHeight + st::contactsMarginBottom); } else { if (cContactsReceived() && !bot()) { if (_addContactLnk->isHidden()) _addContactLnk->show(); @@ -1778,9 +1754,10 @@ void ContactsBox::Inner::refresh() { if (!_addContactLnk->isHidden()) _addContactLnk->hide(); resize(width(), st::noContactsHeight); } else { - resize(width(), (_filtered.size() * _rowHeight) + (_byUsernameFiltered.isEmpty() ? 0 : (st::searchedBarHeight + _byUsernameFiltered.size() * _rowHeight))); + resize(width(), _rowsTop + (_filtered.size() * _rowHeight) + (_byUsernameFiltered.isEmpty() ? 0 : (st::searchedBarHeight + _byUsernameFiltered.size() * _rowHeight)) + st::contactsMarginBottom); } } + loadProfilePhotos(); update(); } @@ -1902,9 +1879,9 @@ void ContactsBox::Inner::selectSkip(int32 dir) { } } if (_selected) { - emit mustScrollTo(_aboutHeight + _selected->pos() * _rowHeight, _aboutHeight + (_selected->pos() + 1) * _rowHeight); + emit mustScrollTo(_rowsTop + _aboutHeight + _selected->pos() * _rowHeight, _rowsTop + _aboutHeight + (_selected->pos() + 1) * _rowHeight); } else if (_searchedSelected >= 0) { - emit mustScrollTo(_aboutHeight + (_contacts->size() + _searchedSelected) * _rowHeight + st::searchedBarHeight, _aboutHeight + (_contacts->size() + _searchedSelected + 1) * _rowHeight + st::searchedBarHeight); + emit mustScrollTo(_rowsTop + _aboutHeight + (_contacts->size() + _searchedSelected) * _rowHeight + st::searchedBarHeight, _rowsTop + _aboutHeight + (_contacts->size() + _searchedSelected + 1) * _rowHeight + st::searchedBarHeight); } } else { int cur = (_filteredSelected >= 0) ? _filteredSelected : ((_searchedSelected >= 0) ? (_filtered.size() + _searchedSelected) : -1); @@ -1948,10 +1925,10 @@ void ContactsBox::Inner::selectSkip(int32 dir) { } } if (_filteredSelected >= 0) { - emit mustScrollTo(_filteredSelected * _rowHeight, (_filteredSelected + 1) * _rowHeight); + emit mustScrollTo(_rowsTop + _filteredSelected * _rowHeight, _rowsTop + (_filteredSelected + 1) * _rowHeight); } else if (_searchedSelected >= 0) { int skip = _filtered.size() * _rowHeight + st::searchedBarHeight; - emit mustScrollTo(skip + _searchedSelected * _rowHeight, skip + (_searchedSelected + 1) * _rowHeight); + emit mustScrollTo(_rowsTop + skip + _searchedSelected * _rowHeight, _rowsTop + skip + (_searchedSelected + 1) * _rowHeight); } } update(); diff --git a/Telegram/SourceFiles/boxes/contactsbox.h b/Telegram/SourceFiles/boxes/contactsbox.h index d5dd70c93..88d7df5f1 100644 --- a/Telegram/SourceFiles/boxes/contactsbox.h +++ b/Telegram/SourceFiles/boxes/contactsbox.h @@ -32,7 +32,6 @@ class IndexedList; namespace Ui { class RippleAnimation; -class RoundButton; class LinkButton; class Checkbox; class MultiSelect; @@ -48,64 +47,79 @@ inline Ui::RoundImageCheckbox::PaintRoundImage PaintUserpicCallback(PeerData *pe }; } -class ContactsBox : public ItemListBox, public RPCSender { +class ContactsBox : public BoxContent, public RPCSender { Q_OBJECT public: - ContactsBox(); - ContactsBox(const QString &name, const QImage &photo); // group creation - ContactsBox(ChannelData *channel); // channel setup - ContactsBox(ChannelData *channel, MembersFilter filter, const MembersAlreadyIn &already); - ContactsBox(ChatData *chat, MembersFilter filter); - ContactsBox(UserData *bot); + ContactsBox(QWidget*); + ContactsBox(QWidget*, const QString &name, const QImage &photo); // group creation + ContactsBox(QWidget*, ChannelData *channel); // channel setup + ContactsBox(QWidget*, ChannelData *channel, MembersFilter filter, const MembersAlreadyIn &already); + ContactsBox(QWidget*, ChatData *chat, MembersFilter filter); + ContactsBox(QWidget*, UserData *bot); + + void closeHook() override; signals: void adminAdded(); private slots: - void onScroll(); - - void onInvite(); - void onCreate(); - void onSaveAdmins(); - void onSubmit(); bool onSearchByUsername(bool searchCache = false); void onNeedSearchByUsername(); protected: + void prepare() override; + void setInnerFocus() override; + void keyPressEvent(QKeyEvent *e) override; - void paintEvent(QPaintEvent *e) override; void resizeEvent(QResizeEvent *e) override; - void closePressed() override; - void doSetInnerFocus() override; - private: - void init(); + object_ptr> createMultiSelect(); + + void updateTitle(); int getTopScrollSkip() const; void updateScrollSkips(); void onFilterUpdate(const QString &filter); void onPeerSelectedChanged(PeerData *peer, bool checked); void addPeerToMultiSelect(PeerData *peer, bool skipAnimation = false); - class Inner; - ChildWidget _inner; - ChildWidget> _select; - ChildWidget _add = { nullptr }; - - ChildWidget _next; - ChildWidget _cancel; - MembersFilter _membersFilter; - - ChildWidget _topShadow; - ChildWidget _bottomShadow = { nullptr }; + void saveChatAdmins(); + void inviteParticipants(); + void createGroup(); + // global search void peopleReceived(const MTPcontacts_Found &result, mtpRequestId req); bool peopleFailed(const RPCError &error, mtpRequestId req); - QTimer _searchTimer; + // saving admins + void saveAdminsDone(const MTPUpdates &result); + void saveSelectedAdmins(); + void getAdminsDone(const MTPmessages_ChatFull &result); + void setAdminDone(UserData *user, const MTPBool &result); + void removeAdminDone(UserData *user, const MTPBool &result); + bool saveAdminsFail(const RPCError &error); + bool editAdminFail(const RPCError &error); + + // group creation + void creationDone(const MTPUpdates &updates); + bool creationFail(const RPCError &e); + + ChatData *_chat = nullptr; + ChannelData *_channel = nullptr; + MembersFilter _membersFilter = MembersFilter::Recent; + UserData *_bot = nullptr; + CreatingGroupType _creating = CreatingGroupNone; + MembersAlreadyIn _alreadyIn; + + object_ptr> _select; + + class Inner; + QPointer _inner; + + object_ptr _searchTimer; QString _peopleQuery; bool _peopleFull; mtpRequestId _peopleRequest; @@ -118,22 +132,9 @@ private: mtpRequestId _saveRequestId = 0; - // saving admins - void saveAdminsDone(const MTPUpdates &result); - void saveSelectedAdmins(); - void getAdminsDone(const MTPmessages_ChatFull &result); - void setAdminDone(UserData *user, const MTPBool &result); - void removeAdminDone(UserData *user, const MTPBool &result); - bool saveAdminsFail(const RPCError &error); - bool editAdminFail(const RPCError &error); - - // group creation QString _creationName; QImage _creationPhoto; - void creationDone(const MTPUpdates &updates); - bool creationFail(const RPCError &e); - }; // This class is hold in header because it requires Qt preprocessing. @@ -162,7 +163,6 @@ public: _allAdminsChangedCallback = std_::move(allAdminsChangedCallback); } - void loadProfilePhotos(int32 yFrom); void chooseParticipant(); void peopleReceived(const QString &query, const QVector &people); @@ -177,13 +177,15 @@ public: bool sharingBotGame() const; - int32 selectedCount() const; + int selectedCount() const; bool hasAlreadyMembersInChannel() const { return !_already.isEmpty(); } void saving(bool flag); + void setVisibleTopBottom(int visibleTop, int visibleBottom) override; + ~Inner(); signals: @@ -197,10 +199,6 @@ private slots: void peerUpdated(PeerData *peer); void onPeerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars); - void onAddBot(); - void onAddAdmin(); - void onNoAddAdminBox(QObject *obj); - void onAllAdminsChanged(); protected: @@ -233,6 +231,9 @@ private: void setSearchedPressed(int pressed); void clearSearchedContactDatas(); + void loadProfilePhotos(); + void addBot(); + void init(); void initList(); @@ -264,7 +265,10 @@ private: base::lambda _peerSelectedChangedCallback; - int _rowHeight; + int _visibleTop = 0; + int _visibleBottom = 0; + int _rowHeight = 0; + int _rowsTop = 0; int _aboutHeight = 0; ChatData *_chat = nullptr; @@ -274,7 +278,7 @@ private: CreatingGroupType _creating = CreatingGroupNone; MembersAlreadyIn _already; - ChildWidget _allAdmins; + object_ptr _allAdmins; int32 _aboutWidth; Text _aboutAllAdmins, _aboutAdmins; base::lambda _allAdminsChangedCallback; @@ -282,7 +286,7 @@ private: PeerData *_addToPeer = nullptr; UserData *_addAdmin = nullptr; mtpRequestId _addAdminRequestId = 0; - ConfirmBox *_addAdminBox = nullptr; + QPointer _addAdminBox; int32 _time; @@ -315,7 +319,7 @@ private: int _searchedPressed = -1; QPoint _lastMousePos; - ChildWidget _addContactLnk; + object_ptr _addContactLnk; bool _saving = false; bool _allAdminsChecked = false; diff --git a/Telegram/SourceFiles/boxes/downloadpathbox.cpp b/Telegram/SourceFiles/boxes/downloadpathbox.cpp index adc5ff772..fdfeee1cf 100644 --- a/Telegram/SourceFiles/boxes/downloadpathbox.cpp +++ b/Telegram/SourceFiles/boxes/downloadpathbox.cpp @@ -29,19 +29,20 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "pspecific.h" #include "styles/style_boxes.h" -DownloadPathBox::DownloadPathBox() : AbstractBox() -, _path(Global::DownloadPath()) +DownloadPathBox::DownloadPathBox(QWidget *parent) +: _path(Global::DownloadPath()) , _pathBookmark(Global::DownloadPathBookmark()) , _default(this, qsl("dir_type"), 0, lang(lng_download_path_default_radio), _path.isEmpty(), st::defaultBoxCheckbox) , _temp(this, qsl("dir_type"), 1, lang(lng_download_path_temp_radio), (_path == qsl("tmp")), st::defaultBoxCheckbox) , _dir(this, qsl("dir_type"), 2, lang(lng_download_path_dir_radio), (!_path.isEmpty() && _path != qsl("tmp")), st::defaultBoxCheckbox) -, _pathLink(this, QString(), st::boxLinkButton) -, _save(this, lang(lng_connection_save), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) { - setTitleText(lang(lng_download_path_header)); +, _pathLink(this, QString(), st::boxLinkButton) { +} - connect(_save, SIGNAL(clicked()), this, SLOT(onSave())); - connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); +void DownloadPathBox::prepare() { + addButton(lang(lng_connection_save), [this] { save(); }); + addButton(lang(lng_cancel), [this] { closeBox(); }); + + setTitle(lang(lng_download_path_header)); connect(_default, SIGNAL(changed()), this, SLOT(onChange())); connect(_temp, SIGNAL(changed()), this, SLOT(onChange())); @@ -57,25 +58,25 @@ DownloadPathBox::DownloadPathBox() : AbstractBox() void DownloadPathBox::updateControlsVisibility() { _pathLink->setVisible(_dir->checked()); - int32 h = titleHeight() + st::boxOptionListPadding.top() + _default->heightNoMargins() + st::boxOptionListPadding.top() + _temp->heightNoMargins() + st::boxOptionListPadding.top() + _dir->heightNoMargins(); - if (_dir->checked()) h += st::downloadPathSkip + _pathLink->height(); - h += st::boxOptionListPadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom(); + auto newHeight = st::boxOptionListPadding.top() + _default->heightNoMargins() + st::boxOptionListSkip + _temp->heightNoMargins() + st::boxOptionListSkip + _dir->heightNoMargins(); + if (_dir->checked()) { + newHeight += st::downloadPathSkip + _pathLink->height(); + } + newHeight += st::boxOptionListPadding.bottom(); - setMaxHeight(h); + setDimensions(st::boxWideWidth, newHeight); } void DownloadPathBox::resizeEvent(QResizeEvent *e) { - _default->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), titleHeight() + st::boxOptionListPadding.top()); - _temp->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _default->bottomNoMargins() + st::boxOptionListPadding.top()); - _dir->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _temp->bottomNoMargins() + st::boxOptionListPadding.top()); - int32 inputx = st::boxPadding.left() + st::boxOptionListPadding.left() + st::defaultBoxCheckbox.textPosition.x(); - int32 inputy = _dir->bottomNoMargins() + st::downloadPathSkip; + BoxContent::resizeEvent(e); + + _default->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), st::boxOptionListPadding.top()); + _temp->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _default->bottomNoMargins() + st::boxOptionListSkip); + _dir->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _temp->bottomNoMargins() + st::boxOptionListSkip); + auto inputx = st::boxPadding.left() + st::boxOptionListPadding.left() + st::defaultBoxCheckbox.textPosition.x(); + auto inputy = _dir->bottomNoMargins() + st::downloadPathSkip; _pathLink->moveToLeft(inputx, inputy); - - _save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height()); - _cancel->moveToRight(st::boxButtonPadding.right() + _save->width() + st::boxButtonPadding.left(), _save->y()); - AbstractBox::resizeEvent(e); } void DownloadPathBox::onChange() { @@ -114,15 +115,15 @@ void DownloadPathBox::onEditPath() { cSetDialogLastPath(lastPath); } -void DownloadPathBox::onSave() { +void DownloadPathBox::save() { Global::SetDownloadPath(_default->checked() ? QString() : (_temp->checked() ? qsl("tmp") : _path)); Global::SetDownloadPathBookmark((_default->checked() || _temp->checked()) ? QByteArray() : _pathBookmark); Local::writeUserSettings(); Global::RefDownloadPathChanged().notify(); - onClose(); + closeBox(); } void DownloadPathBox::setPathText(const QString &text) { - int32 availw = st::boxWideWidth - st::boxPadding.left() - st::defaultBoxCheckbox.textPosition.x() - st::boxPadding.right(); + auto availw = st::boxWideWidth - st::boxPadding.left() - st::defaultBoxCheckbox.textPosition.x() - st::boxPadding.right(); _pathLink->setText(st::boxTextFont->elided(text, availw)); } diff --git a/Telegram/SourceFiles/boxes/downloadpathbox.h b/Telegram/SourceFiles/boxes/downloadpathbox.h index 9637caa9f..a1a3d318e 100644 --- a/Telegram/SourceFiles/boxes/downloadpathbox.h +++ b/Telegram/SourceFiles/boxes/downloadpathbox.h @@ -26,36 +26,34 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org namespace Ui { class Radiobutton; class LinkButton; -class RoundButton; } // namespace Ui -class DownloadPathBox : public AbstractBox { +class DownloadPathBox : public BoxContent { Q_OBJECT public: - DownloadPathBox(); - -public slots: - void onChange(); - void onEditPath(); - void onSave(); + DownloadPathBox(QWidget *parent); protected: + void prepare() override; + void resizeEvent(QResizeEvent *e) override; +private slots: + void onChange(); + void onEditPath(); + private: + void save(); void updateControlsVisibility(); void setPathText(const QString &text); QString _path; QByteArray _pathBookmark; - ChildWidget _default; - ChildWidget _temp; - ChildWidget _dir; - ChildWidget _pathLink; - - ChildWidget _save; - ChildWidget _cancel; + object_ptr _default; + object_ptr _temp; + object_ptr _dir; + object_ptr _pathLink; }; diff --git a/Telegram/SourceFiles/boxes/emojibox.cpp b/Telegram/SourceFiles/boxes/emojibox.cpp index 46a342a6f..be499a798 100644 --- a/Telegram/SourceFiles/boxes/emojibox.cpp +++ b/Telegram/SourceFiles/boxes/emojibox.cpp @@ -71,17 +71,18 @@ namespace { const uint32 replacesCount = sizeof(replaces) / sizeof(EmojiReplace), replacesInRow = 7; } -EmojiBox::EmojiBox() : _esize(EmojiSizes[EIndex + 1]) { - setTitleText(lang(lng_settings_emoji_list)); - setBlockTitle(true); +EmojiBox::EmojiBox(QWidget*) : _esize(EmojiSizes[EIndex + 1]) { +} +void EmojiBox::prepare() { + setTitle(lang(lng_settings_emoji_list)); fillBlocks(); + addButton(lang(lng_close), [this] { closeBox(); }); + _blockHeight = st::emojiReplaceInnerHeight; - resizeMaxHeight(_blocks[0].size() * st::emojiReplaceWidth + 2 * st::emojiReplacePadding, titleHeight() + st::emojiReplacePadding + _blocks.size() * st::emojiReplaceHeight + (st::emojiReplaceHeight - _blockHeight) + st::emojiReplacePadding); - - raiseShadow(); + setDimensions(_blocks[0].size() * st::emojiReplaceWidth + 2 * st::emojiReplacePadding, st::emojiReplacePadding + _blocks.size() * st::emojiReplaceHeight + (st::emojiReplaceHeight - _blockHeight) + st::emojiReplacePadding); } void EmojiBox::fillBlocks() { @@ -116,20 +117,20 @@ void EmojiBox::fillBlocks() { void EmojiBox::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { - onClose(); + closeBox(); } else { - AbstractBox::keyPressEvent(e); + BoxContent::keyPressEvent(e); } } void EmojiBox::paintEvent(QPaintEvent *e) { - AbstractBox::paintEvent(e); + BoxContent::paintEvent(e); Painter p(this); p.setFont(st::emojiTextFont); p.setPen(st::boxTextFg); - int32 top = titleHeight() + st::emojiReplacePadding + (st::emojiReplaceHeight - _blockHeight) / 2; + auto top = st::emojiReplacePadding + (st::emojiReplaceHeight - _blockHeight) / 2; for (Blocks::const_iterator i = _blocks.cbegin(), e = _blocks.cend(); i != e; ++i) { int32 rowSize = i->size(), left = (width() - rowSize * st::emojiReplaceWidth) / 2; for (BlockRow::const_iterator j = i->cbegin(), en = i->cend(); j != en; ++j) { diff --git a/Telegram/SourceFiles/boxes/emojibox.h b/Telegram/SourceFiles/boxes/emojibox.h index 4dad5370f..e6bf46a38 100644 --- a/Telegram/SourceFiles/boxes/emojibox.h +++ b/Telegram/SourceFiles/boxes/emojibox.h @@ -22,13 +22,13 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "boxes/abstractbox.h" -class EmojiBox : public AbstractBox { - Q_OBJECT - +class EmojiBox : public BoxContent { public: - EmojiBox(); + EmojiBox(QWidget*); protected: + void prepare() override; + void keyPressEvent(QKeyEvent *e) override; void paintEvent(QPaintEvent *e) override; diff --git a/Telegram/SourceFiles/boxes/languagebox.cpp b/Telegram/SourceFiles/boxes/languagebox.cpp index 5db3ebc32..16a789905 100644 --- a/Telegram/SourceFiles/boxes/languagebox.cpp +++ b/Telegram/SourceFiles/boxes/languagebox.cpp @@ -31,21 +31,22 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "langloaderplain.h" #include "styles/style_boxes.h" -LanguageBox::LanguageBox() : -_close(this, lang(lng_box_ok), st::defaultBoxButton) { - setTitleText(lang(lng_languages)); +void LanguageBox::prepare() { + addButton(lang(lng_box_ok), [this] { closeBox(); }); - bool haveTestLang = (cLang() == languageTest); + setTitle(lang(lng_languages)); - int32 y = titleHeight() + st::boxOptionListPadding.top(); + auto haveTestLang = (cLang() == languageTest); + + auto y = st::boxOptionListPadding.top(); _langs.reserve(languageCount + (haveTestLang ? 1 : 0)); if (haveTestLang) { _langs.push_back(new Ui::Radiobutton(this, qsl("lang"), languageTest, qsl("Custom Lang"), (cLang() == languageTest), st::langsButton)); _langs.back()->move(st::boxPadding.left() + st::boxOptionListPadding.left(), y); - y += _langs.back()->heightNoMargins() + st::boxOptionListPadding.top(); + y += _langs.back()->heightNoMargins() + st::boxOptionListSkip; connect(_langs.back(), SIGNAL(changed()), this, SLOT(onChange())); } - for (int32 i = 0; i < languageCount; ++i) { + for (auto i = 0; i != languageCount; ++i) { LangLoaderResult result; if (i) { LangLoaderPlain loader(qsl(":/langs/lang_") + LanguageCodes[i].c_str() + qsl(".strings"), langLoaderRequest(lng_language_name)); @@ -55,15 +56,12 @@ _close(this, lang(lng_box_ok), st::defaultBoxButton) { } _langs.push_back(new Ui::Radiobutton(this, qsl("lang"), i, result.value(lng_language_name, LanguageCodes[i].c_str() + qsl(" language")), (cLang() == i), st::langsButton)); _langs.back()->move(st::boxPadding.left() + st::boxOptionListPadding.left(), y); - y += _langs.back()->heightNoMargins() + st::boxOptionListPadding.top(); + y += _langs.back()->heightNoMargins() + st::boxOptionListSkip; connect(_langs.back(), SIGNAL(changed()), this, SLOT(onChange())); } - resizeMaxHeight(st::langsWidth, titleHeight() + (languageCount + (haveTestLang ? 1 : 0)) * (st::boxOptionListPadding.top() + st::langsButton.height) + st::boxOptionListPadding.bottom() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _close->height() + st::boxButtonPadding.bottom()); - - connect(_close, SIGNAL(clicked()), this, SLOT(onClose())); - - _close->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _close->height()); + auto optionsCount = languageCount + (haveTestLang ? 1 : 0); + setDimensions(st::langsWidth, st::boxOptionListPadding.top() + optionsCount * st::langsButton.height + (optionsCount - 1) * st::boxOptionListSkip + st::boxOptionListPadding.bottom() + st::boxPadding.bottom()); } void LanguageBox::mousePressEvent(QMouseEvent *e) { @@ -71,21 +69,21 @@ void LanguageBox::mousePressEvent(QMouseEvent *e) { for (int32 i = 1; i < languageCount; ++i) { LangLoaderPlain loader(qsl(":/langs/lang_") + LanguageCodes[i].c_str() + qsl(".strings"), langLoaderRequest(lngkeys_cnt)); if (!loader.errors().isEmpty()) { - Ui::showLayer(new InformBox(qsl("Lang \"") + LanguageCodes[i].c_str() + qsl("\" error :(\n\nError: ") + loader.errors())); + Ui::show(Box(qsl("Lang \"") + LanguageCodes[i].c_str() + qsl("\" error :(\n\nError: ") + loader.errors())); return; } else if (!loader.warnings().isEmpty()) { QString warn = loader.warnings(); if (warn.size() > 256) warn = warn.mid(0, 253) + qsl("..."); - Ui::showLayer(new InformBox(qsl("Lang \"") + LanguageCodes[i].c_str() + qsl("\" warnings :(\n\nWarnings: ") + warn)); + Ui::show(Box(qsl("Lang \"") + LanguageCodes[i].c_str() + qsl("\" warnings :(\n\nWarnings: ") + warn)); return; } } - Ui::showLayer(new InformBox(qsl("Everything seems great in all %1 languages!").arg(languageCount - 1))); + Ui::show(Box(qsl("Everything seems great in all %1 languages!").arg(languageCount - 1))); } } void LanguageBox::onChange() { - if (isHidden()) return; + if (!isBoxShown()) return; for (int32 i = 0, l = _langs.size(); i < l; ++i) { int32 langId = _langs[i]->val(); @@ -98,27 +96,28 @@ void LanguageBox::onChange() { LangLoaderPlain loader(cLangFile(), langLoaderRequest(lng_sure_save_language, lng_cancel, lng_box_ok)); result = loader.found(); } - QString text = result.value(lng_sure_save_language, langOriginal(lng_sure_save_language)), - save = result.value(lng_box_ok, langOriginal(lng_box_ok)), - cancel = result.value(lng_cancel, langOriginal(lng_cancel)); - ConfirmBox *box = new ConfirmBox(text, save, st::defaultBoxButton, cancel); - connect(box, SIGNAL(confirmed()), this, SLOT(onSave())); - connect(box, SIGNAL(cancelled()), this, SLOT(onRestore())); - Ui::showLayer(box, KeepOtherLayers); + auto text = result.value(lng_sure_save_language, langOriginal(lng_sure_save_language)), + save = result.value(lng_box_ok, langOriginal(lng_box_ok)), + cancel = result.value(lng_cancel, langOriginal(lng_cancel)); + Ui::show(Box(text, save, cancel, base::lambda_guarded(this, [this] { + saveLanguage(); + }), base::lambda_guarded(this, [this] { + restoreLanguage(); + })), KeepOtherLayers); } } } -void LanguageBox::onRestore() { - for (int32 i = 0, l = _langs.size(); i < l; ++i) { +void LanguageBox::restoreLanguage() { + for (auto i = 0, l = _langs.size(); i != l; ++i) { if (_langs[i]->val() == cLang()) { _langs[i]->setChecked(true); } } } -void LanguageBox::onSave() { - for (int32 i = 0, l = _langs.size(); i < l; ++i) { +void LanguageBox::saveLanguage() { + for (auto i = 0, l = _langs.size(); i != l; ++i) { if (_langs[i]->checked()) { cSetLang(_langs[i]->val()); Local::writeSettings(); diff --git a/Telegram/SourceFiles/boxes/languagebox.h b/Telegram/SourceFiles/boxes/languagebox.h index a8b09fa74..e1e666383 100644 --- a/Telegram/SourceFiles/boxes/languagebox.h +++ b/Telegram/SourceFiles/boxes/languagebox.h @@ -24,25 +24,27 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org namespace Ui { class Radiobutton; -class RoundButton; } // namespace Ui -class LanguageBox : public AbstractBox { +class LanguageBox : public BoxContent { Q_OBJECT public: - LanguageBox(); - -public slots: - void onChange(); - void onRestore(); - void onSave(); + LanguageBox(QWidget*) { + } protected: + void prepare() override; + void mousePressEvent(QMouseEvent *e) override; +private slots: + void onChange(); + private: + void saveLanguage(); + void restoreLanguage(); + QVector _langs; - ChildWidget _close; }; diff --git a/Telegram/SourceFiles/boxes/localstoragebox.cpp b/Telegram/SourceFiles/boxes/localstoragebox.cpp index bb08d17aa..1ce948406 100644 --- a/Telegram/SourceFiles/boxes/localstoragebox.cpp +++ b/Telegram/SourceFiles/boxes/localstoragebox.cpp @@ -27,13 +27,16 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "lang.h" #include "mainwindow.h" -LocalStorageBox::LocalStorageBox() : AbstractBox() -, _clear(this, lang(lng_local_storage_clear), st::boxLinkButton) -, _close(this, lang(lng_box_ok), st::defaultBoxButton) { - setTitleText(lang(lng_local_storage_title)); +LocalStorageBox::LocalStorageBox(QWidget *parent) +: _clear(this, lang(lng_local_storage_clear), st::boxLinkButton) { +} - connect(_clear, SIGNAL(clicked()), this, SLOT(onClear())); - connect(_close, SIGNAL(clicked()), this, SLOT(onClose())); +void LocalStorageBox::prepare() { + setTitle(lang(lng_local_storage_title)); + + addButton(lang(lng_box_ok), [this] { closeBox(); }); + + _clear->setClickedCallback([this] { clearStorage(); }); connect(App::wnd(), SIGNAL(tempDirCleared(int)), this, SLOT(onTempDirCleared(int))); connect(App::wnd(), SIGNAL(tempDirClearFailed(int)), this, SLOT(onTempDirClearFailed(int))); @@ -46,16 +49,15 @@ LocalStorageBox::LocalStorageBox() : AbstractBox() } void LocalStorageBox::updateControls() { - int rowsHeight = 0; + auto rowsHeight = 0; if (_imagesCount > 0 && _audiosCount > 0) { rowsHeight = 2 * (st::linkFont->height + st::localStorageBoxSkip); } else { rowsHeight = st::linkFont->height + st::localStorageBoxSkip; } _clear->setVisible(_imagesCount > 0 || _audiosCount > 0); - setMaxHeight(titleHeight() + st::localStorageBoxSkip + rowsHeight + _clear->height() + st::boxButtonPadding.top() + _close->height() + st::boxButtonPadding.bottom()); - _clear->moveToLeft(st::boxPadding.left(), titleHeight() + st::localStorageBoxSkip + rowsHeight); - _close->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _close->height()); + setDimensions(st::boxWidth, st::localStorageBoxSkip + rowsHeight + _clear->height()); + _clear->moveToLeft(st::boxPadding.left(), st::localStorageBoxSkip + rowsHeight); update(); } @@ -73,14 +75,14 @@ void LocalStorageBox::checkLocalStoredCounts() { } void LocalStorageBox::paintEvent(QPaintEvent *e) { - AbstractBox::paintEvent(e); + BoxContent::paintEvent(e); Painter p(this); p.setFont(st::boxTextFont); p.setPen(st::windowFg); checkLocalStoredCounts(); - int top = titleHeight() + st::localStorageBoxSkip; + auto top = st::localStorageBoxSkip; if (_imagesCount > 0) { auto text = lng_settings_images_cached(lt_count, _imagesCount, lt_size, formatSizeText(Local::storageImagesSize() + Local::storageStickersSize() + Local::storageWebFilesSize())); p.drawTextLeft(st::boxPadding.left(), top, width(), text); @@ -108,7 +110,7 @@ void LocalStorageBox::paintEvent(QPaintEvent *e) { } } -void LocalStorageBox::onClear() { +void LocalStorageBox::clearStorage() { App::wnd()->tempDirDelete(Local::ClearManagerStorage); _state = State::Clearing; updateControls(); diff --git a/Telegram/SourceFiles/boxes/localstoragebox.h b/Telegram/SourceFiles/boxes/localstoragebox.h index f8dd5dd50..17e87bf8f 100644 --- a/Telegram/SourceFiles/boxes/localstoragebox.h +++ b/Telegram/SourceFiles/boxes/localstoragebox.h @@ -23,25 +23,26 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "boxes/abstractbox.h" namespace Ui { -class RoundButton; class LinkButton; } // namespace Ui -class LocalStorageBox : public AbstractBox { +class LocalStorageBox : public BoxContent { Q_OBJECT public: - LocalStorageBox(); + LocalStorageBox(QWidget*); private slots: - void onClear(); void onTempDirCleared(int task); void onTempDirClearFailed(int task); protected: + void prepare() override; + void paintEvent(QPaintEvent *e) override; private: + void clearStorage(); void updateControls(); void checkLocalStoredCounts(); @@ -53,8 +54,7 @@ private: }; State _state = State::Normal; - ChildWidget _clear; - ChildWidget _close; + object_ptr _clear; int _imagesCount = -1; int _audiosCount = -1; diff --git a/Telegram/SourceFiles/boxes/members_box.cpp b/Telegram/SourceFiles/boxes/members_box.cpp index 275286afc..570b08735 100644 --- a/Telegram/SourceFiles/boxes/members_box.cpp +++ b/Telegram/SourceFiles/boxes/members_box.cpp @@ -60,22 +60,26 @@ QPoint MembersAddButton::prepareRippleStartPosition() const { return mapFromGlobal(QCursor::pos()) - _st.rippleAreaPosition; } -MembersBox::MembersBox(ChannelData *channel, MembersFilter filter) : ItemListBox(st::boxScroll) -, _inner(this, channel, filter) { - ItemListBox::init(_inner); +MembersBox::MembersBox(QWidget*, ChannelData *channel, MembersFilter filter) +: _channel(channel) +, _filter(filter) { +} - setTitleText(lang(_inner->filter() == MembersFilter::Recent ? lng_channel_members : lng_channel_admins)); - if (channel->amCreator() && (channel->membersCount() < (channel->isMegagroup() ? Global::MegagroupSizeMax() : Global::ChatSizeMax()) || (!channel->isMegagroup() && !channel->isPublic()) || filter == MembersFilter::Admins)) { - _add.create(this, st::contactsAdd); - _add->setClickedCallback([this] { onAdd(); }); +void MembersBox::prepare() { + setTitle(lang(_filter == MembersFilter::Recent ? lng_channel_members : lng_channel_admins)); + + _inner = setInnerWidget(object_ptr(this, _channel, _filter), st::boxLayerScroll); + + setDimensions(st::boxWideWidth, st::boxMaxListHeight); + addButton(lang(lng_close), [this] { closeBox(); }); + if (_channel->amCreator() && (_channel->membersCount() < (_channel->isMegagroup() ? Global::MegagroupSizeMax() : Global::ChatSizeMax()) || (!_channel->isMegagroup() && !_channel->isPublic()) || _filter == MembersFilter::Admins)) { + addLeftButton(lang((_filter == MembersFilter::Admins) ? lng_channel_add_admin : lng_channel_add_members), [this] { onAdd(); }); } - connect(scrollArea(), SIGNAL(scrolled()), this, SLOT(onScroll())); - connect(_inner, SIGNAL(mustScrollTo(int, int)), scrollArea(), SLOT(scrollToY(int, int))); + connect(_inner, SIGNAL(mustScrollTo(int, int)), this, SLOT(onScrollToY(int, int))); - connect(&_loadTimer, SIGNAL(timeout()), _inner, SLOT(load())); - - raiseShadow(); + _loadTimer.create(this); + connect(_loadTimer, SIGNAL(timeout()), _inner, SLOT(load())); } void MembersBox::keyPressEvent(QKeyEvent *e) { @@ -84,47 +88,41 @@ void MembersBox::keyPressEvent(QKeyEvent *e) { } else if (e->key() == Qt::Key_Up) { _inner->selectSkip(-1); } else if (e->key() == Qt::Key_PageDown) { - _inner->selectSkipPage(scrollArea()->height(), 1); + _inner->selectSkipPage(height(), 1); } else if (e->key() == Qt::Key_PageUp) { - _inner->selectSkipPage(scrollArea()->height(), -1); + _inner->selectSkipPage(height(), -1); } else { - ItemListBox::keyPressEvent(e); + BoxContent::keyPressEvent(e); } } void MembersBox::resizeEvent(QResizeEvent *e) { - ItemListBox::resizeEvent(e); + BoxContent::resizeEvent(e); + _inner->resize(width(), _inner->height()); - - if (_add) { - _add->moveToRight(st::contactsAddPosition.x(), height() - st::contactsAddPosition.y() - _add->height()); - } -} - -void MembersBox::onScroll() { - _inner->loadProfilePhotos(scrollArea()->scrollTop()); } void MembersBox::onAdd() { if (_inner->filter() == MembersFilter::Recent && _inner->channel()->membersCount() >= (_inner->channel()->isMegagroup() ? Global::MegagroupSizeMax() : Global::ChatSizeMax())) { - Ui::showLayer(new MaxInviteBox(_inner->channel()->inviteLink()), KeepOtherLayers); + Ui::show(Box(_inner->channel()->inviteLink()), KeepOtherLayers); return; } - ContactsBox *box = new ContactsBox(_inner->channel(), _inner->filter(), _inner->already()); + auto box = Box(_inner->channel(), _inner->filter(), _inner->already()); if (_inner->filter() == MembersFilter::Recent) { - Ui::showLayer(box); + Ui::show(std_::move(box)); } else { - _addBox = box; - connect(_addBox, SIGNAL(adminAdded()), this, SLOT(onAdminAdded())); - Ui::showLayer(_addBox, KeepOtherLayers); + _addBox = Ui::show(std_::move(box), KeepOtherLayers); + if (_addBox) { + connect(_addBox, SIGNAL(adminAdded()), this, SLOT(onAdminAdded())); + } } } void MembersBox::onAdminAdded() { if (!_addBox) return; - _addBox->onClose(); - _addBox = 0; - _loadTimer.start(ReloadChannelMembersTimeout); + _addBox->closeBox(); + _addBox = nullptr; + _loadTimer->start(ReloadChannelMembersTimeout); } MembersBox::Inner::Inner(QWidget *parent, ChannelData *channel, MembersFilter filter) : TWidget(parent) @@ -169,8 +167,9 @@ void MembersBox::Inner::paintEvent(QPaintEvent *e) { _time = unixtime(); p.fillRect(r, st::contactsBg); - int32 yFrom = r.y() - st::membersPadding.top(), yTo = r.y() + r.height() - st::membersPadding.top(); - p.translate(0, st::membersPadding.top()); + auto yFrom = r.y() - st::membersMarginTop; + auto yTo = r.y() + r.height() - st::membersMarginTop; + p.translate(0, st::membersMarginTop); if (_rows.isEmpty()) { p.setFont(st::noContactsFont); p.setPen(st::noContactsColor); @@ -229,28 +228,18 @@ void MembersBox::Inner::mouseReleaseEvent(QMouseEvent *e) { if (_kickDown >= 0 && _kickDown == _kickSel && !_kickRequestId) { _kickConfirm = _rows.at(_kickSel); if (_kickBox) _kickBox->deleteLater(); - _kickBox = new ConfirmBox((_filter == MembersFilter::Recent ? (_channel->isMegagroup() ? lng_profile_sure_kick : lng_profile_sure_kick_channel) : lng_profile_sure_kick_admin)(lt_user, _kickConfirm->firstName)); - connect(_kickBox, SIGNAL(confirmed()), this, SLOT(onKickConfirm())); - connect(_kickBox, SIGNAL(destroyed(QObject*)), this, SLOT(onKickBoxDestroyed(QObject*))); - Ui::showLayer(_kickBox, KeepOtherLayers); + auto text = (_filter == MembersFilter::Recent ? (_channel->isMegagroup() ? lng_profile_sure_kick : lng_profile_sure_kick_channel) : lng_profile_sure_kick_admin)(lt_user, _kickConfirm->firstName); + _kickBox = Ui::show(Box(text, base::lambda_guarded(this, [this] { + if (_filter == MembersFilter::Recent) { + _kickRequestId = MTP::send(MTPchannels_KickFromChannel(_channel->inputChannel, _kickConfirm->inputUser, MTP_bool(true)), rpcDone(&Inner::kickDone), rpcFail(&Inner::kickFail)); + } else { + _kickRequestId = MTP::send(MTPchannels_EditAdmin(_channel->inputChannel, _kickConfirm->inputUser, MTP_channelRoleEmpty()), rpcDone(&Inner::kickAdminDone), rpcFail(&Inner::kickFail)); + } + })), KeepOtherLayers); } _kickDown = -1; } -void MembersBox::Inner::onKickBoxDestroyed(QObject *obj) { - if (_kickBox == obj) { - _kickBox = 0; - } -} - -void MembersBox::Inner::onKickConfirm() { - if (_filter == MembersFilter::Recent) { - _kickRequestId = MTP::send(MTPchannels_KickFromChannel(_channel->inputChannel, _kickConfirm->inputUser, MTP_bool(true)), rpcDone(&Inner::kickDone), rpcFail(&Inner::kickFail)); - } else { - _kickRequestId = MTP::send(MTPchannels_EditAdmin(_channel->inputChannel, _kickConfirm->inputUser, MTP_channelRoleEmpty()), rpcDone(&Inner::kickAdminDone), rpcFail(&Inner::kickFail)); - } -} - void MembersBox::Inner::paintDialog(Painter &p, PeerData *peer, MemberData *data, bool sel, bool kickSel, bool kickDown) { UserData *user = peer->asUser(); @@ -317,9 +306,11 @@ void MembersBox::Inner::selectSkipPage(int32 h, int32 dir) { selectSkip(points * dir); } -void MembersBox::Inner::loadProfilePhotos(int32 yFrom) { - if (!parentWidget()) return; - int32 yTo = yFrom + parentWidget()->height() * 5; +void MembersBox::Inner::loadProfilePhotos() { + if (_visibleTop >= _visibleBottom) return; + + auto yFrom = _visibleTop; + auto yTo = yFrom + (_visibleBottom - _visibleTop) * 5; MTP::clearLoaderPriorities(); if (yTo < 0) return; @@ -349,7 +340,7 @@ void MembersBox::Inner::chooseParticipant() { void MembersBox::Inner::refresh() { if (_rows.isEmpty()) { - resize(width(), st::membersPadding.top() + st::noContactsHeight + st::membersPadding.bottom()); + resize(width(), st::membersMarginTop + st::noContactsHeight + st::membersMarginBottom); _aboutHeight = 0; } else { _about.setText(st::boxTextFont, lng_channel_only_last_shown(lt_count, _rows.size())); @@ -357,7 +348,7 @@ void MembersBox::Inner::refresh() { if (_filter != MembersFilter::Recent || (_rows.size() >= _channel->membersCount() && _rows.size() < Global::ChatSizeMax())) { _aboutHeight = 0; } - resize(width(), st::membersPadding.top() + _rows.size() * _rowHeight + st::membersPadding.bottom() + _aboutHeight); + resize(width(), st::membersMarginTop + _aboutHeight + _rows.size() * _rowHeight + st::membersMarginBottom); } update(); } @@ -380,6 +371,12 @@ MembersAlreadyIn MembersBox::Inner::already() const { return result; } +void MembersBox::Inner::setVisibleTopBottom(int visibleTop, int visibleBottom) { + _visibleTop = visibleTop; + _visibleBottom = visibleBottom; + loadProfilePhotos(); +} + void MembersBox::Inner::clearSel() { updateSelectedRow(); _sel = _kickSel = _kickDown = -1; @@ -426,7 +423,7 @@ void MembersBox::Inner::updateSel() { if (!_mouseSel) return; QPoint p(mapFromGlobal(_lastMousePos)); - p.setY(p.y() - st::membersPadding.top()); + p.setY(p.y() - st::membersMarginTop); bool in = parentWidget()->rect().contains(parentWidget()->mapFromGlobal(_lastMousePos)); int32 newSel = (in && p.y() >= 0 && p.y() < _rows.size() * _rowHeight) ? (p.y() / _rowHeight) : -1; int32 newKickSel = newSel; @@ -448,7 +445,7 @@ void MembersBox::Inner::peerUpdated(PeerData *peer) { void MembersBox::Inner::updateSelectedRow() { if (_sel >= 0) { - update(0, st::membersPadding.top() + _sel * _rowHeight, width(), _rowHeight); + update(0, st::membersMarginTop + _sel * _rowHeight, width(), _rowHeight); } } @@ -457,7 +454,7 @@ void MembersBox::Inner::onPeerNameChanged(PeerData *peer, const PeerData::Names if (_rows.at(i) == peer) { if (_datas.at(i)) { _datas.at(i)->name.setText(st::contactsNameFont, peer->name, _textNameOptions); - update(0, st::membersPadding.top() + i * _rowHeight, width(), _rowHeight); + update(0, st::membersMarginTop + i * _rowHeight, width(), _rowHeight); } else { break; } @@ -566,20 +563,20 @@ void MembersBox::Inner::kickDone(const MTPUpdates &result, mtpRequestId req) { if (_kickRequestId != req) return; removeKicked(); - if (_kickBox) _kickBox->onClose(); + if (_kickBox) _kickBox->closeBox(); } void MembersBox::Inner::kickAdminDone(const MTPUpdates &result, mtpRequestId req) { if (_kickRequestId != req) return; if (App::main()) App::main()->sentUpdatesReceived(result); removeKicked(); - if (_kickBox) _kickBox->onClose(); + if (_kickBox) _kickBox->closeBox(); } bool MembersBox::Inner::kickFail(const RPCError &error, mtpRequestId req) { if (MTP::isDefaultHandledError(error)) return false; - if (_kickBox) _kickBox->onClose(); + if (_kickBox) _kickBox->closeBox(); load(); return true; } diff --git a/Telegram/SourceFiles/boxes/members_box.h b/Telegram/SourceFiles/boxes/members_box.h index ae1957f5f..53cfd0086 100644 --- a/Telegram/SourceFiles/boxes/members_box.h +++ b/Telegram/SourceFiles/boxes/members_box.h @@ -49,31 +49,33 @@ private: }; -class MembersBox : public ItemListBox { +class MembersBox : public BoxContent { Q_OBJECT public: - MembersBox(ChannelData *channel, MembersFilter filter); + MembersBox(QWidget*, ChannelData *channel, MembersFilter filter); public slots: - void onScroll(); - void onAdminAdded(); protected: + void prepare() override; + void keyPressEvent(QKeyEvent *e) override; void resizeEvent(QResizeEvent *e) override; private: void onAdd(); + ChannelData *_channel = nullptr; + MembersFilter _filter = MembersFilter::Recent; + class Inner; - ChildWidget _inner; - ChildWidget _add = { nullptr }; + QPointer _inner; - ContactsBox *_addBox = nullptr; + QPointer _addBox; - SingleTimer _loadTimer; + object_ptr _loadTimer = { nullptr }; }; @@ -87,7 +89,6 @@ public: void selectSkip(int32 dir); void selectSkipPage(int32 h, int32 dir); - void loadProfilePhotos(int32 yFrom); void chooseParticipant(); void refresh(); @@ -101,6 +102,7 @@ public: void clearSel(); MembersAlreadyIn already() const; + void setVisibleTopBottom(int visibleTop, int visibleBottom) override; ~Inner(); @@ -114,8 +116,6 @@ public slots: void updateSel(); void peerUpdated(PeerData *peer); void onPeerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars); - void onKickConfirm(); - void onKickBoxDestroyed(QObject *obj); protected: void paintEvent(QPaintEvent *e) override; @@ -133,6 +133,8 @@ private: bool canKick; }; + void loadProfilePhotos(); + void updateSelectedRow(); MemberData *data(int32 index); @@ -149,6 +151,8 @@ private: void clear(); int _rowHeight; + int _visibleTop = 0; + int _visibleBottom = 0; ChannelData *_channel; MembersFilter _filter; @@ -162,7 +166,7 @@ private: UserData *_kickConfirm; mtpRequestId _kickRequestId; - ConfirmBox *_kickBox; + QPointer _kickBox; enum class MemberRole { None, diff --git a/Telegram/SourceFiles/boxes/notifications_box.cpp b/Telegram/SourceFiles/boxes/notifications_box.cpp index bd21d9e8b..66f9b817b 100644 --- a/Telegram/SourceFiles/boxes/notifications_box.cpp +++ b/Telegram/SourceFiles/boxes/notifications_box.cpp @@ -108,11 +108,15 @@ private: }; -NotificationsBox::NotificationsBox() : AbstractBox() -, _chosenCorner(Global::NotificationsCorner()) +NotificationsBox::NotificationsBox(QWidget *parent) +: _chosenCorner(Global::NotificationsCorner()) , _oldCount(snap(Global::NotificationsCount(), 1, kMaxNotificationsCount)) -, _countSlider(this) -, _done(this, lang(lng_about_done), st::defaultBoxButton) { +, _countSlider(this) { +} + +void NotificationsBox::prepare() { + addButton(lang(lng_close), [this] { closeBox(); }); + _sampleOpacities.reserve(kMaxNotificationsCount); for (int i = 0; i != kMaxNotificationsCount; ++i) { _countSlider->addSection(QString::number(i + 1)); @@ -122,15 +126,15 @@ NotificationsBox::NotificationsBox() : AbstractBox() _countSlider->setSectionActivatedCallback([this] { countChanged(); }); setMouseTracking(true); - _done->setClickedCallback([this] { onClose(); }); prepareNotificationSampleSmall(); prepareNotificationSampleLarge(); - setMaxHeight(st::notificationsBoxHeight); + + setDimensions(st::boxWideWidth, st::notificationsBoxHeight); } void NotificationsBox::paintEvent(QPaintEvent *e) { - AbstractBox::paintEvent(e); + BoxContent::paintEvent(e); Painter p(this); @@ -203,14 +207,13 @@ QRect NotificationsBox::getScreenRect() const { } void NotificationsBox::resizeEvent(QResizeEvent *e) { - _done->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _done->height()); + BoxContent::resizeEvent(e); auto screenRect = getScreenRect(); auto sliderTop = screenRect.y() + screenRect.height() + st::notificationsBoxCountLabelTop + st::notificationsBoxCountTop; auto contentLeft = getContentLeft(); _countSlider->resizeToWidth(width() - 2 * contentLeft); _countSlider->move(contentLeft, sliderTop); - AbstractBox::resizeEvent(e); } void NotificationsBox::prepareNotificationSampleSmall() { diff --git a/Telegram/SourceFiles/boxes/notifications_box.h b/Telegram/SourceFiles/boxes/notifications_box.h index 58259011d..92c3e32a1 100644 --- a/Telegram/SourceFiles/boxes/notifications_box.h +++ b/Telegram/SourceFiles/boxes/notifications_box.h @@ -23,17 +23,18 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "boxes/abstractbox.h" namespace Ui { -class RoundButton; class LinkButton; class SettingsSlider; } // namespace Ui -class NotificationsBox : public AbstractBox { +class NotificationsBox : public BoxContent { public: - NotificationsBox(); + NotificationsBox(QWidget*); ~NotificationsBox(); protected: + void prepare() override; + void paintEvent(QPaintEvent *e) override; void resizeEvent(QResizeEvent *e) override; void mousePressEvent(QMouseEvent *e) override; @@ -70,8 +71,7 @@ private: ScreenCorner _downCorner = ScreenCorner::TopLeft; int _oldCount; - ChildWidget _countSlider; - ChildWidget _done; + object_ptr _countSlider; QVector _cornerSamples[4]; diff --git a/Telegram/SourceFiles/boxes/passcodebox.cpp b/Telegram/SourceFiles/boxes/passcodebox.cpp index 41e23f151..299287312 100644 --- a/Telegram/SourceFiles/boxes/passcodebox.cpp +++ b/Telegram/SourceFiles/boxes/passcodebox.cpp @@ -29,29 +29,24 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "ui/widgets/buttons.h" #include "ui/widgets/input_fields.h" -PasscodeBox::PasscodeBox(bool turningOff) : AbstractBox(st::boxWidth) -, _turningOff(turningOff) +PasscodeBox::PasscodeBox(QWidget*, bool turningOff) +: _turningOff(turningOff) , _about(st::boxWidth - st::boxPadding.left() * 1.5) -, _saveButton(this, lang(_turningOff ? lng_passcode_remove_button : lng_settings_save), st::defaultBoxButton) -, _cancelButton(this, lang(lng_cancel), st::cancelBoxButton) , _oldPasscode(this, st::defaultInputField, lang(lng_passcode_enter_old)) , _newPasscode(this, st::defaultInputField, lang(Global::LocalPasscode() ? lng_passcode_enter_new : lng_passcode_enter_first)) , _reenterPasscode(this, st::defaultInputField, lang(lng_passcode_confirm_new)) , _passwordHint(this, st::defaultInputField, lang(lng_cloud_password_hint)) , _recoverEmail(this, st::defaultInputField, lang(lng_cloud_password_email)) , _recover(this, lang(lng_signin_recover)) { - init(); } -PasscodeBox::PasscodeBox(const QByteArray &newSalt, const QByteArray &curSalt, bool hasRecovery, const QString &hint, bool turningOff) : AbstractBox(st::boxWidth) -, _turningOff(turningOff) +PasscodeBox::PasscodeBox(QWidget*, const QByteArray &newSalt, const QByteArray &curSalt, bool hasRecovery, const QString &hint, bool turningOff) +: _turningOff(turningOff) , _cloudPwd(true) , _newSalt(newSalt) , _curSalt(curSalt) , _hasRecovery(hasRecovery) , _about(st::boxWidth - st::boxPadding.left() * 1.5) -, _saveButton(this, lang(_turningOff ? lng_passcode_remove_button : lng_settings_save), st::defaultBoxButton) -, _cancelButton(this, lang(lng_cancel), st::cancelBoxButton) , _oldPasscode(this, st::defaultInputField, lang(lng_cloud_password_enter_old)) , _newPasscode(this, st::defaultInputField, lang(curSalt.isEmpty() ? lng_cloud_password_enter_first : lng_cloud_password_enter_new)) , _reenterPasscode(this, st::defaultInputField, lang(lng_cloud_password_confirm_new)) @@ -61,12 +56,11 @@ PasscodeBox::PasscodeBox(const QByteArray &newSalt, const QByteArray &curSalt, b textstyleSet(&st::usernameTextStyle); if (!hint.isEmpty()) _hintText.setText(st::normalFont, lng_signin_hint(lt_password_hint, hint)); textstyleRestore(); - - init(); } -void PasscodeBox::init() { - setBlockTitle(true); +void PasscodeBox::prepare() { + addButton(lang(_turningOff ? lng_passcode_remove_button : lng_settings_save), [this] { onSave(); }); + addButton(lang(lng_cancel), [this] { closeBox(); }); textstyleSet(&st::usernameTextStyle); _about.setRichText(st::normalFont, lang(_cloudPwd ? lng_cloud_password_about : lng_passcode_about)); @@ -74,24 +68,21 @@ void PasscodeBox::init() { textstyleRestore(); if (_turningOff) { _oldPasscode->show(); - setTitleText(lang(_cloudPwd ? lng_cloud_password_remove : lng_passcode_remove)); - setMaxHeight(titleHeight() + st::passcodePadding.top() + _oldPasscode->height() + st::passcodeTextLine + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeTextLine : 0) + _aboutHeight + st::passcodePadding.bottom() + st::boxButtonPadding.top() + _saveButton->height() + st::boxButtonPadding.bottom()); + setTitle(lang(_cloudPwd ? lng_cloud_password_remove : lng_passcode_remove)); + setDimensions(st::boxWidth, st::passcodePadding.top() + _oldPasscode->height() + st::passcodeTextLine + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeTextLine : 0) + _aboutHeight + st::passcodePadding.bottom()); } else { - bool has = _cloudPwd ? (!_curSalt.isEmpty()) : Global::LocalPasscode(); + auto has = _cloudPwd ? (!_curSalt.isEmpty()) : Global::LocalPasscode(); if (has) { _oldPasscode->show(); - setTitleText(lang(_cloudPwd ? lng_cloud_password_change : lng_passcode_change)); - setMaxHeight(titleHeight() + st::passcodePadding.top() + _oldPasscode->height() + st::passcodeTextLine + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeTextLine : 0) + _newPasscode->height() + st::contactSkip + _reenterPasscode->height() + st::passcodeSkip + (_cloudPwd ? _passwordHint->height() + st::contactSkip : 0) + _aboutHeight + st::passcodePadding.bottom() + st::boxButtonPadding.top() + _saveButton->height() + st::boxButtonPadding.bottom()); + setTitle(lang(_cloudPwd ? lng_cloud_password_change : lng_passcode_change)); + setDimensions(st::boxWidth, st::passcodePadding.top() + _oldPasscode->height() + st::passcodeTextLine + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeTextLine : 0) + _newPasscode->height() + st::passcodeLittleSkip + _reenterPasscode->height() + st::passcodeSkip + (_cloudPwd ? _passwordHint->height() + st::passcodeLittleSkip : 0) + _aboutHeight + st::passcodePadding.bottom()); } else { _oldPasscode->hide(); - setTitleText(lang(_cloudPwd ? lng_cloud_password_create : lng_passcode_create)); - setMaxHeight(titleHeight() + st::passcodePadding.top() + _newPasscode->height() + st::contactSkip + _reenterPasscode->height() + st::passcodeSkip + (_cloudPwd ? _passwordHint->height() + st::contactSkip : 0) + _aboutHeight + (_cloudPwd ? st::contactSkip + _recoverEmail->height() + st::passcodeSkip : st::passcodePadding.bottom()) + st::boxButtonPadding.top() + _saveButton->height() + st::boxButtonPadding.bottom()); + setTitle(lang(_cloudPwd ? lng_cloud_password_create : lng_passcode_create)); + setDimensions(st::boxWidth, st::passcodePadding.top() + _newPasscode->height() + st::passcodeLittleSkip + _reenterPasscode->height() + st::passcodeSkip + (_cloudPwd ? _passwordHint->height() + st::passcodeLittleSkip : 0) + _aboutHeight + (_cloudPwd ? st::passcodeLittleSkip + _recoverEmail->height() + st::passcodeSkip : st::passcodePadding.bottom())); } } - connect(_saveButton, SIGNAL(clicked()), this, SLOT(onSave())); - connect(_cancelButton, SIGNAL(clicked()), this, SLOT(onClose())); - connect(_oldPasscode, SIGNAL(changed()), this, SLOT(onOldChanged())); connect(_newPasscode, SIGNAL(changed()), this, SLOT(onNewChanged())); connect(_reenterPasscode, SIGNAL(changed()), this, SLOT(onNewChanged())); @@ -113,8 +104,6 @@ void PasscodeBox::init() { _reenterPasscode->setVisible(!_turningOff); _passwordHint->setVisible(!_turningOff && _cloudPwd); _recoverEmail->setVisible(!_turningOff && _cloudPwd && _curSalt.isEmpty()); - - raiseShadow(); } void PasscodeBox::onSubmit() { @@ -153,14 +142,14 @@ void PasscodeBox::onSubmit() { } void PasscodeBox::paintEvent(QPaintEvent *e) { - AbstractBox::paintEvent(e); + BoxContent::paintEvent(e); Painter p(this); textstyleSet(&st::usernameTextStyle); int32 w = st::boxWidth - st::boxPadding.left() * 1.5; - int32 abouty = (_passwordHint->isHidden() ? (_reenterPasscode->isHidden() ? (_oldPasscode->y() + (_hasRecovery && !_hintText.isEmpty() ? st::passcodeTextLine : 0)) : _reenterPasscode->y()) + st::passcodeSkip : _passwordHint->y() + st::contactSkip) + _oldPasscode->height() + st::passcodePadding.bottom(); + int32 abouty = (_passwordHint->isHidden() ? (_reenterPasscode->isHidden() ? (_oldPasscode->y() + (_hasRecovery && !_hintText.isEmpty() ? st::passcodeTextLine : 0)) : _reenterPasscode->y()) + st::passcodeSkip : _passwordHint->y() + st::passcodeLittleSkip) + _oldPasscode->height() + st::passcodePadding.bottom(); p.setPen(st::boxTextFg); _about.drawLeft(p, st::boxPadding.left(), abouty, w, width()); @@ -187,30 +176,27 @@ void PasscodeBox::paintEvent(QPaintEvent *e) { } void PasscodeBox::resizeEvent(QResizeEvent *e) { + BoxContent::resizeEvent(e); + bool has = _cloudPwd ? (!_curSalt.isEmpty()) : Global::LocalPasscode(); int32 w = st::boxWidth - st::boxPadding.left() - st::boxPadding.right(); _oldPasscode->resize(w, _oldPasscode->height()); - _oldPasscode->moveToLeft(st::boxPadding.left(), titleHeight() + st::passcodePadding.top()); + _oldPasscode->moveToLeft(st::boxPadding.left(), st::passcodePadding.top()); _newPasscode->resize(w, _newPasscode->height()); _newPasscode->moveToLeft(st::boxPadding.left(), _oldPasscode->y() + ((_turningOff || has) ? (_oldPasscode->height() + st::passcodeTextLine + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeTextLine : 0)) : 0)); _reenterPasscode->resize(w, _reenterPasscode->height()); - _reenterPasscode->moveToLeft(st::boxPadding.left(), _newPasscode->y() + _newPasscode->height() + st::contactSkip); + _reenterPasscode->moveToLeft(st::boxPadding.left(), _newPasscode->y() + _newPasscode->height() + st::passcodeLittleSkip); _passwordHint->resize(w, _passwordHint->height()); _passwordHint->moveToLeft(st::boxPadding.left(), _reenterPasscode->y() + _reenterPasscode->height() + st::passcodeSkip); _recoverEmail->resize(w, _passwordHint->height()); - _recoverEmail->moveToLeft(st::boxPadding.left(), _passwordHint->y() + _passwordHint->height() + st::contactSkip + _aboutHeight + st::contactSkip); + _recoverEmail->moveToLeft(st::boxPadding.left(), _passwordHint->y() + _passwordHint->height() + st::passcodeLittleSkip + _aboutHeight + st::passcodeLittleSkip); if (!_recover->isHidden()) { _recover->moveToLeft(st::boxPadding.left(), _oldPasscode->y() + _oldPasscode->height() + (_hintText.isEmpty() ? ((st::passcodeTextLine - _recover->height()) / 2) : st::passcodeTextLine)); } - - _saveButton->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _saveButton->height()); - _cancelButton->moveToRight(st::boxButtonPadding.right() + _saveButton->width() + st::boxButtonPadding.left(), _saveButton->y()); - - AbstractBox::resizeEvent(e); } -void PasscodeBox::doSetInnerFocus() { +void PasscodeBox::setInnerFocus() { if (_skipEmailWarning && !_recoverEmail->isHidden()) { _recoverEmail->setFocus(); } else if (_oldPasscode->isHidden()) { @@ -223,15 +209,23 @@ void PasscodeBox::doSetInnerFocus() { void PasscodeBox::setPasswordDone(const MTPBool &result) { _setRequest = 0; emit reloadPassword(); - ConfirmBox *box = new InformBox(lang(_reenterPasscode->isHidden() ? lng_cloud_password_removed : (_oldPasscode->isHidden() ? lng_cloud_password_was_set : lng_cloud_password_updated))); - Ui::showLayer(box); + auto text = lang(_reenterPasscode->isHidden() ? lng_cloud_password_removed : (_oldPasscode->isHidden() ? lng_cloud_password_was_set : lng_cloud_password_updated)); + Ui::show(Box(text)); +} + +void PasscodeBox::closeReplacedBy() { + if (isHidden()) { + if (_replacedBy && !_replacedBy->isHidden()) { + _replacedBy->closeBox(); + } + } } bool PasscodeBox::setPasswordFail(const RPCError &error) { if (MTP::isFloodError(error)) { if (_oldPasscode->isHidden()) return false; - if (isHidden() && _replacedBy && !_replacedBy->isHidden()) _replacedBy->onClose(); + closeReplacedBy(); _setRequest = 0; _oldPasscode->selectAll(); @@ -246,13 +240,13 @@ bool PasscodeBox::setPasswordFail(const RPCError &error) { } if (MTP::isDefaultHandledError(error)) return false; - if (isHidden() && _replacedBy && !_replacedBy->isHidden()) _replacedBy->onClose(); + closeReplacedBy(); _setRequest = 0; QString err = error.type(); if (err == qstr("PASSWORD_HASH_INVALID")) { if (_oldPasscode->isHidden()) { emit reloadPassword(); - onClose(); + closeBox(); } else { onBadOldPasscode(); } @@ -263,14 +257,14 @@ bool PasscodeBox::setPasswordFail(const RPCError &error) { update(); } else if (err == qstr("NEW_SALT_INVALID")) { emit reloadPassword(); - onClose(); + closeBox(); } else if (err == qstr("EMAIL_INVALID")) { _emailError = lang(lng_cloud_password_bad_email); _recoverEmail->setFocus(); _recoverEmail->showError(); update(); } else if (err == qstr("EMAIL_UNCONFIRMED")) { - Ui::showLayer(new InformBox(lang(lng_cloud_password_almost))); + Ui::show(Box(lang(lng_cloud_password_almost))); emit reloadPassword(); } return true; @@ -303,7 +297,7 @@ void PasscodeBox::onSave(bool force) { if (!_turningOff && pwd.isEmpty()) { _newPasscode->setFocus(); _newPasscode->showError(); - if (isHidden() && _replacedBy && !_replacedBy->isHidden()) _replacedBy->onClose(); + closeReplacedBy(); return; } if (pwd != conf) { @@ -314,13 +308,13 @@ void PasscodeBox::onSave(bool force) { _newError = lang(_cloudPwd ? lng_cloud_password_differ : lng_passcode_differ); update(); } - if (isHidden() && _replacedBy && !_replacedBy->isHidden()) _replacedBy->onClose(); + closeReplacedBy(); } else if (!_turningOff && has && old == pwd) { _newPasscode->setFocus(); _newPasscode->showError(); _newError = lang(_cloudPwd ? lng_cloud_password_is_same : lng_passcode_is_same); update(); - if (isHidden() && _replacedBy && !_replacedBy->isHidden()) _replacedBy->onClose(); + closeReplacedBy(); } else if (_cloudPwd) { QString hint = _passwordHint->getLastText(), email = _recoverEmail->getLastText().trimmed(); if (_cloudPwd && pwd == hint && !_passwordHint->isHidden() && !_newPasscode->isHidden()) { @@ -328,15 +322,14 @@ void PasscodeBox::onSave(bool force) { _newPasscode->showError(); _newError = lang(lng_cloud_password_bad); update(); - if (isHidden() && _replacedBy && !_replacedBy->isHidden()) _replacedBy->onClose(); + closeReplacedBy(); return; } if (!_recoverEmail->isHidden() && email.isEmpty() && !force) { _skipEmailWarning = true; - _replacedBy = new ConfirmBox(lang(lng_cloud_password_about_recover), lang(lng_cloud_password_skip_email), st::attentionBoxButton); - connect(_replacedBy, SIGNAL(confirmed()), this, SLOT(onForceNoMail())); - connect(_replacedBy, SIGNAL(destroyed(QObject*)), this, SLOT(onBoxDestroyed(QObject*))); - Ui::showLayer(_replacedBy, KeepOtherLayers); + _replacedBy = Ui::show(Box(lang(lng_cloud_password_about_recover), lang(lng_cloud_password_skip_email), st::attentionBoxButton, base::lambda_guarded(this, [this] { + onSave(true); + })), KeepOtherLayers); } else { QByteArray newPasswordData = pwd.isEmpty() ? QByteArray() : (_newSalt + pwd.toUtf8() + _newSalt); QByteArray newPasswordHash = pwd.isEmpty() ? QByteArray() : QByteArray(32, Qt::Uninitialized); @@ -362,7 +355,7 @@ void PasscodeBox::onSave(bool force) { cSetPasscodeBadTries(0); Local::setPasscode(pwd.toUtf8()); App::wnd()->checkAutoLock(); - onClose(); + closeBox(); } } @@ -401,16 +394,6 @@ void PasscodeBox::onEmailChanged() { } } -void PasscodeBox::onForceNoMail() { - onSave(true); -} - -void PasscodeBox::onBoxDestroyed(QObject *obj) { - if (obj == _replacedBy) { - _replacedBy = 0; - } -} - void PasscodeBox::onRecoverByEmail() { if (_pattern.isEmpty()) { _pattern = "-"; @@ -427,11 +410,9 @@ void PasscodeBox::onRecoverExpired() { void PasscodeBox::recover() { if (_pattern == "-") return; - _replacedBy = new RecoverBox(_pattern); + _replacedBy = Ui::show(Box(_pattern), KeepOtherLayers); connect(_replacedBy, SIGNAL(reloadPassword()), this, SIGNAL(reloadPassword())); connect(_replacedBy, SIGNAL(recoveryExpired()), this, SLOT(onRecoverExpired())); - connect(_replacedBy, SIGNAL(destroyed(QObject*)), this, SLOT(onBoxDestroyed(QObject*))); - Ui::showLayer(_replacedBy, KeepOtherLayers); } void PasscodeBox::recoverStarted(const MTPauth_PasswordRecovery &result) { @@ -443,31 +424,29 @@ bool PasscodeBox::recoverStartFail(const RPCError &error) { if (MTP::isDefaultHandledError(error)) return false; _pattern = QString(); - onClose(); + closeBox(); return true; } -RecoverBox::RecoverBox(const QString &pattern) : AbstractBox(st::boxWidth, lang(lng_signin_recover_title)) -, _submitRequest(0) -, _pattern(st::normalFont->elided(lng_signin_recover_hint(lt_recover_email, pattern), st::boxWidth - st::boxPadding.left() * 1.5)) -, _saveButton(this, lang(lng_passcode_submit), st::defaultBoxButton) -, _cancelButton(this, lang(lng_cancel), st::cancelBoxButton) +RecoverBox::RecoverBox(QWidget*, const QString &pattern) +: _pattern(st::normalFont->elided(lng_signin_recover_hint(lt_recover_email, pattern), st::boxWidth - st::boxPadding.left() * 1.5)) , _recoverCode(this, st::defaultInputField, lang(lng_signin_code)) { - setBlockTitle(true); +} - setMaxHeight(titleHeight() + st::passcodePadding.top() + st::passcodePadding.bottom() + st::passcodeTextLine + _recoverCode->height() + st::passcodeTextLine + st::boxButtonPadding.top() + _saveButton->height() + st::boxButtonPadding.bottom()); +void RecoverBox::prepare() { + setTitle(lang(lng_signin_recover_title)); - connect(_saveButton, SIGNAL(clicked()), this, SLOT(onSubmit())); - connect(_cancelButton, SIGNAL(clicked()), this, SLOT(onClose())); + addButton(lang(lng_passcode_submit), [this] { onSubmit(); }); + addButton(lang(lng_cancel), [this] { closeBox(); }); + + setDimensions(st::boxWidth, st::passcodePadding.top() + st::passcodePadding.bottom() + st::passcodeTextLine + _recoverCode->height() + st::passcodeTextLine); connect(_recoverCode, SIGNAL(changed()), this, SLOT(onCodeChanged())); connect(_recoverCode, SIGNAL(submitted(bool)), this, SLOT(onSubmit())); - - raiseShadow(); } void RecoverBox::paintEvent(QPaintEvent *e) { - AbstractBox::paintEvent(e); + BoxContent::paintEvent(e); Painter p(this); @@ -483,16 +462,13 @@ void RecoverBox::paintEvent(QPaintEvent *e) { } void RecoverBox::resizeEvent(QResizeEvent *e) { + BoxContent::resizeEvent(e); + _recoverCode->resize(st::boxWidth - st::boxPadding.left() - st::boxPadding.right(), _recoverCode->height()); - _recoverCode->moveToLeft(st::boxPadding.left(), titleHeight() + st::passcodePadding.top() + st::passcodePadding.bottom() + st::passcodeTextLine); - - _saveButton->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _saveButton->height()); - _cancelButton->moveToRight(st::boxButtonPadding.right() + _saveButton->width() + st::boxButtonPadding.left(), _saveButton->y()); - - AbstractBox::resizeEvent(e); + _recoverCode->moveToLeft(st::boxPadding.left(), st::passcodePadding.top() + st::passcodePadding.bottom() + st::passcodeTextLine); } -void RecoverBox::doSetInnerFocus() { +void RecoverBox::setInnerFocus() { _recoverCode->setFocus(); } @@ -518,7 +494,7 @@ void RecoverBox::codeSubmitDone(bool recover, const MTPauth_Authorization &resul _submitRequest = 0; emit reloadPassword(); - Ui::showLayer(new InformBox(lang(lng_cloud_password_removed))); + Ui::show(Box(lang(lng_cloud_password_removed))); } bool RecoverBox::codeSubmitFail(const RPCError &error) { @@ -536,14 +512,14 @@ bool RecoverBox::codeSubmitFail(const RPCError &error) { const QString &err = error.type(); if (err == qstr("PASSWORD_EMPTY")) { emit reloadPassword(); - Ui::showLayer(new InformBox(lang(lng_cloud_password_removed))); + Ui::show(Box(lang(lng_cloud_password_removed))); return true; } else if (err == qstr("PASSWORD_RECOVERY_NA")) { - onClose(); + closeBox(); return true; } else if (err == qstr("PASSWORD_RECOVERY_EXPIRED")) { emit recoveryExpired(); - onClose(); + closeBox(); return true; } else if (err == qstr("CODE_INVALID")) { _error = lang(lng_signin_wrong_code); diff --git a/Telegram/SourceFiles/boxes/passcodebox.h b/Telegram/SourceFiles/boxes/passcodebox.h index 308c40d75..8847163f7 100644 --- a/Telegram/SourceFiles/boxes/passcodebox.h +++ b/Telegram/SourceFiles/boxes/passcodebox.h @@ -26,15 +26,14 @@ namespace Ui { class InputField; class PasswordInput; class LinkButton; -class RoundButton; } // namespace Ui -class PasscodeBox : public AbstractBox, public RPCSender { +class PasscodeBox : public BoxContent, public RPCSender { Q_OBJECT public: - PasscodeBox(bool turningOff = false); - PasscodeBox(const QByteArray &newSalt, const QByteArray &curSalt, bool hasRecovery, const QString &hint, bool turningOff = false); + PasscodeBox(QWidget*, bool turningOff); + PasscodeBox(QWidget*, const QByteArray &newSalt, const QByteArray &curSalt, bool hasRecovery, const QString &hint, bool turningOff = false); private slots: void onSave(bool force = false); @@ -42,8 +41,6 @@ private slots: void onOldChanged(); void onNewChanged(); void onEmailChanged(); - void onForceNoMail(); - void onBoxDestroyed(QObject *obj); void onRecoverByEmail(); void onRecoverExpired(); void onSubmit(); @@ -52,12 +49,14 @@ signals: void reloadPassword(); protected: + void prepare() override; + void setInnerFocus() override; + void paintEvent(QPaintEvent *e) override; void resizeEvent(QResizeEvent *e) override; - void doSetInnerFocus() override; private: - void init(); + void closeReplacedBy(); void setPasswordDone(const MTPBool &result); bool setPasswordFail(const RPCError &error); @@ -68,7 +67,7 @@ private: void recover(); QString _pattern; - AbstractBox *_replacedBy = nullptr; + QPointer _replacedBy; bool _turningOff = false; bool _cloudPwd = false; mtpRequestId _setRequest = 0; @@ -81,24 +80,22 @@ private: Text _about, _hintText; - ChildWidget _saveButton; - ChildWidget _cancelButton; - ChildWidget _oldPasscode; - ChildWidget _newPasscode; - ChildWidget _reenterPasscode; - ChildWidget _passwordHint; - ChildWidget _recoverEmail; - ChildWidget _recover; + object_ptr _oldPasscode; + object_ptr _newPasscode; + object_ptr _reenterPasscode; + object_ptr _passwordHint; + object_ptr _recoverEmail; + object_ptr _recover; QString _oldError, _newError, _emailError; }; -class RecoverBox : public AbstractBox, public RPCSender { +class RecoverBox : public BoxContent, public RPCSender { Q_OBJECT public: - RecoverBox(const QString &pattern); + RecoverBox(QWidget*, const QString &pattern); public slots: void onSubmit(); @@ -109,22 +106,21 @@ signals: void recoveryExpired(); protected: + void prepare() override; + void setInnerFocus() override; + void paintEvent(QPaintEvent *e) override; void resizeEvent(QResizeEvent *e) override; - void doSetInnerFocus() override; - private: void codeSubmitDone(bool recover, const MTPauth_Authorization &result); bool codeSubmitFail(const RPCError &error); - mtpRequestId _submitRequest; + mtpRequestId _submitRequest = 0; QString _pattern; - ChildWidget _saveButton; - ChildWidget _cancelButton; - ChildWidget _recoverCode; + object_ptr _recoverCode; QString _error; diff --git a/Telegram/SourceFiles/boxes/photocropbox.cpp b/Telegram/SourceFiles/boxes/photocropbox.cpp index 3429a1a76..d684bce18 100644 --- a/Telegram/SourceFiles/boxes/photocropbox.cpp +++ b/Telegram/SourceFiles/boxes/photocropbox.cpp @@ -29,20 +29,14 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "ui/widgets/buttons.h" #include "styles/style_boxes.h" -PhotoCropBox::PhotoCropBox(const QImage &img, const PeerId &peer) : AbstractBox() -, _downState(0) -, _done(this, lang(lng_settings_save), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) -, _img(img) +PhotoCropBox::PhotoCropBox(QWidget*, const QImage &img, const PeerId &peer) +: _img(img) , _peerId(peer) { - init(img, 0); + init(img, nullptr); } -PhotoCropBox::PhotoCropBox(const QImage &img, PeerData *peer) : AbstractBox() -, _downState(0) -, _done(this, lang(lng_settings_save), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) -, _img(img) +PhotoCropBox::PhotoCropBox(QWidget*, const QImage &img, PeerData *peer) +: _img(img) , _peerId(peer->id) { init(img, peer); } @@ -55,15 +49,17 @@ void PhotoCropBox::init(const QImage &img, PeerData *peer) { } else { _title = lang(lng_settings_crop_profile); } +} - connect(_done, SIGNAL(clicked()), this, SLOT(onSend())); - connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); +void PhotoCropBox::prepare() { + addButton(lang(lng_settings_save), [this] { sendPhoto(); }); + addButton(lang(lng_cancel), [this] { closeBox(); }); if (peerToBareInt(_peerId)) { connect(this, SIGNAL(ready(const QImage&)), this, SLOT(onReady(const QImage&))); } int32 s = st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right(); - _thumb = App::pixmapFromImageInPlace(img.scaled(s * cIntRetinaFactor(), s * cIntRetinaFactor(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); + _thumb = App::pixmapFromImageInPlace(_img.scaled(s * cIntRetinaFactor(), s * cIntRetinaFactor(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); _thumb.setDevicePixelRatio(cRetinaFactor()); _mask = QImage(_thumb.size(), QImage::Format_ARGB32_Premultiplied); _mask.setDevicePixelRatio(cRetinaFactor()); @@ -83,23 +79,22 @@ void PhotoCropBox::init(const QImage &img, PeerData *peer) { _thumby = st::boxPhotoPadding.top(); setMouseTracking(true); - resizeMaxHeight(st::boxWideWidth, st::boxPhotoPadding.top() + _thumbh + st::boxPhotoPadding.bottom() + st::boxTextFont->height + st::cropSkip + st::boxButtonPadding.top() + _done->height() + st::boxButtonPadding.bottom()); + setDimensions(st::boxWideWidth, st::boxPhotoPadding.top() + _thumbh + st::boxPhotoPadding.bottom() + st::boxTextFont->height + st::cropSkip); } void PhotoCropBox::mousePressEvent(QMouseEvent *e) { - if (e->button() != Qt::LeftButton) return LayerWidget::mousePressEvent(e); - - _downState = mouseState(e->pos()); - _fromposx = e->pos().x(); - _fromposy = e->pos().y(); - _fromcropx = _cropx; - _fromcropy = _cropy; - _fromcropw = _cropw; - - return LayerWidget::mousePressEvent(e); + if (e->button() == Qt::LeftButton) { + _downState = mouseState(e->pos()); + _fromposx = e->pos().x(); + _fromposy = e->pos().y(); + _fromcropx = _cropx; + _fromcropy = _cropy; + _fromcropw = _cropw; + } + return BoxContent::mousePressEvent(e); } -int32 PhotoCropBox::mouseState(QPoint p) { +int PhotoCropBox::mouseState(QPoint p) { p -= QPoint(_thumbx, _thumby); int32 delta = st::cropPointSize, mdelta(-delta / 2); if (QRect(_cropx + mdelta, _cropy + mdelta, delta, delta).contains(p)) { @@ -225,14 +220,14 @@ void PhotoCropBox::mouseMoveEvent(QMouseEvent *e) { void PhotoCropBox::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { - onSend(); + sendPhoto(); } else { - AbstractBox::keyPressEvent(e); + BoxContent::keyPressEvent(e); } } void PhotoCropBox::paintEvent(QPaintEvent *e) { - AbstractBox::paintEvent(e); + BoxContent::paintEvent(e); Painter p(this); @@ -262,14 +257,8 @@ void PhotoCropBox::paintEvent(QPaintEvent *e) { p.fillRect(QRect(_cropx + mdelta, _cropy + _cropw + mdelta, delta, delta), st::photoCropPointFg); } -void PhotoCropBox::resizeEvent(QResizeEvent *e) { - _done->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _done->height()); - _cancel->moveToRight(st::boxButtonPadding.right() + _done->width() + st::boxButtonPadding.left(), _done->y()); - AbstractBox::resizeEvent(e); -} - -void PhotoCropBox::onSend() { - QImage from(_img); +void PhotoCropBox::sendPhoto() { + auto from = _img; if (_img.width() < _thumb.width()) { from = _thumb.toImage(); } @@ -302,7 +291,7 @@ void PhotoCropBox::onSend() { } emit ready(tosend); - onClose(); + closeBox(); } void PhotoCropBox::onReady(const QImage &tosend) { diff --git a/Telegram/SourceFiles/boxes/photocropbox.h b/Telegram/SourceFiles/boxes/photocropbox.h index d6eb2a6bd..3c30b752a 100644 --- a/Telegram/SourceFiles/boxes/photocropbox.h +++ b/Telegram/SourceFiles/boxes/photocropbox.h @@ -22,44 +22,44 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "boxes/abstractbox.h" -namespace Ui { -class RoundButton; -} // namespace Ui - -class PhotoCropBox : public AbstractBox { +class PhotoCropBox : public BoxContent { Q_OBJECT public: - PhotoCropBox(const QImage &img, const PeerId &peer); - PhotoCropBox(const QImage &img, PeerData *peer); + PhotoCropBox(QWidget*, const QImage &img, const PeerId &peer); + PhotoCropBox(QWidget*, const QImage &img, PeerData *peer); int32 mouseState(QPoint p); -public slots: - void onSend(); - void onReady(const QImage &tosend); + void closeHook() override { + emit closed(); + } signals: void ready(const QImage &tosend); + void closed(); + +private slots: + void onReady(const QImage &tosend); protected: + void prepare() override; + void keyPressEvent(QKeyEvent *e) override; void paintEvent(QPaintEvent *e) override; - void resizeEvent(QResizeEvent *e) override; void mousePressEvent(QMouseEvent *e) override; void mouseReleaseEvent(QMouseEvent *e) override; void mouseMoveEvent(QMouseEvent *e) override; private: void init(const QImage &img, PeerData *peer); + void sendPhoto(); QString _title; - int32 _downState; + int32 _downState = 0; int32 _thumbx, _thumby, _thumbw, _thumbh; int32 _cropx, _cropy, _cropw; int32 _fromposx, _fromposy, _fromcropx, _fromcropy, _fromcropw; - ChildWidget _done; - ChildWidget _cancel; QImage _img; QPixmap _thumb; QImage _mask, _fade; diff --git a/Telegram/SourceFiles/boxes/report_box.cpp b/Telegram/SourceFiles/boxes/report_box.cpp index 7c582dd6a..0f78f0f51 100644 --- a/Telegram/SourceFiles/boxes/report_box.cpp +++ b/Telegram/SourceFiles/boxes/report_box.cpp @@ -30,18 +30,18 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "ui/widgets/input_fields.h" #include "mainwindow.h" -ReportBox::ReportBox(PeerData *peer) : AbstractBox(st::boxWidth) -, _peer(peer) +ReportBox::ReportBox(QWidget*, PeerData *peer) : _peer(peer) , _reasonSpam(this, qsl("report_reason"), ReasonSpam, lang(lng_report_reason_spam), true, st::defaultBoxCheckbox) , _reasonViolence(this, qsl("report_reason"), ReasonViolence, lang(lng_report_reason_violence), false, st::defaultBoxCheckbox) , _reasonPornography(this, qsl("report_reason"), ReasonPornography, lang(lng_report_reason_pornography), false, st::defaultBoxCheckbox) -, _reasonOther(this, qsl("report_reason"), ReasonOther, lang(lng_report_reason_other), false, st::defaultBoxCheckbox) -, _report(this, lang(lng_report_button), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) { - setTitleText(lang(_peer->isUser() ? lng_report_bot_title : (_peer->isMegagroup() ? lng_report_group_title : lng_report_title))); +, _reasonOther(this, qsl("report_reason"), ReasonOther, lang(lng_report_reason_other), false, st::defaultBoxCheckbox) { +} - connect(_report, SIGNAL(clicked()), this, SLOT(onReport())); - connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); +void ReportBox::prepare() { + setTitle(lang(_peer->isUser() ? lng_report_bot_title : (_peer->isMegagroup() ? lng_report_group_title : lng_report_title))); + + addButton(lang(lng_report_button), [this] { onReport(); }); + addButton(lang(lng_cancel), [this] { closeBox(); }); connect(_reasonSpam, SIGNAL(changed()), this, SLOT(onChange())); connect(_reasonViolence, SIGNAL(changed()), this, SLOT(onChange())); @@ -52,18 +52,16 @@ ReportBox::ReportBox(PeerData *peer) : AbstractBox(st::boxWidth) } void ReportBox::resizeEvent(QResizeEvent *e) { - _reasonSpam->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), titleHeight() + st::boxOptionListPadding.top()); - _reasonViolence->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _reasonSpam->bottomNoMargins() + st::boxOptionListPadding.top()); - _reasonPornography->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _reasonViolence->bottomNoMargins() + st::boxOptionListPadding.top()); - _reasonOther->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _reasonPornography->bottomNoMargins() + st::boxOptionListPadding.top()); + BoxContent::resizeEvent(e); + + _reasonSpam->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), st::boxOptionListPadding.top()); + _reasonViolence->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _reasonSpam->bottomNoMargins() + st::boxOptionListSkip); + _reasonPornography->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _reasonViolence->bottomNoMargins() + st::boxOptionListSkip); + _reasonOther->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _reasonPornography->bottomNoMargins() + st::boxOptionListSkip); if (_reasonOtherText) { _reasonOtherText->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left() - st::defaultInputField.textMargins.left(), _reasonOther->bottomNoMargins() + st::newGroupDescriptionPadding.top()); } - - _report->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _report->height()); - _cancel->moveToRight(st::boxButtonPadding.right() + _report->width() + st::boxButtonPadding.left(), _report->y()); - AbstractBox::resizeEvent(e); } void ReportBox::onChange() { @@ -87,7 +85,7 @@ void ReportBox::onChange() { } } -void ReportBox::doSetInnerFocus() { +void ReportBox::setInnerFocus() { if (_reasonOtherText) { _reasonOtherText->setFocus(); } else { @@ -124,7 +122,7 @@ void ReportBox::onReport() { void ReportBox::reportDone(const MTPBool &result) { _requestId = 0; - Ui::showLayer(new InformBox(lang(lng_report_thanks))); + Ui::show(Box(lang(lng_report_thanks))); } bool ReportBox::reportFail(const RPCError &error) { @@ -138,9 +136,9 @@ bool ReportBox::reportFail(const RPCError &error) { } void ReportBox::updateMaxHeight() { - int32 h = titleHeight() + 4 * (st::boxOptionListPadding.top() + _reasonSpam->heightNoMargins()) + st::boxButtonPadding.top() + _report->height() + st::boxButtonPadding.bottom(); + auto newHeight = st::boxOptionListPadding.top() + 4 * _reasonSpam->heightNoMargins() + 3 * st::boxOptionListSkip + st::boxOptionListPadding.bottom(); if (_reasonOtherText) { - h += st::newGroupDescriptionPadding.top() + _reasonOtherText->height() + st::newGroupDescriptionPadding.bottom(); + newHeight += st::newGroupDescriptionPadding.top() + _reasonOtherText->height() + st::newGroupDescriptionPadding.bottom(); } - setMaxHeight(h); + setDimensions(st::boxWidth, newHeight); } diff --git a/Telegram/SourceFiles/boxes/report_box.h b/Telegram/SourceFiles/boxes/report_box.h index c674c59e2..89b8ebc2b 100644 --- a/Telegram/SourceFiles/boxes/report_box.h +++ b/Telegram/SourceFiles/boxes/report_box.h @@ -24,15 +24,14 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org namespace Ui { class Radiobutton; -class RoundButton; class InputArea; } // namespace Ui -class ReportBox : public AbstractBox, public RPCSender { +class ReportBox : public BoxContent, public RPCSender { Q_OBJECT public: - ReportBox(PeerData *peer); + ReportBox(QWidget*, PeerData *peer); private slots: void onReport(); @@ -40,9 +39,10 @@ private slots: void onDescriptionResized(); protected: - void resizeEvent(QResizeEvent *e) override; + void prepare() override; + void setInnerFocus() override; - void doSetInnerFocus() override; + void resizeEvent(QResizeEvent *e) override; private: void updateMaxHeight(); @@ -52,13 +52,11 @@ private: PeerData *_peer; - ChildWidget _reasonSpam; - ChildWidget _reasonViolence; - ChildWidget _reasonPornography; - ChildWidget _reasonOther; - ChildWidget _reasonOtherText = { nullptr }; - - ChildWidget _report, _cancel; + object_ptr _reasonSpam; + object_ptr _reasonViolence; + object_ptr _reasonPornography; + object_ptr _reasonOther; + object_ptr _reasonOtherText = { nullptr }; enum Reason { ReasonSpam, diff --git a/Telegram/SourceFiles/boxes/send_files_box.cpp b/Telegram/SourceFiles/boxes/send_files_box.cpp index 57e2978ae..f6dc7537a 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.cpp +++ b/Telegram/SourceFiles/boxes/send_files_box.cpp @@ -38,14 +38,12 @@ constexpr auto kMinPreviewWidth = 20; } // namespace -SendFilesBox::SendFilesBox(const QString &filepath, QImage image, CompressConfirm compressed, bool animated) : AbstractBox(st::boxWideWidth) -, _files(filepath) +SendFilesBox::SendFilesBox(QWidget*, const QString &filepath, QImage image, CompressConfirm compressed, bool animated) +: _files(filepath) , _image(image) , _compressConfirm(compressed) , _animated(image.isNull() ? false : animated) -, _caption(this, st::confirmCaptionArea, lang(lng_photo_caption)) -, _send(this, lang(lng_send_button), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) { +, _caption(this, st::confirmCaptionArea, lang(lng_photo_caption)) { if (!image.isNull()) { if (!_animated && _compressConfirm == CompressConfirm::None) { auto originalWidth = image.width(); @@ -60,7 +58,7 @@ SendFilesBox::SendFilesBox(const QString &filepath, QImage image, CompressConfir auto maxW = 0; auto maxH = 0; if (_animated) { - auto limitW = width() - st::boxPhotoPadding.left() - st::boxPhotoPadding.right(); + auto limitW = st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right(); auto limitH = st::confirmMaxHeight; maxW = qMax(image.width(), 1); maxH = qMax(image.height(), 1); @@ -82,7 +80,7 @@ SendFilesBox::SendFilesBox(const QString &filepath, QImage image, CompressConfir if (!originalWidth || !originalHeight) { originalWidth = originalHeight = 1; } - _previewWidth = width() - st::boxPhotoPadding.left() - st::boxPhotoPadding.right(); + _previewWidth = st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right(); if (image.width() < _previewWidth) { _previewWidth = qMax(image.width(), kMinPreviewWidth); } @@ -93,7 +91,7 @@ SendFilesBox::SendFilesBox(const QString &filepath, QImage image, CompressConfir accumulate_max(_previewWidth, kMinPreviewWidth); _previewHeight = maxthumbh; } - _previewLeft = (width() - _previewWidth) / 2; + _previewLeft = (st::boxWideWidth - _previewWidth) / 2; image = std_::move(image).scaled(_previewWidth * cIntRetinaFactor(), _previewHeight * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); image = Images::prepareOpaque(std_::move(image)); @@ -117,37 +115,30 @@ SendFilesBox::SendFilesBox(const QString &filepath, QImage image, CompressConfir _fileIsImage = fileIsImage(filename, mimeTypeForFile(fileinfo).name()); } } - - setup(); } -SendFilesBox::SendFilesBox(const QStringList &files, CompressConfirm compressed) : AbstractBox(st::boxWideWidth) -, _files(files) +SendFilesBox::SendFilesBox(QWidget*, const QStringList &files, CompressConfirm compressed) +: _files(files) , _compressConfirm(compressed) -, _caption(this, st::confirmCaptionArea, lang(lng_photos_comment)) -, _send(this, lang(lng_send_button), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) { - updateTitleText(); - - setup(); +, _caption(this, st::confirmCaptionArea, lang(lng_photos_comment)) { } -SendFilesBox::SendFilesBox(const QString &phone, const QString &firstname, const QString &lastname) : AbstractBox(st::boxWideWidth) -, _contactPhone(phone) +SendFilesBox::SendFilesBox(QWidget*, const QString &phone, const QString &firstname, const QString &lastname) +: _contactPhone(phone) , _contactFirstName(firstname) -, _contactLastName(lastname) -, _send(this, lang(lng_send_button), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) { +, _contactLastName(lastname) { _nameText.setText(st::semiboldFont, lng_full_name(lt_first_name, _contactFirstName, lt_last_name, _contactLastName), _textNameOptions); _statusText = _contactPhone; _statusWidth = qMax(_nameText.maxWidth(), st::normalFont->width(_statusText)); - - setup(); } -void SendFilesBox::setup() { - _send->setClickedCallback([this] { onSend(); }); - _cancel->setClickedCallback([this] { onClose(); }); +void SendFilesBox::prepare() { + if (_files.size() > 1) { + updateTitleText(); + } + + _send = addButton(lang(lng_send_button), [this] { onSend(); }); + addButton(lang(lng_cancel), [this] { closeBox(); }); if (_compressConfirm != CompressConfirm::None) { auto compressed = (_compressConfirm == CompressConfirm::Auto) ? cCompressPastedImage() : (_compressConfirm == CompressConfirm::Yes); @@ -163,6 +154,7 @@ void SendFilesBox::setup() { connect(_caption, SIGNAL(cancelled()), this, SLOT(onClose())); } _send->setText(getSendButtonText()); + updateButtonsGeometry(); updateBoxSize(); } @@ -176,8 +168,9 @@ QString SendFilesBox::getSendButtonText() const { } void SendFilesBox::onCompressedChange() { - doSetInnerFocus(); + setInnerFocus(); _send->setText(getSendButtonText()); + updateButtonsGeometry(); updateControlsGeometry(); } @@ -188,7 +181,7 @@ void SendFilesBox::onCaptionResized() { } void SendFilesBox::updateTitleText() { - _titleText = (_compressConfirm == CompressConfirm::None) ? lng_send_files_selected(lt_count, _files.size()) : lng_send_images_selected(lt_count, _files.size()); + setTitle((_compressConfirm == CompressConfirm::None) ? lng_send_files_selected(lt_count, _files.size()) : lng_send_images_selected(lt_count, _files.size())); update(); } @@ -199,7 +192,7 @@ void SendFilesBox::updateBoxSize() { } else if (!_fileThumb.isNull()) { newHeight += st::boxPhotoPadding.top() + st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom(); } else if (_files.size() > 1) { - newHeight += titleHeight(); + newHeight += 0; } else { newHeight += st::boxPhotoPadding.top() + st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom(); } @@ -209,20 +202,19 @@ void SendFilesBox::updateBoxSize() { if (_caption) { newHeight += st::boxPhotoCaptionSkip + _caption->height(); } - newHeight += st::boxButtonPadding.top() + _send->height() + st::boxButtonPadding.bottom(); - setMaxHeight(newHeight); + setDimensions(st::boxWideWidth, newHeight); } void SendFilesBox::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { onSend((e->modifiers().testFlag(Qt::ControlModifier) || e->modifiers().testFlag(Qt::MetaModifier)) && e->modifiers().testFlag(Qt::ShiftModifier)); } else { - AbstractBox::keyPressEvent(e); + BoxContent::keyPressEvent(e); } } void SendFilesBox::paintEvent(QPaintEvent *e) { - AbstractBox::paintEvent(e); + BoxContent::paintEvent(e); Painter p(this); @@ -306,14 +298,12 @@ void SendFilesBox::paintEvent(QPaintEvent *e) { } void SendFilesBox::resizeEvent(QResizeEvent *e) { + BoxContent::resizeEvent(e); updateControlsGeometry(); - AbstractBox::resizeEvent(e); } void SendFilesBox::updateControlsGeometry() { - _send->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _send->height()); - _cancel->moveToRight(st::boxButtonPadding.right() + _send->width() + st::boxButtonPadding.left(), _send->y()); - auto bottom = _send->y() - st::boxButtonPadding.top(); + auto bottom = height(); if (_caption) { _caption->resize(st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right(), _caption->height()); _caption->moveToLeft(st::boxPhotoPadding.left(), bottom - _caption->height()); @@ -325,7 +315,7 @@ void SendFilesBox::updateControlsGeometry() { } } -void SendFilesBox::doSetInnerFocus() { +void SendFilesBox::setInnerFocus() { if (!_caption || _caption->isHidden()) { setFocus(); } else { @@ -344,33 +334,17 @@ void SendFilesBox::onSend(bool ctrlShiftEnter) { auto caption = _caption ? prepareText(_caption->getLastText(), true) : QString(); _confirmedCallback(_files, compressed, caption, ctrlShiftEnter); } - onClose(); + closeBox(); } -void SendFilesBox::closePressed() { +void SendFilesBox::closeHook() { if (!_confirmed && _cancelledCallback) { _cancelledCallback(); } } -EditCaptionBox::EditCaptionBox(HistoryItem *msg) : AbstractBox(st::boxWideWidth) -, _msgId(msg->fullId()) -, _animated(false) -, _photo(false) -, _doc(false) -, _save(this, lang(lng_settings_save), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) -, _thumbx(0) -, _thumby(0) -, _thumbw(0) -, _thumbh(0) -, _statusw(0) -, _isImage(false) -, _previewCancelled(false) -, _saveRequestId(0) { - connect(_save, SIGNAL(clicked()), this, SLOT(onSave())); - connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); - +EditCaptionBox::EditCaptionBox(QWidget*, HistoryItem *msg) +: _msgId(msg->fullId()) { QSize dimensions; ImagePtr image; QString caption; @@ -437,7 +411,7 @@ EditCaptionBox::EditCaptionBox(HistoryItem *msg) : AbstractBox(st::boxWideWidth) } else { int32 maxW = 0, maxH = 0; if (_animated) { - int32 limitW = width() - st::boxPhotoPadding.left() - st::boxPhotoPadding.right(); + int32 limitW = st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right(); int32 limitH = st::confirmMaxHeight; maxW = qMax(dimensions.width(), 1); maxH = qMax(dimensions.height(), 1); @@ -462,7 +436,7 @@ EditCaptionBox::EditCaptionBox(HistoryItem *msg) : AbstractBox(st::boxWideWidth) if (!tw || !th) { tw = th = 1; } - _thumbw = width() - st::boxPhotoPadding.left() - st::boxPhotoPadding.right(); + _thumbw = st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right(); if (_thumb.width() < _thumbw) { _thumbw = (_thumb.width() > 20) ? _thumb.width() : 20; } @@ -475,35 +449,50 @@ EditCaptionBox::EditCaptionBox(HistoryItem *msg) : AbstractBox(st::boxWideWidth) _thumbw = 10; } } - _thumbx = (width() - _thumbw) / 2; + _thumbx = (st::boxWideWidth - _thumbw) / 2; _thumb = App::pixmapFromImageInPlace(_thumb.toImage().scaled(_thumbw * cIntRetinaFactor(), _thumbh * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); _thumb.setDevicePixelRatio(cRetinaFactor()); } - if (_animated || _photo || _doc) { _field.create(this, st::confirmCaptionArea, lang(lng_photo_caption), caption); _field->setMaxLength(MaxPhotoCaption); _field->setCtrlEnterSubmit(Ui::CtrlEnterSubmit::Both); } else { auto original = msg->originalText(); - QString text = textApplyEntities(original.text, original.entities); + auto text = textApplyEntities(original.text, original.entities); _field.create(this, st::editTextArea, lang(lng_photo_caption), text); // _field->setMaxLength(MaxMessageSize); // entities can make text in input field larger but still valid _field->setCtrlEnterSubmit(cCtrlEnter() ? Ui::CtrlEnterSubmit::CtrlEnter : Ui::CtrlEnterSubmit::Enter); } +} + +bool EditCaptionBox::canEdit(HistoryItem *message) { + if (auto media = message->getMedia()) { + switch (media->type()) { + case MediaTypeGif: + case MediaTypePhoto: + case MediaTypeVideo: + case MediaTypeFile: + case MediaTypeMusicFile: + case MediaTypeVoiceFile: return true; + } + } + return false; +} + +void EditCaptionBox::prepare() { + addButton(lang(lng_settings_save), [this] { onSave(); }); + addButton(lang(lng_cancel), [this] { closeBox(); }); + updateBoxSize(); connect(_field, SIGNAL(submitted(bool)), this, SLOT(onSave(bool))); connect(_field, SIGNAL(cancelled()), this, SLOT(onClose())); connect(_field, SIGNAL(resized()), this, SLOT(onCaptionResized())); - QTextCursor c(_field->textCursor()); - c.movePosition(QTextCursor::End); - _field->setTextCursor(c); -} - -bool EditCaptionBox::captionFound() const { - return _animated || _photo || _doc; + auto cursor = _field->textCursor(); + cursor.movePosition(QTextCursor::End); + _field->setTextCursor(cursor); } void EditCaptionBox::onCaptionResized() { @@ -513,29 +502,30 @@ void EditCaptionBox::onCaptionResized() { } void EditCaptionBox::updateBoxSize() { - auto bottomh = st::boxPhotoCaptionSkip + _field->height() + st::normalFont->height + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom(); + auto newHeight = st::boxPhotoPadding.top() + st::boxPhotoCaptionSkip + _field->height() + st::normalFont->height; if (_photo || _animated) { - setMaxHeight(st::boxPhotoPadding.top() + _thumbh + bottomh); + newHeight += _thumbh; } else if (_thumbw) { - setMaxHeight(st::boxPhotoPadding.top() + 0 + st::msgFileThumbSize + 0 + bottomh); + newHeight += 0 + st::msgFileThumbSize + 0; } else if (_doc) { - setMaxHeight(st::boxPhotoPadding.top() + 0 + st::msgFileSize + 0 + bottomh); + newHeight += 0 + st::msgFileSize + 0; } else { - setMaxHeight(st::boxPhotoPadding.top() + st::boxTitleFont->height + bottomh); + newHeight += st::boxTitleFont->height; } + setDimensions(st::boxWideWidth, newHeight); } void EditCaptionBox::paintEvent(QPaintEvent *e) { - AbstractBox::paintEvent(e); + BoxContent::paintEvent(e); Painter p(this); if (_photo || _animated) { if (_thumbx > st::boxPhotoPadding.left()) { - p.fillRect(st::boxPhotoPadding.left(), st::boxPhotoPadding.top(), _thumbx - st::boxPhotoPadding.left(), _thumbh, st::confirmBg->b); + p.fillRect(st::boxPhotoPadding.left(), st::boxPhotoPadding.top(), _thumbx - st::boxPhotoPadding.left(), _thumbh, st::confirmBg); } if (_thumbx + _thumbw < width() - st::boxPhotoPadding.right()) { - p.fillRect(_thumbx + _thumbw, st::boxPhotoPadding.top(), width() - st::boxPhotoPadding.right() - _thumbx - _thumbw, _thumbh, st::confirmBg->b); + p.fillRect(_thumbx + _thumbw, st::boxPhotoPadding.top(), width() - st::boxPhotoPadding.right() - _thumbx - _thumbw, _thumbh, st::confirmBg); } p.drawPixmap(_thumbx, st::boxPhotoPadding.top(), _thumb); if (_animated) { @@ -613,14 +603,12 @@ void EditCaptionBox::paintEvent(QPaintEvent *e) { } void EditCaptionBox::resizeEvent(QResizeEvent *e) { - _save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height()); - _cancel->moveToRight(st::boxButtonPadding.right() + _save->width() + st::boxButtonPadding.left(), _save->y()); + BoxContent::resizeEvent(e); _field->resize(st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right(), _field->height()); - _field->moveToLeft(st::boxPhotoPadding.left(), _save->y() - st::boxButtonPadding.top() - st::normalFont->height - _field->height()); - AbstractBox::resizeEvent(e); + _field->moveToLeft(st::boxPhotoPadding.left(), height() - st::normalFont->height - _field->height()); } -void EditCaptionBox::doSetInnerFocus() { +void EditCaptionBox::setInnerFocus() { _field->setFocus(); } @@ -648,7 +636,7 @@ void EditCaptionBox::onSave(bool ctrlShiftEnter) { void EditCaptionBox::saveDone(const MTPUpdates &updates) { _saveRequestId = 0; - onClose(); + closeBox(); if (App::main()) { App::main()->sentUpdatesReceived(updates); } @@ -662,7 +650,7 @@ bool EditCaptionBox::saveFail(const RPCError &error) { if (err == qstr("MESSAGE_ID_INVALID") || err == qstr("CHAT_ADMIN_REQUIRED") || err == qstr("MESSAGE_EDIT_TIME_EXPIRED")) { _error = lang(lng_edit_error); } else if (err == qstr("MESSAGE_NOT_MODIFIED")) { - onClose(); + closeBox(); return true; } else if (err == qstr("MESSAGE_EMPTY")) { _field->setFocus(); diff --git a/Telegram/SourceFiles/boxes/send_files_box.h b/Telegram/SourceFiles/boxes/send_files_box.h index 46d11bc72..fd0a17322 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.h +++ b/Telegram/SourceFiles/boxes/send_files_box.h @@ -29,13 +29,13 @@ class RoundButton; class InputArea; } // namespace Ui -class SendFilesBox : public AbstractBox { +class SendFilesBox : public BoxContent { Q_OBJECT public: - SendFilesBox(const QString &filepath, QImage image, CompressConfirm compressed, bool animated = false); - SendFilesBox(const QStringList &files, CompressConfirm compressed); - SendFilesBox(const QString &phone, const QString &firstname, const QString &lastname); + SendFilesBox(QWidget*, const QString &filepath, QImage image, CompressConfirm compressed, bool animated = false); + SendFilesBox(QWidget*, const QStringList &files, CompressConfirm compressed); + SendFilesBox(QWidget*, const QString &phone, const QString &firstname, const QString &lastname); void setConfirmedCallback(base::lambda &&callback) { _confirmedCallback = std_::move(callback); @@ -44,21 +44,22 @@ public: _cancelledCallback = std_::move(callback); } -public slots: - void onCompressedChange(); - void onSend(bool ctrlShiftEnter = false); - void onCaptionResized(); + void closeHook() override; protected: + void prepare() override; + void setInnerFocus() override; + void keyPressEvent(QKeyEvent *e) override; void paintEvent(QPaintEvent *e) override; void resizeEvent(QResizeEvent *e) override; - void closePressed() override; - void doSetInnerFocus() override; +private slots: + void onCompressedChange(); + void onSend(bool ctrlShiftEnter = false); + void onCaptionResized(); private: - void setup(); void updateTitleText(); void updateBoxSize(); void updateControlsGeometry(); @@ -90,32 +91,31 @@ private: base::lambda _cancelledCallback; bool _confirmed = false; - ChildWidget _caption = { nullptr }; - ChildWidget _compressed = { nullptr }; + object_ptr _caption = { nullptr }; + object_ptr _compressed = { nullptr }; - ChildWidget _send; - ChildWidget _cancel; + QPointer _send; }; -class EditCaptionBox : public AbstractBox, public RPCSender { +class EditCaptionBox : public BoxContent, public RPCSender { Q_OBJECT public: - EditCaptionBox(HistoryItem *msg); - - bool captionFound() const; + EditCaptionBox(QWidget*, HistoryItem *msg); + static bool canEdit(HistoryItem *message); public slots: void onCaptionResized(); void onSave(bool ctrlShiftEnter = false); protected: + void prepare() override; + void setInnerFocus() override; + void paintEvent(QPaintEvent *e) override; void resizeEvent(QResizeEvent *e) override; - void doSetInnerFocus() override; - private: void updateBoxSize(); @@ -123,22 +123,25 @@ private: bool saveFail(const RPCError &error); FullMsgId _msgId; - bool _animated, _photo, _doc; + bool _animated = false; + bool _photo = false; + bool _doc = false; QPixmap _thumb; - ChildWidget _field = { nullptr }; - ChildWidget _save; - ChildWidget _cancel; + object_ptr _field = { nullptr }; - int32 _thumbx, _thumby, _thumbw, _thumbh; + int _thumbx = 0; + int _thumby = 0; + int _thumbw = 0; + int _thumbh = 0; Text _name; QString _status; - int32 _statusw; - bool _isImage; + int _statusw = 0; + bool _isImage = false; - bool _previewCancelled; - mtpRequestId _saveRequestId; + bool _previewCancelled = false; + mtpRequestId _saveRequestId = 0; QString _error; diff --git a/Telegram/SourceFiles/boxes/sessionsbox.cpp b/Telegram/SourceFiles/boxes/sessionsbox.cpp index 49df138ac..db94e3006 100644 --- a/Telegram/SourceFiles/boxes/sessionsbox.cpp +++ b/Telegram/SourceFiles/boxes/sessionsbox.cpp @@ -31,53 +31,49 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "ui/widgets/scroll_area.h" #include "styles/style_boxes.h" -SessionsBox::SessionsBox() : ScrollableBox(st::sessionsScroll) -, _loading(false) -, _inner(this, &_list, &_current) -, _shadow(this) -, _done(this, lang(lng_about_done), st::defaultBoxButton) -, _shortPollRequest(0) { - setMaxHeight(st::sessionsHeight); - setTitleText(lang(lng_sessions_other_header)); +SessionsBox::SessionsBox(QWidget*) +: _shortPollTimer(this) { +} + +void SessionsBox::prepare() { + setTitle(lang(lng_sessions_other_header)); + + addButton(lang(lng_close), [this] { closeBox(); }); + + setDimensions(st::boxWideWidth, st::sessionsHeight); - connect(_done, SIGNAL(clicked()), this, SLOT(onClose())); connect(_inner, SIGNAL(oneTerminated()), this, SLOT(onOneTerminated())); connect(_inner, SIGNAL(allTerminated()), this, SLOT(onAllTerminated())); connect(_inner, SIGNAL(terminateAll()), this, SLOT(onTerminateAll())); connect(App::wnd(), SIGNAL(checkNewAuthorization()), this, SLOT(onCheckNewAuthorization())); - connect(&_shortPollTimer, SIGNAL(timeout()), this, SLOT(onShortPollAuthorizations())); + connect(_shortPollTimer, SIGNAL(timeout()), this, SLOT(onShortPollAuthorizations())); - init(_inner, st::boxButtonPadding.bottom() + _done->height() + st::boxButtonPadding.top(), titleHeight()); + _inner = setInnerWidget(object_ptr(this, &_list, &_current), st::sessionsScroll); _inner->resize(width(), st::noContactsHeight); setLoading(true); - raiseShadow(); - MTP::send(MTPaccount_GetAuthorizations(), rpcDone(&SessionsBox::gotAuthorizations)); } void SessionsBox::setLoading(bool loading) { if (_loading != loading) { _loading = loading; - scrollArea()->setVisible(!_loading); - _shadow->setVisible(!_loading); + setInnerVisible(!_loading); } } void SessionsBox::resizeEvent(QResizeEvent *e) { - ScrollableBox::resizeEvent(e); - _shadow->setGeometry(0, height() - st::boxButtonPadding.bottom() - _done->height() - st::boxButtonPadding.top() - st::lineWidth, width(), st::lineWidth); - _done->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _done->height()); + BoxContent::resizeEvent(e); + + _inner->resize(width(), _inner->height()); } void SessionsBox::paintEvent(QPaintEvent *e) { - AbstractBox::paintEvent(e); + BoxContent::paintEvent(e); Painter p(this); - p.translate(0, titleHeight()); - if (_loading) { p.setFont(st::noContactsFont); p.setPen(st::noContactsColor); @@ -202,7 +198,7 @@ void SessionsBox::gotAuthorizations(const MTPaccount_Authorizations &result) { update(); - _shortPollTimer.start(SessionsShortPollTimeout); + _shortPollTimer->start(SessionsShortPollTimeout); } void SessionsBox::onOneTerminated() { @@ -236,9 +232,7 @@ void SessionsBox::onTerminateAll() { SessionsBox::Inner::Inner(QWidget *parent, SessionsBox::List *list, SessionsBox::Data *current) : TWidget(parent) , _list(list) , _current(current) -, _terminating(0) -, _terminateAll(this, lang(lng_sessions_terminate_all), st::sessionTerminateAllButton) -, _terminateBox(0) { +, _terminateAll(this, lang(lng_sessions_terminate_all), st::sessionTerminateAllButton) { connect(_terminateAll, SIGNAL(clicked()), this, SLOT(onTerminateAll())); _terminateAll->hide(); setAttribute(Qt::WA_OpaquePaintEvent); @@ -312,49 +306,33 @@ void SessionsBox::Inner::paintEvent(QPaintEvent *e) { void SessionsBox::Inner::onTerminate() { for (TerminateButtons::iterator i = _terminateButtons.begin(), e = _terminateButtons.end(); i != e; ++i) { if (i.value()->isOver()) { - _terminating = i.key(); - if (_terminateBox) _terminateBox->deleteLater(); - _terminateBox = new ConfirmBox(lang(lng_settings_reset_one_sure), lang(lng_settings_reset_button), st::attentionBoxButton); - connect(_terminateBox, SIGNAL(confirmed()), this, SLOT(onTerminateSure())); - connect(_terminateBox, SIGNAL(destroyed(QObject*)), this, SLOT(onNoTerminateBox(QObject*))); - Ui::showLayer(_terminateBox, KeepOtherLayers); + _terminateBox = Ui::show(Box(lang(lng_settings_reset_one_sure), lang(lng_settings_reset_button), st::attentionBoxButton, base::lambda_guarded(this, [this, terminating = i.key()] { + if (_terminateBox) { + _terminateBox->closeBox(); + _terminateBox = nullptr; + } + MTP::send(MTPaccount_ResetAuthorization(MTP_long(terminating)), rpcDone(&Inner::terminateDone, terminating), rpcFail(&Inner::terminateFail, terminating)); + TerminateButtons::iterator i = _terminateButtons.find(terminating); + if (i != _terminateButtons.cend()) { + i.value()->clearState(); + i.value()->hide(); + } + })), KeepOtherLayers); } } } -void SessionsBox::Inner::onTerminateSure() { - if (_terminateBox) { - _terminateBox->onClose(); - _terminateBox = 0; - } - MTP::send(MTPaccount_ResetAuthorization(MTP_long(_terminating)), rpcDone(&Inner::terminateDone, _terminating), rpcFail(&Inner::terminateFail, _terminating)); - TerminateButtons::iterator i = _terminateButtons.find(_terminating); - if (i != _terminateButtons.cend()) { - i.value()->clearState(); - i.value()->hide(); - } -} - void SessionsBox::Inner::onTerminateAll() { if (_terminateBox) _terminateBox->deleteLater(); - _terminateBox = new ConfirmBox(lang(lng_settings_reset_sure), lang(lng_settings_reset_button), st::attentionBoxButton); - connect(_terminateBox, SIGNAL(confirmed()), this, SLOT(onTerminateAllSure())); - connect(_terminateBox, SIGNAL(destroyed(QObject*)), this, SLOT(onNoTerminateBox(QObject*))); - Ui::showLayer(_terminateBox, KeepOtherLayers); -} - -void SessionsBox::Inner::onTerminateAllSure() { - if (_terminateBox) { - _terminateBox->onClose(); - _terminateBox = 0; - } - MTP::send(MTPauth_ResetAuthorizations(), rpcDone(&Inner::terminateAllDone), rpcFail(&Inner::terminateAllFail)); - emit terminateAll(); -} - -void SessionsBox::Inner::onNoTerminateBox(QObject *obj) { - if (obj == _terminateBox) _terminateBox = 0; + _terminateBox = Ui::show(Box(lang(lng_settings_reset_sure), lang(lng_settings_reset_button), st::attentionBoxButton, base::lambda_guarded(this, [this] { + if (_terminateBox) { + _terminateBox->closeBox(); + _terminateBox = nullptr; + } + MTP::send(MTPauth_ResetAuthorizations(), rpcDone(&Inner::terminateAllDone), rpcFail(&Inner::terminateAllFail)); + emit terminateAll(); + })), KeepOtherLayers); } void SessionsBox::Inner::terminateDone(uint64 hash, const MTPBool &result) { diff --git a/Telegram/SourceFiles/boxes/sessionsbox.h b/Telegram/SourceFiles/boxes/sessionsbox.h index ec67d8486..8ede15969 100644 --- a/Telegram/SourceFiles/boxes/sessionsbox.h +++ b/Telegram/SourceFiles/boxes/sessionsbox.h @@ -28,26 +28,27 @@ class ConfirmBox; namespace Ui { class IconButton; class LinkButton; -class RoundButton; } // namespace Ui -class SessionsBox : public ScrollableBox, public RPCSender { +class SessionsBox : public BoxContent, public RPCSender { Q_OBJECT public: - SessionsBox(); + SessionsBox(QWidget*); -public slots: +protected: + void prepare() override; + + void resizeEvent(QResizeEvent *e) override; + void paintEvent(QPaintEvent *e) override; + +private slots: void onOneTerminated(); void onAllTerminated(); void onTerminateAll(); void onShortPollAuthorizations(); void onCheckNewAuthorization(); -protected: - void resizeEvent(QResizeEvent *e) override; - void paintEvent(QPaintEvent *e) override; - private: void setLoading(bool loading); struct Data { @@ -61,18 +62,16 @@ private: void gotAuthorizations(const MTPaccount_Authorizations &result); - bool _loading; + bool _loading = false; Data _current; List _list; class Inner; - ChildWidget _inner; - ChildWidget _shadow; - ChildWidget _done; + QPointer _inner; - SingleTimer _shortPollTimer; - mtpRequestId _shortPollRequest; + object_ptr _shortPollTimer; + mtpRequestId _shortPollRequest = 0; }; @@ -96,10 +95,7 @@ signals: public slots: void onTerminate(); - void onTerminateSure(); void onTerminateAll(); - void onTerminateAllSure(); - void onNoTerminateBox(QObject *obj); private: void terminateDone(uint64 hash, const MTPBool &result); @@ -114,8 +110,7 @@ private: typedef QMap TerminateButtons; TerminateButtons _terminateButtons; - uint64 _terminating; - ChildWidget _terminateAll; - ConfirmBox *_terminateBox; + object_ptr _terminateAll; + QPointer _terminateBox; }; diff --git a/Telegram/SourceFiles/boxes/sharebox.cpp b/Telegram/SourceFiles/boxes/sharebox.cpp index 3a53d8647..4110a3e18 100644 --- a/Telegram/SourceFiles/boxes/sharebox.cpp +++ b/Telegram/SourceFiles/boxes/sharebox.cpp @@ -39,29 +39,27 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "ui/widgets/scroll_area.h" #include "boxes/contactsbox.h" -ShareBox::ShareBox(CopyCallback &©Callback, SubmitCallback &&submitCallback, FilterCallback &&filterCallback) : ItemListBox(st::boxScroll) -, _copyCallback(std_::move(copyCallback)) +ShareBox::ShareBox(QWidget*, CopyCallback &©Callback, SubmitCallback &&submitCallback, FilterCallback &&filterCallback) +: _copyCallback(std_::move(copyCallback)) , _submitCallback(std_::move(submitCallback)) -, _inner(this, std_::move(filterCallback)) +, _filterCallback(std_::move(filterCallback)) , _select(this, st::contactsMultiSelect, lang(lng_participant_filter)) -, _copy(this, lang(lng_share_copy_link), st::defaultBoxButton) -, _share(this, lang(lng_share_confirm), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) -, _topShadow(this) -, _bottomShadow(this) { +, _searchTimer(this) { +} + +void ShareBox::prepare() { _select->resizeToWidth(st::boxWideWidth); myEnsureResized(_select); - setTitleText(lang(lng_share_title)); - auto topSkip = getTopScrollSkip(); - auto bottomSkip = st::boxButtonPadding.top() + _share->height() + st::boxButtonPadding.bottom(); - init(_inner, bottomSkip, topSkip); + setTitle(lang(lng_share_title)); + _inner = setInnerWidget(object_ptr(this, std_::move(_filterCallback)), getTopScrollSkip()); connect(_inner, SIGNAL(mustScrollTo(int,int)), this, SLOT(onMustScrollTo(int,int))); - connect(_copy, SIGNAL(clicked()), this, SLOT(onCopyLink())); - connect(_share, SIGNAL(clicked()), this, SLOT(onSubmit())); - connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); - connect(scrollArea(), SIGNAL(scrolled()), this, SLOT(onScroll())); + + createButtons(); + + setDimensions(st::boxWideWidth, st::boxMaxListHeight); + _select->setQueryChangedCallback([this](const QString &query) { onFilterUpdate(query); }); _select->setItemRemovedCallback([this](uint64 itemId) { if (auto peer = App::peerLoaded(itemId)) { @@ -77,16 +75,14 @@ ShareBox::ShareBox(CopyCallback &©Callback, SubmitCallback &&submitCallback, onPeerSelectedChanged(peer, checked); }); - _searchTimer.setSingleShot(true); - connect(&_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchByUsername())); + _searchTimer->setSingleShot(true); + connect(_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchByUsername())); - updateButtonsVisibility(); - - raiseShadow(); + _select->raise(); } int ShareBox::getTopScrollSkip() const { - auto result = titleHeight(); + auto result = 0; if (!_select->isHidden()) { result += _select->height(); } @@ -94,16 +90,7 @@ int ShareBox::getTopScrollSkip() const { } void ShareBox::updateScrollSkips() { - auto oldScrollHeight = scrollArea()->height(); - auto topSkip = getTopScrollSkip(); - auto bottomSkip = st::boxButtonPadding.top() + _share->height() + st::boxButtonPadding.bottom(); - setScrollSkips(bottomSkip, topSkip); - auto scrollHeightDelta = scrollArea()->height() - oldScrollHeight; - if (scrollHeightDelta) { - scrollArea()->scrollToY(scrollArea()->scrollTop() - scrollHeightDelta); - } - - _topShadow->setGeometry(0, topSkip, width(), st::lineWidth); + setInnerTopSkip(getTopScrollSkip(), true); } bool ShareBox::onSearchByUsername(bool searchCache) { @@ -135,7 +122,7 @@ bool ShareBox::onSearchByUsername(bool searchCache) { void ShareBox::onNeedSearchByUsername() { if (!onSearchByUsername(true)) { - _searchTimer.start(AutoSearchTimeout); + _searchTimer->start(AutoSearchTimeout); } } @@ -160,7 +147,6 @@ void ShareBox::peopleReceived(const MTPcontacts_Found &result, mtpRequestId requ } _peopleRequest = 0; - onScroll(); } } @@ -174,22 +160,19 @@ bool ShareBox::peopleFailed(const RPCError &error, mtpRequestId requestId) { return true; } -void ShareBox::doSetInnerFocus() { +void ShareBox::setInnerFocus() { _select->setInnerFocus(); } void ShareBox::resizeEvent(QResizeEvent *e) { - ItemListBox::resizeEvent(e); + BoxContent::resizeEvent(e); _select->resizeToWidth(width()); - _select->moveToLeft(0, titleHeight()); + _select->moveToLeft(0, 0); updateScrollSkips(); _inner->resizeToWidth(width()); - moveButtons(); - _topShadow->setGeometry(0, getTopScrollSkip(), width(), st::lineWidth); - _bottomShadow->setGeometry(0, height() - st::boxButtonPadding.bottom() - _share->height() - st::boxButtonPadding.top() - st::lineWidth, width(), st::lineWidth); } void ShareBox::keyPressEvent(QKeyEvent *e) { @@ -200,32 +183,37 @@ void ShareBox::keyPressEvent(QKeyEvent *e) { } else if (e->key() == Qt::Key_Down) { _inner->activateSkipColumn(1); } else if (e->key() == Qt::Key_PageUp) { - _inner->activateSkipPage(scrollArea()->height(), -1); + _inner->activateSkipPage(height() - getTopScrollSkip(), -1); } else if (e->key() == Qt::Key_PageDown) { - _inner->activateSkipPage(scrollArea()->height(), 1); + _inner->activateSkipPage(height() - getTopScrollSkip(), 1); } else { - ItemListBox::keyPressEvent(e); + BoxContent::keyPressEvent(e); } } else { - ItemListBox::keyPressEvent(e); + BoxContent::keyPressEvent(e); } } -void ShareBox::moveButtons() { - _copy->moveToRight(st::boxButtonPadding.right(), _share->y()); - _share->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _share->height()); - _cancel->moveToRight(st::boxButtonPadding.right() + _share->width() + st::boxButtonPadding.left(), _share->y()); +void ShareBox::updateButtons() { + auto hasSelected = _inner->hasSelected(); + if (_hasSelected != hasSelected) { + _hasSelected = hasSelected; + createButtons(); + } } -void ShareBox::updateButtonsVisibility() { - auto hasSelected = _inner->hasSelected(); - _copy->setVisible(!hasSelected); - _share->setVisible(hasSelected); - _cancel->setVisible(hasSelected); +void ShareBox::createButtons() { + clearButtons(); + if (_hasSelected) { + addButton(lang(lng_share_confirm), [this] { onSubmit(); }); + } else { + addButton(lang(lng_share_copy_link), [this] { onCopyLink(); }); + } + addButton(lang(lng_cancel), [this] { closeBox(); }); } void ShareBox::onFilterUpdate(const QString &query) { - scrollArea()->scrollToY(0); + onScrollToY(0); _inner->updateFilter(query); } @@ -259,33 +247,27 @@ void ShareBox::onCopyLink() { } void ShareBox::onSelectedChanged() { - updateButtonsVisibility(); - moveButtons(); + updateButtons(); update(); } void ShareBox::onMustScrollTo(int top, int bottom) { - auto scrollTop = scrollArea()->scrollTop(), scrollBottom = scrollTop + scrollArea()->height(); - auto from = scrollTop, to = scrollTop; - if (scrollTop > top) { - to = top; - } else if (scrollBottom < bottom) { - to = bottom - (scrollBottom - scrollTop); - } - if (from != to) { - _scrollAnimation.start([this]() { scrollAnimationCallback(); }, from, to, st::shareScrollDuration, anim::sineInOut); - } + onScrollToY(top, bottom); + //auto scrollTop = scrollArea()->scrollTop(), scrollBottom = scrollTop + scrollArea()->height(); + //auto from = scrollTop, to = scrollTop; + //if (scrollTop > top) { + // to = top; + //} else if (scrollBottom < bottom) { + // to = bottom - (scrollBottom - scrollTop); + //} + //if (from != to) { + // _scrollAnimation.start([this]() { scrollAnimationCallback(); }, from, to, st::shareScrollDuration, anim::sineInOut); + //} } void ShareBox::scrollAnimationCallback() { - auto scrollTop = qRound(_scrollAnimation.current(scrollArea()->scrollTop())); - scrollArea()->scrollToY(scrollTop); -} - -void ShareBox::onScroll() { - auto scroll = scrollArea(); - auto scrollTop = scroll->scrollTop(); - _inner->setVisibleTopBottom(scrollTop, scrollTop + scroll->height()); + //auto scrollTop = qRound(_scrollAnimation.current(scrollArea()->scrollTop())); + //scrollArea()->scrollToY(scrollTop); } ShareBox::Inner::Inner(QWidget *parent, ShareBox::FilterCallback &&filterCallback) : TWidget(parent) @@ -928,7 +910,7 @@ void shareGameScoreFromItem(HistoryItem *item) { } return false; }; - Ui::showLayer(new ShareBox(std_::move(copyCallback), std_::move(submitCallback), std_::move(filterCallback))); + Ui::show(Box(std_::move(copyCallback), std_::move(submitCallback), std_::move(filterCallback))); } } // namespace @@ -938,7 +920,7 @@ void shareGameScoreByHash(const QString &hash) { auto hashEncrypted = QByteArray::fromBase64(hash.toLatin1(), QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals); if (hashEncrypted.size() <= key128Size || (hashEncrypted.size() % 0x10) != 0) { - Ui::showLayer(new InformBox(lang(lng_confirm_phone_link_invalid))); + Ui::show(Box(lang(lng_confirm_phone_link_invalid))); return; } @@ -958,20 +940,20 @@ void shareGameScoreByHash(const QString &hash) { // Check next 64 bits of SHA1() of data. auto skipSha1Part = sizeof(channelAccessHash); if (memcmp(dataSha1 + skipSha1Part, hashEncrypted.constData() + skipSha1Part, key128Size - skipSha1Part) != 0) { - Ui::showLayer(new InformBox(lang(lng_share_wrong_user))); + Ui::show(Box(lang(lng_share_wrong_user))); return; } auto hashDataInts = reinterpret_cast(hashData.data()); if (hashDataInts[0] != MTP::authedId()) { - Ui::showLayer(new InformBox(lang(lng_share_wrong_user))); + Ui::show(Box(lang(lng_share_wrong_user))); return; } // Check first 32 bits of channel access hash. auto channelAccessHashInts = reinterpret_cast(&channelAccessHash); if (channelAccessHashInts[0] != hashDataInts[3]) { - Ui::showLayer(new InformBox(lang(lng_share_wrong_user))); + Ui::show(Box(lang(lng_share_wrong_user))); return; } @@ -979,7 +961,7 @@ void shareGameScoreByHash(const QString &hash) { auto msgId = hashDataInts[2]; if (!channelId && channelAccessHash) { // If there is no channel id, there should be no channel access_hash. - Ui::showLayer(new InformBox(lang(lng_share_wrong_user))); + Ui::show(Box(lang(lng_share_wrong_user))); return; } @@ -991,7 +973,7 @@ void shareGameScoreByHash(const QString &hash) { if (auto item = App::histItemById(channel, msgId)) { shareGameScoreFromItem(item); } else { - Ui::showLayer(new InformBox(lang(lng_edit_deleted))); + Ui::show(Box(lang(lng_edit_deleted))); } }); }; diff --git a/Telegram/SourceFiles/boxes/sharebox.h b/Telegram/SourceFiles/boxes/sharebox.h index 214ae2505..e29566009 100644 --- a/Telegram/SourceFiles/boxes/sharebox.h +++ b/Telegram/SourceFiles/boxes/sharebox.h @@ -36,24 +36,28 @@ struct PeerUpdate; namespace Ui { class MultiSelect; -class RoundButton; } // namespace Ui QString appendShareGameScoreUrl(const QString &url, const FullMsgId &fullId); void shareGameScoreByHash(const QString &hash); -class ShareBox : public ItemListBox, public RPCSender { +class ShareBox : public BoxContent, public RPCSender { Q_OBJECT public: using CopyCallback = base::lambda; using SubmitCallback = base::lambda &)>; using FilterCallback = base::lambda; - ShareBox(CopyCallback &©Callback, SubmitCallback &&submitCallback, FilterCallback &&filterCallback); + ShareBox(QWidget*, CopyCallback &©Callback, SubmitCallback &&submitCallback, FilterCallback &&filterCallback); + +protected: + void prepare() override; + void setInnerFocus() override; + + void resizeEvent(QResizeEvent *e) override; + void keyPressEvent(QKeyEvent *e) override; private slots: - void onScroll(); - bool onSearchByUsername(bool searchCache = false); void onNeedSearchByUsername(); @@ -62,19 +66,13 @@ private slots: void onMustScrollTo(int top, int bottom); -protected: - void resizeEvent(QResizeEvent *e) override; - void keyPressEvent(QKeyEvent *e) override; - - void doSetInnerFocus() override; - private: void scrollAnimationCallback(); void onFilterUpdate(const QString &query); void onSelectedChanged(); - void moveButtons(); - void updateButtonsVisibility(); + void updateButtons(); + void createButtons(); int getTopScrollSkip() const; void updateScrollSkips(); @@ -86,19 +84,16 @@ private: CopyCallback _copyCallback; SubmitCallback _submitCallback; + FilterCallback _filterCallback; + + object_ptr _select; class Inner; - ChildWidget _inner; - ChildWidget _select; + QPointer _inner; - ChildWidget _copy; - ChildWidget _share; - ChildWidget _cancel; + bool _hasSelected = false; - ChildWidget _topShadow; - ChildWidget _bottomShadow; - - QTimer _searchTimer; + object_ptr _searchTimer; QString _peopleQuery; bool _peopleFull = false; mtpRequestId _peopleRequest = 0; diff --git a/Telegram/SourceFiles/boxes/stickers_box.cpp b/Telegram/SourceFiles/boxes/stickers_box.cpp index 2c7a0e88b..b62ea5a31 100644 --- a/Telegram/SourceFiles/boxes/stickers_box.cpp +++ b/Telegram/SourceFiles/boxes/stickers_box.cpp @@ -39,8 +39,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org namespace { -constexpr int kArchivedLimitFirstRequest = 10; -constexpr int kArchivedLimitPerPage = 30; +constexpr int kArchivedLimitFirstRequest = 1;// 10; +constexpr int kArchivedLimitPerPage = 1;// 30; } // namespace @@ -89,7 +89,6 @@ StickersBox::CounterWidget::CounterWidget(QWidget *parent) : TWidget(parent) { updateCounter(); } - void StickersBox::CounterWidget::setCounter(int counter) { _text = (counter > 0) ? QString::number(counter) : QString(); auto dummy = QImage(1, 1, QImage::Format_ARGB32_Premultiplied); @@ -116,24 +115,40 @@ void StickersBox::CounterWidget::updateCounter() { update(); } -StickersBox::StickersBox(Section section) : ItemListBox(st::boxScroll) -, _topShadow(this, st::shadowColor) -, _tabs(this, st::defaultTabsSlider) +template +StickersBox::Tab::Tab(int index, Args&&... args) +: _index(index) +, _widget(std_::forward(args)...) +, _weak(_widget) { +} + +object_ptr StickersBox::Tab::takeWidget() { + return std_::move(_widget); +} + +void StickersBox::Tab::returnWidget(object_ptr widget) { + _widget = std_::move(widget); + t_assert(_widget == _weak); +} + +void StickersBox::Tab::saveScrollTop() { + _scrollTop = widget()->getVisibleTop(); +} + +StickersBox::StickersBox(QWidget*, Section section) +: _tabs(this, st::stickersTabs) , _unreadBadge(this) , _section(section) , _installed(0, this, Section::Installed) , _featured(1, this, Section::Featured) , _archived(2, this, Section::Archived) { - setup(); } -StickersBox::StickersBox(const Stickers::Order &archivedIds) : ItemListBox(st::boxScroll) -, _topShadow(this, st::shadowColor) -, _section(Section::ArchivedPart) +StickersBox::StickersBox(QWidget*, const Stickers::Order &archivedIds) +: _section(Section::ArchivedPart) , _archived(0, this, archivedIds) , _aboutWidth(st::boxWideWidth - 2 * st::stickersReorderPadding.top()) , _about(st::boxTextFont, lang(lng_stickers_packs_archived), _defaultOptions, _aboutWidth) { - setup(); } void StickersBox::getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedStickers &result) { @@ -154,7 +169,8 @@ void StickersBox::getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedSti archived.clear(); } - bool addedSet = false; + auto addedSet = false; + auto changedSets = false; auto &v = stickers.vsets.c_vector().v; for_const (auto &stickerSet, v) { const MTPDstickerSet *setData = nullptr; @@ -177,12 +193,13 @@ void StickersBox::getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedSti if (auto set = Stickers::feedSet(*setData)) { auto index = archived.indexOf(set->id); if (archived.isEmpty() || index != archived.size() - 1) { + changedSets = true; if (index < archived.size() - 1) { archived.removeAt(index); } archived.push_back(set->id); } - if (_archived.widget->appendSet(*set)) { + if (_archived.widget()->appendSet(*set)) { addedSet = true; if (set->stickers.isEmpty() || (set->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) { App::api()->scheduleStickerSetRequest(set->id, set->access); @@ -191,10 +208,12 @@ void StickersBox::getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedSti } } if (addedSet) { - _archived.widget->updateSize(); - _archived.widget->setVisibleScrollbar((scrollArea()->scrollTopMax() > 0) ? (st::boxScroll.width - st::boxScroll.deltax) : 0); + _archived.widget()->updateSize(); } else { _allArchivedLoaded = v.isEmpty() || (offsetId != 0); + if (changedSets && !_allArchivedLoaded) { + loadMoreArchived(); + } } refreshTabs(); @@ -202,69 +221,63 @@ void StickersBox::getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedSti if (_section == Section::Archived && addedSet) { App::api()->requestStickerSets(); } - checkLoadMoreArchived(); } -void StickersBox::setup() { +void StickersBox::prepare() { if (_section == Section::Installed) { Local::readArchivedStickers(); } else if (_section == Section::Archived) { requestArchivedSets(); } else if (_section == Section::ArchivedPart) { - setTitleText(lang(lng_stickers_archived)); + setTitle(lang(lng_stickers_archived)); } if (Global::ArchivedStickerSetsOrder().isEmpty()) { preloadArchivedSets(); } if (_tabs) { + setNoContentMargin(true); _tabs->setSectionActivatedCallback([this] { switchTab(); }); refreshTabs(); } - if (_installed.widget && _section != Section::Installed) _installed.widget->hide(); - if (_featured.widget && _section != Section::Featured) _featured.widget->hide(); - if (_section != Section::Archived && _section != Section::ArchivedPart) _archived.widget->hide(); + if (_installed.widget() && _section != Section::Installed) _installed.widget()->hide(); + if (_featured.widget() && _section != Section::Featured) _featured.widget()->hide(); + if (_section != Section::Archived && _section != Section::ArchivedPart) _archived.widget()->hide(); - if (_featured.widget) { - _featured.widget->setInstallSetCallback([this](uint64 setId) { installSet(setId); }); + if (_featured.widget()) { + _featured.widget()->setInstallSetCallback([this](uint64 setId) { installSet(setId); }); } - _archived.widget->setInstallSetCallback([this](uint64 setId) { installSet(setId); }); + _archived.widget()->setInstallSetCallback([this](uint64 setId) { installSet(setId); }); + _archived.widget()->setLoadMoreCallback([this] { loadMoreArchived(); }); - _done.create(this, lang(lng_about_done), st::defaultBoxButton); - connect(_done, SIGNAL(clicked()), this, SLOT(onClose())); + addButton(lang(lng_about_done), [this] { closeBox(); }); - auto bottomSkip = st::boxButtonPadding.top() + _done->height() + st::boxButtonPadding.bottom(); if (_section == Section::Installed) { - _bottomShadow.create(this); _tab = &_installed; } else if (_section == Section::ArchivedPart) { _aboutHeight = st::stickersReorderPadding.top() + _about.countHeight(_aboutWidth) + st::stickersReorderPadding.bottom(); + _titleShadow.create(this); _tab = &_archived; } else if (_section == Section::Archived) { - _bottomShadow.create(this); _tab = &_archived; } else { // _section == Section::Featured - _bottomShadow.create(this); _tab = &_featured; } - ItemListBox::init(_tab->widget, bottomSkip, titleHeight() + _aboutHeight); - setMaxHeight((_section == Section::ArchivedPart) ? st::sessionsHeight : st::boxMaxListHeight); + setInnerWidget(_tab->takeWidget(), getTopSkip()); + setDimensions(st::boxWideWidth, (_section == Section::ArchivedPart) ? st::sessionsHeight : st::boxMaxListHeight); connect(App::main(), SIGNAL(stickersUpdated()), this, SLOT(onStickersUpdated())); App::main()->updateStickers(); - if (_installed.widget) { - connect(_installed.widget, SIGNAL(checkDraggingScroll(int)), this, SLOT(onCheckDraggingScroll(int))); - connect(_installed.widget, SIGNAL(noDraggingScroll()), this, SLOT(onNoDraggingScroll())); + if (_installed.widget()) { + connect(_installed.widget(), SIGNAL(draggingScrollDelta(int)), this, SLOT(onDraggingScrollDelta(int))); } - connect(&_scrollTimer, SIGNAL(timeout()), this, SLOT(onScrollTimer())); - connect(scrollArea(), SIGNAL(scrolled()), this, SLOT(onScroll())); - _scrollTimer.setSingleShot(false); + if (_tabs) { + _tabs->raise(); + } rebuildList(); - - raiseShadow(); } void StickersBox::refreshTabs() { @@ -288,61 +301,44 @@ void StickersBox::refreshTabs() { switchTab(); } updateTabsGeometry(); - setBlockTitle(true, (sections.size() < 3), false); } -void StickersBox::onScroll() { - updateVisibleTopBottom(); - checkLoadMoreArchived(); -} +void StickersBox::loadMoreArchived() { + if (_section != Section::Archived || _allArchivedLoaded || _archivedRequestId) { + return; + } -void StickersBox::updateVisibleTopBottom() { - auto visibleTop = scrollArea()->scrollTop(); - auto visibleBottom = visibleTop + scrollArea()->height(); - _tab->widget->setVisibleTopBottom(visibleTop, visibleBottom); -} - -void StickersBox::checkLoadMoreArchived() { - if (_section != Section::Archived) return; - - int scrollTop = scrollArea()->scrollTop(), scrollTopMax = scrollArea()->scrollTopMax(); - if (scrollTop + PreloadHeightsCount * scrollArea()->height() >= scrollTopMax) { - if (!_archivedRequestId && !_allArchivedLoaded) { - uint64 lastId = 0; - for (auto setId = Global::ArchivedStickerSetsOrder().cend(), e = Global::ArchivedStickerSetsOrder().cbegin(); setId != e;) { - --setId; - auto it = Global::StickerSets().constFind(*setId); - if (it != Global::StickerSets().cend()) { - if (it->flags & MTPDstickerSet::Flag::f_archived) { - lastId = it->id; - break; - } - } + uint64 lastId = 0; + for (auto setIt = Global::ArchivedStickerSetsOrder().cend(), e = Global::ArchivedStickerSetsOrder().cbegin(); setIt != e;) { + --setIt; + auto it = Global::StickerSets().constFind(*setIt); + if (it != Global::StickerSets().cend()) { + if (it->flags & MTPDstickerSet::Flag::f_archived) { + lastId = it->id; + break; } - MTPmessages_GetArchivedStickers::Flags flags = 0; - _archivedRequestId = MTP::send(MTPmessages_GetArchivedStickers(MTP_flags(flags), MTP_long(lastId), MTP_int(kArchivedLimitPerPage)), rpcDone(&StickersBox::getArchivedDone, lastId)); } } + MTPmessages_GetArchivedStickers::Flags flags = 0; + _archivedRequestId = MTP::send(MTPmessages_GetArchivedStickers(MTP_flags(flags), MTP_long(lastId), MTP_int(kArchivedLimitPerPage)), rpcDone(&StickersBox::getArchivedDone, lastId)); } void StickersBox::paintEvent(QPaintEvent *e) { - AbstractBox::paintEvent(e); + BoxContent::paintEvent(e); Painter p(this); - p.translate(0, titleHeight()); - if (_aboutHeight > 0) { - p.fillRect(0, 0, width(), _aboutHeight, st::contactsAboutBg); + p.fillRect(0, st::lineWidth, width(), _aboutHeight - st::lineWidth, st::contactsAboutBg); p.setPen(st::stickersReorderFg); _about.draw(p, st::stickersReorderPadding.top(), st::stickersReorderPadding.top(), _aboutWidth, style::al_center); } if (_slideAnimation) { - _slideAnimation->paintFrame(p, scrollArea()->x(), scrollArea()->y() - titleHeight(), width(), getms()); + _slideAnimation->paintFrame(p, 0, getTopSkip(), width(), getms()); if (!_slideAnimation->animating()) { _slideAnimation.reset(); - scrollArea()->show(); + setInnerVisible(true); update(); } } @@ -354,9 +350,11 @@ void StickersBox::updateTabsGeometry() { _tabs->resizeToWidth(_tabIndices.size() * width() / 3); _unreadBadge->setVisible(_tabIndices.contains(Section::Featured)); + setInnerTopSkip(getTopSkip()); + auto featuredLeft = width() / 3; auto featuredRight = 2 * width() / 3; - auto featuredTextWidth = st::defaultTabsSlider.labelFont->width(lang(lng_stickers_featured_tab).toUpper()); + auto featuredTextWidth = st::stickersTabs.labelFont->width(lang(lng_stickers_featured_tab).toUpper()); auto featuredTextRight = featuredLeft + (featuredRight - featuredLeft - featuredTextWidth) / 2 + featuredTextWidth; auto unreadBadgeLeft = featuredTextRight - st::stickersFeaturedBadgeSkip; auto unreadBadgeTop = st::stickersFeaturedBadgeTop; @@ -368,6 +366,10 @@ void StickersBox::updateTabsGeometry() { _tabs->moveToLeft(0, 0); } +int StickersBox::getTopSkip() const { + return (_tabs ? (_tabs->height() - st::lineWidth) : 0) + _aboutHeight; +} + void StickersBox::switchTab() { if (!_tabs) return; @@ -386,41 +388,37 @@ void StickersBox::switchTab() { } if (_tab != newTab) { if (_tab == &_installed) { - _localOrder = _tab->widget->getFullOrder(); - _localRemoved = _tab->widget->getRemovedSets(); + _localOrder = _tab->widget()->getFullOrder(); + _localRemoved = _tab->widget()->getRemovedSets(); } - auto scroll = scrollArea(); auto wasCache = grabContentCache(); - auto wasIndex = _tab->index; - _tab->scrollTop = scroll->scrollTop(); - auto widget = scroll->takeWidget(); + auto wasIndex = _tab->index(); + _tab->saveScrollTop(); + auto widget = takeInnerWidget(); widget->setParent(this); widget->hide(); + _tab->returnWidget(std_::move(widget)); _tab = newTab; _section = newSection; - scroll->setOwnedWidget(newTab->widget); - _tab->widget->show(); + setInnerWidget(_tab->takeWidget(), getTopSkip()); + _tab->widget()->show(); rebuildList(); - scroll->scrollToY(_tab->scrollTop); + onScrollToY(_tab->getScrollTop()); auto nowCache = grabContentCache(); - auto nowIndex = _tab->index; + auto nowIndex = _tab->index(); _slideAnimation = std_::make_unique(); _slideAnimation->setSnapshots(std_::move(wasCache), std_::move(nowCache)); auto slideLeft = wasIndex > nowIndex; _slideAnimation->start(slideLeft, [this] { update(); }, st::slideDuration); - scrollArea()->hide(); + setInnerVisible(false); update(); } } QPixmap StickersBox::grabContentCache() { - _topShadow->hide(); - _bottomShadow->hide(); _tabs->hide(); - auto result = myGrab(this, scrollArea()->geometry()); - _topShadow->show(); - _bottomShadow->show(); + auto result = grabInnerCache(); _tabs->show(); return std_::move(result); } @@ -435,9 +433,9 @@ void StickersBox::installSet(uint64 setId) { if (_localRemoved.contains(setId)) { _localRemoved.removeOne(setId); - if (_installed.widget) _installed.widget->setRemovedSets(_localRemoved); - if (_featured.widget) _featured.widget->setRemovedSets(_localRemoved); - _archived.widget->setRemovedSets(_localRemoved); + if (_installed.widget()) _installed.widget()->setRemovedSets(_localRemoved); + if (_featured.widget()) _featured.widget()->setRemovedSets(_localRemoved); + _archived.widget()->setRemovedSets(_localRemoved); } if (!(it->flags & MTPDstickerSet::Flag::f_installed) || (it->flags & MTPDstickerSet::Flag::f_archived)) { MTP::send(MTPmessages_InstallStickerSet(Stickers::inputSetId(*it), MTP_boolFalse()), rpcDone(&StickersBox::installDone), rpcFail(&StickersBox::installFail, setId)); @@ -449,6 +447,8 @@ void StickersBox::installSet(uint64 setId) { void StickersBox::installDone(const MTPmessages_StickerSetInstallResult &result) { if (result.type() == mtpc_messages_stickerSetInstallResultArchive) { Stickers::applyArchivedResult(result.c_messages_stickerSetInstallResultArchive()); + } else { + Stickers::applyArchivedResultFake(); } } @@ -492,31 +492,24 @@ void StickersBox::requestArchivedSets() { } void StickersBox::resizeEvent(QResizeEvent *e) { - ItemListBox::resizeEvent(e); + BoxContent::resizeEvent(e); + if (_tabs) { updateTabsGeometry(); - _topShadow->setGeometryToLeft(0, _tabs->height() - st::lineWidth, width(), st::lineWidth); - } else { - _topShadow->setGeometryToLeft(0, scrollArea()->y(), width(), st::lineWidth); } - if (_installed.widget) _installed.widget->resize(width(), _installed.widget->height()); - if (_featured.widget) _featured.widget->resize(width(), _featured.widget->height()); - _archived.widget->resize(width(), _archived.widget->height()); - _tab->widget->setVisibleScrollbar((scrollArea()->scrollTopMax() > 0) ? (st::boxScroll.width - st::boxScroll.deltax) : 0); - updateVisibleTopBottom(); - if (_done) { - _done->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _done->height()); - } - if (_bottomShadow) { - _bottomShadow->setGeometry(0, height() - st::boxButtonPadding.bottom() - _done->height() - st::boxButtonPadding.top() - st::lineWidth, width(), st::lineWidth); + if (_titleShadow) { + _titleShadow->setGeometry(0, 0, width(), st::lineWidth); } + if (_installed.widget()) _installed.widget()->resize(width(), _installed.widget()->height()); + if (_featured.widget()) _featured.widget()->resize(width(), _featured.widget()->height()); + _archived.widget()->resize(width(), _archived.widget()->height()); } void StickersBox::onStickersUpdated() { if (_section == Section::Installed || _section == Section::Featured) { rebuildList(); } else { - _tab->widget->updateRows(); + _tab->widget()->updateRows(); } if (Global::ArchivedStickerSetsOrder().isEmpty()) { preloadArchivedSets(); @@ -527,50 +520,25 @@ void StickersBox::onStickersUpdated() { void StickersBox::rebuildList() { if (_tab == &_installed) { - _localOrder = _tab->widget->getFullOrder(); - _localRemoved = _tab->widget->getRemovedSets(); + _localOrder = _tab->widget()->getFullOrder(); + _localRemoved = _tab->widget()->getRemovedSets(); } - _tab->widget->rebuild(); + _tab->widget()->rebuild(); if (_tab == &_installed) { - _tab->widget->setFullOrder(_localOrder); + _tab->widget()->setFullOrder(_localOrder); } - _tab->widget->setRemovedSets(_localRemoved); - _tab->widget->setVisibleScrollbar((scrollArea()->scrollTopMax() > 0) ? (st::boxScroll.width - st::boxScroll.deltax) : 0); + _tab->widget()->setRemovedSets(_localRemoved); } -void StickersBox::onCheckDraggingScroll(int localY) { - if (localY < scrollArea()->scrollTop()) { - _scrollDelta = localY - scrollArea()->scrollTop(); - } else if (localY >= scrollArea()->scrollTop() + scrollArea()->height()) { - _scrollDelta = localY - scrollArea()->scrollTop() - scrollArea()->height() + 1; - } else { - _scrollDelta = 0; - } - if (_scrollDelta) { - _scrollTimer.start(15); - } else { - _scrollTimer.stop(); - } -} - -void StickersBox::onNoDraggingScroll() { - _scrollTimer.stop(); -} - -void StickersBox::onScrollTimer() { - int32 d = (_scrollDelta > 0) ? qMin(_scrollDelta * 3 / 20 + 1, int32(MaxScrollSpeed)) : qMax(_scrollDelta * 3 / 20 - 1, -int32(MaxScrollSpeed)); - scrollArea()->scrollToY(scrollArea()->scrollTop() + d); -} - -void StickersBox::closePressed() { - if (!_installed.widget) { +void StickersBox::closeHook() { + if (!_installed.widget()) { return; } if (_someArchivedLoaded) { Local::writeArchivedStickers(); } if (auto api = App::api()) { - api->saveStickerSets(_installed.widget->getOrder(), _installed.widget->getRemovedSets()); + api->saveStickerSets(_installed.widget()->getOrder(), _installed.widget()->getRemovedSets()); } } @@ -580,12 +548,11 @@ StickersBox::Inner::Inner(QWidget *parent, StickersBox::Section section) : TWidg , _section(section) , _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom()) , _a_shifting(animation(this, &Inner::step_shifting)) -, _itemsTop(st::membersPadding.top()) +, _itemsTop(st::membersMarginTop) , _addText(lang(lng_stickers_featured_add).toUpper()) , _addWidth(st::stickersTrendingAdd.font->width(_addText)) , _undoText(lang(lng_stickers_return).toUpper()) -, _undoWidth(st::stickersUndoRemove.font->width(_undoText)) -, _aboveShadow(st::boxShadow) { +, _undoWidth(st::stickersUndoRemove.font->width(_undoText)) { setup(); } @@ -594,10 +561,9 @@ StickersBox::Inner::Inner(QWidget *parent, const Stickers::Order &archivedIds) : , _archivedIds(archivedIds) , _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom()) , _a_shifting(animation(this, &Inner::step_shifting)) -, _itemsTop(st::membersPadding.top()) +, _itemsTop(st::membersMarginTop) , _addText(lang(lng_stickers_featured_add).toUpper()) -, _addWidth(st::stickersTrendingAdd.font->width(_addText)) -, _aboveShadow(st::boxShadow) { +, _addWidth(st::stickersTrendingAdd.font->width(_addText)) { setup(); } @@ -619,7 +585,7 @@ void StickersBox::Inner::paintEvent(QPaintEvent *e) { p.fillRect(r, st::boxBg); p.setClipRect(r); - int y = st::membersPadding.top(); + auto y = _itemsTop; if (_rows.isEmpty()) { p.setFont(st::noContactsFont); p.setPen(st::noContactsColor); @@ -667,21 +633,27 @@ void StickersBox::Inner::paintRow(Painter &p, int index, TimeMs ms) { if (xadd || yadd) p.translate(xadd, yadd); if (_section == Section::Installed) { - paintFakeButton(p, index, ms); if (index == _above) { - float64 current = _aboveShadowFadeOpacity.current(); + auto current = _aboveShadowFadeOpacity.current(); if (_started >= 0) { - float64 o = aboveShadowOpacity(); - if (o > current) { - _aboveShadowFadeOpacity = anim::value(o, o); - current = o; + auto reachedOpacity = aboveShadowOpacity(); + if (reachedOpacity > current) { + _aboveShadowFadeOpacity = anim::value(reachedOpacity, reachedOpacity); + current = reachedOpacity; } } + auto row = myrtlrect(st::contactsPadding.left() / 2, st::contactsPadding.top() / 2, width() - (st::contactsPadding.left() / 2) - _scrollbar - st::contactsPadding.left() / 2, _rowHeight - ((st::contactsPadding.top() + st::contactsPadding.bottom()) / 2)); p.setOpacity(current); - QRect row(myrtlrect(_aboveShadow.getDimensions(st::boxShadowShift).left(), st::contactsPadding.top() / 2, width() - (st::contactsPadding.left() / 2) - _scrollbar - _aboveShadow.getDimensions(st::boxShadowShift).right(), _rowHeight - ((st::contactsPadding.top() + st::contactsPadding.bottom()) / 2))); - _aboveShadow.paint(p, row, st::boxShadowShift); - p.fillRect(row, st::boxBg); + Ui::Shadow::paint(p, row, width(), st::boxRoundShadow); p.setOpacity(1); + + App::roundRect(p, row, st::boxBg, BoxCorners); + + p.setOpacity(1. - current); + paintFakeButton(p, index, ms); + p.setOpacity(1.); + } else { + paintFakeButton(p, index, ms); } } else { paintFakeButton(p, index, ms); @@ -881,9 +853,18 @@ void StickersBox::Inner::onUpdateSelected() { _animStartTimes[_dragging] = 0; _a_shifting.step(getms(), true); - emit checkDraggingScroll(local.y()); + auto countDraggingScrollDelta = [this, local] { + if (local.y() < _visibleTop) { + return local.y() - _visibleTop; + } else if (local.y() >= _visibleBottom) { + return local.y() + 1 - _visibleBottom; + } + return 0; + }; + + emit draggingScrollDelta(countDraggingScrollDelta()); } else { - bool in = rect().marginsRemoved(QMargins(0, _itemsTop, 0, st::membersPadding.bottom())).contains(local); + bool in = rect().marginsRemoved(QMargins(0, _itemsTop, 0, st::membersMarginBottom)).contains(local); auto selected = -1; auto actionSel = -1; auto inDragArea = false; @@ -919,7 +900,7 @@ void StickersBox::Inner::onUpdateSelected() { setCursor(_inDragArea ? style::cur_sizeall : (_selected >= 0 || _pressed >= 0) ? style::cur_pointer : style::cur_default); } setActionSel(actionSel); - emit noDraggingScroll(); + emit draggingScrollDelta(0); } } @@ -964,7 +945,7 @@ void StickersBox::Inner::mouseReleaseEvent(QMouseEvent *e) { auto it = sets.find(row->id); if (it != sets.cend()) { _selected = -1; - Ui::showLayer(new StickerSetBox(Stickers::inputSetId(*it)), KeepOtherLayers); + Ui::show(Box(Stickers::inputSetId(*it)), KeepOtherLayers); } } } @@ -1018,9 +999,14 @@ void StickersBox::Inner::step_shifting(TimeMs ms, bool timer) { } if (timer) { if (_dragging >= 0) { - if (updateMin < 0 || updateMin > _dragging) updateMin = _dragging; + if (updateMin < 0 || updateMin > _dragging) { + updateMin = _dragging; + } if (updateMax < _dragging) updateMax = _dragging; } + if (updateMin == 1 && _rows[0]->isRecentSet()) { + updateMin = 0; // Repaint from the very top of the content. + } if (updateMin >= 0) { update(0, _itemsTop + _rowHeight * (updateMin - 1), width(), _rowHeight * (updateMax - updateMin + 3)); } @@ -1060,7 +1046,7 @@ void StickersBox::Inner::setActionSel(int32 actionSel) { } void StickersBox::Inner::rebuild() { - _itemsTop = st::membersPadding.top(); + _itemsTop = st::membersMarginTop; int maxNameWidth = countMaxNameWidth(); @@ -1102,7 +1088,8 @@ void StickersBox::Inner::rebuild() { } void StickersBox::Inner::updateSize() { - resize(width(), _itemsTop + _rows.size() * _rowHeight + st::membersPadding.bottom()); + resize(width(), _itemsTop + _rows.size() * _rowHeight + st::membersMarginBottom); + checkLoadMore(); } void StickersBox::Inner::updateRows() { @@ -1314,11 +1301,23 @@ void StickersBox::Inner::setRemovedSets(const Stickers::Order &removed) { } void StickersBox::Inner::setVisibleTopBottom(int visibleTop, int visibleBottom) { + _visibleTop = visibleTop; + _visibleBottom = visibleBottom; + updateScrollbarWidth(); if (_section == Section::Featured) { - _visibleTop = visibleTop; - _visibleBottom = visibleBottom; readVisibleSets(); } + checkLoadMore(); +} + +void StickersBox::Inner::checkLoadMore() { + if (_loadMoreCallback) { + auto scrollHeight = (_visibleBottom - _visibleTop); + int scrollTop = _visibleTop, scrollTopMax = height() - scrollHeight; + if (scrollTop + PreloadHeightsCount * scrollHeight >= scrollTopMax) { + _loadMoreCallback(); + } + } } void StickersBox::Inner::readVisibleSets() { @@ -1339,8 +1338,12 @@ void StickersBox::Inner::readVisibleSets() { } } -void StickersBox::Inner::setVisibleScrollbar(int32 width) { - _scrollbar = width; +void StickersBox::Inner::updateScrollbarWidth() { + auto width = (_visibleBottom - _visibleTop < height()) ? (st::boxLayerScroll.width - st::boxLayerScroll.deltax) : 0; + if (_scrollbar != width) { + _scrollbar = width; + update(); + } } StickersBox::Inner::~Inner() { diff --git a/Telegram/SourceFiles/boxes/stickers_box.h b/Telegram/SourceFiles/boxes/stickers_box.h index 46dca7015..0a3dffc4e 100644 --- a/Telegram/SourceFiles/boxes/stickers_box.h +++ b/Telegram/SourceFiles/boxes/stickers_box.h @@ -30,13 +30,12 @@ struct RippleAnimation; namespace Ui { class PlainShadow; -class RoundButton; class RippleAnimation; class SettingsSlider; class SlideAnimation; } // namespace Ui -class StickersBox : public ItemListBox, public RPCSender { +class StickersBox : public BoxContent, public RPCSender { Q_OBJECT public: @@ -46,78 +45,85 @@ public: Archived, ArchivedPart, }; - StickersBox(Section section = Section::Installed); - StickersBox(const Stickers::Order &archivedIds); + StickersBox(QWidget*, Section section); + StickersBox(QWidget*, const Stickers::Order &archivedIds); + + void closeHook() override; ~StickersBox(); -public slots: - void onStickersUpdated(); - - void onCheckDraggingScroll(int localY); - void onNoDraggingScroll(); - void onScrollTimer(); - -private slots: - void onScroll(); - protected: + void prepare() override; + void resizeEvent(QResizeEvent *e) override; void paintEvent(QPaintEvent *e) override; - void closePressed() override; +private slots: + void onStickersUpdated(); private: void refreshTabs(); - void setup(); void rebuildList(); void updateTabsGeometry(); void switchTab(); void installSet(uint64 setId); + int getTopSkip() const; QPixmap grabContentCache(); void installDone(const MTPmessages_StickerSetInstallResult &result); bool installFail(uint64 setId, const RPCError &error); - void updateVisibleTopBottom(); void preloadArchivedSets(); void requestArchivedSets(); - void checkLoadMoreArchived(); + void loadMoreArchived(); void getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedStickers &result); - ChildWidget _topShadow; - ChildWidget _tabs = { nullptr }; + object_ptr _tabs = { nullptr }; QList
_tabIndices; class CounterWidget; - ChildWidget _unreadBadge = { nullptr }; + object_ptr _unreadBadge = { nullptr }; Section _section; class Inner; - struct Tab { - Tab() : widget(nullptr) { - } + class Tab { + public: + Tab() = default; + template - Tab(int index, Args&&... args) : index(index), widget(std_::forward(args)...) { + Tab(int index, Args&&... args); + + object_ptr takeWidget(); + void returnWidget(object_ptr widget); + + Inner *widget() { + return _weak; + } + int index() const { + return _index; } - int index = 0; - ChildWidget widget = { nullptr }; - int scrollTop = 0; + void saveScrollTop(); + int getScrollTop() const { + return _scrollTop; + } + + private: + int _index = 0; + object_ptr _widget = { nullptr }; + QPointer _weak; + int _scrollTop = 0; + }; Tab _installed; Tab _featured; Tab _archived; Tab *_tab = nullptr; - ChildWidget _done = { nullptr }; - ChildWidget _bottomShadow = { nullptr }; std_::unique_ptr _slideAnimation; - - QTimer _scrollTimer; - int32 _scrollDelta = 0; + object_ptr _titleShadow = { nullptr }; int _aboutWidth = 0; Text _about; @@ -159,10 +165,16 @@ public: void setInstallSetCallback(base::lambda &&callback) { _installSetCallback = std_::move(callback); } + void setLoadMoreCallback(base::lambda &&callback) { + _loadMoreCallback = std_::move(callback); + } - void setVisibleScrollbar(int32 width); void setVisibleTopBottom(int visibleTop, int visibleBottom) override; + int getVisibleTop() const { + return _visibleTop; + } + ~Inner(); protected: @@ -173,8 +185,7 @@ protected: void leaveEvent(QEvent *e) override; signals: - void checkDraggingScroll(int localY); - void noDraggingScroll(); + void draggingScrollDelta(int delta); public slots: void onUpdateSelected(); @@ -183,6 +194,8 @@ private: template Stickers::Order collectSets(Check check) const; + void checkLoadMore(); + void updateScrollbarWidth(); int getRowIndex(uint64 setId) const; void setRowRemoved(int index, bool removed); @@ -249,6 +262,7 @@ private: BasicAnimation _a_shifting; base::lambda _installSetCallback; + base::lambda _loadMoreCallback; int _visibleTop = 0; int _visibleBottom = 0; @@ -273,8 +287,6 @@ private: int _dragging = -1; int _above = -1; - Ui::RectShadow _aboveShadow; - int _scrollbar = 0; }; diff --git a/Telegram/SourceFiles/boxes/stickersetbox.cpp b/Telegram/SourceFiles/boxes/stickersetbox.cpp index c60d8e7e4..7f1571b75 100644 --- a/Telegram/SourceFiles/boxes/stickersetbox.cpp +++ b/Telegram/SourceFiles/boxes/stickersetbox.cpp @@ -34,45 +34,33 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "ui/widgets/buttons.h" #include "ui/widgets/scroll_area.h" -StickerSetBox::StickerSetBox(const MTPInputStickerSet &set) : ScrollableBox(st::stickersScroll) -, _inner(this, set) -, _shadow(this) -, _add(this, lang(lng_stickers_add_pack), st::defaultBoxButton) -, _share(this, lang(lng_stickers_share_pack), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) -, _done(this, lang(lng_about_done), st::defaultBoxButton) { - setTitleText(lang(lng_contacts_loading)); +StickerSetBox::StickerSetBox(QWidget*, const MTPInputStickerSet &set) +: _set(set) { +} - setMaxHeight(st::stickersMaxHeight); +void StickerSetBox::prepare() { + setTitle(lang(lng_contacts_loading)); + + _inner = setInnerWidget(object_ptr(this, _set), st::stickersScroll); connect(App::main(), SIGNAL(stickersUpdated()), this, SLOT(onStickersUpdated())); - init(_inner, st::boxButtonPadding.bottom() + _cancel->height() + st::boxButtonPadding.top()); + setDimensions(st::boxWideWidth, st::stickersMaxHeight); - connect(_add, SIGNAL(clicked()), this, SLOT(onAddStickers())); - connect(_share, SIGNAL(clicked()), this, SLOT(onShareStickers())); - connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); - connect(_done, SIGNAL(clicked()), this, SLOT(onClose())); + onUpdateButtons(); connect(_inner, SIGNAL(updateButtons()), this, SLOT(onUpdateButtons())); - connect(scrollArea(), SIGNAL(scrolled()), this, SLOT(onScroll())); - connect(_inner, SIGNAL(installed(uint64)), this, SLOT(onInstalled(uint64))); onStickersUpdated(); - updateControlsVisibility(); - - onScroll(); - - raiseShadow(); } void StickerSetBox::onInstalled(uint64 setId) { emit installed(setId); - onClose(); + closeBox(); } void StickerSetBox::onStickersUpdated() { - updateControlsVisibility(); + updateButtons(); } void StickerSetBox::onAddStickers() { @@ -82,66 +70,35 @@ void StickerSetBox::onAddStickers() { void StickerSetBox::onShareStickers() { QString url = qsl("https://telegram.me/addstickers/") + _inner->shortName(); QApplication::clipboard()->setText(url); - Ui::showLayer(new InformBox(lang(lng_stickers_copied))); + Ui::show(Box(lang(lng_stickers_copied))); } void StickerSetBox::onUpdateButtons() { - setTitleText(_inner->title()); - if (!_cancel->isHidden() || !_done->isHidden()) { - updateControlsVisibility(); - } + setTitle(_inner->title()); + updateButtons(); } -void StickerSetBox::onScroll() { - auto scroll = scrollArea(); - auto scrollTop = scroll->scrollTop(); - _inner->setVisibleTopBottom(scrollTop, scrollTop + scroll->height()); -} - -void StickerSetBox::updateControlsVisibility() { +void StickerSetBox::updateButtons() { + clearButtons(); if (_inner->loaded()) { - _shadow.show(); if (_inner->notInstalled()) { - _add->show(); - _cancel->show(); - _share->hide(); - _done->hide(); + addButton(lang(lng_stickers_add_pack), [this] { onAddStickers(); }); + addButton(lang(lng_cancel), [this] { closeBox(); }); } else if (_inner->official()) { - _add->hide(); - _share->hide(); - _cancel->hide(); - _done->show(); + addButton(lang(lng_about_done), [this] { closeBox(); }); } else { - _share->show(); - _cancel->show(); - _add->hide(); - _done->hide(); + addButton(lang(lng_stickers_share_pack), [this] { onShareStickers(); }); + addButton(lang(lng_cancel), [this] { closeBox(); }); } } else { - _shadow.hide(); - _add->hide(); - _share->hide(); - _cancel->show(); - _done->hide(); + addButton(lang(lng_cancel), [this] { closeBox(); }); } - resizeEvent(0); update(); } void StickerSetBox::resizeEvent(QResizeEvent *e) { - ScrollableBox::resizeEvent(e); + BoxContent::resizeEvent(e); _inner->resize(width(), _inner->height()); - _shadow.setGeometry(0, height() - st::boxButtonPadding.bottom() - _cancel->height() - st::boxButtonPadding.top() - st::lineWidth, width(), st::lineWidth); - _add->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _add->height()); - _share->moveToRight(st::boxButtonPadding.right(), _add->y()); - _done->moveToRight(st::boxButtonPadding.right(), _add->y()); - if (_add->isHidden() && _share->isHidden()) { - _cancel->moveToRight(st::boxButtonPadding.right(), _add->y()); - } else if (_add->isHidden()) { - _cancel->moveToRight(st::boxButtonPadding.right() + _share->width() + st::boxButtonPadding.left(), _add->y()); - } else { - _cancel->moveToRight(st::boxButtonPadding.right() + _add->width() + st::boxButtonPadding.left(), _add->y()); - } } StickerSetBox::Inner::Inner(QWidget *parent, const MTPInputStickerSet &set) : TWidget(parent) @@ -199,7 +156,7 @@ void StickerSetBox::Inner::gotSet(const MTPmessages_StickerSet &set) { if (d.vset.type() == mtpc_stickerSet) { auto &s = d.vset.c_stickerSet(); _setTitle = stickerSetTitle(s); - _title = st::boxBlockTitleFont->elided(_setTitle, width() - st::boxBlockTitlePosition.x() - st::boxBlockTitleHeight); + _title = st::boxTitleFont->elided(_setTitle, width() - st::boxTitlePosition.x() - st::boxTitleHeight); _setShortName = qs(s.vshort_name); _setId = s.vid.v; _setAccess = s.vaccess_hash.v; @@ -219,7 +176,7 @@ void StickerSetBox::Inner::gotSet(const MTPmessages_StickerSet &set) { } if (_pack.isEmpty()) { - Ui::showLayer(new InformBox(lang(lng_stickers_not_found))); + Ui::show(Box(lang(lng_stickers_not_found))); } else { int32 rows = _pack.size() / StickerPanPerRow + ((_pack.size() % StickerPanPerRow) ? 1 : 0); resize(st::stickersPadding.left() + StickerPanPerRow * st::stickersSize.width(), st::stickersPadding.top() + rows * st::stickersSize.height() + st::stickersPadding.bottom()); @@ -236,7 +193,7 @@ bool StickerSetBox::Inner::failedSet(const RPCError &error) { _loaded = true; - Ui::showLayer(new InformBox(lang(lng_stickers_not_found))); + Ui::show(Box(lang(lng_stickers_not_found))); return true; } @@ -297,7 +254,7 @@ void StickerSetBox::Inner::installDone(const MTPmessages_StickerSetInstallResult bool StickerSetBox::Inner::installFail(const RPCError &error) { if (MTP::isDefaultHandledError(error)) return false; - Ui::showLayer(new InformBox(lang(lng_stickers_not_found))); + Ui::show(Box(lang(lng_stickers_not_found))); return true; } @@ -467,7 +424,7 @@ QString StickerSetBox::Inner::shortName() const { void StickerSetBox::Inner::install() { if (isMasksSet()) { - Ui::showLayer(new InformBox(lang(lng_stickers_masks_pack)), KeepOtherLayers); + Ui::show(Box(lang(lng_stickers_masks_pack)), KeepOtherLayers); return; } if (_installRequest) return; diff --git a/Telegram/SourceFiles/boxes/stickersetbox.h b/Telegram/SourceFiles/boxes/stickersetbox.h index b780e588c..0e92a20ad 100644 --- a/Telegram/SourceFiles/boxes/stickersetbox.h +++ b/Telegram/SourceFiles/boxes/stickersetbox.h @@ -27,42 +27,38 @@ class ConfirmBox; namespace Ui { class PlainShadow; -class RoundButton; } // namespace Ui -class StickerSetBox : public ScrollableBox, public RPCSender { +class StickerSetBox : public BoxContent, public RPCSender { Q_OBJECT public: - StickerSetBox(const MTPInputStickerSet &set); - -public slots: - void onStickersUpdated(); - void onAddStickers(); - void onShareStickers(); - void onUpdateButtons(); - - void onScroll(); - -private slots: - void onInstalled(uint64 id); + StickerSetBox(QWidget*, const MTPInputStickerSet &set); signals: void installed(uint64 id); protected: + void prepare() override; + void resizeEvent(QResizeEvent *e) override; +private slots: + void onStickersUpdated(); + void onAddStickers(); + void onShareStickers(); + void onUpdateButtons(); + + void onInstalled(uint64 id); + private: - void updateControlsVisibility(); + void updateButtons(); + + MTPInputStickerSet _set; class Inner; - ChildWidget _inner; - ScrollableBoxShadow _shadow; - ChildWidget _add; - ChildWidget _share; - ChildWidget _cancel; - ChildWidget _done; + QPointer _inner; + QString _title; }; diff --git a/Telegram/SourceFiles/boxes/usernamebox.cpp b/Telegram/SourceFiles/boxes/usernamebox.cpp index 4d5472fd1..fec57634b 100644 --- a/Telegram/SourceFiles/boxes/usernamebox.cpp +++ b/Telegram/SourceFiles/boxes/usernamebox.cpp @@ -29,42 +29,42 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "ui/widgets/input_fields.h" #include "styles/style_boxes.h" -UsernameBox::UsernameBox() : AbstractBox(st::boxWidth, lang(lng_username_title)) -, _save(this, lang(lng_settings_save), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) -, _username(this, st::defaultInputField, qsl("@username"), App::self()->username, false) +UsernameBox::UsernameBox(QWidget*) +: _username(this, st::defaultInputField, qsl("@username"), App::self()->username, false) , _link(this, QString(), st::boxLinkButton) -, _about(st::boxWidth - st::usernamePadding.left()) { - setBlockTitle(true); +, _about(st::boxWidth - st::usernamePadding.left()) +, _checkTimer(this) { +} +void UsernameBox::prepare() { _goodText = App::self()->username.isEmpty() ? QString() : lang(lng_username_available); + setTitle(lang(lng_username_title)); + + addButton(lang(lng_settings_save), [this] { onSave(); }); + addButton(lang(lng_cancel), [this] { closeBox(); }); + + connect(_username, SIGNAL(changed()), this, SLOT(onChanged())); + connect(_username, SIGNAL(submitted(bool)), this, SLOT(onSave())); + connect(_link, SIGNAL(clicked()), this, SLOT(onLinkClick())); + textstyleSet(&st::usernameTextStyle); _about.setRichText(st::boxTextFont, lang(lng_username_about)); - resizeMaxHeight(st::boxWidth, titleHeight() + st::usernamePadding.top() + _username->height() + st::usernameSkip + _about.countHeight(st::boxWidth - st::usernamePadding.left()) + 3 * st::usernameTextStyle.lineHeight + st::usernamePadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom()); + setDimensions(st::boxWidth, st::usernamePadding.top() + _username->height() + st::usernameSkip + _about.countHeight(st::boxWidth - st::usernamePadding.left()) + 3 * st::usernameTextStyle.lineHeight + st::usernamePadding.bottom()); textstyleRestore(); - connect(_save, SIGNAL(clicked()), this, SLOT(onSave())); - connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); - connect(_username, SIGNAL(changed()), this, SLOT(onChanged())); - connect(_username, SIGNAL(submitted(bool)), this, SLOT(onSave())); - - connect(_link, SIGNAL(clicked()), this, SLOT(onLinkClick())); - - _checkTimer.setSingleShot(true); - connect(&_checkTimer, SIGNAL(timeout()), this, SLOT(onCheck())); + _checkTimer->setSingleShot(true); + connect(_checkTimer, SIGNAL(timeout()), this, SLOT(onCheck())); updateLinkText(); - - raiseShadow(); } -void UsernameBox::doSetInnerFocus() { +void UsernameBox::setInnerFocus() { _username->setFocus(); } void UsernameBox::paintEvent(QPaintEvent *e) { - AbstractBox::paintEvent(e); + BoxContent::paintEvent(e); Painter p(this); @@ -99,19 +99,16 @@ void UsernameBox::paintEvent(QPaintEvent *e) { } void UsernameBox::resizeEvent(QResizeEvent *e) { + BoxContent::resizeEvent(e); + _username->resize(width() - st::usernamePadding.left() - st::usernamePadding.right(), _username->height()); - _username->moveToLeft(st::usernamePadding.left(), titleHeight() + st::usernamePadding.top()); + _username->moveToLeft(st::usernamePadding.left(), st::usernamePadding.top()); textstyleSet(&st::usernameTextStyle); int32 availw = st::boxWidth - st::usernamePadding.left(), h = _about.countHeight(availw); textstyleRestore(); int32 linky = _username->y() + _username->height() + st::usernameSkip + h + st::usernameTextStyle.lineHeight + ((st::usernameTextStyle.lineHeight - st::boxTextFont->height) / 2); _link->moveToLeft(st::usernamePadding.left(), linky + st::usernameTextStyle.lineHeight + ((st::usernameTextStyle.lineHeight - st::boxTextFont->height) / 2)); - - _save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height()); - _cancel->moveToRight(st::boxButtonPadding.right() + _save->width() + st::boxButtonPadding.left(), _save->y()); - - AbstractBox::resizeEvent(e); } void UsernameBox::onSave() { @@ -140,7 +137,7 @@ void UsernameBox::onChanged() { _copiedTextLink = _errorText = _goodText = QString(); update(); } - _checkTimer.stop(); + _checkTimer->stop(); } else { int32 len = name.size(); for (int32 i = 0; i < len; ++i) { @@ -151,7 +148,7 @@ void UsernameBox::onChanged() { _errorText = lang(lng_username_bad_symbols); update(); } - _checkTimer.stop(); + _checkTimer->stop(); return; } } @@ -161,13 +158,13 @@ void UsernameBox::onChanged() { _errorText = lang(lng_username_too_short); update(); } - _checkTimer.stop(); + _checkTimer->stop(); } else { if (!_errorText.isEmpty() || !_goodText.isEmpty() || !_copiedTextLink.isEmpty()) { _copiedTextLink = _errorText = _goodText = QString(); update(); } - _checkTimer.start(UsernameCheckTimeout); + _checkTimer->start(UsernameCheckTimeout); } } } @@ -180,7 +177,7 @@ void UsernameBox::onLinkClick() { void UsernameBox::onUpdateDone(const MTPUser &user) { App::feedUsers(MTP_vector(1, user)); - onClose(); + closeBox(); } bool UsernameBox::onUpdateFail(const RPCError &error) { @@ -190,7 +187,7 @@ bool UsernameBox::onUpdateFail(const RPCError &error) { QString err(error.type()); if (err == qstr("USERNAME_NOT_MODIFIED") || _sentUsername == App::self()->username) { App::self()->setName(textOneLine(App::self()->firstName), textOneLine(App::self()->lastName), textOneLine(App::self()->nameOrPhone), textOneLine(_sentUsername)); - onClose(); + closeBox(); return true; } else if (err == qstr("USERNAME_INVALID")) { _username->setFocus(); diff --git a/Telegram/SourceFiles/boxes/usernamebox.h b/Telegram/SourceFiles/boxes/usernamebox.h index e75ae0cab..52b09ecd4 100644 --- a/Telegram/SourceFiles/boxes/usernamebox.h +++ b/Telegram/SourceFiles/boxes/usernamebox.h @@ -24,17 +24,23 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org namespace Ui { class UsernameInput; -class RoundButton; class LinkButton; } // namespace Ui -class UsernameBox : public AbstractBox, public RPCSender { +class UsernameBox : public BoxContent, public RPCSender { Q_OBJECT public: - UsernameBox(); + UsernameBox(QWidget*); -public slots: +protected: + void prepare() override; + void setInnerFocus() override; + + void paintEvent(QPaintEvent *e) override; + void resizeEvent(QResizeEvent *e) override; + +private slots: void onSave(); void onCheck(); @@ -42,12 +48,6 @@ public slots: void onLinkClick(); -protected: - void paintEvent(QPaintEvent *e) override; - void resizeEvent(QResizeEvent *e) override; - - void doSetInnerFocus() override; - private: void onUpdateDone(const MTPUser &result); bool onUpdateFail(const RPCError &error); @@ -58,16 +58,14 @@ private: QString getName() const; void updateLinkText(); - ChildWidget _save; - ChildWidget _cancel; - ChildWidget _username; - ChildWidget _link; + object_ptr _username; + object_ptr _link; mtpRequestId _saveRequestId = 0; mtpRequestId _checkRequestId = 0; QString _sentUsername, _checkUsername, _errorText, _goodText, _copiedTextLink; Text _about; - QTimer _checkTimer; + object_ptr _checkTimer; }; diff --git a/Telegram/SourceFiles/core/click_handler_types.cpp b/Telegram/SourceFiles/core/click_handler_types.cpp index 3adfc1c85..18ff045ce 100644 --- a/Telegram/SourceFiles/core/click_handler_types.cpp +++ b/Telegram/SourceFiles/core/click_handler_types.cpp @@ -104,24 +104,31 @@ TextWithEntities UrlClickHandler::getExpandedLinkTextWithEntities(ExpandLinksMod } void HiddenUrlClickHandler::onClick(Qt::MouseButton button) const { - auto u = tryConvertUrlToLocal(url()); + auto urlText = tryConvertUrlToLocal(url()); - if (u.startsWith(qstr("tg://"))) { - App::openLocalUrl(u); + if (urlText.startsWith(qstr("tg://"))) { + App::openLocalUrl(urlText); } else { - Ui::showLayer(new ConfirmLinkBox(u)); + Ui::show(Box(lang(lng_open_this_link) + qsl("\n\n") + urlText, lang(lng_open_link), [urlText] { + Ui::hideLayer(); + UrlClickHandler::doOpen(urlText); + })); } } void BotGameUrlClickHandler::onClick(Qt::MouseButton button) const { - auto u = tryConvertUrlToLocal(url()); + auto urlText = tryConvertUrlToLocal(url()); - if (u.startsWith(qstr("tg://"))) { - App::openLocalUrl(u); + if (urlText.startsWith(qstr("tg://"))) { + App::openLocalUrl(urlText); } else if (!_bot || _bot->isVerified() || Local::isBotTrusted(_bot)) { - doOpen(u); + doOpen(urlText); } else { - Ui::showLayer(new ConfirmBotGameBox(_bot, u)); + Ui::show(Box(lng_allow_bot_pass(lt_bot_name, _bot->name), lang(lng_allow_bot), [bot = _bot, urlText] { + Ui::hideLayer(); + Local::makeBotTrusted(bot); + UrlClickHandler::doOpen(urlText); + })); } } diff --git a/Telegram/SourceFiles/core/single_timer.cpp b/Telegram/SourceFiles/core/single_timer.cpp index e054ef517..af467b95f 100644 --- a/Telegram/SourceFiles/core/single_timer.cpp +++ b/Telegram/SourceFiles/core/single_timer.cpp @@ -23,7 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "application.h" -SingleTimer::SingleTimer() { +SingleTimer::SingleTimer(QObject *parent) : QTimer(parent) { QTimer::setSingleShot(true); if (App::app()) { connect(App::app(), SIGNAL(adjustSingleTimers()), this, SLOT(adjust())); diff --git a/Telegram/SourceFiles/core/single_timer.h b/Telegram/SourceFiles/core/single_timer.h index 7ef638184..bd0bd0edd 100644 --- a/Telegram/SourceFiles/core/single_timer.h +++ b/Telegram/SourceFiles/core/single_timer.h @@ -26,7 +26,7 @@ class SingleTimer : public QTimer { // single shot timer with check Q_OBJECT public: - SingleTimer(); + SingleTimer(QObject *parent = nullptr); void setSingleShot(bool); // is not available void start(); // is not available diff --git a/Telegram/SourceFiles/core/version.h b/Telegram/SourceFiles/core/version.h index 0b0bcddf1..623b143df 100644 --- a/Telegram/SourceFiles/core/version.h +++ b/Telegram/SourceFiles/core/version.h @@ -22,7 +22,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "core/utils.h" -#define BETA_VERSION_MACRO (10019014ULL) +#define BETA_VERSION_MACRO (10020001ULL) constexpr int AppVersion = 10020; constexpr str_const AppVersionStr = "0.10.20"; diff --git a/Telegram/SourceFiles/dialogs/dialogs.style b/Telegram/SourceFiles/dialogs/dialogs.style index c1a5429e9..5b0c06a3b 100644 --- a/Telegram/SourceFiles/dialogs/dialogs.style +++ b/Telegram/SourceFiles/dialogs/dialogs.style @@ -50,7 +50,7 @@ dialogsSkip: 8px; dialogsWidthMin: 260px; dialogsWidthMax: 540px; dialogsTextWidthMin: 150px; -dialogsScroll: FlatScroll(defaultFlatScroll) { +dialogsScroll: ScrollArea(defaultScrollArea) { topsh: 0px; bottomsh: 0px; } diff --git a/Telegram/SourceFiles/dialogswidget.cpp b/Telegram/SourceFiles/dialogswidget.cpp index e93f2826e..b3d9d3fde 100644 --- a/Telegram/SourceFiles/dialogswidget.cpp +++ b/Telegram/SourceFiles/dialogswidget.cpp @@ -1887,9 +1887,8 @@ DialogsWidget::DialogsWidget(QWidget *parent) : TWidget(parent) , _filter(this, st::dialogsFilter, lang(lng_dlg_filter)) , _cancelSearch(this, st::dialogsCancelSearch) , _lockUnlock(this, st::dialogsLock) -, _scroll(this, st::dialogsScroll) -, _inner(this, parent) { - _scroll->setOwnedWidget(_inner); +, _scroll(this, st::dialogsScroll) { + _inner = _scroll->setOwnedWidget(object_ptr(this, parent)); connect(_inner, SIGNAL(mustScrollTo(int,int)), _scroll, SLOT(scrollToY(int,int))); connect(_inner, SIGNAL(dialogMoved(int,int)), this, SLOT(onDialogMoved(int,int))); connect(_inner, SIGNAL(searchMessages()), this, SLOT(onNeedSearchMessages())); diff --git a/Telegram/SourceFiles/dialogswidget.h b/Telegram/SourceFiles/dialogswidget.h index bda714578..c79d045b5 100644 --- a/Telegram/SourceFiles/dialogswidget.h +++ b/Telegram/SourceFiles/dialogswidget.h @@ -254,8 +254,8 @@ private: State _state = DefaultState; - ChildWidget _addContactLnk; - ChildWidget _cancelSearchInPeer; + object_ptr _addContactLnk; + object_ptr _cancelSearchInPeer; PeerData *_searchInPeer = nullptr; PeerData *_searchInMigrated = nullptr; @@ -382,14 +382,14 @@ private: mtpRequestId _contactsRequestId = 0; bool _pinnedDialogsReceived = false; - ChildWidget _forwardCancel = { nullptr }; - ChildWidget _mainMenuToggle; - ChildWidget _filter; - ChildWidget _cancelSearch; - ChildWidget _lockUnlock; - ChildWidget _scroll; - ChildWidget _inner; - ChildWidget _updateTelegram = { nullptr }; + object_ptr _forwardCancel = { nullptr }; + object_ptr _mainMenuToggle; + object_ptr _filter; + object_ptr _cancelSearch; + object_ptr _lockUnlock; + object_ptr _scroll; + QPointer _inner; + object_ptr _updateTelegram = { nullptr }; Animation _a_show; Window::SlideDirection _showDirection; diff --git a/Telegram/SourceFiles/facades.cpp b/Telegram/SourceFiles/facades.cpp index b897e28a4..2c045de17 100644 --- a/Telegram/SourceFiles/facades.cpp +++ b/Telegram/SourceFiles/facades.cpp @@ -99,14 +99,16 @@ void activateBotCommand(const HistoryItem *msg, int row, int col) { case ButtonType::RequestLocation: { hideSingleUseKeyboard(msg); - Ui::showLayer(new InformBox(lang(lng_bot_share_location_unavailable))); + Ui::show(Box(lang(lng_bot_share_location_unavailable))); } break; case ButtonType::RequestPhone: { hideSingleUseKeyboard(msg); - auto box = new SharePhoneConfirmBox(msg->history()->peer); - box->connect(box, SIGNAL(confirmed(PeerData*)), App::main(), SLOT(onSharePhoneWithBot(PeerData*))); - Ui::showLayer(box); + Ui::show(Box(lang(lng_bot_share_phone), lang(lng_bot_share_phone_confirm), [peerId = msg->history()->peer->id] { + if (auto m = App::main()) { + m->onShareContact(peerId, App::self()); + } + })); } break; case ButtonType::SwitchInlineSame: @@ -188,6 +190,15 @@ void logOutDelayed() { } // namespace App namespace Ui { +namespace internal { + +void showBox(object_ptr content, ShowLayerOptions options) { + if (auto w = App::wnd()) { + w->ui_showBox(std_::move(content), options); + } +} + +} // namespace internal void showMediaPreview(DocumentData *document) { if (auto w = App::wnd()) { @@ -207,20 +218,16 @@ void hideMediaPreview() { } } -void showLayer(LayerWidget *box, ShowLayerOptions options) { +void hideLayer(bool fast) { if (auto w = App::wnd()) { - w->ui_showLayer(box, options); - } else { - delete box; + w->ui_showBox({ nullptr }, CloseOtherLayers | (fast ? ForceFastShowLayer : AnimatedShowLayer)); } } -void hideLayer(bool fast) { - if (auto w = App::wnd()) w->ui_showLayer(0, CloseOtherLayers | (fast ? ForceFastShowLayer : AnimatedShowLayer)); -} - void hideSettingsAndLayer(bool fast) { - if (auto w = App::wnd()) w->ui_hideSettingsAndLayer(fast ? ForceFastShowLayer : AnimatedShowLayer); + if (auto w = App::wnd()) { + w->ui_hideSettingsAndLayer(fast ? ForceFastShowLayer : AnimatedShowLayer); + } } bool isLayerShown() { diff --git a/Telegram/SourceFiles/facades.h b/Telegram/SourceFiles/facades.h index c6001df71..785dc94b7 100644 --- a/Telegram/SourceFiles/facades.h +++ b/Telegram/SourceFiles/facades.h @@ -24,6 +24,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "core/observer.h" class LayerWidget; +class BoxContent; namespace InlineBots { namespace Layout { @@ -76,12 +77,23 @@ void logOutDelayed(); } // namespace App namespace Ui { +namespace internal { + +void showBox(object_ptr content, ShowLayerOptions options); + +} // namespace internal void showMediaPreview(DocumentData *document); void showMediaPreview(PhotoData *photo); void hideMediaPreview(); -void showLayer(LayerWidget *box, ShowLayerOptions options = CloseOtherLayers); +template +QPointer show(object_ptr content, ShowLayerOptions options = CloseOtherLayers) { + auto result = QPointer(content.data()); + internal::showBox(std_::move(content), options); + return result; +} + void hideLayer(bool fast = false); void hideSettingsAndLayer(bool fast = false); bool isLayerShown(); diff --git a/Telegram/SourceFiles/history/field_autocomplete.cpp b/Telegram/SourceFiles/history/field_autocomplete.cpp index 21ddbc353..4f9699b76 100644 --- a/Telegram/SourceFiles/history/field_autocomplete.cpp +++ b/Telegram/SourceFiles/history/field_autocomplete.cpp @@ -30,18 +30,18 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "styles/style_stickers.h" FieldAutocomplete::FieldAutocomplete(QWidget *parent) : TWidget(parent) -, _scroll(this, st::mentionScroll) -, _inner(this, &_mrows, &_hrows, &_brows, &_srows) { - connect(_inner, SIGNAL(mentionChosen(UserData*,FieldAutocomplete::ChooseMethod)), this, SIGNAL(mentionChosen(UserData*,FieldAutocomplete::ChooseMethod))); - connect(_inner, SIGNAL(hashtagChosen(QString,FieldAutocomplete::ChooseMethod)), this, SIGNAL(hashtagChosen(QString,FieldAutocomplete::ChooseMethod))); - connect(_inner, SIGNAL(botCommandChosen(QString,FieldAutocomplete::ChooseMethod)), this, SIGNAL(botCommandChosen(QString,FieldAutocomplete::ChooseMethod))); - connect(_inner, SIGNAL(stickerChosen(DocumentData*,FieldAutocomplete::ChooseMethod)), this, SIGNAL(stickerChosen(DocumentData*,FieldAutocomplete::ChooseMethod))); - connect(_inner, SIGNAL(mustScrollTo(int, int)), _scroll, SLOT(scrollToY(int, int))); - - _inner->setGeometry(rect()); +, _scroll(this, st::mentionScroll) { _scroll->setGeometry(rect()); - _scroll->setOwnedWidget(_inner); + _inner = _scroll->setOwnedWidget(object_ptr(this, &_mrows, &_hrows, &_brows, &_srows)); + _inner->setGeometry(rect()); + + connect(_inner, SIGNAL(mentionChosen(UserData*, FieldAutocomplete::ChooseMethod)), this, SIGNAL(mentionChosen(UserData*, FieldAutocomplete::ChooseMethod))); + connect(_inner, SIGNAL(hashtagChosen(QString, FieldAutocomplete::ChooseMethod)), this, SIGNAL(hashtagChosen(QString, FieldAutocomplete::ChooseMethod))); + connect(_inner, SIGNAL(botCommandChosen(QString, FieldAutocomplete::ChooseMethod)), this, SIGNAL(botCommandChosen(QString, FieldAutocomplete::ChooseMethod))); + connect(_inner, SIGNAL(stickerChosen(DocumentData*, FieldAutocomplete::ChooseMethod)), this, SIGNAL(stickerChosen(DocumentData*, FieldAutocomplete::ChooseMethod))); + connect(_inner, SIGNAL(mustScrollTo(int, int)), _scroll, SLOT(scrollToY(int, int))); + _scroll->show(); _inner->show(); @@ -412,7 +412,7 @@ void FieldAutocomplete::hideAnimated() { } _scroll->hide(); _hiding = true; - _a_opacity.start([this] { animationCallback(); }, 1., 0., st::defaultDropdownDuration); + _a_opacity.start([this] { animationCallback(); }, 1., 0., st::emojiPanDuration); setAttribute(Qt::WA_OpaquePaintEvent, false); } @@ -434,7 +434,7 @@ void FieldAutocomplete::showAnimated() { _scroll->hide(); _hiding = false; show(); - _a_opacity.start([this] { animationCallback(); }, 0., 1., st::defaultDropdownDuration); + _a_opacity.start([this] { animationCallback(); }, 0., 1., st::emojiPanDuration); setAttribute(Qt::WA_OpaquePaintEvent, false); } diff --git a/Telegram/SourceFiles/history/field_autocomplete.h b/Telegram/SourceFiles/history/field_autocomplete.h index 0a05d5f0a..d2a21137b 100644 --- a/Telegram/SourceFiles/history/field_autocomplete.h +++ b/Telegram/SourceFiles/history/field_autocomplete.h @@ -21,7 +21,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #pragma once #include "ui/twidget.h" -#include "ui/effects/rect_shadow.h" namespace Ui { class ScrollArea; @@ -109,8 +108,8 @@ private: void rowsUpdated(const internal::MentionRows &mrows, const internal::HashtagRows &hrows, const internal::BotCommandRows &brows, const StickerPack &srows, bool resetScroll); - ChildWidget _scroll; - ChildWidget _inner; + object_ptr _scroll; + QPointer _inner; ChatData *_chat = nullptr; UserData *_user = nullptr; diff --git a/Telegram/SourceFiles/history/history.style b/Telegram/SourceFiles/history/history.style index 92e8b29dd..95afbccd4 100644 --- a/Telegram/SourceFiles/history/history.style +++ b/Telegram/SourceFiles/history/history.style @@ -22,7 +22,7 @@ using "basic.style"; using "dialogs/dialogs.style"; using "ui/widgets/widgets.style"; -historyScroll: FlatScroll(defaultFlatScroll) { +historyScroll: ScrollArea(defaultScrollArea) { barColor: #89a0b47a; bgColor: #89a0b44c; barOverColor: #89a0b4bc; @@ -70,7 +70,7 @@ historyToDownDuration: 150; membersInnerWidth: 310px; membersInnerHeightMax: 360px; membersInnerDropdown: InnerDropdown(defaultInnerDropdown) { - scroll: FlatScroll(defaultSolidScroll) { + scroll: ScrollArea(defaultSolidScroll) { deltat: 3px; deltab: 3px; round: 1px; @@ -389,7 +389,7 @@ botKbTinyButton: BotKeyboardButton { botKbScroll: defaultSolidScroll; mentionHeight: 40px; -mentionScroll: FlatScroll(defaultFlatScroll) { +mentionScroll: ScrollArea(defaultScrollArea) { topsh: 0px; bottomsh: 0px; } diff --git a/Telegram/SourceFiles/history/history_drag_area.cpp b/Telegram/SourceFiles/history/history_drag_area.cpp index f4a588838..19b81c565 100644 --- a/Telegram/SourceFiles/history/history_drag_area.cpp +++ b/Telegram/SourceFiles/history/history_drag_area.cpp @@ -35,14 +35,23 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "apiwrap.h" #include "mainwidget.h" -DragArea::DragArea(QWidget *parent) : TWidget(parent) -, _hiding(false) -, _in(false) -, _shadow(st::boxShadow) { +DragArea::DragArea(QWidget *parent) : TWidget(parent) { setMouseTracking(true); setAcceptDrops(true); } +bool DragArea::overlaps(const QRect &globalRect) { + if (isHidden() || _a_opacity.animating()) { + return false; + } + + auto inner = innerRect(); + auto testRect = QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size()); + return inner.marginsRemoved(QMargins(st::boxRadius, 0, st::boxRadius, 0)).contains(testRect) + || inner.marginsRemoved(QMargins(0, st::boxRadius, 0, st::boxRadius)).contains(testRect); +} + + void DragArea::mouseMoveEvent(QMouseEvent *e) { if (_hiding) return; @@ -60,7 +69,7 @@ void DragArea::dragMoveEvent(QDragMoveEvent *e) { void DragArea::setIn(bool in) { if (_in != in) { _in = in; - _a_in.start([this] { update(); }, _in ? 0. : 1., _in ? 1. : 0., st::defaultDropdownDuration); + _a_in.start([this] { update(); }, _in ? 0. : 1., _in ? 1. : 0., st::boxDuration); } } @@ -79,13 +88,15 @@ void DragArea::paintEvent(QPaintEvent *e) { return; } p.setOpacity(opacity); + auto inner = innerRect(); - QRect r(st::dragPadding.left(), st::dragPadding.top(), width() - st::dragPadding.left() - st::dragPadding.right(), height() - st::dragPadding.top() - st::dragPadding.bottom()); + if (!_cache.isNull()) { + p.drawPixmapLeft(inner.x() - st::boxRoundShadow.extend.left(), inner.y() - st::boxRoundShadow.extend.top(), width(), _cache); + return; + } - // draw shadow - _shadow.paint(p, r, st::boxShadowShift); - - p.fillRect(r, st::dragBg); + Ui::Shadow::paint(p, inner, width(), st::boxRoundShadow); + App::roundRect(p, inner, st::boxBg, BoxCorners); p.setPen(anim::pen(st::dragColor, st::dragDropColor, _a_in.current(ms, _in ? 1. : 0.))); @@ -128,9 +139,15 @@ void DragArea::hideFast() { } void DragArea::hideStart() { + if (_hiding || isHidden()) { + return; + } + if (_cache.isNull()) { + _cache = myGrab(this, innerRect().marginsAdded(st::boxRoundShadow.extend)); + } _hiding = true; setIn(false); - _a_opacity.start([this] { opacityAnimationCallback(); }, 1., 0., st::defaultDropdownDuration); + _a_opacity.start([this] { opacityAnimationCallback(); }, 1., 0., st::boxDuration); } void DragArea::hideFinish() { @@ -140,14 +157,21 @@ void DragArea::hideFinish() { } void DragArea::showStart() { + if (!_hiding && !isHidden()) { + return; + } _hiding = false; + if (_cache.isNull()) { + _cache = myGrab(this, innerRect().marginsAdded(st::boxRoundShadow.extend)); + } show(); - _a_opacity.start([this] { opacityAnimationCallback(); }, 0., 1., st::defaultDropdownDuration); + _a_opacity.start([this] { opacityAnimationCallback(); }, 0., 1., st::boxDuration); } void DragArea::opacityAnimationCallback() { update(); if (!_a_opacity.animating()) { + _cache = QPixmap(); if (_hiding) { hideFinish(); } diff --git a/Telegram/SourceFiles/history/history_drag_area.h b/Telegram/SourceFiles/history/history_drag_area.h index ef5ee9be4..b5b6e05ec 100644 --- a/Telegram/SourceFiles/history/history_drag_area.h +++ b/Telegram/SourceFiles/history/history_drag_area.h @@ -21,7 +21,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #pragma once #include "ui/twidget.h" -#include "ui/effects/rect_shadow.h" class DragArea : public TWidget { Q_OBJECT @@ -34,15 +33,7 @@ public: void otherEnter(); void otherLeave(); - bool overlaps(const QRect &globalRect) { - if (isHidden() || _a_opacity.animating()) return false; - - return QRect(st::dragPadding.left(), - st::dragPadding.top(), - width() - st::dragPadding.left() - st::dragPadding.right(), - height() - st::dragPadding.top() - st::dragPadding.bottom() - ).contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size())); - } + bool overlaps(const QRect &globalRect); void hideFast(); @@ -67,16 +58,23 @@ public slots: private: void setIn(bool in); void opacityAnimationCallback(); + QRect innerRect() const { + return QRect( + st::dragPadding.left(), + st::dragPadding.top(), + width() - st::dragPadding.left() - st::dragPadding.right(), + height() - st::dragPadding.top() - st::dragPadding.bottom() + ); + } bool _hiding = false; bool _in = false; + QPixmap _cache; base::lambda _droppedCallback; Animation _a_opacity; Animation _a_in; - Ui::RectShadow _shadow; - QString _text, _subtext; }; diff --git a/Telegram/SourceFiles/history/history_media_types.cpp b/Telegram/SourceFiles/history/history_media_types.cpp index e47091bf2..089925b3e 100644 --- a/Telegram/SourceFiles/history/history_media_types.cpp +++ b/Telegram/SourceFiles/history/history_media_types.cpp @@ -1554,7 +1554,7 @@ void HistoryGif::initDimensions() { int32 tw = 0, th = 0; if (_gif && _gif->state() == Media::Clip::State::Error) { if (!_gif->autoplay()) { - Ui::showLayer(new InformBox(lang(lng_gif_error))); + Ui::show(Box(lang(lng_gif_error))); } App::unregGifItem(_gif.get()); _gif.setBad(); @@ -2204,7 +2204,7 @@ ClickHandlerPtr addContactClickHandler(HistoryItem *item) { auto fname = contact->fname(); auto lname = contact->lname(); auto phone = contact->phone(); - Ui::showLayer(new AddContactBox(fname, lname, phone)); + Ui::show(Box(fname, lname, phone)); } } } diff --git a/Telegram/SourceFiles/history/history_message.cpp b/Telegram/SourceFiles/history/history_message.cpp index fe55da9b2..4f7233b7d 100644 --- a/Telegram/SourceFiles/history/history_message.cpp +++ b/Telegram/SourceFiles/history/history_message.cpp @@ -29,6 +29,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "history/history_service_layout.h" #include "history/history_media_types.h" #include "styles/style_dialogs.h" +#include "styles/style_widgets.h" #include "styles/style_history.h" namespace { diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index a66777814..7adf14f99 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -2677,32 +2677,28 @@ void BotKeyboard::updateSelected() { HistoryHider::HistoryHider(MainWidget *parent, bool forwardSelected) : TWidget(parent) , _forwardSelected(forwardSelected) , _send(this, lang(lng_forward_send), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) -, _shadow(st::boxShadow) { +, _cancel(this, lang(lng_cancel), st::cancelBoxButton) { init(); } HistoryHider::HistoryHider(MainWidget *parent, UserData *sharedContact) : TWidget(parent) , _sharedContact(sharedContact) , _send(this, lang(lng_forward_send), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) -, _shadow(st::boxShadow) { +, _cancel(this, lang(lng_cancel), st::cancelBoxButton) { init(); } HistoryHider::HistoryHider(MainWidget *parent) : TWidget(parent) , _sendPath(true) , _send(this, lang(lng_forward_send), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) -, _shadow(st::boxShadow) { +, _cancel(this, lang(lng_cancel), st::cancelBoxButton) { init(); } HistoryHider::HistoryHider(MainWidget *parent, const QString &botAndQuery) : TWidget(parent) , _botAndQuery(botAndQuery) , _send(this, lang(lng_forward_send), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) -, _shadow(st::boxShadow) { +, _cancel(this, lang(lng_cancel), st::cancelBoxButton) { init(); } @@ -2710,8 +2706,7 @@ HistoryHider::HistoryHider(MainWidget *parent, const QString &url, const QString , _shareUrl(url) , _shareText(text) , _send(this, lang(lng_forward_send), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) -, _shadow(st::boxShadow) { +, _cancel(this, lang(lng_cancel), st::cancelBoxButton) { init(); } @@ -2747,15 +2742,16 @@ void HistoryHider::paintEvent(QPaintEvent *e) { if (_cacheForAnim.isNull() || !_offered) { p.setFont(st::forwardFont); if (_offered) { - _shadow.paint(p, _box, st::boxShadowShift); - - // fill bg - p.fillRect(_box, st::boxBg); + Ui::Shadow::paint(p, _box, width(), st::boxRoundShadow); + App::roundRect(p, _box, st::boxBg, BoxCorners); p.setPen(st::boxTextFg); - _toText.drawElided(p, _box.left() + st::boxPadding.left(), _box.top() + st::boxPadding.top(), _toTextWidth + 2); + textstyleSet(&st::boxTextStyle); + _toText.drawLeftElided(p, _box.left() + st::boxPadding.left(), _box.y() + st::boxTopMargin + st::boxPadding.top(), _toTextWidth + 2, width(), 1, style::al_left); + textstyleRestore(); } else { - int32 w = st::forwardMargins.left() + _chooseWidth + st::forwardMargins.right(), h = st::forwardMargins.top() + st::forwardFont->height + st::forwardMargins.bottom(); + auto w = st::forwardMargins.left() + _chooseWidth + st::forwardMargins.right(); + auto h = st::forwardMargins.top() + st::forwardFont->height + st::forwardMargins.bottom(); App::roundRect(p, (width() - w) / 2, (height() - h) / 2, w, h, st::forwardBg, ForwardCorners); p.setPen(st::forwardFg); @@ -2839,20 +2835,21 @@ MainWidget *HistoryHider::parent() { } void HistoryHider::resizeEvent(QResizeEvent *e) { - int32 w = st::boxWidth, h = st::boxPadding.top() + st::boxPadding.bottom(); + auto w = st::boxWidth; + auto h = st::boxPadding.top() + st::boxPadding.bottom(); if (_offered) { if (!_hiding) { _send->show(); _cancel->show(); } - h += st::boxTextFont->height + st::boxButtonPadding.top() + _send->height() + st::boxButtonPadding.bottom(); + h += st::boxTopMargin + qMax(st::boxTextFont->height, st::boxTextStyle.lineHeight) + st::boxButtonPadding.top() + _send->height() + st::boxButtonPadding.bottom(); } else { h += st::forwardFont->height; _send->hide(); _cancel->hide(); } _box = QRect((width() - w) / 2, (height() - h) / 2, w, h); - _send->moveToRight(width() - (_box.x() + _box.width()) + st::boxButtonPadding.right(), _box.y() + h - st::boxButtonPadding.bottom() - _send->height()); + _send->moveToRight(width() - (_box.x() + _box.width()) + st::boxButtonPadding.right(), _box.y() + _box.height() - st::boxButtonPadding.bottom() - _send->height()); _cancel->moveToRight(width() - (_box.x() + _box.width()) + st::boxButtonPadding.right() + _send->width() + st::boxButtonPadding.left(), _send->y()); } @@ -2899,10 +2896,12 @@ bool HistoryHider::offerPeer(PeerId peer) { return false; } + textstyleSet(&st::boxTextStyle); _toText.setText(st::boxTextFont, phrase, _textNameOptions); + textstyleRestore(); _toTextWidth = _toText.maxWidth(); - if (_toTextWidth > _box.width() - st::boxPadding.left() - st::boxButtonPadding.right()) { - _toTextWidth = _box.width() - st::boxPadding.left() - st::boxButtonPadding.right(); + if (_toTextWidth > _box.width() - st::boxPadding.left() - st::boxLayerButtonPadding.right()) { + _toTextWidth = _box.width() - st::boxPadding.left() - st::boxLayerButtonPadding.right(); } resizeEvent(nullptr); @@ -3047,7 +3046,6 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent) , _recordCancelWidth(st::historyRecordFont->width(lang(lng_record_cancel))) , _a_recording(animation(this, &HistoryWidget::step_recording)) , _kbScroll(this, st::botKbScroll) -, _keyboard(this) , _emojiPan(this) , _attachDragDocument(this) , _attachDragPhoto(this) @@ -3123,7 +3121,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent) _scroll->hide(); - _kbScroll->setOwnedWidget(_keyboard); + _keyboard = _kbScroll->setOwnedWidget(object_ptr(this)); _kbScroll->hide(); updateScrollColors(); @@ -4233,9 +4231,8 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re _fieldBarCancel->hide(); _membersDropdownShowTimer.stop(); - if (_list) _list->deleteLater(); + _scroll->takeWidget().destroyDelayed(); _list = nullptr; - _scroll->takeWidget(); clearInlineBot(); @@ -4299,10 +4296,8 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re } } - _list = new HistoryInner(this, _scroll, _history); - _list->hide(); _scroll->hide(); - _scroll->setWidget(_list); + _list = _scroll->setOwnedWidget(object_ptr(this, _scroll, _history)); _list->show(); _updateHistoryItems.stop(); @@ -4790,7 +4785,7 @@ bool HistoryWidget::messagesFailed(const RPCError &error, mtpRequestId requestId if (error.type() == qstr("CHANNEL_PRIVATE") || error.type() == qstr("CHANNEL_PUBLIC_GROUP_NA") || error.type() == qstr("USER_BANNED_IN_CHANNEL")) { PeerData *was = _peer; App::main()->showBackFromStack(); - Ui::showLayer(new InformBox(lang((was && was->isMegagroup()) ? lng_group_not_accessible : lng_channel_not_accessible))); + Ui::show(Box(lang((was && was->isMegagroup()) ? lng_group_not_accessible : lng_channel_not_accessible))); return true; } @@ -5175,7 +5170,7 @@ void HistoryWidget::saveEditMsg() { _field->setFocus(); return; } else if (!leftText.isEmpty()) { - Ui::showLayer(new InformBox(lang(lng_edit_too_long))); + Ui::show(Box(lang(lng_edit_too_long))); return; } @@ -5219,14 +5214,14 @@ bool HistoryWidget::saveEditMsgFail(History *history, const RPCError &error, mtp QString err = error.type(); if (err == qstr("MESSAGE_ID_INVALID") || err == qstr("CHAT_ADMIN_REQUIRED") || err == qstr("MESSAGE_EDIT_TIME_EXPIRED")) { - Ui::showLayer(new InformBox(lang(lng_edit_error))); + Ui::show(Box(lang(lng_edit_error))); } else if (err == qstr("MESSAGE_NOT_MODIFIED")) { cancelEdit(); } else if (err == qstr("MESSAGE_EMPTY")) { _field->selectAll(); _field->setFocus(); } else { - Ui::showLayer(new InformBox(lang(lng_edit_error))); + Ui::show(Box(lang(lng_edit_error))); } update(); return true; @@ -5347,10 +5342,10 @@ bool HistoryWidget::joinFail(const RPCError &error, mtpRequestId req) { if (_unblockRequest == req) _unblockRequest = 0; if (error.type() == qstr("CHANNEL_PRIVATE") || error.type() == qstr("CHANNEL_PUBLIC_GROUP_NA") || error.type() == qstr("USER_BANNED_IN_CHANNEL")) { - Ui::showLayer(new InformBox(lang((_peer && _peer->isMegagroup()) ? lng_group_not_accessible : lng_channel_not_accessible))); + Ui::show(Box(lang((_peer && _peer->isMegagroup()) ? lng_group_not_accessible : lng_channel_not_accessible))); return true; } else if (error.type() == qstr("CHANNELS_TOO_MUCH")) { - Ui::showLayer(new InformBox(lang(lng_join_channel_error))); + Ui::show(Box(lang(lng_join_channel_error))); } return false; @@ -5779,7 +5774,7 @@ void HistoryWidget::botCallbackDone(BotCallbackInfo info, const MTPmessages_BotC auto &answerData = answer.c_messages_botCallbackAnswer(); if (answerData.has_message()) { if (answerData.is_alert()) { - Ui::showLayer(new InformBox(qs(answerData.vmessage))); + Ui::show(Box(qs(answerData.vmessage))); } else if (App::wnd()) { Ui::Toast::Config toast; toast.text = qs(answerData.vmessage); @@ -5923,29 +5918,30 @@ DragState HistoryWidget::getDragState(const QMimeData *d) { void HistoryWidget::updateDragAreas() { _field->setAcceptDrops(!_attachDrag); + updateControlsGeometry(); + switch (_attachDrag) { case DragStateNone: _attachDragDocument->otherLeave(); _attachDragPhoto->otherLeave(); break; case DragStateFiles: - _attachDragDocument->otherEnter(); _attachDragDocument->setText(lang(lng_drag_files_here), lang(lng_drag_to_send_files)); + _attachDragDocument->otherEnter(); _attachDragPhoto->hideFast(); break; case DragStatePhotoFiles: - _attachDragDocument->otherEnter(); _attachDragDocument->setText(lang(lng_drag_images_here), lang(lng_drag_to_send_no_compression)); - _attachDragPhoto->otherEnter(); _attachDragPhoto->setText(lang(lng_drag_photos_here), lang(lng_drag_to_send_quick)); + _attachDragDocument->otherEnter(); + _attachDragPhoto->otherEnter(); break; case DragStateImage: + _attachDragPhoto->setText(lang(lng_drag_images_here), lang(lng_drag_to_send_quick)); _attachDragDocument->hideFast(); _attachDragPhoto->otherEnter(); - _attachDragPhoto->setText(lang(lng_drag_images_here), lang(lng_drag_to_send_quick)); break; }; - resizeEvent(0); } bool HistoryWidget::canSendMessages(PeerData *peer) const { @@ -6157,13 +6153,6 @@ void HistoryWidget::selectMessage() { if (_list) _list->selectItem(item); } -void HistoryWidget::onForwardHere() { - HistoryItem *item = App::contextItem(); - if (!item || item->type() != HistoryItemMsg || item->serviceMsg()) return; - - App::forward(_peer->id, ForwardContextMessage); -} - bool HistoryWidget::paintTopBar(Painter &p, int decreaseWidth, TimeMs ms) { if (_a_show.animating()) { auto progress = _a_show.current(1.); @@ -6462,7 +6451,7 @@ void HistoryWidget::updateFieldPlaceholder() { } template -bool HistoryWidget::showSendFilesBox(SendFilesBox *box, const QString &insertTextOnCancel, const QString *addedComment, SendCallback callback) { +bool HistoryWidget::showSendFilesBox(object_ptr box, const QString &insertTextOnCancel, const QString *addedComment, SendCallback callback) { App::wnd()->activateWindow(); auto withComment = (addedComment != nullptr); @@ -6488,7 +6477,7 @@ bool HistoryWidget::showSendFilesBox(SendFilesBox *box, const QString &insertTex })); } - Ui::showLayer(box); + Ui::show(std_::move(box)); return true; } @@ -6498,11 +6487,11 @@ bool HistoryWidget::validateSendingFiles(const SendingFilesLists &lists, Callbac App::wnd()->activateWindow(); if (!lists.nonLocalUrls.isEmpty()) { - Ui::showLayer(new InformBox(lng_send_image_non_local(lt_name, lists.nonLocalUrls.front().toDisplayString()))); + Ui::show(Box(lng_send_image_non_local(lt_name, lists.nonLocalUrls.front().toDisplayString()))); } else if (!lists.emptyFiles.isEmpty()) { - Ui::showLayer(new InformBox(lng_send_image_empty(lt_name, lists.emptyFiles.front()))); + Ui::show(Box(lng_send_image_empty(lt_name, lists.emptyFiles.front()))); } else if (!lists.tooLargeFiles.isEmpty()) { - Ui::showLayer(new InformBox(lng_send_image_too_large(lt_name, lists.tooLargeFiles.front()))); + Ui::show(Box(lng_send_image_too_large(lt_name, lists.tooLargeFiles.front()))); } else if (!lists.filesToSend.isEmpty()) { return callback(lists.filesToSend); } @@ -6523,12 +6512,12 @@ bool HistoryWidget::confirmSendingFiles(const SendingFilesLists &lists, Compress auto insertTextOnCancel = QString(); auto prepareBox = [this, &files, &lists, compressed, &image] { if (files.size() > 1) { - return new SendFilesBox(files, lists.allFilesForCompress ? compressed : CompressConfirm::None); + return Box(files, lists.allFilesForCompress ? compressed : CompressConfirm::None); } auto filepath = files.front(); auto animated = false; image = App::readImage(filepath, nullptr, false, &animated); - return new SendFilesBox(filepath, image, imageCompressConfirm(image, compressed, animated), animated); + return Box(filepath, image, imageCompressConfirm(image, compressed, animated), animated); }; auto sendCallback = [this, image](const QStringList &files, bool compressed, const QString &caption, MsgId replyTo) { auto type = compressed ? SendMediaType::Photo : SendMediaType::File; @@ -6543,12 +6532,12 @@ bool HistoryWidget::confirmSendingFiles(const QImage &image, const QByteArray &c App::wnd()->activateWindow(); auto animated = false; - auto box = new SendFilesBox(QString(), image, imageCompressConfirm(image, compressed), animated); auto sendCallback = [this, content, image](const QStringList &files, bool compressed, const QString &caption, MsgId replyTo) { auto type = compressed ? SendMediaType::Photo : SendMediaType::File; uploadFilesAfterConfirmation(files, image, content, type, caption); }; - return showSendFilesBox(box, insertTextOnCancel, nullptr, std_::move(sendCallback)); + auto box = Box(QString(), image, imageCompressConfirm(image, compressed), animated); + return showSendFilesBox(std_::move(box), insertTextOnCancel, nullptr, std_::move(sendCallback)); } bool HistoryWidget::confirmSendingFiles(const QMimeData *data, CompressConfirm compressed, const QString &insertTextOnCancel) { @@ -6578,12 +6567,12 @@ bool HistoryWidget::confirmSendingFiles(const QMimeData *data, CompressConfirm c bool HistoryWidget::confirmShareContact(const QString &phone, const QString &fname, const QString &lname, const QString *addedComment) { if (!canWriteMessage()) return false; - auto box = new SendFilesBox(phone, fname, lname); + auto box = Box(phone, fname, lname); auto sendCallback = [this, phone, fname, lname](const QStringList &files, bool compressed, const QString &caption, MsgId replyTo) { shareContact(_peer->id, phone, fname, lname, replyTo); }; auto insertTextOnCancel = QString(); - return showSendFilesBox(box, insertTextOnCancel, addedComment, std_::move(sendCallback)); + return showSendFilesBox(std_::move(box), insertTextOnCancel, addedComment, std_::move(sendCallback)); } HistoryWidget::SendingFilesLists HistoryWidget::getSendingFilesLists(const QList &files) { @@ -6901,18 +6890,15 @@ void HistoryWidget::onDocumentFailed(const FullMsgId &newId) { } void HistoryWidget::onReportSpamClicked() { - ConfirmBox *box = new ConfirmBox(lang(_peer->isUser() ? lng_report_spam_sure : ((_peer->isChat() || _peer->isMegagroup()) ? lng_report_spam_sure_group : lng_report_spam_sure_channel)), lang(lng_report_spam_ok), st::attentionBoxButton); - connect(box, SIGNAL(confirmed()), this, SLOT(onReportSpamSure())); - Ui::showLayer(box); _clearPeer = _peer; -} + auto text = lang(_peer->isUser() ? lng_report_spam_sure : ((_peer->isChat() || _peer->isMegagroup()) ? lng_report_spam_sure_group : lng_report_spam_sure_channel)); + Ui::show(Box(text, lang(lng_report_spam_ok), st::attentionBoxButton, base::lambda_guarded(this, [this] { + if (_reportSpamRequest) return; -void HistoryWidget::onReportSpamSure() { - if (_reportSpamRequest) return; - - Ui::hideLayer(); - if (_clearPeer->isUser()) MTP::send(MTPcontacts_Block(_clearPeer->asUser()->inputUser), rpcDone(&HistoryWidget::blockDone, _clearPeer), RPCFailHandlerPtr(), 0, 5); - _reportSpamRequest = MTP::send(MTPmessages_ReportSpam(_clearPeer->input), rpcDone(&HistoryWidget::reportSpamDone, _clearPeer), rpcFail(&HistoryWidget::reportSpamFail)); + Ui::hideLayer(); + if (_clearPeer->isUser()) MTP::send(MTPcontacts_Block(_clearPeer->asUser()->inputUser), rpcDone(&HistoryWidget::blockDone, _clearPeer), RPCFailHandlerPtr(), 0, 5); + _reportSpamRequest = MTP::send(MTPmessages_ReportSpam(_clearPeer->input), rpcDone(&HistoryWidget::reportSpamDone, _clearPeer), rpcFail(&HistoryWidget::reportSpamFail)); + }))); } void HistoryWidget::reportSpamDone(PeerData *peer, const MTPBool &result, mtpRequestId req) { @@ -7091,7 +7077,7 @@ void HistoryWidget::updateControlsGeometry() { updateHistoryDownPosition(); - _emojiPan->setMaxHeight(height() - st::defaultDropdownPadding.top() - st::defaultDropdownPadding.bottom() - _attachEmoji->height()); + _emojiPan->setMaxHeight(height() - _attachEmoji->height()); if (_membersDropdown) { _membersDropdown->setMaxHeight(countMembersDropdownHeightMax()); } @@ -7855,14 +7841,16 @@ void HistoryWidget::onReplyToMessage() { onReplyToMessage(); App::contextItem(to); } else { - LayerWidget *box = nullptr; if (to->type() != HistoryItemMsg || to->serviceMsg()) { - box = new InformBox(lang(lng_reply_cant)); + Ui::show(Box(lang(lng_reply_cant))); } else { - box = new ConfirmBox(lang(lng_reply_cant_forward), lang(lng_selected_forward)); - connect(box, SIGNAL(confirmed()), this, SLOT(onForwardHere())); + Ui::show(Box(lang(lng_reply_cant_forward), lang(lng_selected_forward), base::lambda_guarded(this, [this] { + auto item = App::contextItem(); + if (!item || item->type() != HistoryItemMsg || item->serviceMsg()) return; + + App::forward(_peer->id, ForwardContextMessage); + }))); } - Ui::showLayer(box); } return; } @@ -7897,15 +7885,12 @@ void HistoryWidget::onReplyToMessage() { } void HistoryWidget::onEditMessage() { - HistoryItem *to = App::contextItem(); + auto to = App::contextItem(); if (!to) return; - EditCaptionBox *box = new EditCaptionBox(to); - if (box->captionFound()) { - Ui::showLayer(box); + if (EditCaptionBox::canEdit(to)) { + Ui::show(Box(to)); } else { - delete box; - if (!_editMsgId) { if (_replyToId || !_field->isEmpty()) { _history->setLocalDraft(std_::make_unique(_field, _replyToId, _previewCancelled)); @@ -7954,29 +7939,25 @@ void HistoryWidget::onPinMessage() { HistoryItem *to = App::contextItem(); if (!to || !to->canPin() || !_peer || !_peer->isMegagroup()) return; - Ui::showLayer(new PinMessageBox(_peer->asChannel(), to->id)); + Ui::show(Box(_peer->asChannel(), to->id)); } void HistoryWidget::onUnpinMessage() { if (!_peer || !_peer->isMegagroup()) return; - ConfirmBox *box = new ConfirmBox(lang(lng_pinned_unpin_sure), lang(lng_pinned_unpin)); - connect(box, SIGNAL(confirmed()), this, SLOT(onUnpinMessageSure())); - Ui::showLayer(box); -} + Ui::show(Box(lang(lng_pinned_unpin_sure), lang(lng_pinned_unpin), base::lambda_guarded(this, [this] { + if (!_peer || !_peer->isMegagroup()) return; -void HistoryWidget::onUnpinMessageSure() { - if (!_peer || !_peer->isMegagroup()) return; + _peer->asChannel()->mgInfo->pinnedMsgId = 0; + if (pinnedMsgVisibilityUpdated()) { + resizeEvent(0); + update(); + } - _peer->asChannel()->mgInfo->pinnedMsgId = 0; - if (pinnedMsgVisibilityUpdated()) { - resizeEvent(0); - update(); - } - - Ui::hideLayer(); - MTPchannels_UpdatePinnedMessage::Flags flags = 0; - MTP::send(MTPchannels_UpdatePinnedMessage(MTP_flags(flags), _peer->asChannel()->inputChannel, MTP_int(0)), rpcDone(&HistoryWidget::unpinDone)); + Ui::hideLayer(); + MTPchannels_UpdatePinnedMessage::Flags flags = 0; + MTP::send(MTPchannels_UpdatePinnedMessage(MTP_flags(flags), _peer->asChannel()->inputChannel, MTP_int(0)), rpcDone(&HistoryWidget::unpinDone)); + }))); } void HistoryWidget::unpinDone(const MTPUpdates &updates) { @@ -8279,9 +8260,13 @@ void HistoryWidget::onCancel() { auto editTags = textTagsFromEntities(original.entities); TextWithTags editData = { editText, editTags }; if (_replyEditMsg && editData != _field->getTextWithTags()) { - auto box = new ConfirmBox(lang(lng_cancel_edit_post_sure), lang(lng_cancel_edit_post_yes), st::defaultBoxButton, lang(lng_cancel_edit_post_no)); - connect(box, SIGNAL(confirmed()), this, SLOT(onFieldBarCancel())); - Ui::showLayer(box); + Ui::show(Box( + lang(lng_cancel_edit_post_sure), + lang(lng_cancel_edit_post_yes), + lang(lng_cancel_edit_post_no), + base::lambda_guarded(this, [this] { + onFieldBarCancel(); + }))); } else { onFieldBarCancel(); } @@ -8326,7 +8311,7 @@ void HistoryWidget::peerUpdated(PeerData *data) { QString restriction = _peer->restrictionReason(); if (!restriction.isEmpty()) { App::main()->showBackFromStack(); - Ui::showLayer(new InformBox(restriction)); + Ui::show(Box(restriction)); return; } bool resize = false; @@ -8926,7 +8911,3 @@ bool HistoryWidget::touchScroll(const QPoint &delta) { _scroll->scrollToY(scNew); return true; } - -HistoryWidget::~HistoryWidget() { - delete base::take(_list); -} diff --git a/Telegram/SourceFiles/historywidget.h b/Telegram/SourceFiles/historywidget.h index 147f501aa..33fadbbfb 100644 --- a/Telegram/SourceFiles/historywidget.h +++ b/Telegram/SourceFiles/historywidget.h @@ -22,7 +22,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "localimageloader.h" #include "ui/filedialog.h" -#include "ui/effects/rect_shadow.h" #include "ui/widgets/tooltip.h" #include "ui/widgets/input_fields.h" #include "ui/widgets/scroll_area.h" @@ -365,9 +364,9 @@ protected: void paintEvent(QPaintEvent *e) override; private: - ChildWidget _report; - ChildWidget _hide; - ChildWidget _clear; + object_ptr _report; + object_ptr _hide; + object_ptr _clear; }; @@ -506,8 +505,8 @@ private: QString _shareUrl, _shareText; QString _botAndQuery; - ChildWidget _send; - ChildWidget _cancel; + object_ptr _send; + object_ptr _cancel; PeerData *_offered = nullptr; Animation _a_opacity; @@ -523,8 +522,6 @@ private: int32 _toTextWidth = 0; QPixmap _cacheForAnim; - Ui::RectShadow _shadow; - }; EntitiesInText entitiesFromTextTags(const TextWithTags::Tags &tags); @@ -724,8 +721,6 @@ public: bool cmd_next_chat(); bool cmd_previous_chat(); - ~HistoryWidget(); - protected: void resizeEvent(QResizeEvent *e) override; void keyPressEvent(QKeyEvent *e) override; @@ -746,7 +741,6 @@ public slots: void onEditMessage(); void onPinMessage(); void onUnpinMessage(); - void onUnpinMessageSure(); void onPinnedHide(); void onCopyPostLink(); void onFieldBarCancel(); @@ -773,7 +767,6 @@ public slots: void onDocumentFailed(const FullMsgId &msgId); void onReportSpamClicked(); - void onReportSpamSure(); void onReportSpamHide(); void onReportSpamClear(); @@ -805,8 +798,6 @@ public slots: void forwardMessage(); void selectMessage(); - void onForwardHere(); // instead of a reply - void onFieldFocused(); void onFieldResize(); void onCheckFieldAutocomplete(); @@ -867,7 +858,7 @@ private: template bool validateSendingFiles(const SendingFilesLists &lists, Callback callback); template - bool showSendFilesBox(SendFilesBox *box, const QString &insertTextOnCancel, const QString *addedComment, SendCallback callback); + bool showSendFilesBox(object_ptr box, const QString &insertTextOnCancel, const QString *addedComment, SendCallback callback); CompressConfirm imageCompressConfirm(const QImage &image, CompressConfirm compressed, bool animated = false); // If an empty filepath is found we upload (possible) "image" with (possible) "content". @@ -908,7 +899,7 @@ private: Text _replyEditMsgText; mutable SingleTimer _updateEditTimeLeftDisplay; - ChildWidget _fieldBarCancel; + object_ptr _fieldBarCancel; void updateReplyEditTexts(bool force = false); struct PinnedBar { @@ -918,8 +909,8 @@ private: MsgId msgId = 0; HistoryItem *msg = nullptr; Text text; - ChildWidget cancel; - ChildWidget shadow; + object_ptr cancel; + object_ptr shadow; }; std_::unique_ptr _pinnedBar; void updatePinnedBar(bool force = false); @@ -1078,8 +1069,8 @@ private: MsgId _activeAnimMsgId = 0; - ChildWidget _scroll; - HistoryInner *_list = nullptr; + object_ptr _scroll; + QPointer _list; History *_migrated = nullptr; History *_history = nullptr; bool _histInited = false; // initial updateListSize() called @@ -1091,9 +1082,9 @@ private: Animation _historyDownShown; bool _historyDownIsShown = false; - ChildWidget _historyDown; + object_ptr _historyDown; - ChildWidget _fieldAutocomplete; + object_ptr _fieldAutocomplete; UserData *_inlineBot = nullptr; QString _inlineBotUsername; @@ -1108,23 +1099,23 @@ private: bool isMuteUnmute() const; bool updateCmdStartShown(); - ChildWidget _reportSpamPanel; + object_ptr _reportSpamPanel; - ChildWidget _send; - ChildWidget _unblock; - ChildWidget _botStart; - ChildWidget _joinChannel; - ChildWidget _muteUnmute; + object_ptr _send; + object_ptr _unblock; + object_ptr _botStart; + object_ptr _joinChannel; + object_ptr _muteUnmute; mtpRequestId _unblockRequest = 0; mtpRequestId _reportSpamRequest = 0; - ChildWidget _attachToggle; - ChildWidget _attachEmoji; - ChildWidget _botKeyboardShow; - ChildWidget _botKeyboardHide; - ChildWidget _botCommandStart; - ChildWidget _silent; + object_ptr _attachToggle; + object_ptr _attachEmoji; + object_ptr _botKeyboardShow; + object_ptr _botKeyboardHide; + object_ptr _botCommandStart; + object_ptr _silent; bool _cmdStartShown = false; - ChildWidget _field; + object_ptr _field; bool _recording = false; bool _inRecord = false; bool _inField = false; @@ -1147,15 +1138,15 @@ private: bool _kbShown = false; HistoryItem *_kbReplyTo = nullptr; - ChildWidget _kbScroll; - ChildWidget _keyboard; + object_ptr _kbScroll; + QPointer _keyboard; - ChildWidget _membersDropdown = { nullptr }; + object_ptr _membersDropdown = { nullptr }; QTimer _membersDropdownShowTimer; - ChildWidget _emojiPan; + object_ptr _emojiPan; DragState _attachDrag = DragStateNone; - ChildWidget _attachDragDocument, _attachDragPhoto; + object_ptr _attachDragDocument, _attachDragPhoto; int32 _selCount; // < 0 - text selected, focus list, not _field @@ -1186,7 +1177,7 @@ private: bool _saveDraftText = false; QTimer _saveDraftTimer, _saveCloudDraftTimer; - ChildWidget _topShadow; + object_ptr _topShadow; bool _inGrab = false; }; diff --git a/Telegram/SourceFiles/intro/introcode.h b/Telegram/SourceFiles/intro/introcode.h index 81b37a82a..4f0fb01e1 100644 --- a/Telegram/SourceFiles/intro/introcode.h +++ b/Telegram/SourceFiles/intro/introcode.h @@ -91,20 +91,20 @@ private: void stopCheck(); - ChildWidget _noTelegramCode; + object_ptr _noTelegramCode; mtpRequestId _noTelegramCodeRequestId = 0; - ChildWidget _code; + object_ptr _code; QString _sentCode; mtpRequestId _sentRequest = 0; - ChildObject _callTimer; + object_ptr _callTimer; Widget::Data::CallStatus _callStatus; int _callTimeout; mtpRequestId _callRequestId = 0; - ChildWidget _callLabel; + object_ptr _callLabel; - ChildObject _checkRequest; + object_ptr _checkRequest; }; diff --git a/Telegram/SourceFiles/intro/introphone.cpp b/Telegram/SourceFiles/intro/introphone.cpp index ef1d7beb6..69e5d51f8 100644 --- a/Telegram/SourceFiles/intro/introphone.cpp +++ b/Telegram/SourceFiles/intro/introphone.cpp @@ -81,7 +81,7 @@ void PhoneWidget::showPhoneError(const QString &text) { void PhoneWidget::hidePhoneError() { hideError(); if (_signup) { - _signup->fadeOut(); + _signup->hideAnimated(); showDescription(); } } @@ -90,8 +90,8 @@ void PhoneWidget::showSignup() { showPhoneError(lang(lng_bad_phone_noreg)); if (!_signup) { auto signupText = lng_phone_notreg(lt_link_start, textcmdStartLink(1), lt_link_end, textcmdStopLink(), lt_signup_start, textcmdStartLink(2), lt_signup_end, textcmdStopLink()); - auto inner = new Ui::FlatLabel(this, signupText, Ui::FlatLabel::InitType::Rich, st::introDescription, st::introDescriptionTextStyle); - _signup.create(this, inner, base::lambda(), st::introErrorDuration); + auto inner = object_ptr(this, signupText, Ui::FlatLabel::InitType::Rich, st::introDescription, st::introDescriptionTextStyle); + _signup.create(this, std_::move(inner), st::introErrorDuration); _signup->entity()->setLink(1, MakeShared(qsl("https://telegram.org"), false)); _signup->entity()->setLink(2, MakeShared([this] { toSignUp(); @@ -99,7 +99,7 @@ void PhoneWidget::showSignup() { _signup->hideFast(); updateSignupGeometry(); } - _signup->fadeIn(); + _signup->showAnimated(); hideDescription(); } diff --git a/Telegram/SourceFiles/intro/introphone.h b/Telegram/SourceFiles/intro/introphone.h index 0dbfedd5b..9c67fb52b 100644 --- a/Telegram/SourceFiles/intro/introphone.h +++ b/Telegram/SourceFiles/intro/introphone.h @@ -76,16 +76,16 @@ private: bool _changed = false; - ChildWidget _country; - ChildWidget _code; - ChildWidget _phone; + object_ptr _country; + object_ptr _code; + object_ptr _phone; - ChildWidget> _signup = { nullptr }; + object_ptr> _signup = { nullptr }; QString _sentPhone; mtpRequestId _sentRequest = 0; - ChildObject _checkRequest; + object_ptr _checkRequest; }; diff --git a/Telegram/SourceFiles/intro/intropwdcheck.cpp b/Telegram/SourceFiles/intro/intropwdcheck.cpp index 04a7fa5a9..74039575f 100644 --- a/Telegram/SourceFiles/intro/intropwdcheck.cpp +++ b/Telegram/SourceFiles/intro/intropwdcheck.cpp @@ -229,19 +229,15 @@ void PwdCheckWidget::onToRecover() { MTP::send(MTPauth_RequestPasswordRecovery(), rpcDone(&PwdCheckWidget::recoverStarted), rpcFail(&PwdCheckWidget::recoverStartFail)); } } else { - ConfirmBox *box = new InformBox(lang(lng_signin_no_email_forgot)); - Ui::showLayer(box); - connect(box, SIGNAL(destroyed(QObject*)), this, SLOT(onToReset())); + Ui::show(Box(lang(lng_signin_no_email_forgot), [this] { showReset(); })); } } void PwdCheckWidget::onToPassword() { - ConfirmBox *box = new InformBox(lang(lng_signin_cant_email_forgot)); - Ui::showLayer(box); - connect(box, SIGNAL(destroyed(QObject*)), this, SLOT(onToReset())); + Ui::show(Box(lang(lng_signin_cant_email_forgot), [this] { showReset(); })); } -void PwdCheckWidget::onToReset() { +void PwdCheckWidget::showReset() { if (_sentRequest) { MTP::cancel(base::take(_sentRequest)); } diff --git a/Telegram/SourceFiles/intro/intropwdcheck.h b/Telegram/SourceFiles/intro/intropwdcheck.h index 359fe4c62..8179440e2 100644 --- a/Telegram/SourceFiles/intro/intropwdcheck.h +++ b/Telegram/SourceFiles/intro/intropwdcheck.h @@ -51,9 +51,10 @@ private slots: void onToPassword(); void onInputChange(); void onCheckRequest(); - void onToReset(); private: + void showReset(); + void pwdSubmitDone(bool recover, const MTPauth_Authorization &result); bool pwdSubmitFail(const RPCError &error); bool codeSubmitFail(const RPCError &error); @@ -68,16 +69,16 @@ private: bool _hasRecovery; QString _hint, _emailPattern; - ChildWidget _pwdField; - ChildWidget _pwdHint; - ChildWidget _codeField; - ChildWidget _toRecover; - ChildWidget _toPassword; + object_ptr _pwdField; + object_ptr _pwdHint; + object_ptr _codeField; + object_ptr _toRecover; + object_ptr _toPassword; mtpRequestId _sentRequest = 0; QByteArray _pwdSalt; - ChildObject _checkRequest; + object_ptr _checkRequest; }; diff --git a/Telegram/SourceFiles/intro/introsignup.cpp b/Telegram/SourceFiles/intro/introsignup.cpp index f2c06815a..3849f9921 100644 --- a/Telegram/SourceFiles/intro/introsignup.cpp +++ b/Telegram/SourceFiles/intro/introsignup.cpp @@ -81,9 +81,8 @@ void SignupWidget::notifyFileQueryUpdated(const FileDialog::QueryUpdate &update) showError(lang(lng_bad_photo)); return; } - auto box = new PhotoCropBox(img, PeerId(0)); - connect(box, SIGNAL(ready(const QImage &)), this, SLOT(onPhotoReady(const QImage &))); - Ui::showLayer(box); + auto box = Ui::show(Box(img, PeerId(0))); + connect(box, SIGNAL(ready(const QImage&)), this, SLOT(onPhotoReady(const QImage&))); } void SignupWidget::resizeEvent(QResizeEvent *e) { diff --git a/Telegram/SourceFiles/intro/introsignup.h b/Telegram/SourceFiles/intro/introsignup.h index 88ab525a7..cf41e32da 100644 --- a/Telegram/SourceFiles/intro/introsignup.h +++ b/Telegram/SourceFiles/intro/introsignup.h @@ -61,9 +61,9 @@ private: QImage _photoImage; - ChildWidget _photo; - ChildWidget _first; - ChildWidget _last; + object_ptr _photo; + object_ptr _first; + object_ptr _last; QString _firstName, _lastName; mtpRequestId _sentRequest = 0; @@ -71,7 +71,7 @@ private: bool _invertOrder = false; - ChildObject _checkRequest; + object_ptr _checkRequest; }; diff --git a/Telegram/SourceFiles/intro/introwidget.cpp b/Telegram/SourceFiles/intro/introwidget.cpp index c479cd8e8..f9629fbfa 100644 --- a/Telegram/SourceFiles/intro/introwidget.cpp +++ b/Telegram/SourceFiles/intro/introwidget.cpp @@ -47,8 +47,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org namespace Intro { Widget::Widget(QWidget *parent) : TWidget(parent) -, _back(this, new Ui::IconButton(this, st::introBackButton), base::lambda(), st::introSlideDuration) -, _settings(this, new Ui::RoundButton(this, lang(lng_menu_settings), st::defaultBoxButton), base::lambda(), st::introCoverDuration) +, _back(this, object_ptr(this, st::introBackButton), st::introSlideDuration) +, _settings(this, object_ptr(this, lang(lng_menu_settings), st::defaultBoxButton), st::introCoverDuration) , _next(this, QString(), st::introNextButton) { getData()->country = psCurrentCountry(); @@ -65,12 +65,12 @@ Widget::Widget(QWidget *parent) : TWidget(parent) LangLoaderPlain loader(qsl(":/langs/lang_") + LanguageCodes[systemLangId].c_str() + qsl(".strings"), langLoaderRequest(lng_switch_to_this)); QString text = loader.found().value(lng_switch_to_this); if (!text.isEmpty()) { - _changeLanguage.create(this, new Ui::LinkButton(this, text), base::lambda(), st::introCoverDuration); + _changeLanguage.create(this, object_ptr(this, text), st::introCoverDuration); _changeLanguage->entity()->setClickedCallback([this, systemLangId] { changeLanguage(systemLangId); }); } } } else { - _changeLanguage.create(this, new Ui::LinkButton(this, langOriginal(lng_switch_to_this)), base::lambda(), st::introCoverDuration); + _changeLanguage.create(this, object_ptr(this, langOriginal(lng_switch_to_this)), st::introCoverDuration); _changeLanguage->entity()->setClickedCallback([this] { changeLanguage(languageDefault); }); } @@ -98,7 +98,7 @@ Widget::Widget(QWidget *parent) : TWidget(parent) void Widget::onCheckUpdateStatus() { if (Sandbox::updatingState() == Application::UpdatingReady) { if (_update) return; - _update.create(this, new Ui::RoundButton(this, lang(lng_menu_update).toUpper(), st::defaultBoxButton), base::lambda(), st::introCoverDuration); + _update.create(this, object_ptr(this, lang(lng_menu_update).toUpper(), st::defaultBoxButton), st::introCoverDuration); if (!_a_show.animating()) _update->show(); _update->entity()->setClickedCallback([] { checkReadyUpdate(); @@ -152,21 +152,21 @@ void Widget::historyMove(Direction direction) { delete base::take(wasStep); } if (getStep()->hasBack()) { - _back->fadeIn(); + _back->showAnimated(); } else { - _back->fadeOut(); + _back->hideAnimated(); } if (getStep()->hasCover()) { - _settings->fadeOut(); - if (_update) _update->fadeOut(); - if (_changeLanguage) _changeLanguage->fadeIn(); + _settings->hideAnimated(); + if (_update) _update->hideAnimated(); + if (_changeLanguage) _changeLanguage->showAnimated(); } else { - _settings->fadeIn(); - if (_update) _update->fadeIn(); - if (_changeLanguage) _changeLanguage->fadeOut(); + _settings->showAnimated(); + if (_update) _update->showAnimated(); + if (_changeLanguage) _changeLanguage->hideAnimated(); } _next->setText(getStep()->nextButtonText()); - if (_resetAccount) _resetAccount->fadeOut(); + if (_resetAccount) _resetAccount->hideAnimated(); getStep()->showAnimated(direction); fixOrder(); } @@ -206,25 +206,22 @@ void Widget::appendStep(Step *step) { void Widget::showResetButton() { if (!_resetAccount) { - _resetAccount.create(this, new Ui::RoundButton(this, lang(lng_signin_reset_account), st::introResetButton), base::lambda(), st::introErrorDuration); + auto entity = object_ptr(this, lang(lng_signin_reset_account), st::introResetButton); + _resetAccount.create(this, std_::move(entity), st::introErrorDuration); _resetAccount->hideFast(); _resetAccount->entity()->setClickedCallback([this] { resetAccount(); }); updateControlsGeometry(); } - _resetAccount->fadeIn(); + _resetAccount->showAnimated(); } void Widget::resetAccount() { if (_resetRequest) return; - auto box = new ConfirmBox(lang(lng_signin_sure_reset), lang(lng_signin_reset), st::attentionBoxButton); - box->setConfirmedCallback([this] { resetAccountSure(); }); - Ui::showLayer(box); -} - -void Widget::resetAccountSure() { - if (_resetRequest) return; - _resetRequest = MTP::send(MTPaccount_DeleteAccount(MTP_string("Forgot password")), rpcDone(&Widget::resetDone), rpcFail(&Widget::resetFail)); + Ui::show(Box(lang(lng_signin_sure_reset), lang(lng_signin_reset), st::attentionBoxButton, base::lambda_guarded(this, [this] { + if (_resetRequest) return; + _resetRequest = MTP::send(MTPaccount_DeleteAccount(MTP_string("Forgot password")), rpcDone(&Widget::resetDone), rpcFail(&Widget::resetFail)); + }))); } void Widget::resetDone(const MTPBool &result) { @@ -251,9 +248,9 @@ bool Widget::resetFail(const RPCError &error) { } else { when = lng_signin_reset_in_minutes(lt_count_minutes, minutes); } - Ui::showLayer(new InformBox(lng_signin_reset_wait(lt_phone_number, App::formatPhone(getData()->phone), lt_when, when))); + Ui::show(Box(lng_signin_reset_wait(lt_phone_number, App::formatPhone(getData()->phone), lt_when, when))); } else if (type == qstr("2FA_RECENT_CONFIRM")) { - Ui::showLayer(new InformBox(lang(lng_signin_reset_cancelled))); + Ui::show(Box(lang(lng_signin_reset_cancelled))); } else { Ui::hideLayer(); getStep()->showError(lang(lng_server_error)); @@ -544,11 +541,11 @@ void Widget::Step::fillSentCodeData(const MTPauth_SentCodeType &type) { } void Widget::Step::showDescription() { - _description->fadeIn(); + _description->showAnimated(); } void Widget::Step::hideDescription() { - _description->fadeOut(); + _description->hideAnimated(); } void Widget::Step::paintContentSnapshot(Painter &p, const QPixmap &snapshot, float64 alpha, float64 howMuchHidden) { @@ -647,16 +644,16 @@ void Widget::Step::setErrorBelowLink(bool below) { void Widget::Step::showError(const QString &text) { _errorText = text; if (_errorText.isEmpty()) { - if (_error) _error->fadeOut(); + if (_error) _error->hideAnimated(); } else { if (!_error) { auto &st = _errorCentered ? st::introErrorCentered : st::introError; - _error.create(this, new Ui::FlatLabel(this, st, st::introErrorTextStyle), base::lambda(), st::introErrorDuration); + _error.create(this, object_ptr(this, st, st::introErrorTextStyle), st::introErrorDuration); _error->hideFast(); } _error->entity()->setText(text); updateLabelsPosition(); - _error->fadeIn(); + _error->showAnimated(); } } @@ -664,7 +661,7 @@ Widget::Step::Step(QWidget *parent, Data *data, bool hasCover) : TWidget(parent) , _data(data) , _hasCover(hasCover) , _title(this, _hasCover ? st::introCoverTitle : st::introTitle, st::defaultTextStyle) -, _description(this, new Ui::FlatLabel(this, _hasCover ? st::introCoverDescription : st::introDescription, _hasCover ? st::introCoverDescriptionTextStyle : st::introDescriptionTextStyle), base::lambda(), st::introErrorDuration) { +, _description(this, object_ptr(this, _hasCover ? st::introCoverDescription : st::introDescription, _hasCover ? st::introCoverDescriptionTextStyle : st::introDescriptionTextStyle), st::introErrorDuration) { hide(); } diff --git a/Telegram/SourceFiles/intro/introwidget.h b/Telegram/SourceFiles/intro/introwidget.h index 9deaaed94..7970e4fd1 100644 --- a/Telegram/SourceFiles/intro/introwidget.h +++ b/Telegram/SourceFiles/intro/introwidget.h @@ -190,13 +190,13 @@ public: base::lambda _goCallback; base::lambda _showResetCallback; - ChildWidget _title; - ChildWidget> _description; + object_ptr _title; + object_ptr> _description; bool _errorCentered = false; bool _errorBelowLink = false; QString _errorText; - ChildWidget> _error = { nullptr }; + object_ptr> _error = { nullptr }; Animation _a_show; CoverAnimation _coverAnimation; @@ -222,7 +222,6 @@ private: void showResetButton(); void resetAccount(); - void resetAccountSure(); void resetDone(const MTPBool &result); bool resetFail(const RPCError &error); @@ -247,13 +246,13 @@ private: int _nextTopFrom = 0; int _controlsTopFrom = 0; - ChildWidget> _back; - ChildWidget> _update = { nullptr }; - ChildWidget> _settings; + object_ptr> _back; + object_ptr> _update = { nullptr }; + object_ptr> _settings; - ChildWidget _next; - ChildWidget> _changeLanguage = { nullptr }; - ChildWidget> _resetAccount = { nullptr }; + object_ptr _next; + object_ptr> _changeLanguage = { nullptr }; + object_ptr> _resetAccount = { nullptr }; mtpRequestId _resetRequest = 0; diff --git a/Telegram/SourceFiles/layerwidget.cpp b/Telegram/SourceFiles/layerwidget.cpp index d77c2a9c5..6fe750c47 100644 --- a/Telegram/SourceFiles/layerwidget.cpp +++ b/Telegram/SourceFiles/layerwidget.cpp @@ -22,13 +22,16 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "lang.h" #include "media/media_clip_reader.h" +#include "boxes/abstractbox.h" #include "layerwidget.h" #include "application.h" #include "mainwindow.h" #include "mainwidget.h" #include "ui/filedialog.h" #include "styles/style_boxes.h" +#include "styles/style_widgets.h" #include "styles/style_stickers.h" +#include "ui/widgets/shadow.h" #include "window/window_main_menu.h" namespace { @@ -39,8 +42,7 @@ constexpr int kStickerPreviewEmojiLimit = 10; class LayerStackWidget::BackgroundWidget : public TWidget { public: - BackgroundWidget(QWidget *parent) : TWidget(parent) - , _shadow(st::boxShadow) { + BackgroundWidget(QWidget *parent) : TWidget(parent) { } void setDoneCallback(base::lambda &&callback) { @@ -72,6 +74,7 @@ private: QPixmap _bodyCache; QPixmap _mainMenuCache; + int _mainMenuCacheWidth = 0; QPixmap _specialLayerCache; QPixmap _layerCache; @@ -84,8 +87,6 @@ private: Animation _a_specialLayerShown; Animation _a_layerShown; - Ui::RectShadow _shadow; - QRect _specialLayerBox, _specialLayerCacheBox; QRect _layerBox, _layerCacheBox; int _mainMenuRight = 0; @@ -144,7 +145,8 @@ void LayerStackWidget::BackgroundWidget::setMainMenuShown(bool shown) { _mainMenuShown = shown; _a_mainMenuShown.start([this] { animationCallback(); }, _mainMenuShown ? 0. : 1., _mainMenuShown ? 1. : 0., st::boxDuration, anim::easeOutCirc); } - _mainMenuRight = _mainMenuShown ? (_mainMenuCache.width() / cIntRetinaFactor()) : 0; + _mainMenuCacheWidth = (_mainMenuCache.width() / cIntRetinaFactor()) - st::boxRoundShadow.extend.right(); + _mainMenuRight = _mainMenuShown ? _mainMenuCacheWidth : 0; checkWasShown(wasShown); } @@ -196,13 +198,14 @@ void LayerStackWidget::BackgroundWidget::paintEvent(QPaintEvent *e) { auto ms = getms(); auto mainMenuProgress = _a_mainMenuShown.current(ms, -1); - auto mainMenuRight = (_mainMenuCache.isNull() || mainMenuProgress < 0) ? _mainMenuRight : (mainMenuProgress < 0) ? _mainMenuRight : anim::interpolate(0, _mainMenuCache.width() / cIntRetinaFactor(), mainMenuProgress); + auto mainMenuRight = (_mainMenuCache.isNull() || mainMenuProgress < 0) ? _mainMenuRight : (mainMenuProgress < 0) ? _mainMenuRight : anim::interpolate(0, _mainMenuCacheWidth, mainMenuProgress); if (mainMenuRight) { + // Move showing boxes to the right while main menu is hiding. if (!_specialLayerCache.isNull()) { - specialLayerBox.setX(specialLayerBox.x() + mainMenuRight / 2); + specialLayerBox.moveLeft(specialLayerBox.left() + mainMenuRight / 2); } if (!_layerCache.isNull()) { - layerBox.setX(layerBox.x() + mainMenuRight / 2); + layerBox.moveLeft(layerBox.left() + mainMenuRight / 2); } } auto bgOpacity = _a_shown.current(ms, isShown() ? 1. : 0.); @@ -213,41 +216,85 @@ void LayerStackWidget::BackgroundWidget::paintEvent(QPaintEvent *e) { } p.setOpacity(bgOpacity); + auto overSpecialOpacity = (layerOpacity * specialLayerOpacity); auto bg = myrtlrect(mainMenuRight, 0, width() - mainMenuRight, height()); - p.fillRect(bg, st::layerBg); - if (mainMenuRight > 0) { - _shadow.paint(p, myrtlrect(0, 0, mainMenuRight, height()), 0, Ui::RectShadow::Side::Right); - } - if (!specialLayerBox.isEmpty()) { - p.setClipRegion(QRegion(bg) - specialLayerBox); - _shadow.paint(p, specialLayerBox, st::boxShadowShift); + + if (_mainMenuCache.isNull() && mainMenuRight > 0) { + // All cache images are taken together with their shadows, + // so we paint shadow only when there is no cache. + Ui::Shadow::paint(p, myrtlrect(0, 0, mainMenuRight, height()), width(), st::boxRoundShadow, Ui::Shadow::Side::Right); + } + + if (_specialLayerCache.isNull() && !specialLayerBox.isEmpty()) { + // All cache images are taken together with their shadows, + // so we paint shadow only when there is no cache. + auto sides = Ui::Shadow::Side::Left | Ui::Shadow::Side::Right; + auto topCorners = (specialLayerBox.y() > 0); + auto bottomCorners = (specialLayerBox.y() + specialLayerBox.height() < height()); + if (topCorners) { + sides |= Ui::Shadow::Side::Top; + } + if (bottomCorners) { + sides |= Ui::Shadow::Side::Bottom; + } + if (topCorners || bottomCorners) { + p.setClipRegion(QRegion(rect()) - specialLayerBox.marginsRemoved(QMargins(st::boxRadius, 0, st::boxRadius, 0)) - specialLayerBox.marginsRemoved(QMargins(0, st::boxRadius, 0, st::boxRadius))); + } + Ui::Shadow::paint(p, specialLayerBox, width(), st::boxRoundShadow, sides); + + if (topCorners || bottomCorners) { + // In case of painting the shadow above the special layer we get + // glitches in the corners, so we need to paint the corners once more. + p.setClipping(false); + auto parts = (topCorners ? (App::RectPart::TopLeft | App::RectPart::TopRight) : App::RectPart::None) + | (bottomCorners ? (App::RectPart::BottomLeft | App::RectPart::BottomRight) : App::RectPart::None); + App::roundRect(p, specialLayerBox, st::boxBg, BoxCorners, nullptr, parts); + } + } + + if (!layerBox.isEmpty() && !_specialLayerCache.isNull() && overSpecialOpacity < bgOpacity) { + // In case of moving special layer below the background while showing a box + // we need to fill special layer rect below its cache with a complex opacity + // (alpha_final - alpha_current) / (1 - alpha_current) so we won't get glitches + // in the transparent special layer cache corners after filling special layer + // rect above its cache with alpha_current opacity. + auto region = QRegion(bg) - specialLayerBox; + for_const (auto rect, region.rects()) { + p.fillRect(rect, st::layerBg); + } + p.setOpacity((bgOpacity - overSpecialOpacity) / (1. - (overSpecialOpacity * st::layerBg->c.alphaF()))); + p.fillRect(specialLayerBox, st::layerBg); + p.setOpacity(bgOpacity); + } else { + p.fillRect(bg, st::layerBg); } - p.setClipping(false); if (!_specialLayerCache.isNull() && specialLayerOpacity > 0) { p.setOpacity(specialLayerOpacity); - p.drawPixmap(specialLayerBox.topLeft(), _specialLayerCache); + auto cacheLeft = specialLayerBox.x() - st::boxRoundShadow.extend.left(); + auto cacheTop = specialLayerBox.y() - (specialLayerBox.y() > 0 ? st::boxRoundShadow.extend.top() : 0); + p.drawPixmapLeft(cacheLeft, cacheTop, width(), _specialLayerCache); } if (!layerBox.isEmpty()) { if (!_specialLayerCache.isNull()) { - p.setOpacity(layerOpacity * specialLayerOpacity); - p.setClipRegion(QRegion(specialLayerBox) - layerBox); + p.setOpacity(overSpecialOpacity); p.fillRect(specialLayerBox, st::layerBg); } - p.setOpacity(layerOpacity); - p.setClipRegion(QRegion(bg) - layerBox); - _shadow.paint(p, layerBox, st::boxShadowShift); - p.setClipping(false); + if (_layerCache.isNull()) { + p.setOpacity(layerOpacity); + Ui::Shadow::paint(p, layerBox, width(), st::boxRoundShadow); + } } if (!_layerCache.isNull() && layerOpacity > 0) { p.setOpacity(layerOpacity); - p.drawPixmap(layerBox.topLeft(), _layerCache); + p.drawPixmapLeft(layerBox.topLeft() - QPoint(st::boxRoundShadow.extend.left(), st::boxRoundShadow.extend.top()), width(), _layerCache); } if (!_mainMenuCache.isNull() && mainMenuRight > 0) { p.setOpacity(1.); - auto shownWidth = mainMenuRight * cIntRetinaFactor(); - auto shownRect = rtlrect(_mainMenuCache.width() - shownWidth, 0, shownWidth, _mainMenuCache.height(), _mainMenuCache.width()); - p.drawPixmapLeft(0, 0, mainMenuRight, height(), width(), _mainMenuCache, shownRect); + auto shownWidth = mainMenuRight + st::boxRoundShadow.extend.right(); + auto sourceWidth = shownWidth * cIntRetinaFactor(); + auto sourceRect = rtlrect(_mainMenuCache.width() - sourceWidth, 0, sourceWidth, _mainMenuCache.height(), _mainMenuCache.width()); + p.drawPixmapLeft(0, 0, shownWidth, height(), width(), _mainMenuCache, sourceRect); } } @@ -277,6 +324,23 @@ void LayerWidget::setInnerFocus() { } } +bool LayerWidget::overlaps(const QRect &globalRect) { + if (isHidden()) { + return false; + } + auto testRect = QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size()); + if (testAttribute(Qt::WA_OpaquePaintEvent)) { + return rect().contains(testRect); + } + if (QRect(0, st::boxRadius, width(), height() - 2 * st::boxRadius).contains(testRect)) { + return true; + } + if (QRect(st::boxRadius, 0, width() - 2 * st::boxRadius, height()).contains(testRect)) { + return true; + } + return false; +} + void LayerStackWidget::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Escape) { hideCurrent(); @@ -300,11 +364,23 @@ void LayerStackWidget::hideLayers() { void LayerStackWidget::hideAll() { startAnimation([] {}, [this] { clearLayers(); - _specialLayer.destroyDelayed(); + clearSpecialLayer(); _mainMenu.destroyDelayed(); }, Action::HideAll); } +void LayerStackWidget::hideTopLayer() { + if (_specialLayer) { + hideLayers(); + } else { + hideAll(); + } +} + +bool LayerStackWidget::layerShown() const { + return _specialLayer || currentLayer(); +} + void LayerStackWidget::setCacheImages() { auto bodyCache = QPixmap(), mainMenuCache = QPixmap(); if (isAncestorOf(App::wnd()->focusWidget())) { @@ -315,12 +391,22 @@ void LayerStackWidget::setCacheImages() { hideChildren(); bodyCache = myGrab(App::wnd()->bodyWidget()); showChildren(); - mainMenuCache = myGrab(_mainMenu); + mainMenuCache = Ui::Shadow::grab(_mainMenu, st::boxRoundShadow, Ui::Shadow::Side::Right); + } + auto specialLayerCache = QPixmap(); + if (_specialLayer) { + auto sides = Ui::Shadow::Side::Left | Ui::Shadow::Side::Right; + if (_specialLayer->y() > 0) { + sides |= Ui::Shadow::Side::Top; + } + if (_specialLayer->y() + _specialLayer->height() < height()) { + sides |= Ui::Shadow::Side::Bottom; + } + specialLayerCache = Ui::Shadow::grab(_specialLayer, st::boxRoundShadow, sides); } - auto specialLayerCache = _specialLayer ? myGrab(_specialLayer) : QPixmap(); auto layerCache = QPixmap(); if (auto layer = currentLayer()) { - layerCache = myGrab(layer); + layerCache = Ui::Shadow::grab(layer, st::boxRoundShadow); } setAttribute(Qt::WA_OpaquePaintEvent, !bodyCache.isNull()); updateLayerBoxes(); @@ -328,6 +414,7 @@ void LayerStackWidget::setCacheImages() { } void LayerStackWidget::onLayerClosed(LayerWidget *layer) { + layer->closing(); layer->deleteLater(); if (layer == _specialLayer) { hideAll(); @@ -430,12 +517,13 @@ void LayerStackWidget::resizeEvent(QResizeEvent *e) { updateLayerBoxes(); } -void LayerStackWidget::showLayer(LayerWidget *layer) { - appendLayer(layer); - while (!_layers.isEmpty() && _layers.front() != layer) { +void LayerStackWidget::showBox(object_ptr box) { + auto pointer = pushBox(std_::move(box)); + while (!_layers.isEmpty() && _layers.front() != pointer) { auto removingLayer = _layers.front(); _layers.pop_front(); + removingLayer->closing(); removingLayer->hide(); removingLayer->deleteLater(); } @@ -496,10 +584,10 @@ void LayerStackWidget::showFinished() { } } -void LayerStackWidget::showSpecialLayer(LayerWidget *layer) { - startAnimation([this, layer] { +void LayerStackWidget::showSpecialLayer(object_ptr layer) { + startAnimation([this, layer = std_::move(layer)]() mutable { _specialLayer.destroyDelayed(); - _specialLayer = layer; + _specialLayer = std_::move(layer); initChildLayer(_specialLayer); }, [this] { clearLayers(); @@ -518,11 +606,16 @@ void LayerStackWidget::showMainMenu() { }, Action::ShowMainMenu); } -void LayerStackWidget::appendLayer(LayerWidget *layer) { +void LayerStackWidget::appendBox(object_ptr box) { + pushBox(std_::move(box)); +} + +LayerWidget *LayerStackWidget::pushBox(object_ptr box) { auto oldLayer = currentLayer(); if (oldLayer) { oldLayer->hide(); } + auto layer = object_ptr(std_::move(box)); _layers.push_back(layer); initChildLayer(layer); @@ -536,12 +629,15 @@ void LayerStackWidget::appendLayer(LayerWidget *layer) { _mainMenu.destroyDelayed(); }, Action::ShowLayer); } + + return layer.data(); } -void LayerStackWidget::prependLayer(LayerWidget *layer) { +void LayerStackWidget::prependBox(object_ptr box) { if (_layers.empty()) { - return showLayer(layer); + return showBox(std_::move(box)); } + auto layer = object_ptr(std_::move(box)); layer->hide(); _layers.push_front(layer); initChildLayer(layer); @@ -549,15 +645,23 @@ void LayerStackWidget::prependLayer(LayerWidget *layer) { void LayerStackWidget::clearLayers() { for (auto layer : base::take(_layers)) { + layer->closing(); layer->hide(); layer->deleteLater(); } } +void LayerStackWidget::clearSpecialLayer() { + if (_specialLayer) { + _specialLayer->closing(); + _specialLayer.destroyDelayed(); + } +} + void LayerStackWidget::initChildLayer(LayerWidget *layer) { layer->setParent(this); - connect(layer, SIGNAL(closed(LayerWidget*)), this, SLOT(onLayerClosed(LayerWidget*))); - connect(layer, SIGNAL(resized()), this, SLOT(onLayerResized())); + layer->setClosedCallback([this, layer] { onLayerClosed(layer); }); + layer->setResizedCallback([this] { onLayerResized(); }); connect(layer, SIGNAL(destroyed(QObject*)), this, SLOT(onLayerDestroyed(QObject*))); layer->parentResized(); } diff --git a/Telegram/SourceFiles/layerwidget.h b/Telegram/SourceFiles/layerwidget.h index b42773d27..1067c46d4 100644 --- a/Telegram/SourceFiles/layerwidget.h +++ b/Telegram/SourceFiles/layerwidget.h @@ -24,8 +24,6 @@ namespace Window { class MainMenu; } // namespace Window -#include "ui/effects/rect_shadow.h" - class LayerWidget : public TWidget { Q_OBJECT @@ -36,26 +34,46 @@ public: virtual void showFinished() { } void setInnerFocus(); + void closing() { + if (!_closing) { + _closing = true; + closeHook(); + } + } - bool overlaps(const QRect &globalRect) { - if (isHidden() || !testAttribute(Qt::WA_OpaquePaintEvent)) return false; - return rect().contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size())); + bool overlaps(const QRect &globalRect); + + void setClosedCallback(base::lambda &&callback) { + _closedCallback = std_::move(callback); + } + void setResizedCallback(base::lambda &&callback) { + _resizedCallback = std_::move(callback); } protected: + void closeLayer() { + if (_closedCallback) { + _closedCallback(); + } + } void mousePressEvent(QMouseEvent *e) override { e->accept(); } void resizeEvent(QResizeEvent *e) override { - emit resized(); + if (_resizedCallback) { + _resizedCallback(); + } } virtual void doSetInnerFocus() { setFocus(); } + virtual void closeHook() { + } -signals: - void closed(LayerWidget *layer); - void resized(); +private: + bool _closing = false; + base::lambda _closedCallback; + base::lambda _resizedCallback; }; @@ -67,11 +85,11 @@ public: void finishAnimation(); - void showLayer(LayerWidget *layer); - void showSpecialLayer(LayerWidget *layer); + void showBox(object_ptr box); + void showSpecialLayer(object_ptr layer); void showMainMenu(); - void appendLayer(LayerWidget *layer); - void prependLayer(LayerWidget *layer); + void appendBox(object_ptr box); + void prependBox(object_ptr box); bool canSetFocus() const; void setInnerFocus(); @@ -80,6 +98,9 @@ public: void hideLayers(); void hideAll(); + void hideTopLayer(); + + bool layerShown() const; ~LayerStackWidget(); @@ -94,6 +115,7 @@ private slots: void onLayerResized(); private: + LayerWidget *pushBox(object_ptr box); void showFinished(); void hideCurrent(); @@ -112,6 +134,7 @@ private: void setCacheImages(); void clearLayers(); + void clearSpecialLayer(); void initChildLayer(LayerWidget *layer); void updateLayerBoxes(); void fixOrder(); @@ -127,11 +150,11 @@ private: using Layers = QList; Layers _layers; - ChildWidget _specialLayer = { nullptr }; - ChildWidget _mainMenu = { nullptr }; + object_ptr _specialLayer = { nullptr }; + object_ptr _mainMenu = { nullptr }; class BackgroundWidget; - ChildWidget _background; + object_ptr _background; }; @@ -141,15 +164,16 @@ class MediaPreviewWidget : public TWidget, private base::Subscriber { public: MediaPreviewWidget(QWidget *parent); - void paintEvent(QPaintEvent *e); - void resizeEvent(QResizeEvent *e); - void showPreview(DocumentData *document); void showPreview(PhotoData *photo); void hidePreview(); ~MediaPreviewWidget(); +protected: + void paintEvent(QPaintEvent *e) override; + void resizeEvent(QResizeEvent *e) override; + private: QSize currentDimensions() const; QPixmap currentImage() const; diff --git a/Telegram/SourceFiles/layout.h b/Telegram/SourceFiles/layout.h index 72a1b2a3d..d828a80e9 100644 --- a/Telegram/SourceFiles/layout.h +++ b/Telegram/SourceFiles/layout.h @@ -36,6 +36,7 @@ enum RoundCorners { SmallMaskCorners = 0x00, // for images LargeMaskCorners, + BoxCorners, MenuCorners, BotKbOverCorners, StickerCorners, diff --git a/Telegram/SourceFiles/localimageloader.cpp b/Telegram/SourceFiles/localimageloader.cpp index f3bfe166a..35f4bb73d 100644 --- a/Telegram/SourceFiles/localimageloader.cpp +++ b/Telegram/SourceFiles/localimageloader.cpp @@ -250,15 +250,26 @@ void FileLoadTask::process() { filename = filedialogDefaultName(qsl("file"), ext, QString(), true); } } - } else if (!fullimage.isNull()) { - filemime = mimeTypeForName("image/png").name(); - filename = filedialogDefaultName(qsl("image"), qsl(".png"), QString(), true); - { - QBuffer buffer(&_content); - fullimage.save(&buffer, "PNG"); + } else if (!fullimage.isNull() && fullimage.width() > 0) { + if (_type == SendMediaType::Photo) { + auto w = fullimage.width(), h = fullimage.height(); + if (w >= 20 * h || h >= 20 * w) { + _type = SendMediaType::File; + } else { + filesize = -1; // Fill later. + filemime = mimeTypeForName("image/jpeg").name(); + filename = filedialogDefaultName(qsl("image"), qsl(".jpg"), QString(), true); + } + } + if (_type == SendMediaType::File) { + filemime = mimeTypeForName("image/png").name(); + filename = filedialogDefaultName(qsl("image"), qsl(".png"), QString(), true); + { + QBuffer buffer(&_content); + fullimage.save(&buffer, "PNG"); + } + filesize = _content.size(); } - filesize = _content.size(); - fullimage = Images::prepareOpaque(std_::move(fullimage)); } _result->filesize = (int32)qMin(filesize, qint64(INT_MAX)); @@ -367,6 +378,10 @@ void FileLoadTask::process() { MTPDphoto::Flags photoFlags = 0; photo = MTP_photo(MTP_flags(photoFlags), MTP_long(_id), MTP_long(0), MTP_int(unixtime()), MTP_vector(photoSizes)); + + if (filesize < 0) { + filesize = _result->filesize = filedata.size(); + } } QByteArray thumbFormat = "JPG"; @@ -396,11 +411,9 @@ void FileLoadTask::process() { attributes[0] = MTP_documentAttributeAudio(MTP_flags(MTPDdocumentAttributeAudio::Flag::f_voice | MTPDdocumentAttributeAudio::Flag::f_waveform), MTP_int(_duration), MTPstring(), MTPstring(), MTP_bytes(documentWaveformEncode5bit(_waveform))); attributes.resize(1); document = MTP_document(MTP_long(_id), MTP_long(0), MTP_int(unixtime()), MTP_string(filemime), MTP_int(filesize), thumbSize, MTP_int(MTP::maindc()), MTP_int(0), MTP_vector(attributes)); - } else { + } else if (_type != SendMediaType::Photo) { document = MTP_document(MTP_long(_id), MTP_long(0), MTP_int(unixtime()), MTP_string(filemime), MTP_int(filesize), thumbSize, MTP_int(MTP::maindc()), MTP_int(0), MTP_vector(attributes)); - if (photo.type() == mtpc_photoEmpty) { - _type = SendMediaType::File; - } + _type = SendMediaType::File; } _result->type = _type; @@ -423,11 +436,11 @@ void FileLoadTask::process() { void FileLoadTask::finish() { if (!_result || !_result->filesize) { - Ui::showLayer(new InformBox(lng_send_image_empty(lt_name, _filepath)), KeepOtherLayers); + Ui::show(Box(lng_send_image_empty(lt_name, _filepath)), KeepOtherLayers); } else if (_result->filesize == -1) { // dir - Ui::showLayer(new InformBox(lng_send_folder(lt_name, QFileInfo(_filepath).dir().dirName())), KeepOtherLayers); + Ui::show(Box(lng_send_folder(lt_name, QFileInfo(_filepath).dir().dirName())), KeepOtherLayers); } else if (_result->filesize > App::kFileSizeLimit) { - Ui::showLayer(new InformBox(lng_send_image_too_large(lt_name, _filepath)), KeepOtherLayers); + Ui::show(Box(lng_send_image_too_large(lt_name, _filepath)), KeepOtherLayers); } else if (App::main()) { App::main()->onSendFileConfirm(_result); } diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index a29cd64f9..ca6048190 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -177,7 +177,7 @@ MainWidget::MainWidget(QWidget *parent) : TWidget(parent) bool MainWidget::onForward(const PeerId &peer, ForwardWhatMessages what) { PeerData *p = App::peer(peer); if (!peer || (p->isChannel() && !p->asChannel()->canPublish() && p->asChannel()->isBroadcast()) || (p->isChat() && !p->asChat()->canWrite()) || (p->isUser() && p->asUser()->access == UserNoAccess)) { - Ui::showLayer(new InformBox(lang(lng_forward_cant))); + Ui::show(Box(lang(lng_forward_cant))); return false; } _history->cancelReply(); @@ -212,7 +212,7 @@ bool MainWidget::onForward(const PeerId &peer, ForwardWhatMessages what) { bool MainWidget::onShareUrl(const PeerId &peer, const QString &url, const QString &text) { PeerData *p = App::peer(peer); if (!peer || (p->isChannel() && !p->asChannel()->canPublish() && p->asChannel()->isBroadcast()) || (p->isChat() && !p->asChat()->canWrite()) || (p->isUser() && p->asUser()->access == UserNoAccess)) { - Ui::showLayer(new InformBox(lang(lng_share_cant))); + Ui::show(Box(lang(lng_share_cant))); return false; } History *h = App::history(peer); @@ -232,7 +232,7 @@ bool MainWidget::onShareUrl(const PeerId &peer, const QString &url, const QStrin bool MainWidget::onInlineSwitchChosen(const PeerId &peer, const QString &botAndQuery) { PeerData *p = App::peer(peer); if (!peer || (p->isChannel() && !p->asChannel()->canPublish() && p->asChannel()->isBroadcast()) || (p->isChat() && !p->asChat()->canWrite()) || (p->isUser() && p->asUser()->access == UserNoAccess)) { - Ui::showLayer(new InformBox(lang(lng_inline_switch_cant))); + Ui::show(Box(lang(lng_inline_switch_cant))); return false; } History *h = App::history(peer); @@ -591,8 +591,8 @@ void MainWidget::noHider(HistoryHider *destroyed) { _hider = nullptr; if (Adaptive::OneColumn()) { if (_forwardConfirm) { - _forwardConfirm->onClose(); - _forwardConfirm = 0; + _forwardConfirm->closeBox(); + _forwardConfirm = nullptr; } onHistoryShown(_history->history(), _history->msgId()); if (_wideSection || _overview || (_history->peer() && _history->peer()->id)) { @@ -616,19 +616,18 @@ void MainWidget::noHider(HistoryHider *destroyed) { } else { if (_forwardConfirm) { _forwardConfirm->deleteLater(); - _forwardConfirm = 0; + _forwardConfirm = nullptr; } } } } -void MainWidget::hiderLayer(HistoryHider *h) { +void MainWidget::hiderLayer(object_ptr h) { if (App::passcoded()) { - delete h; return; } - _hider = h; + _hider = std_::move(h); connect(_hider, SIGNAL(forwarded()), _dialogs, SLOT(onCancelSearch())); if (Adaptive::OneColumn()) { dialogsToUp(); @@ -657,66 +656,76 @@ void MainWidget::hiderLayer(HistoryHider *h) { } void MainWidget::forwardLayer(int32 forwardSelected) { - hiderLayer((forwardSelected < 0) ? (new HistoryHider(this)) : (new HistoryHider(this, forwardSelected > 0))); + hiderLayer((forwardSelected < 0) ? object_ptr(this) : object_ptr(this, forwardSelected > 0)); } void MainWidget::deleteLayer(int32 selectedCount) { if (selectedCount == -1 && !_overview) { if (HistoryItem *item = App::contextItem()) { if (item->suggestBanReportDeleteAll()) { - Ui::showLayer(new RichDeleteMessageBox(item->history()->peer->asChannel(), item->from()->asUser(), item->id)); + Ui::show(Box(item->history()->peer->asChannel(), item->from()->asUser(), item->id)); return; } } } - QString str((selectedCount < 0) ? lang(selectedCount < -1 ? lng_selected_cancel_sure_this : lng_selected_delete_sure_this) : lng_selected_delete_sure(lt_count, selectedCount)); - QString btn(lang((selectedCount < -1) ? lng_selected_upload_stop : lng_box_delete)), cancel(lang((selectedCount < -1) ? lng_continue : lng_cancel)); - ConfirmBox *box = new ConfirmBox(str, btn, st::defaultBoxButton, cancel); - if (selectedCount < 0) { - if (selectedCount < -1) { - if (HistoryItem *item = App::contextItem()) { - App::uploader()->pause(item->fullId()); - connect(box, SIGNAL(destroyed(QObject*)), App::uploader(), SLOT(unpause())); + auto text = (selectedCount < 0) ? lang(selectedCount < -1 ? lng_selected_cancel_sure_this : lng_selected_delete_sure_this) : lng_selected_delete_sure(lt_count, selectedCount); + auto confirmText = lang((selectedCount < -1) ? lng_selected_upload_stop : lng_box_delete); + auto cancelText = lang((selectedCount < -1) ? lng_continue : lng_cancel); + if (selectedCount < -1) { + if (auto item = App::contextItem()) { + App::uploader()->pause(item->fullId()); + } + } + Ui::show(Box(text, confirmText, cancelText, base::lambda_guarded(this, [this, selectedCount] { + if (selectedCount < 0) { + if (_overview) { + _overview->onDeleteContextSure(); + } else { + _history->onDeleteContextSure(); + } + if (selectedCount < -1) { + App::uploader()->unpause(); + } + } else { + if (_overview) { + _overview->onDeleteSelectedSure(); + } else { + _history->onDeleteSelectedSure(); } } - connect(box, SIGNAL(confirmed()), _overview ? static_cast(_overview) : static_cast(_history), SLOT(onDeleteContextSure())); - } else { - connect(box, SIGNAL(confirmed()), _overview ? static_cast(_overview) : static_cast(_history), SLOT(onDeleteSelectedSure())); - } - Ui::showLayer(box); + }), base::lambda_guarded(this, [selectedCount] { + if (selectedCount < -1) { + App::uploader()->unpause(); + } + }))); } void MainWidget::deletePhotoLayer(PhotoData *photo) { - _deletingPhoto = photo; - auto box = new ConfirmBox(lang(lng_delete_photo_sure), lang(lng_box_delete)); - connect(box, SIGNAL(confirmed()), this, SLOT(onDeletePhotoSure())); - Ui::showLayer(box); -} + if (!photo) return; + Ui::show(Box(lang(lng_delete_photo_sure), lang(lng_box_delete), base::lambda_guarded(this, [this, photo] { + Ui::hideLayer(); -void MainWidget::onDeletePhotoSure() { - Ui::hideLayer(); + auto me = App::self(); + if (!me) return; - auto me = App::self(); - auto photo = _deletingPhoto; - if (!photo || !me) return; - - if (me->photoId == photo->id) { - App::app()->peerClearPhoto(me->id); - } else if (photo->peer && !photo->peer->isUser() && photo->peer->photoId == photo->id) { - App::app()->peerClearPhoto(photo->peer->id); - } else { - for (int i = 0, l = me->photos.size(); i != l; ++i) { - if (me->photos.at(i) == photo) { - me->photos.removeAt(i); - MTP::send(MTPphotos_DeletePhotos(MTP_vector(1, MTP_inputPhoto(MTP_long(photo->id), MTP_long(photo->access))))); - break; + if (me->photoId == photo->id) { + App::app()->peerClearPhoto(me->id); + } else if (photo->peer && !photo->peer->isUser() && photo->peer->photoId == photo->id) { + App::app()->peerClearPhoto(photo->peer->id); + } else { + for (int i = 0, l = me->photos.size(); i != l; ++i) { + if (me->photos.at(i) == photo) { + me->photos.removeAt(i); + MTP::send(MTPphotos_DeletePhotos(MTP_vector(1, MTP_inputPhoto(MTP_long(photo->id), MTP_long(photo->access))))); + break; + } } } - } + }))); } void MainWidget::shareContactLayer(UserData *contact) { - hiderLayer(new HistoryHider(this, contact)); + hiderLayer(object_ptr(this, contact)); } void MainWidget::shareUrlLayer(const QString &url, const QString &text) { @@ -724,11 +733,11 @@ void MainWidget::shareUrlLayer(const QString &url, const QString &text) { if (url.trimmed().startsWith('@')) { return; } - hiderLayer(new HistoryHider(this, url, text)); + hiderLayer(object_ptr(this, url, text)); } void MainWidget::inlineSwitchLayer(const QString &botAndQuery) { - hiderLayer(new HistoryHider(this, botAndQuery)); + hiderLayer(object_ptr(this, botAndQuery)); } bool MainWidget::selectingPeer(bool withConfirm) { @@ -742,21 +751,13 @@ bool MainWidget::selectingPeerForInlineSwitch() { void MainWidget::offerPeer(PeerId peer) { Ui::hideLayer(); if (_hider->offerPeer(peer) && Adaptive::OneColumn()) { - _forwardConfirm = new ConfirmBox(_hider->offeredText(), lang(lng_forward_send)); - connect(_forwardConfirm, SIGNAL(confirmed()), _hider, SLOT(forward())); - connect(_forwardConfirm, SIGNAL(cancelled()), this, SLOT(onForwardCancel())); - connect(_forwardConfirm, SIGNAL(destroyed(QObject*)), this, SLOT(onForwardCancel(QObject*))); - Ui::showLayer(_forwardConfirm); - } -} - -void MainWidget::onForwardCancel(QObject *obj) { - if (!obj || obj == _forwardConfirm) { - if (_forwardConfirm) { - if (!obj) _forwardConfirm->onClose(); - _forwardConfirm = 0; - } - if (_hider) _hider->offerPeer(0); + _forwardConfirm = Ui::show(Box(_hider->offeredText(), lang(lng_forward_send), base::lambda_guarded(this, [this] { + _hider->forward(); + if (_forwardConfirm) _forwardConfirm->closeBox(); + if (_hider) _hider->offerPeer(0); + }), base::lambda_guarded(this, [this] { + if (_hider && _forwardConfirm) _hider->offerPeer(0); + }))); } } @@ -953,7 +954,7 @@ bool MainWidget::addParticipantFail(UserData *user, const RPCError &error) { } else if (error.type() == qstr("PEER_FLOOD")) { text = cantInviteError(); } - Ui::showLayer(new InformBox(text)); + Ui::show(Box(text)); return false; } @@ -971,7 +972,7 @@ bool MainWidget::addParticipantsFail(ChannelData *channel, const RPCError &error } else if (error.type() == qstr("PEER_FLOOD")) { text = cantInviteError(); } - Ui::showLayer(new InformBox(text)); + Ui::show(Box(text)); return false; } @@ -1059,7 +1060,7 @@ bool MainWidget::sendMessageFail(const RPCError &error) { if (MTP::isDefaultHandledError(error)) return false; if (error.type() == qstr("PEER_FLOOD")) { - Ui::showLayer(new InformBox(cantInviteError())); + Ui::show(Box(cantInviteError())); return true; } return false; @@ -1526,29 +1527,6 @@ void MainWidget::messagesAffected(PeerData *peer, const MTPmessages_AffectedMess } } -void MainWidget::loadFailed(mtpFileLoader *loader, bool started, const char *retrySlot) { - failedObjId = loader->objId(); - failedFileName = loader->fileName(); - ConfirmBox *box = new ConfirmBox(lang(started ? lng_download_finish_failed : lng_download_path_failed), started ? QString() : lang(lng_download_path_settings)); - if (started) { - connect(box, SIGNAL(confirmed()), this, retrySlot); - } else { - connect(box, SIGNAL(confirmed()), this, SLOT(onDownloadPathSettings())); - } - Ui::showLayer(box); -} - -void MainWidget::onDownloadPathSettings() { - Global::SetDownloadPath(QString()); - Global::SetDownloadPathBookmark(QByteArray()); - Ui::showLayer(new DownloadPathBox()); - Global::RefDownloadPathChanged().notify(); -} - -void MainWidget::onSharePhoneWithBot(PeerData *recipient) { - onShareContact(recipient->id, App::self()); -} - void MainWidget::ui_showPeerHistoryAsync(quint64 peerId, qint32 showAtMsgId, Ui::ShowWay way) { Ui::showPeerHistory(peerId, showAtMsgId, way); } @@ -1719,20 +1697,28 @@ void MainWidget::documentLoadFailed(FileLoader *loader, bool started) { mtpFileLoader *l = loader ? loader->mtpLoader() : 0; if (!l) return; - loadFailed(l, started, SLOT(documentLoadRetry())); - DocumentData *document = App::document(l->objId()); + auto document = App::document(l->objId()); + if (started) { + auto failedFileName = l->fileName(); + Ui::show(Box(lang(lng_download_finish_failed), base::lambda_guarded(this, [this, document, failedFileName] { + Ui::hideLayer(); + if (document) document->save(failedFileName); + }))); + } else { + Ui::show(Box(lang(lng_download_path_failed), lang(lng_download_path_settings), base::lambda_guarded(this, [this] { + Global::SetDownloadPath(QString()); + Global::SetDownloadPathBookmark(QByteArray()); + Ui::show(Box()); + Global::RefDownloadPathChanged().notify(); + }))); + } + if (document) { if (document->loading()) document->cancel(); document->status = FileDownloadFailed; } } -void MainWidget::documentLoadRetry() { - Ui::hideLayer(); - DocumentData *document = App::document(failedObjId); - if (document) document->save(failedFileName); -} - void MainWidget::inlineResultLoadProgress(FileLoader *loader) { //InlineBots::Result *result = InlineBots::resultFromLoader(loader); //if (!result) return; @@ -1956,9 +1942,9 @@ void MainWidget::setInnerFocus() { if (_hider || !_history->peer()) { if (_hider && _hider->wasOffered()) { _hider->setFocus(); - } else if (_overview) { + } else if (!_hider && _overview) { _overview->activate(); - } else if (_wideSection) { + } else if (!_hider && _wideSection) { _wideSection->setInnerFocus(); } else { dialogsActivate(); @@ -2034,14 +2020,13 @@ void MainWidget::fillPeerMenu(PeerData *peer, base::lambdaisUser() ? lng_sure_delete_history(lt_contact, peer->name) : lng_sure_delete_group_history(lt_group, peer->name), lang(lng_box_delete), st::attentionBoxButton); - box->setConfirmedCallback([peer] { + auto text = peer->isUser() ? lng_sure_delete_history(lt_contact, peer->name) : lng_sure_delete_group_history(lt_group, peer->name); + Ui::show(Box(text, lang(lng_box_delete), st::attentionBoxButton, [peer] { if (!App::main()) return; Ui::hideLayer(); App::main()->clearHistory(peer); - }); - Ui::showLayer(box); + })); }; auto deleteAndLeaveHandler = [peer] { auto warningText = peer->isUser() ? lng_sure_delete_history(lt_contact, peer->name) : @@ -2049,8 +2034,7 @@ void MainWidget::fillPeerMenu(PeerData *peer, base::lambdaisMegagroup() ? lng_sure_leave_group : lng_sure_leave_channel); auto confirmText = lang(peer->isUser() ? lng_box_delete : lng_box_leave); auto &confirmStyle = peer->isChannel() ? st::defaultBoxButton : st::attentionBoxButton; - auto box = new ConfirmBox(warningText, confirmText, confirmStyle); - box->setConfirmedCallback([peer] { + Ui::show(Box(warningText, confirmText, confirmStyle, [peer] { if (!App::main()) return; Ui::hideLayer(); @@ -2065,8 +2049,7 @@ void MainWidget::fillPeerMenu(PeerData *peer, base::lambdaasChannel()->inputChannel), App::main()->rpcDone(&MainWidget::sentUpdatesReceived)); } - }); - Ui::showLayer(box); + })); }; if (auto user = peer->asUser()) { callback(lang(lng_profile_delete_conversation), std_::move(deleteAndLeaveHandler)); @@ -2204,7 +2187,7 @@ void MainWidget::ui_showPeerHistory(quint64 peerId, qint32 showAtMsgId, Ui::Show QString restriction = peer->restrictionReason(); if (!restriction.isEmpty()) { Ui::showChatsList(); - Ui::showLayer(new InformBox(restriction)); + Ui::show(Box(restriction)); return; } } @@ -2422,7 +2405,7 @@ void MainWidget::showMediaOverview(PeerData *peer, MediaOverviewType type, bool _wideSection->deleteLater(); _wideSection = nullptr; } - _overview = new OverviewWidget(this, peer, type); + _overview.create(this, peer, type); _mediaTypeMask = 0; _topBar->show(); resizeEvent(nullptr); @@ -2449,9 +2432,7 @@ void MainWidget::showWideSection(const Window::SectionMemento &memento) { if (_wideSection && _wideSection->showInternal(&memento)) { return; } - - saveSectionInStack(); - showWideSectionAnimated(&memento, false); + showWideSectionAnimated(&memento, false, true); } Window::SectionSlideParams MainWidget::prepareShowAnimation(bool willHaveTopBarShadow) { @@ -2538,13 +2519,16 @@ Window::SectionSlideParams MainWidget::prepareDialogsAnimation() { return prepareShowAnimation(false); } -void MainWidget::showWideSectionAnimated(const Window::SectionMemento *memento, bool back) { +void MainWidget::showWideSectionAnimated(const Window::SectionMemento *memento, bool back, bool saveInStack) { QPixmap animCache; auto newWideGeometry = QRect(_history->x(), _playerHeight, _history->width(), height() - _playerHeight); auto newWideSection = memento->createWidget(this, newWideGeometry); Window::SectionSlideParams animationParams = prepareWideSectionAnimation(newWideSection); + if (saveInStack) { + saveSectionInStack(); + } if (_overview) { _overview->hide(); _overview->clear(); @@ -2557,7 +2541,7 @@ void MainWidget::showWideSectionAnimated(const Window::SectionMemento *memento, _wideSection->deleteLater(); _wideSection = nullptr; } - _wideSection = newWideSection; + _wideSection = std_::move(newWideSection); _topBar->hide(); resizeEvent(0); auto direction = back ? Window::SlideDirection::FromLeft : Window::SlideDirection::FromRight; @@ -2603,7 +2587,7 @@ void MainWidget::showBackFromStack() { _history->setReplyReturns(histItem->peer->id, histItem->replyReturns); } else if (item->type() == SectionStackItem) { StackItemSection *sectionItem = static_cast(item.get()); - showWideSectionAnimated(sectionItem->memento(), true); + showWideSectionAnimated(sectionItem->memento(), true, false); } else if (item->type() == OverviewStackItem) { StackItemOverview *overItem = static_cast(item.get()); showMediaOverview(overItem->peer, overItem->mediaType, true, overItem->lastScrollTop); @@ -2707,7 +2691,7 @@ bool MainWidget::deleteChannelFailed(const RPCError &error) { if (MTP::isDefaultHandledError(error)) return false; //if (error.type() == qstr("CHANNEL_TOO_LARGE")) { - // Ui::showLayer(new InformBox(lang(lng_cant_delete_channel))); + // Ui::show(Box(lang(lng_cant_delete_channel))); //} return true; @@ -2811,17 +2795,20 @@ void MainWidget::hideAll() { void MainWidget::showAll() { if (cPasswordRecovered()) { cSetPasswordRecovered(false); - Ui::showLayer(new InformBox(lang(lng_signin_password_removed))); + Ui::show(Box(lang(lng_signin_password_removed))); } if (Adaptive::OneColumn()) { _sideShadow->hide(); if (_hider) { _hider->hide(); if (!_forwardConfirm && _hider->wasOffered()) { - _forwardConfirm = new ConfirmBox(_hider->offeredText(), lang(lng_forward_send)); - connect(_forwardConfirm, SIGNAL(confirmed()), _hider, SLOT(forward())); - connect(_forwardConfirm, SIGNAL(cancelled()), this, SLOT(onForwardCancel())); - Ui::showLayer(_forwardConfirm, ForceFastShowLayer); + _forwardConfirm = Ui::show(Box(_hider->offeredText(), lang(lng_forward_send), base::lambda_guarded(this, [this] { + _hider->forward(); + if (_forwardConfirm) _forwardConfirm->closeBox(); + if (_hider) _hider->offerPeer(0); + }), base::lambda_guarded(this, [this] { + if (_hider && _forwardConfirm) _hider->offerPeer(0); + })), ForceFastShowLayer); } } if (selectingPeer()) { @@ -2855,8 +2842,11 @@ void MainWidget::showAll() { if (_hider) { _hider->show(); if (_forwardConfirm) { + _forwardConfirm = nullptr; Ui::hideLayer(true); - _forwardConfirm = 0; + if (_hider->wasOffered()) { + _hider->setFocus(); + } } } _dialogs->showFast(); @@ -3651,14 +3641,14 @@ void MainWidget::openPeerByName(const QString &username, MsgId msgId, const QStr if (msgId == ShowAtGameShareMsgId) { if (peer->isUser() && peer->asUser()->botInfo && !startToken.isEmpty()) { peer->asUser()->botInfo->shareGameShortName = startToken; - Ui::showLayer(new ContactsBox(peer->asUser())); + Ui::show(Box(peer->asUser())); } else { Ui::showPeerHistoryAsync(peer->id, ShowAtUnreadMsgId, Ui::ShowWay::Forward); } } else if (msgId == ShowAtProfileMsgId && !peer->isChannel()) { if (peer->isUser() && peer->asUser()->botInfo && !peer->asUser()->botInfo->cantJoinGroups && !startToken.isEmpty()) { peer->asUser()->botInfo->startGroupToken = startToken; - Ui::showLayer(new ContactsBox(peer->asUser())); + Ui::show(Box(peer->asUser())); } else if (peer->isUser() && peer->asUser()->botInfo) { // Always open bot chats, even from mention links. Ui::showPeerHistoryAsync(peer->id, ShowAtUnreadMsgId, Ui::ShowWay::Forward); @@ -3690,9 +3680,8 @@ void MainWidget::joinGroupByHash(const QString &hash) { void MainWidget::stickersBox(const MTPInputStickerSet &set) { App::wnd()->hideMediaview(); - StickerSetBox *box = new StickerSetBox(set); + auto box = Ui::show(Box(set)); connect(box, SIGNAL(installed(uint64)), this, SLOT(onStickersInstalled(uint64))); - Ui::showLayer(box); } void MainWidget::onStickersInstalled(uint64 setId) { @@ -3743,7 +3732,7 @@ void MainWidget::usernameResolveDone(QPair msgIdAndStartToken, c if (msgId == ShowAtProfileMsgId && !peer->isChannel()) { if (peer->isUser() && peer->asUser()->botInfo && !peer->asUser()->botInfo->cantJoinGroups && !startToken.isEmpty()) { peer->asUser()->botInfo->startGroupToken = startToken; - Ui::showLayer(new ContactsBox(peer->asUser())); + Ui::show(Box(peer->asUser())); } else if (peer->isUser() && peer->asUser()->botInfo) { // Always open bot chats, even from mention links. Ui::showPeerHistoryAsync(peer->id, ShowAtUnreadMsgId, Ui::ShowWay::Forward); @@ -3769,7 +3758,7 @@ bool MainWidget::usernameResolveFail(QString name, const RPCError &error) { if (MTP::isDefaultHandledError(error)) return false; if (error.code() == 400) { - Ui::showLayer(new InformBox(lng_username_not_found(lt_user, name))); + Ui::show(Box(lng_username_not_found(lt_user, name))); } return true; } @@ -3789,9 +3778,8 @@ void MainWidget::inviteCheckDone(QString hash, const MTPChatInvite &invite) { } } } - auto box = std_::make_unique(qs(d.vtitle), d.vphoto, d.vparticipants_count.v, participants); _inviteHash = hash; - Ui::showLayer(box.release()); + Ui::show(Box(qs(d.vtitle), d.vphoto, d.vparticipants_count.v, participants)); } break; case mtpc_chatInviteAlready: { @@ -3808,7 +3796,7 @@ bool MainWidget::inviteCheckFail(const RPCError &error) { if (MTP::isDefaultHandledError(error)) return false; if (error.code() == 400) { - Ui::showLayer(new InformBox(lang(lng_group_invite_bad_link))); + Ui::show(Box(lang(lng_group_invite_bad_link))); } return true; } @@ -3841,9 +3829,9 @@ bool MainWidget::inviteImportFail(const RPCError &error) { if (MTP::isDefaultHandledError(error)) return false; if (error.type() == qstr("CHANNELS_TOO_MUCH")) { - Ui::showLayer(new InformBox(lang(lng_join_channel_error))); + Ui::show(Box(lang(lng_join_channel_error))); } else if (error.code() == 400) { - Ui::showLayer(new InformBox(lang(error.type() == qstr("USERS_TOO_MUCH") ? lng_group_invite_no_room : lng_group_invite_bad_link))); + Ui::show(Box(lang(error.type() == qstr("USERS_TOO_MUCH") ? lng_group_invite_no_room : lng_group_invite_bad_link))); } return true; @@ -4775,7 +4763,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { case mtpc_updateServiceNotification: { auto &d = update.c_updateServiceNotification(); if (d.is_popup()) { - Ui::showLayer(new InformBox(qs(d.vmessage))); + Ui::show(Box(qs(d.vmessage))); } else { App::wnd()->serviceNotification({ qs(d.vmessage), entitiesFromMTP(d.ventities.c_vector().v) }, d.vmedia); emit App::wnd()->checkNewAuthorization(); diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index f615320d6..cdd10c2e1 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -232,7 +232,7 @@ public: void shareContactLayer(UserData *contact); void shareUrlLayer(const QString &url, const QString &text); void inlineSwitchLayer(const QString &botAndQuery); - void hiderLayer(HistoryHider *h); + void hiderLayer(object_ptr h); void noHider(HistoryHider *destroyed); bool onForward(const PeerId &peer, ForwardWhatMessages what); bool onShareUrl(const PeerId &peer, const QString &url, const QString &text); @@ -423,7 +423,6 @@ public slots: void documentLoadProgress(FileLoader *loader); void documentLoadFailed(FileLoader *loader, bool started); - void documentLoadRetry(); void inlineResultLoadProgress(FileLoader *loader); void inlineResultLoadFailed(FileLoader *loader, bool started); @@ -452,8 +451,6 @@ public slots: void onAudiosSelect(); void onLinksSelect(); - void onForwardCancel(QObject *obj = 0); - void onCacheBackground(); void onInviteImport(); @@ -466,15 +463,9 @@ public slots: void onViewsIncrement(); void onActiveChannelUpdateFull(); - void onDownloadPathSettings(); - - void onSharePhoneWithBot(PeerData *recipient); - void ui_showPeerHistoryAsync(quint64 peerId, qint32 showAtMsgId, Ui::ShowWay way); void ui_autoplayMediaInlineAsync(qint32 channelId, qint32 msgId); - void onDeletePhotoSure(); - protected: void paintEvent(QPaintEvent *e) override; void resizeEvent(QResizeEvent *e) override; @@ -507,7 +498,7 @@ private: void overviewLoaded(History *history, const MTPmessages_Messages &result, mtpRequestId req); Window::SectionSlideParams prepareShowAnimation(bool willHaveTopBarShadow); - void showWideSectionAnimated(const Window::SectionMemento *memento, bool back); + void showWideSectionAnimated(const Window::SectionMemento *memento, bool back, bool saveInStack); // All this methods use the prepareShowAnimation(). Window::SectionSlideParams prepareWideSectionAnimation(Window::SectionWidget *section); @@ -519,10 +510,6 @@ private: bool _started = false; - uint64 failedObjId = 0; - QString failedFileName; - void loadFailed(mtpFileLoader *loader, bool started, const char *retrySlot); - SelectedItemSet _toForward; Text _toForwardFrom, _toForwardText; int32 _toForwardNameVersion = 0; @@ -592,21 +579,21 @@ private: int _dialogsWidth; - ChildWidget _sideShadow; - ChildWidget _dialogs; - ChildWidget _history; - ChildWidget _wideSection = { nullptr }; - ChildWidget _overview = { nullptr }; - ChildWidget _topBar; + object_ptr _sideShadow; + object_ptr _dialogs; + object_ptr _history; + object_ptr _wideSection = { nullptr }; + object_ptr _overview = { nullptr }; + object_ptr _topBar; - ChildWidget _player = { nullptr }; - ChildWidget _playerVolume = { nullptr }; - ChildWidget _playerPlaylist; - ChildWidget _playerPanel; + object_ptr _player = { nullptr }; + object_ptr _playerVolume = { nullptr }; + object_ptr _playerPlaylist; + object_ptr _playerPanel; bool _playerUsingPanel = false; - ConfirmBox *_forwardConfirm = nullptr; // for single column layout - ChildWidget _hider = { nullptr }; + QPointer _forwardConfirm; // for single column layout + object_ptr _hider = { nullptr }; std_::vector_of_moveable> _stack; PeerData *_peerInStack = nullptr; MsgId _msgIdInStack = 0; @@ -614,7 +601,7 @@ private: int _playerHeight = 0; int _contentScrollAddToY = 0; - ChildWidget _mediaType; + object_ptr _mediaType; int32 _mediaTypeMask = 0; int32 updDate = 0; diff --git a/Telegram/SourceFiles/mainwindow.cpp b/Telegram/SourceFiles/mainwindow.cpp index b96a60b05..c20597a51 100644 --- a/Telegram/SourceFiles/mainwindow.cpp +++ b/Telegram/SourceFiles/mainwindow.cpp @@ -52,7 +52,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "window/window_main_menu.h" ConnectingWidget::ConnectingWidget(QWidget *parent, const QString &text, const QString &reconnect) : TWidget(parent) -, _shadow(st::boxShadow) , _reconnect(this, QString()) { set(text, reconnect); connect(_reconnect, SIGNAL(clicked()), this, SLOT(onReconnect())); @@ -67,21 +66,24 @@ void ConnectingWidget::set(const QString &text, const QString &reconnect) { } else { _reconnect->setText(reconnect); _reconnect->show(); - _reconnect->move(st::connectingPadding.left() + _textWidth, st::boxShadow.height() + st::connectingPadding.top()); + _reconnect->move(st::connectingPadding.left() + _textWidth, st::boxRoundShadow.extend.top() + st::connectingPadding.top()); _reconnectWidth = _reconnect->width(); } - resize(st::connectingPadding.left() + _textWidth + _reconnectWidth + st::connectingPadding.right() + st::boxShadow.width(), st::boxShadow.height() + st::connectingPadding.top() + st::linkFont->height + st::connectingPadding.bottom()); + resize(st::connectingPadding.left() + _textWidth + _reconnectWidth + st::connectingPadding.right() + st::boxRoundShadow.extend.right(), st::boxRoundShadow.extend.top() + st::connectingPadding.top() + st::normalFont->height + st::connectingPadding.bottom()); update(); } void ConnectingWidget::paintEvent(QPaintEvent *e) { Painter p(this); - _shadow.paint(p, QRect(0, st::boxShadow.height(), width() - st::boxShadow.width(), height() - st::boxShadow.height()), 0, Ui::RectShadow::Side::Top | Ui::RectShadow::Side::Right); - p.fillRect(0, st::boxShadow.height(), width() - st::boxShadow.width(), height() - st::boxShadow.height(), st::connectingBG->b); - p.setFont(st::linkFont->f); - p.setPen(st::connectingColor->p); - p.drawText(st::connectingPadding.left(), st::boxShadow.height() + st::connectingPadding.top() + st::linkFont->ascent, _text); + auto sides = Ui::Shadow::Side::Top | Ui::Shadow::Side::Right; + Ui::Shadow::paint(p, QRect(0, st::boxRoundShadow.extend.top(), width() - st::boxRoundShadow.extend.right(), height() - st::boxRoundShadow.extend.top()), width(), st::boxRoundShadow, sides); + auto parts = App::RectPart::Top | App::RectPart::TopRight | App::RectPart::Center | App::RectPart::Right; + App::roundRect(p, QRect(-st::boxRadius, st::boxRoundShadow.extend.top(), width() - st::boxRoundShadow.extend.right() + st::boxRadius, height() - st::boxRoundShadow.extend.top() + st::boxRadius), st::boxBg, BoxCorners, nullptr, parts); + + p.setFont(st::normalFont); + p.setPen(st::windowSubTextFg); + p.drawText(st::connectingPadding.left(), st::boxRoundShadow.extend.top() + st::connectingPadding.top() + st::normalFont->ascent, _text); } void ConnectingWidget::onReconnect() { @@ -260,9 +262,7 @@ void MainWindow::setupPasscode() { updateControlsGeometry(); if (_main) _main->hide(); - if (_settings) { - _settings.destroyDelayed(); - } + Ui::hideSettingsAndLayer(true); if (_intro) _intro->hide(); if (animated) { _passcode->showAnimated(bg); @@ -392,17 +392,10 @@ void MainWindow::showSettings() { if (isHidden()) showFromTray(); - if (_settings) { - Ui::hideSettingsAndLayer(); - return; - } - if (!_layerBg) { _layerBg.create(bodyWidget()); } - _settings.create(this); - connect(_settings, SIGNAL(destroyed(QObject*)), this, SLOT(onSettingsDestroyed(QObject*))); - _layerBg->showSpecialLayer(_settings); + _layerBg->showSpecialLayer(Box()); } void MainWindow::showMainMenu() { @@ -479,32 +472,28 @@ void MainWindow::showDocument(DocumentData *doc, HistoryItem *item) { _mediaView->setFocus(); } -void MainWindow::ui_showLayer(LayerWidget *box, ShowLayerOptions options) { +void MainWindow::ui_showBox(object_ptr box, ShowLayerOptions options) { if (box) { if (!_layerBg) { _layerBg.create(bodyWidget()); } if (options.testFlag(KeepOtherLayers)) { if (options.testFlag(ShowAfterOtherLayers)) { - _layerBg->prependLayer(box); + _layerBg->prependBox(std_::move(box)); } else { - _layerBg->appendLayer(box); + _layerBg->appendBox(std_::move(box)); } } else { - _layerBg->showLayer(box); + _layerBg->showBox(std_::move(box)); } if (options.testFlag(ForceFastShowLayer)) { _layerBg->finishAnimation(); } } else { if (_layerBg) { - if (_settings) { - _layerBg->hideLayers(); - } else { - _layerBg->hideAll(); - if (options.testFlag(ForceFastShowLayer)) { - _layerBg.destroyDelayed(); - } + _layerBg->hideTopLayer(); + if (options.testFlag(ForceFastShowLayer) && !_layerBg->layerShown()) { + _layerBg.destroyDelayed(); } } hideMediaview(); @@ -642,8 +631,6 @@ void MainWindow::setInnerFocus() { _layerBg->setInnerFocus(); } else if (_passcode) { _passcode->setInnerFocus(); - } else if (_settings) { - _settings->setInnerFocus(); } else if (_main) { _main->setInnerFocus(); } else if (_intro) { @@ -776,7 +763,7 @@ void MainWindow::onShowAddContact() { if (isHidden()) showFromTray(); if (App::self()) { - Ui::showLayer(new AddContactBox(), KeepOtherLayers); + Ui::show(Box(), KeepOtherLayers); } } @@ -784,26 +771,22 @@ void MainWindow::onShowNewGroup() { if (isHidden()) showFromTray(); if (App::self()) { - Ui::showLayer(new GroupInfoBox(CreatingGroupGroup, false), KeepOtherLayers); + Ui::show(Box(CreatingGroupGroup, false), KeepOtherLayers); } } void MainWindow::onShowNewChannel() { if (isHidden()) showFromTray(); - if (_main) Ui::showLayer(new GroupInfoBox(CreatingGroupChannel, false), KeepOtherLayers); + if (_main) Ui::show(Box(CreatingGroupChannel, false), KeepOtherLayers); } void MainWindow::onLogout() { if (isHidden()) showFromTray(); - auto box = new ConfirmBox(lang(lng_sure_logout), lang(lng_settings_logout), st::attentionBoxButton); - connect(box, SIGNAL(confirmed()), this, SLOT(onLogoutSure())); - Ui::showLayer(box); -} - -void MainWindow::onLogoutSure() { - App::logOut(); + Ui::show(Box(lang(lng_sure_logout), lang(lng_settings_logout), st::attentionBoxButton, [] { + App::logOut(); + })); } void MainWindow::updateGlobalMenu() { @@ -838,13 +821,6 @@ void MainWindow::noIntro(Intro::Widget *was) { } } -void MainWindow::onSettingsDestroyed(QObject *was) { - if (was == _settings) { - _settings = nullptr; - } - checkHistoryActivation(); -} - void MainWindow::noMain(MainWidget *was) { if (was == _main) { _main = nullptr; @@ -896,7 +872,7 @@ void MainWindow::toggleTray(QSystemTrayIcon::ActivationReason reason) { void MainWindow::toggleDisplayNotifyFromTray() { if (App::passcoded()) { if (!isActive()) showFromTray(); - Ui::showLayer(new InformBox(lang(lng_passcode_need_unblock))); + Ui::show(Box(lang(lng_passcode_need_unblock))); return; } diff --git a/Telegram/SourceFiles/mainwindow.h b/Telegram/SourceFiles/mainwindow.h index b39e372bd..f69587007 100644 --- a/Telegram/SourceFiles/mainwindow.h +++ b/Telegram/SourceFiles/mainwindow.h @@ -21,7 +21,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #pragma once #include "pspecific.h" -#include "ui/effects/rect_shadow.h" #include "platform/platform_main_window.h" #include "core/single_timer.h" @@ -29,7 +28,7 @@ class MediaView; class PasscodeWidget; class MainWidget; class LayerStackWidget; -class LayerWidget; +class BoxContent; namespace Intro { class Widget; @@ -39,10 +38,6 @@ namespace Local { class ClearManager; } // namespace Local -namespace Settings { -class Widget; -} // namespace Settings - namespace Window { namespace Theme { struct BackgroundUpdate; @@ -68,10 +63,9 @@ public slots: void onReconnect(); private: - Ui::RectShadow _shadow; QString _text; - int32 _textWidth; - ChildWidget _reconnect; + int _textWidth = 0; + object_ptr _reconnect; }; @@ -162,7 +156,7 @@ public: void showMainMenu(); - void ui_showLayer(LayerWidget *box, ShowLayerOptions options); + void ui_showBox(object_ptr box, ShowLayerOptions options); void ui_hideSettingsAndLayer(ShowLayerOptions options); bool ui_isLayerShown(); bool ui_isMediaViewShown(); @@ -206,7 +200,6 @@ public slots: void onShowNewGroup(); void onShowNewChannel(); void onLogout(); - void onLogoutSure(); void updateGlobalMenu(); // for OS X top menu void onReActivate(); @@ -220,7 +213,6 @@ signals: private slots: void onStateChanged(Qt::WindowState state); - void onSettingsDestroyed(QObject *was); void onWindowActiveChanged(); @@ -247,18 +239,17 @@ private: QList _delayedServiceMsgs; mtpRequestId _serviceHistoryRequest = 0; - ChildWidget _passcode = { nullptr }; - ChildWidget _intro = { nullptr }; - ChildWidget _main = { nullptr }; - ChildWidget _settings = { nullptr }; - ChildWidget _layerBg = { nullptr }; - ChildWidget _mediaPreview = { nullptr }; + object_ptr _passcode = { nullptr }; + object_ptr _intro = { nullptr }; + object_ptr _main = { nullptr }; + object_ptr _layerBg = { nullptr }; + object_ptr _mediaPreview = { nullptr }; QTimer _isActiveTimer; bool _isActive = false; - ChildWidget _connecting = { nullptr }; - ChildWidget _testingThemeWarning = { nullptr }; + object_ptr _connecting = { nullptr }; + object_ptr _testingThemeWarning = { nullptr }; Local::ClearManager *_clearManager = nullptr; diff --git a/Telegram/SourceFiles/media/player/media_player.style b/Telegram/SourceFiles/media/player/media_player.style index 4dc8b7eec..cfa2a6459 100644 --- a/Telegram/SourceFiles/media/player/media_player.style +++ b/Telegram/SourceFiles/media/player/media_player.style @@ -229,13 +229,16 @@ mediaPlayerPanelVolumeWidth: 64px; mediaPlayerPanelVolumeToggleSkip: 0px; mediaPlayerPanelVolumeToggleTop: 57px; -mediaPlayerScroll: FlatScroll(defaultSolidScroll) { +mediaPlayerScroll: ScrollArea(defaultSolidScroll) { deltat: 10px; deltab: 0px; } mediaPlayerListHeightMax: 280px; mediaPlayerListMarginBottom: 10px; -mediaPlayerScrollShadow: icon {{ "playlist_shadow", windowShadowFg }}; +mediaPlayerScrollShadow: Shadow { + bottom: icon {{ "playlist_shadow", windowShadowFg }}; + extend: margins(2px, 2px, 2px, 2px); +} mediaPlayerListMarginTop: 8px; mediaPlayerFileLayout: OverviewFileLayout(overviewFileLayout) { diff --git a/Telegram/SourceFiles/media/player/media_player_cover.cpp b/Telegram/SourceFiles/media/player/media_player_cover.cpp index 6e7efdb8f..417904fa3 100644 --- a/Telegram/SourceFiles/media/player/media_player_cover.cpp +++ b/Telegram/SourceFiles/media/player/media_player_cover.cpp @@ -73,7 +73,7 @@ CoverWidget::CoverWidget(QWidget *parent) : TWidget(parent) , _nameLabel(this, st::mediaPlayerName) , _timeLabel(this, st::mediaPlayerTime) , _close(this, st::mediaPlayerPanelClose) -, _playback(new Ui::MediaSlider(this, st::mediaPlayerPanelPlayback)) +, _playback(std_::make_unique(new Ui::MediaSlider(this, st::mediaPlayerPanelPlayback))) , _playPause(this) , _volumeToggle(this, st::mediaPlayerVolumeToggle) , _volumeController(this) diff --git a/Telegram/SourceFiles/media/player/media_player_cover.h b/Telegram/SourceFiles/media/player/media_player_cover.h index 18674fbbc..4d01275fc 100644 --- a/Telegram/SourceFiles/media/player/media_player_cover.h +++ b/Telegram/SourceFiles/media/player/media_player_cover.h @@ -78,17 +78,17 @@ private: QString _time; class PlayButton; - ChildWidget _nameLabel; - ChildWidget _timeLabel; - ChildWidget _close; - ChildWidget _playback; - ChildWidget _previousTrack = { nullptr }; - ChildWidget _playPause; - ChildWidget _nextTrack = { nullptr }; - ChildWidget _volumeToggle; - ChildWidget _volumeController; - ChildWidget _pinPlayer; - ChildWidget _repeatTrack; + object_ptr _nameLabel; + object_ptr _timeLabel; + object_ptr _close; + std_::unique_ptr _playback; + object_ptr _previousTrack = { nullptr }; + object_ptr _playPause; + object_ptr _nextTrack = { nullptr }; + object_ptr _volumeToggle; + object_ptr _volumeController; + object_ptr _pinPlayer; + object_ptr _repeatTrack; }; diff --git a/Telegram/SourceFiles/media/player/media_player_list.cpp b/Telegram/SourceFiles/media/player/media_player_list.cpp index daeba189e..4fda60100 100644 --- a/Telegram/SourceFiles/media/player/media_player_list.cpp +++ b/Telegram/SourceFiles/media/player/media_player_list.cpp @@ -28,7 +28,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org namespace Media { namespace Player { -ListWidget::ListWidget() { +ListWidget::ListWidget(QWidget *parent) : TWidget(parent) { setMouseTracking(true); playlistUpdated(); if (exists()) { diff --git a/Telegram/SourceFiles/media/player/media_player_list.h b/Telegram/SourceFiles/media/player/media_player_list.h index b6aa5f1da..1abea0248 100644 --- a/Telegram/SourceFiles/media/player/media_player_list.h +++ b/Telegram/SourceFiles/media/player/media_player_list.h @@ -31,7 +31,7 @@ namespace Player { class ListWidget : public TWidget, private base::Subscriber { public: - ListWidget(); + ListWidget(QWidget *parent); void ui_repaintHistoryItem(const HistoryItem *item); diff --git a/Telegram/SourceFiles/media/player/media_player_panel.cpp b/Telegram/SourceFiles/media/player/media_player_panel.cpp index 1de46609d..6938af7dd 100644 --- a/Telegram/SourceFiles/media/player/media_player_panel.cpp +++ b/Telegram/SourceFiles/media/player/media_player_panel.cpp @@ -36,7 +36,6 @@ namespace Player { Panel::Panel(QWidget *parent, Layout layout) : TWidget(parent) , _layout(layout) -, _shadow(st::defaultDropdownShadow) , _scroll(this, st::mediaPlayerScroll) { _hideTimer.setSingleShot(true); connect(&_hideTimer, SIGNAL(timeout()), this, SLOT(onHideStart())); @@ -84,7 +83,7 @@ void Panel::updateControlsGeometry() { _cover->moveToRight(contentRight(), scrollTop); scrollTop += _cover->height(); if (_scrollShadow) { - _scrollShadow->resizeToWidth(width); + _scrollShadow->resize(width, st::mediaPlayerScrollShadow.extend.bottom()); _scrollShadow->moveToRight(contentRight(), scrollTop); } } @@ -167,14 +166,15 @@ void Panel::paintEvent(QPaintEvent *e) { } // draw shadow - using Side = Ui::RectShadow::Side; + using Side = Ui::Shadow::Side; auto shadowedRect = myrtlrect(contentLeft(), contentTop(), contentWidth(), contentHeight()); auto shadowedSides = (rtl() ? Side::Right : Side::Left) | Side::Bottom; if (_layout != Layout::Full) { shadowedSides |= (rtl() ? Side::Left : Side::Right) | Side::Top; } - _shadow.paint(p, shadowedRect, st::defaultDropdownShadowShift, shadowedSides); - p.fillRect(shadowedRect, st::windowBg); + Ui::Shadow::paint(p, shadowedRect, width(), st::defaultRoundShadow, shadowedSides); + auto parts = App::RectPart::Full; + App::roundRect(p, shadowedRect, st::menuBg, MenuCorners, nullptr, parts); } void Panel::enterEvent(QEvent *e) { @@ -225,11 +225,11 @@ void Panel::ensureCreated() { setPinCallback(std_::move(_pinCallback)); setCloseCallback(std_::move(_closeCallback)); - _scrollShadow.create(this, st::mediaPlayerScrollShadow); + _scrollShadow.create(this, st::mediaPlayerScrollShadow, Ui::Shadow::Side::Bottom); } - auto list = std_::make_unique(); - connect(list.get(), SIGNAL(heightUpdated()), this, SLOT(onListHeightUpdated())); - _scroll->setOwnedWidget(list.release()); + auto list = object_ptr(this); + connect(list, SIGNAL(heightUpdated()), this, SLOT(onListHeightUpdated())); + _scroll->setOwnedWidget(std_::move(list)); if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) { if (auto window = App::wnd()) { @@ -246,9 +246,7 @@ void Panel::performDestroy() { if (!_scroll->widget()) return; _cover.destroy(); - auto list = _scroll->takeWidget(); - list->hide(); - list->deleteLater(); + _scroll->takeWidget().destroyDelayed(); if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) { if (auto window = App::wnd()) { diff --git a/Telegram/SourceFiles/media/player/media_player_panel.h b/Telegram/SourceFiles/media/player/media_player_panel.h index 87071cbba..65d50a585 100644 --- a/Telegram/SourceFiles/media/player/media_player_panel.h +++ b/Telegram/SourceFiles/media/player/media_player_panel.h @@ -20,11 +20,9 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org */ #pragma once -#include "ui/effects/rect_shadow.h" - namespace Ui { class ScrollArea; -class GradientShadow; +class Shadow; } // namespace Ui namespace Media { @@ -106,11 +104,10 @@ private: QTimer _hideTimer, _showTimer; - Ui::RectShadow _shadow; ButtonCallback _pinCallback, _closeCallback; - ChildWidget _cover = { nullptr }; - ChildWidget _scroll; - ChildWidget _scrollShadow = { nullptr }; + object_ptr _cover = { nullptr }; + object_ptr _scroll; + object_ptr _scrollShadow = { nullptr }; }; diff --git a/Telegram/SourceFiles/media/player/media_player_volume_controller.cpp b/Telegram/SourceFiles/media/player/media_player_volume_controller.cpp index edf91ba27..4fe481e8a 100644 --- a/Telegram/SourceFiles/media/player/media_player_volume_controller.cpp +++ b/Telegram/SourceFiles/media/player/media_player_volume_controller.cpp @@ -23,6 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "media/media_audio.h" #include "ui/widgets/buttons.h" +#include "ui/widgets/shadow.h" #include "ui/widgets/continuous_sliders.h" #include "styles/style_media_player.h" #include "styles/style_widgets.h" @@ -81,7 +82,6 @@ void VolumeController::applyVolumeChange(float64 volume) { } VolumeWidget::VolumeWidget(QWidget *parent) : TWidget(parent) -, _shadow(st::defaultDropdownShadow) , _controller(this) { hide(); _controller->setIsVertical(true); @@ -143,10 +143,11 @@ void VolumeWidget::paintEvent(QPaintEvent *e) { // draw shadow auto shadowedRect = rect().marginsRemoved(getMargin()); - using ShadowSide = Ui::RectShadow::Side; + using ShadowSide = Ui::Shadow::Side; auto shadowedSides = ShadowSide::Left | ShadowSide::Right | ShadowSide::Bottom; - _shadow.paint(p, shadowedRect, st::defaultDropdownShadowShift, shadowedSides); - p.fillRect(shadowedRect.x(), 0, shadowedRect.width(), shadowedRect.y() + shadowedRect.height(), st::windowBg); + Ui::Shadow::paint(p, shadowedRect, width(), st::defaultRoundShadow, shadowedSides); + auto parts = App::RectPart::NoTopBottom | App::RectPart::BottomFull; + App::roundRect(p, QRect(shadowedRect.x(), -st::buttonRadius, shadowedRect.width(), shadowedRect.y() + shadowedRect.height() + st::buttonRadius), st::menuBg, MenuCorners, nullptr, parts); } void VolumeWidget::enterEvent(QEvent *e) { diff --git a/Telegram/SourceFiles/media/player/media_player_volume_controller.h b/Telegram/SourceFiles/media/player/media_player_volume_controller.h index 14dc4796a..ab442405c 100644 --- a/Telegram/SourceFiles/media/player/media_player_volume_controller.h +++ b/Telegram/SourceFiles/media/player/media_player_volume_controller.h @@ -20,12 +20,9 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org */ #pragma once -#include "ui/effects/rect_shadow.h" - namespace Ui { class IconButton; class MediaSlider; -class RectShadow; } // namespace Ui namespace Media { @@ -44,7 +41,7 @@ private: void setVolume(float64 volume, bool animated = true); void applyVolumeChange(float64 volume); - ChildWidget _slider; + object_ptr _slider; }; @@ -86,8 +83,7 @@ private: QTimer _hideTimer, _showTimer; - Ui::RectShadow _shadow; - ChildWidget _controller; + object_ptr _controller; }; diff --git a/Telegram/SourceFiles/media/player/media_player_widget.cpp b/Telegram/SourceFiles/media/player/media_player_widget.cpp index e507cd784..d0ac697dc 100644 --- a/Telegram/SourceFiles/media/player/media_player_widget.cpp +++ b/Telegram/SourceFiles/media/player/media_player_widget.cpp @@ -92,7 +92,7 @@ Widget::Widget(QWidget *parent) : TWidget(parent) , _repeatTrack(this, st::mediaPlayerRepeatButton) , _close(this, st::mediaPlayerClose) , _shadow(this, st::shadowColor) -, _playback(new Ui::FilledSlider(this, st::mediaPlayerPlayback)) { +, _playback(std_::make_unique(new Ui::FilledSlider(this, st::mediaPlayerPlayback))) { setAttribute(Qt::WA_OpaquePaintEvent); setMouseTracking(true); resize(width(), st::mediaPlayerHeight + st::lineWidth); @@ -192,6 +192,8 @@ void Widget::volumeWidgetCreated(VolumeWidget *widget) { _volumeToggle->installEventFilter(widget); } +Widget::~Widget() = default; + void Widget::handleSeekProgress(float64 progress) { if (!_lastDurationMs) return; diff --git a/Telegram/SourceFiles/media/player/media_player_widget.h b/Telegram/SourceFiles/media/player/media_player_widget.h index cbcf9223f..83c0195a9 100644 --- a/Telegram/SourceFiles/media/player/media_player_widget.h +++ b/Telegram/SourceFiles/media/player/media_player_widget.h @@ -55,6 +55,8 @@ public: QPoint getPositionForVolumeWidget() const; void volumeWidgetCreated(VolumeWidget *widget); + ~Widget(); + protected: void resizeEvent(QResizeEvent *e) override; void paintEvent(QPaintEvent *e) override; @@ -91,16 +93,16 @@ private: QString _time; class PlayButton; - ChildWidget _nameLabel; - ChildWidget _timeLabel; - ChildWidget _previousTrack = { nullptr }; - ChildWidget _playPause; - ChildWidget _nextTrack = { nullptr }; - ChildWidget _volumeToggle; - ChildWidget _repeatTrack; - ChildWidget _close; - ChildWidget _shadow = { nullptr }; - ChildWidget _playback; + object_ptr _nameLabel; + object_ptr _timeLabel; + object_ptr _previousTrack = { nullptr }; + object_ptr _playPause; + object_ptr _nextTrack = { nullptr }; + object_ptr _volumeToggle; + object_ptr _repeatTrack; + object_ptr _close; + object_ptr _shadow = { nullptr }; + std_::unique_ptr _playback; }; diff --git a/Telegram/SourceFiles/media/view/media_clip_controller.cpp b/Telegram/SourceFiles/media/view/media_clip_controller.cpp index e3af74d29..67c716c5e 100644 --- a/Telegram/SourceFiles/media/view/media_clip_controller.cpp +++ b/Telegram/SourceFiles/media/view/media_clip_controller.cpp @@ -35,7 +35,7 @@ namespace Clip { Controller::Controller(QWidget *parent) : TWidget(parent) , _playPauseResume(this, st::mediaviewPlayButton) -, _playback(new Ui::MediaSlider(this, st::mediaviewPlayback)) +, _playback(std_::make_unique(new Ui::MediaSlider(this, st::mediaviewPlayback))) , _volumeController(this) , _fullScreenToggle(this, st::mediaviewFullScreenButton) , _playedAlready(this, st::mediaviewPlayProgressLabel) @@ -218,8 +218,7 @@ void Controller::mousePressEvent(QMouseEvent *e) { e->accept(); // Don't pass event to the MediaView. } -Controller::~Controller() { -} +Controller::~Controller() = default; } // namespace Clip } // namespace Media diff --git a/Telegram/SourceFiles/media/view/media_clip_controller.h b/Telegram/SourceFiles/media/view/media_clip_controller.h index 203d2a6a2..be0d60d21 100644 --- a/Telegram/SourceFiles/media/view/media_clip_controller.h +++ b/Telegram/SourceFiles/media/view/media_clip_controller.h @@ -83,12 +83,12 @@ private: TimeMs _seekPositionMs = -1; TimeMs _lastDurationMs = 0; - ChildWidget _playPauseResume; - ChildWidget _playback; - ChildWidget _volumeController; - ChildWidget _fullScreenToggle; - ChildWidget _playedAlready; - ChildWidget _toPlayLeft; + object_ptr _playPauseResume; + std_::unique_ptr _playback; + object_ptr _volumeController; + object_ptr _fullScreenToggle; + object_ptr _playedAlready; + object_ptr _toPlayLeft; std_::unique_ptr _fadeAnimation; diff --git a/Telegram/SourceFiles/mediaview.cpp b/Telegram/SourceFiles/mediaview.cpp index e6422fc4c..4762b68a3 100644 --- a/Telegram/SourceFiles/mediaview.cpp +++ b/Telegram/SourceFiles/mediaview.cpp @@ -1366,8 +1366,7 @@ void MediaView::createClipReader() { void MediaView::createClipController() { if (!_doc->isVideo()) return; - _clipController.destroy(); - _clipController = new Media::Clip::Controller(this); + _clipController.create(this); setClipControllerGeometry(); _clipController->show(); diff --git a/Telegram/SourceFiles/mediaview.h b/Telegram/SourceFiles/mediaview.h index 958bd1d41..2271554cb 100644 --- a/Telegram/SourceFiles/mediaview.h +++ b/Telegram/SourceFiles/mediaview.h @@ -204,7 +204,7 @@ private: QString _dateText; QString _headerText; - ChildWidget _clipController = { nullptr }; + object_ptr _clipController = { nullptr }; DocumentData *_autoplayVideoDocument = nullptr; bool _fullScreenVideo = false; int _fullScreenZoomCache = 0; @@ -244,9 +244,9 @@ private: int _docNameWidth = 0, _docSizeWidth = 0, _docExtWidth = 0; QRect _docRect, _docIconRect; int _docThumbx = 0, _docThumby = 0, _docThumbw = 0; - ChildWidget _docDownload; - ChildWidget _docSaveAs; - ChildWidget _docCancel; + object_ptr _docDownload; + object_ptr _docSaveAs; + object_ptr _docCancel; QRect _photoRadialRect; Ui::RadialAnimation _radial; @@ -311,7 +311,7 @@ private: bool _mousePressed = false; Ui::PopupMenu *_menu = nullptr; - ChildWidget _dropdown; + object_ptr _dropdown; struct ActionData { QString text; diff --git a/Telegram/SourceFiles/overviewwidget.cpp b/Telegram/SourceFiles/overviewwidget.cpp index 095766417..5f56f6aee 100644 --- a/Telegram/SourceFiles/overviewwidget.cpp +++ b/Telegram/SourceFiles/overviewwidget.cpp @@ -1885,9 +1885,8 @@ OverviewInner::~OverviewInner() { OverviewWidget::OverviewWidget(QWidget *parent, PeerData *peer, MediaOverviewType type) : TWidget(parent) , _scroll(this, st::settingsScroll, false) -, _inner(this, _scroll, peer, type) , _topShadow(this, st::shadowColor) { - _scroll->setOwnedWidget(_inner); + _inner = _scroll->setOwnedWidget(object_ptr(this, _scroll, peer, type)); _scroll->move(0, 0); _inner->move(0, 0); diff --git a/Telegram/SourceFiles/overviewwidget.h b/Telegram/SourceFiles/overviewwidget.h index 851625f09..d3e30ef1e 100644 --- a/Telegram/SourceFiles/overviewwidget.h +++ b/Telegram/SourceFiles/overviewwidget.h @@ -183,8 +183,8 @@ private: Overview::Layout::AbstractItem *layoutPrepare(const QDate &date, bool month); int32 setLayoutItem(int32 index, Overview::Layout::AbstractItem *item, int32 top); - ChildWidget _search; - ChildWidget _cancelSearch; + object_ptr _search; + object_ptr _cancelSearch; QVector _results; int32 _itemsToBeLoaded; @@ -357,8 +357,8 @@ public slots: private: void animationCallback(); - ChildWidget _scroll; - ChildWidget _inner; + object_ptr _scroll; + QPointer _inner; bool _noDropResizeIndex = false; QString _header; @@ -374,7 +374,7 @@ private: int32 _selCount = 0; - ChildWidget _topShadow; + object_ptr _topShadow; bool _inGrab = false; }; diff --git a/Telegram/SourceFiles/passcodewidget.h b/Telegram/SourceFiles/passcodewidget.h index bb1996332..c2f69d77c 100644 --- a/Telegram/SourceFiles/passcodewidget.h +++ b/Telegram/SourceFiles/passcodewidget.h @@ -55,9 +55,9 @@ private: bool _showBack = false; QPixmap _cacheUnder, _cacheOver; - ChildWidget _passcode; - ChildWidget _submit; - ChildWidget _logout; + object_ptr _passcode; + object_ptr _submit; + object_ptr _logout; QString _error; }; diff --git a/Telegram/SourceFiles/platform/mac/main_window_mac.mm b/Telegram/SourceFiles/platform/mac/main_window_mac.mm index 110d5326a..73359553a 100644 --- a/Telegram/SourceFiles/platform/mac/main_window_mac.mm +++ b/Telegram/SourceFiles/platform/mac/main_window_mac.mm @@ -395,7 +395,7 @@ void MainWindow::createGlobalMenu() { auto about = main->addAction(lng_mac_menu_about_telegram(lt_telegram, qsl("Telegram"))); connect(about, SIGNAL(triggered()), base::lambda_slot(about, [] { if (App::wnd() && App::wnd()->isHidden()) App::wnd()->showFromTray(); - Ui::showLayer(new AboutBox()); + Ui::show(Box()); }), SLOT(action())); about->setMenuRole(QAction::AboutQtRole); @@ -423,7 +423,7 @@ void MainWindow::createGlobalMenu() { if (App::wnd() && App::wnd()->isHidden()) App::wnd()->showFromTray(); if (!App::self()) return; - Ui::showLayer(new ContactsBox()); + Ui::show(Box()); }), SLOT(action())); psAddContact = window->addAction(lang(lng_mac_menu_add_contact), App::wnd(), SLOT(onShowAddContact())); window->addSeparator(); diff --git a/Telegram/SourceFiles/platform/mac/window_title_mac.h b/Telegram/SourceFiles/platform/mac/window_title_mac.h index 3ccdfe3b7..48d165ed5 100644 --- a/Telegram/SourceFiles/platform/mac/window_title_mac.h +++ b/Telegram/SourceFiles/platform/mac/window_title_mac.h @@ -40,11 +40,11 @@ protected: void mouseDoubleClickEvent(QMouseEvent *e) override; private: - ChildWidget _shadow; + object_ptr _shadow; QFont _font; }; -Window::TitleWidget *CreateTitleWidget(QWidget *parent); +object_ptr CreateTitleWidget(QWidget *parent); } // namespace Platform diff --git a/Telegram/SourceFiles/platform/mac/window_title_mac.mm b/Telegram/SourceFiles/platform/mac/window_title_mac.mm index 2eb2e9216..a0cdc64e1 100644 --- a/Telegram/SourceFiles/platform/mac/window_title_mac.mm +++ b/Telegram/SourceFiles/platform/mac/window_title_mac.mm @@ -75,13 +75,13 @@ void TitleWidget::mouseDoubleClickEvent(QMouseEvent *e) { } } -Window::TitleWidget *CreateTitleWidget(QWidget *parent) { +object_ptr CreateTitleWidget(QWidget *parent) { if (auto window = qobject_cast(parent)) { if (auto height = window->getCustomTitleHeight()) { - return new TitleWidget(window, height); + return object_ptr(window, height); } } - return nullptr; + return { nullptr }; } } // namespace Platform diff --git a/Telegram/SourceFiles/platform/platform_window_title.h b/Telegram/SourceFiles/platform/platform_window_title.h index 195ac8cbc..2a1f45752 100644 --- a/Telegram/SourceFiles/platform/platform_window_title.h +++ b/Telegram/SourceFiles/platform/platform_window_title.h @@ -30,8 +30,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org namespace Platform { -inline Window::TitleWidget *CreateTitleWidget(QWidget *parent) { - return nullptr; +inline object_ptr CreateTitleWidget(QWidget *parent) { + return { nullptr }; } } // namespace Platform diff --git a/Telegram/SourceFiles/platform/win/window_title_win.h b/Telegram/SourceFiles/platform/win/window_title_win.h index cc7a0fa49..261bb2f5b 100644 --- a/Telegram/SourceFiles/platform/win/window_title_win.h +++ b/Telegram/SourceFiles/platform/win/window_title_win.h @@ -51,17 +51,17 @@ private: void updateMaximizeRestoreButton(); void updateControlsPosition(); - ChildWidget _minimize; - ChildWidget _maximizeRestore; - ChildWidget _close; - ChildWidget _shadow; + object_ptr _minimize; + object_ptr _maximizeRestore; + object_ptr _close; + object_ptr _shadow; bool _maximized = false; }; -inline Window::TitleWidget *CreateTitleWidget(QWidget *parent) { - return new TitleWidget(parent); +inline object_ptr CreateTitleWidget(QWidget *parent) { + return object_ptr(parent); } } // namespace Platform diff --git a/Telegram/SourceFiles/profile/profile_block_actions.cpp b/Telegram/SourceFiles/profile/profile_block_actions.cpp index 75d89a8ae..e60db4558 100644 --- a/Telegram/SourceFiles/profile/profile_block_actions.cpp +++ b/Telegram/SourceFiles/profile/profile_block_actions.cpp @@ -277,18 +277,14 @@ void ActionsWidget::onClearHistory() { confirmation = lng_sure_delete_group_history(lt_group, App::peerName(peer())); } if (!confirmation.isEmpty()) { - auto box = new ConfirmBox(confirmation, lang(lng_box_delete), st::attentionBoxButton); - connect(box, SIGNAL(confirmed()), this, SLOT(onClearHistorySure())); - Ui::showLayer(box); + Ui::show(Box(confirmation, lang(lng_box_delete), st::attentionBoxButton, base::lambda_guarded(this, [this] { + Ui::hideLayer(); + App::main()->clearHistory(peer()); + Ui::showPeerHistory(peer(), ShowAtUnreadMsgId); + }))); } } -void ActionsWidget::onClearHistorySure() { - Ui::hideLayer(); - App::main()->clearHistory(peer()); - Ui::showPeerHistory(peer(), ShowAtUnreadMsgId); -} - void ActionsWidget::onDeleteConversation() { QString confirmation, confirmButton; if (auto user = peer()->asUser()) { @@ -299,19 +295,15 @@ void ActionsWidget::onDeleteConversation() { confirmButton = lang(lng_box_leave); } if (!confirmation.isEmpty()) { - auto box = new ConfirmBox(confirmation, confirmButton, st::attentionBoxButton); - connect(box, SIGNAL(confirmed()), this, SLOT(onDeleteConversationSure())); - Ui::showLayer(box); - } -} - -void ActionsWidget::onDeleteConversationSure() { - Ui::hideLayer(); - Ui::showChatsList(); - if (auto user = peer()->asUser()) { - App::main()->deleteConversation(peer()); - } else if (auto chat = peer()->asChat()) { - App::main()->deleteAndExit(chat); + Ui::show(Box(confirmation, confirmButton, st::attentionBoxButton, base::lambda_guarded(this, [this] { + Ui::hideLayer(); + Ui::showChatsList(); + if (auto user = peer()->asUser()) { + App::main()->deleteConversation(peer()); + } else if (auto chat = peer()->asChat()) { + App::main()->deleteAndExit(chat); + } + }))); } } @@ -327,42 +319,36 @@ void ActionsWidget::onBlockUser() { void ActionsWidget::onUpgradeToSupergroup() { if (auto chat = peer()->asChat()) { - Ui::showLayer(new ConvertToSupergroupBox(chat)); + Ui::show(Box(chat)); } } void ActionsWidget::onDeleteChannel() { - auto box = new ConfirmBox(lang(peer()->isMegagroup() ? lng_sure_delete_group : lng_sure_delete_channel), lang(lng_box_delete), st::attentionBoxButton); - connect(box, SIGNAL(confirmed()), this, SLOT(onDeleteChannelSure())); - Ui::showLayer(box); -} - -void ActionsWidget::onDeleteChannelSure() { - Ui::hideLayer(); - Ui::showChatsList(); - if (auto chat = peer()->migrateFrom()) { - App::main()->deleteAndExit(chat); - } - if (auto channel = peer()->asChannel()) { - MTP::send(MTPchannels_DeleteChannel(channel->inputChannel), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::deleteChannelFailed)); - } + auto text = lang(peer()->isMegagroup() ? lng_sure_delete_group : lng_sure_delete_channel); + Ui::show(Box(text, lang(lng_box_delete), st::attentionBoxButton, base::lambda_guarded(this, [this] { + Ui::hideLayer(); + Ui::showChatsList(); + if (auto chat = peer()->migrateFrom()) { + App::main()->deleteAndExit(chat); + } + if (auto channel = peer()->asChannel()) { + MTP::send(MTPchannels_DeleteChannel(channel->inputChannel), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::deleteChannelFailed)); + } + }))); } void ActionsWidget::onLeaveChannel() { auto channel = peer()->asChannel(); if (!channel) return; - auto box = new ConfirmBox(lang(channel->isMegagroup() ? lng_sure_leave_group : lng_sure_leave_channel), lang(lng_box_leave)); - connect(box, SIGNAL(confirmed()), this, SLOT(onLeaveChannelSure())); - Ui::showLayer(box); -} - -void ActionsWidget::onLeaveChannelSure() { - App::api()->leaveChannel(peer()->asChannel()); + auto text = lang(channel->isMegagroup() ? lng_sure_leave_group : lng_sure_leave_channel); + Ui::show(Box(text, lang(lng_box_leave), base::lambda_guarded(this, [this] { + App::api()->leaveChannel(peer()->asChannel()); + }))); } void ActionsWidget::onReport() { - Ui::showLayer(new ReportBox(peer())); + Ui::show(Box(peer())); } } // namespace Profile diff --git a/Telegram/SourceFiles/profile/profile_block_actions.h b/Telegram/SourceFiles/profile/profile_block_actions.h index a3ebf1911..cd9c9ded8 100644 --- a/Telegram/SourceFiles/profile/profile_block_actions.h +++ b/Telegram/SourceFiles/profile/profile_block_actions.h @@ -54,15 +54,11 @@ private slots: void onBotHelp(); void onBotSettings(); void onClearHistory(); - void onClearHistorySure(); void onDeleteConversation(); - void onDeleteConversationSure(); void onBlockUser(); void onUpgradeToSupergroup(); void onDeleteChannel(); - void onDeleteChannelSure(); void onLeaveChannel(); - void onLeaveChannelSure(); void onReport(); private: diff --git a/Telegram/SourceFiles/profile/profile_block_channel_members.cpp b/Telegram/SourceFiles/profile/profile_block_channel_members.cpp index d8475f908..bf5441883 100644 --- a/Telegram/SourceFiles/profile/profile_block_channel_members.cpp +++ b/Telegram/SourceFiles/profile/profile_block_channel_members.cpp @@ -59,7 +59,7 @@ void ChannelMembersWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) { contentSizeUpdated(); } -void ChannelMembersWidget::addButton(const QString &text, ChildWidget *button, const char *slot) { +void ChannelMembersWidget::addButton(const QString &text, object_ptr *button, const char *slot) { if (text.isEmpty()) { button->destroy(); } else if (*button) { @@ -111,7 +111,7 @@ void ChannelMembersWidget::refreshVisibility() { int ChannelMembersWidget::resizeGetHeight(int newWidth) { int newHeight = contentTop(); - auto resizeButton = [this, &newHeight, newWidth](ChildWidget &button) { + auto resizeButton = [this, &newHeight, newWidth](object_ptr &button) { if (!button) { return; } @@ -132,13 +132,13 @@ int ChannelMembersWidget::resizeGetHeight(int newWidth) { void ChannelMembersWidget::onAdmins() { if (auto channel = peer()->asChannel()) { - Ui::showLayer(new MembersBox(channel, MembersFilter::Admins)); + Ui::show(Box(channel, MembersFilter::Admins)); } } void ChannelMembersWidget::onMembers() { if (auto channel = peer()->asChannel()) { - Ui::showLayer(new MembersBox(channel, MembersFilter::Recent)); + Ui::show(Box(channel, MembersFilter::Recent)); } } diff --git a/Telegram/SourceFiles/profile/profile_block_channel_members.h b/Telegram/SourceFiles/profile/profile_block_channel_members.h index ae3cddef4..5cc3768ed 100644 --- a/Telegram/SourceFiles/profile/profile_block_channel_members.h +++ b/Telegram/SourceFiles/profile/profile_block_channel_members.h @@ -55,10 +55,10 @@ private: void refreshMembers(); void refreshVisibility(); - void addButton(const QString &text, ChildWidget *button, const char *slot); + void addButton(const QString &text, object_ptr *button, const char *slot); - ChildWidget _admins = { nullptr }; - ChildWidget _members = { nullptr }; + object_ptr _admins = { nullptr }; + object_ptr _members = { nullptr }; }; diff --git a/Telegram/SourceFiles/profile/profile_block_group_members.cpp b/Telegram/SourceFiles/profile/profile_block_group_members.cpp index 7477315aa..d4da91f86 100644 --- a/Telegram/SourceFiles/profile/profile_block_group_members.cpp +++ b/Telegram/SourceFiles/profile/profile_block_group_members.cpp @@ -24,6 +24,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "styles/style_profile.h" #include "ui/widgets/labels.h" #include "boxes/confirmbox.h" +#include "mainwidget.h" #include "apiwrap.h" #include "observer_peer.h" #include "lang.h" @@ -49,7 +50,16 @@ GroupMembersWidget::GroupMembersWidget(QWidget *parent, PeerData *peer, TitleVis })); setRemovedCallback([this, peer](PeerData *selectedPeer) { - Ui::showLayer(new KickMemberBox(peer, selectedPeer->asUser())); + auto user = selectedPeer->asUser(); + auto text = lng_profile_sure_kick(lt_user, user->firstName); + Ui::show(Box(text, lang(lng_box_remove), base::lambda_guarded(this, [peer, user] { + Ui::hideLayer(); + if (auto chat = peer->asChat()) { + if (App::main()) App::main()->kickParticipant(chat, user); + } else if (auto channel = peer->asChannel()) { + if (App::api()) App::api()->kickParticipant(channel, user); + } + }))); }); setSelectedCallback([this](PeerData *selectedPeer) { Ui::showPeerProfile(selectedPeer); @@ -206,7 +216,7 @@ void GroupMembersWidget::refreshLimitReached() { QString text = qsl("%1%2%3\n%4 [a href=\"https://telegram.org/blog/supergroups5k\"]%5[/a]").arg(textcmdStartSemibold()).arg(title).arg(textcmdStopSemibold()).arg(body).arg(link); _limitReachedInfo->setRichText(text); _limitReachedInfo->setClickHandlerHook([this](const ClickHandlerPtr &handler, Qt::MouseButton button) { - Ui::showLayer(new ConvertToSupergroupBox(peer()->asChat())); + Ui::show(Box(peer()->asChat())); return false; }); } else if (!limitReachedShown && _limitReachedInfo) { diff --git a/Telegram/SourceFiles/profile/profile_block_group_members.h b/Telegram/SourceFiles/profile/profile_block_group_members.h index b70b6c11d..4d03e5e88 100644 --- a/Telegram/SourceFiles/profile/profile_block_group_members.h +++ b/Telegram/SourceFiles/profile/profile_block_group_members.h @@ -104,7 +104,7 @@ private: void setItemFlags(Item *item, ChannelData *megagroup); bool addUsersToEnd(ChannelData *megagroup); - ChildWidget _limitReachedInfo = { nullptr }; + object_ptr _limitReachedInfo = { nullptr }; QMap _membersByUser; bool _sortByOnline = false; diff --git a/Telegram/SourceFiles/profile/profile_block_info.cpp b/Telegram/SourceFiles/profile/profile_block_info.cpp index 9872fea02..1282274ff 100644 --- a/Telegram/SourceFiles/profile/profile_block_info.cpp +++ b/Telegram/SourceFiles/profile/profile_block_info.cpp @@ -21,8 +21,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "stdafx.h" #include "profile/profile_block_info.h" -#include "profile/profile_common_groups_section.h" -#include "profile/profile_section_memento.h" #include "styles/style_profile.h" #include "ui/widgets/labels.h" #include "ui/widgets/buttons.h" @@ -43,31 +41,12 @@ InfoWidget::InfoWidget(QWidget *parent, PeerData *peer) : BlockWidget(parent, pe auto observeEvents = UpdateFlag::AboutChanged | UpdateFlag::UsernameChanged | UpdateFlag::UserPhoneChanged - | UpdateFlag::UserCanShareContact - | UpdateFlag::UserCommonChatsChanged; + | UpdateFlag::UserCanShareContact; subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(observeEvents, [this](const Notify::PeerUpdate &update) { notifyPeerUpdated(update); })); refreshLabels(); - if (_commonGroups && _commonGroups->isHidden()) { - _commonGroups->show(); - refreshVisibility(); - } -} - -void InfoWidget::showFinished() { - _showFinished = true; - if (_commonGroups && _commonGroups->isHidden() && getCommonGroupsCount() > 0) { - slideCommonGroupsDown(); - } -} - -void InfoWidget::slideCommonGroupsDown() { - _commonGroups->show(); - refreshVisibility(); - _height.start([this] { contentSizeUpdated(); }, isHidden() ? 0 : height(), resizeGetHeight(width()), st::widgetSlideDuration); - contentSizeUpdated(); } void InfoWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) { @@ -85,9 +64,6 @@ void InfoWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) { if (update.flags & (UpdateFlag::UserPhoneChanged | UpdateFlag::UserCanShareContact)) { refreshMobileNumber(); } - if (update.flags & UpdateFlag::UserCommonChatsChanged) { - refreshCommonGroups(); - } refreshVisibility(); contentSizeUpdated(); @@ -140,18 +116,8 @@ int InfoWidget::resizeGetHeight(int newWidth) { moveLabeledText(_mobileNumberLabel, _mobileNumber, nullptr); moveLabeledText(_usernameLabel, _username, nullptr); - if (_commonGroups && !_commonGroups->isHidden()) { - int left = defaultOutlineButtonLeft(); - int availableWidth = newWidth - left - st::profileBlockMarginRight; - accumulate_min(availableWidth, st::profileBlockOneLineWidthMax); - - _commonGroups->resizeToWidth(availableWidth); - _commonGroups->moveToLeft(left, newHeight); - newHeight += _commonGroups->height(); - } - newHeight += st::profileBlockMarginBottom; - return qRound(_height.current(newHeight)); + return newHeight; } void InfoWidget::leaveEvent(QEvent *e) { @@ -164,13 +130,12 @@ void InfoWidget::refreshLabels() { refreshMobileNumber(); refreshUsername(); refreshChannelLink(); - refreshCommonGroups(); refreshVisibility(); } void InfoWidget::refreshVisibility() { - setVisible(_about || _mobileNumber || _username || _channelLink || (_commonGroups && !_commonGroups->isHidden())); + setVisible(_about || _mobileNumber || _username || _channelLink); } void InfoWidget::refreshAbout() { @@ -240,44 +205,8 @@ void InfoWidget::refreshChannelLink() { } } -int InfoWidget::getCommonGroupsCount() const { - if (auto user = peer()->asUser()) { - return user->commonChatsCount(); - } - return 0; -} - -void InfoWidget::refreshCommonGroups() { - if (auto count = getCommonGroupsCount()) { - auto text = lng_profile_common_groups(lt_count, count); - if (_commonGroups) { - _commonGroups->setText(text); - } else { - _commonGroups.create(this, text, st::defaultLeftOutlineButton); - _commonGroups->setClickedCallback([this] { onShowCommonGroups(); }); - _commonGroups->hide(); - if (_showFinished) { - slideCommonGroupsDown(); - } - } - } else if (_commonGroups) { - _commonGroups.destroyDelayed(); - } -} - -void InfoWidget::onShowCommonGroups() { - auto count = getCommonGroupsCount(); - if (count <= 0) { - refreshCommonGroups(); - return; - } - if (auto main = App::main()) { - main->showWideSection(Profile::CommonGroups::SectionMemento(peer())); - } -} - -void InfoWidget::setLabeledText(ChildWidget *labelWidget, const QString &label, - ChildWidget *textWidget, const TextWithEntities &textWithEntities, const QString ©Text) { +void InfoWidget::setLabeledText(object_ptr *labelWidget, const QString &label, + object_ptr *textWidget, const TextWithEntities &textWithEntities, const QString ©Text) { if (labelWidget) labelWidget->destroy(); textWidget->destroy(); if (textWithEntities.text.isEmpty()) return; diff --git a/Telegram/SourceFiles/profile/profile_block_info.h b/Telegram/SourceFiles/profile/profile_block_info.h index dd9956d92..6dff38bb4 100644 --- a/Telegram/SourceFiles/profile/profile_block_info.h +++ b/Telegram/SourceFiles/profile/profile_block_info.h @@ -30,18 +30,12 @@ namespace Notify { struct PeerUpdate; } // namespace Notify -namespace Ui { -class LeftOutlineButton; -} // namespace Ui - namespace Profile { class InfoWidget : public BlockWidget, public RPCSender { public: InfoWidget(QWidget *parent, PeerData *peer); - void showFinished() override; - protected: // Resizes content and counts natural widget height for the desired width. int resizeGetHeight(int newWidth) override; @@ -57,29 +51,20 @@ private: void refreshMobileNumber(); void refreshUsername(); void refreshChannelLink(); - void refreshCommonGroups(); void refreshVisibility(); - int getCommonGroupsCount() const; - void onShowCommonGroups(); - void slideCommonGroupsDown(); - // labelWidget may be nullptr. - void setLabeledText(ChildWidget *labelWidget, const QString &label, - ChildWidget *textWidget, const TextWithEntities &textWithEntities, const QString ©Text); + void setLabeledText(object_ptr *labelWidget, const QString &label, + object_ptr *textWidget, const TextWithEntities &textWithEntities, const QString ©Text); - ChildWidget _about = { nullptr }; - ChildWidget _channelLinkLabel = { nullptr }; - ChildWidget _channelLink = { nullptr }; - ChildWidget _channelLinkShort = { nullptr }; - ChildWidget _mobileNumberLabel = { nullptr }; - ChildWidget _mobileNumber = { nullptr }; - ChildWidget _usernameLabel = { nullptr }; - ChildWidget _username = { nullptr }; - ChildWidget _commonGroups = { nullptr }; - - Animation _height; - bool _showFinished = false; + object_ptr _about = { nullptr }; + object_ptr _channelLinkLabel = { nullptr }; + object_ptr _channelLink = { nullptr }; + object_ptr _channelLinkShort = { nullptr }; + object_ptr _mobileNumberLabel = { nullptr }; + object_ptr _mobileNumber = { nullptr }; + object_ptr _usernameLabel = { nullptr }; + object_ptr _username = { nullptr }; }; diff --git a/Telegram/SourceFiles/profile/profile_block_invite_link.h b/Telegram/SourceFiles/profile/profile_block_invite_link.h index ed9942be7..1e4661ad0 100644 --- a/Telegram/SourceFiles/profile/profile_block_invite_link.h +++ b/Telegram/SourceFiles/profile/profile_block_invite_link.h @@ -48,7 +48,7 @@ private: void refreshLink(); void refreshVisibility(); - ChildWidget _link = { nullptr }; + object_ptr _link = { nullptr }; }; diff --git a/Telegram/SourceFiles/profile/profile_block_settings.cpp b/Telegram/SourceFiles/profile/profile_block_settings.cpp index 7a85981cd..1fd5ee557 100644 --- a/Telegram/SourceFiles/profile/profile_block_settings.cpp +++ b/Telegram/SourceFiles/profile/profile_block_settings.cpp @@ -164,9 +164,9 @@ void SettingsWidget::onNotificationsChange() { void SettingsWidget::onManageAdmins() { if (auto chat = peer()->asChat()) { - Ui::showLayer(new ContactsBox(chat, MembersFilter::Admins)); + Ui::show(Box(chat, MembersFilter::Admins)); } else if (auto channel = peer()->asChannel()) { - Ui::showLayer(new MembersBox(channel, MembersFilter::Admins)); + Ui::show(Box(channel, MembersFilter::Admins)); } } @@ -181,14 +181,11 @@ void SettingsWidget::onInviteLink() { }; auto link = getInviteLink(); - ConfirmBox *box = new ConfirmBox(lang(link.isEmpty() ? lng_group_invite_about : lng_group_invite_about_new)); - connect(box, SIGNAL(confirmed()), this, SLOT(onInviteLinkSure())); - Ui::showLayer(box); -} - -void SettingsWidget::onInviteLinkSure() { - Ui::hideLayer(); - App::api()->exportInviteLink(peer()); + auto text = lang(link.isEmpty() ? lng_group_invite_about : lng_group_invite_about_new); + Ui::show(Box(text, base::lambda_guarded(this, [this] { + Ui::hideLayer(); + App::api()->exportInviteLink(peer()); + }))); } } // namespace Profile diff --git a/Telegram/SourceFiles/profile/profile_block_settings.h b/Telegram/SourceFiles/profile/profile_block_settings.h index ba727cb57..e8f5fab58 100644 --- a/Telegram/SourceFiles/profile/profile_block_settings.h +++ b/Telegram/SourceFiles/profile/profile_block_settings.h @@ -47,7 +47,6 @@ private slots: void onNotificationsChange(); void onManageAdmins(); void onInviteLink(); - void onInviteLinkSure(); private: // Observed notifications. @@ -58,12 +57,12 @@ private: void refreshManageAdminsButton(); void refreshInviteLinkButton(); - ChildWidget _enableNotifications; + object_ptr _enableNotifications; // In groups: creator of non-deactivated groups can see this link. // In channels: creator of supergroup can see this link. - ChildWidget _manageAdmins = { nullptr }; - ChildWidget _inviteLink = { nullptr }; + object_ptr _manageAdmins = { nullptr }; + object_ptr _inviteLink = { nullptr }; }; diff --git a/Telegram/SourceFiles/profile/profile_block_shared_media.cpp b/Telegram/SourceFiles/profile/profile_block_shared_media.cpp index bece07ce2..4ec6a965f 100644 --- a/Telegram/SourceFiles/profile/profile_block_shared_media.cpp +++ b/Telegram/SourceFiles/profile/profile_block_shared_media.cpp @@ -21,6 +21,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "stdafx.h" #include "profile/profile_block_shared_media.h" +#include "profile/profile_common_groups_section.h" +#include "profile/profile_section_memento.h" #include "styles/style_profile.h" #include "observer_peer.h" #include "ui/widgets/buttons.h" @@ -51,7 +53,8 @@ QString getButtonText(MediaOverviewType type, int count) { SharedMediaWidget::SharedMediaWidget(QWidget *parent, PeerData *peer) : BlockWidget(parent, peer, lang(lng_profile_shared_media)) , _history(App::history(peer)) , _migrated(peer->migrateFrom() ? App::history(peer->migrateFrom()) : nullptr) { - auto observeEvents = Notify::PeerUpdate::Flag::SharedMediaChanged; + auto observeEvents = Notify::PeerUpdate::Flag::SharedMediaChanged + | Notify::PeerUpdate::Flag::UserCommonChatsChanged; subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(observeEvents, [this](const Notify::PeerUpdate &update) { notifyPeerUpdated(update); })); @@ -77,6 +80,10 @@ void SharedMediaWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) { updated = true; } } + if (update.flags & Notify::PeerUpdate::Flag::UserCommonChatsChanged) { + refreshCommonGroups(); + updated = true; + } if (updated) { refreshVisibility(); @@ -96,6 +103,7 @@ void SharedMediaWidget::refreshButtons() { for (int typeIndex = 0; typeIndex < OverviewCount; ++typeIndex) { refreshButton(static_cast(typeIndex)); } + refreshCommonGroups(); } void SharedMediaWidget::refreshButton(MediaOverviewType type) { @@ -125,7 +133,7 @@ void SharedMediaWidget::refreshVisibility() { return; } } - hide(); + setVisible(_commonGroups != nullptr); } void SharedMediaWidget::onMediaChosen() { @@ -151,6 +159,46 @@ void SharedMediaWidget::resizeButtons(int newWidth, int *top) { button->moveToLeft(left, *top); *top += button->height(); } + + if (_commonGroups) { + _commonGroups->resizeToWidth(availableWidth); + _commonGroups->moveToLeft(left, *top); + *top += _commonGroups->height(); + } + +} + +int SharedMediaWidget::getCommonGroupsCount() const { + if (auto user = peer()->asUser()) { + return user->commonChatsCount(); + } + return 0; +} + +void SharedMediaWidget::refreshCommonGroups() { + if (auto count = getCommonGroupsCount()) { + auto text = lng_profile_common_groups(lt_count, count); + if (_commonGroups) { + _commonGroups->setText(text); + } else { + _commonGroups.create(this, text, st::defaultLeftOutlineButton); + _commonGroups->setClickedCallback([this] { onShowCommonGroups(); }); + _commonGroups->show(); + } + } else if (_commonGroups) { + _commonGroups.destroyDelayed(); + } +} + +void SharedMediaWidget::onShowCommonGroups() { + auto count = getCommonGroupsCount(); + if (count <= 0) { + refreshCommonGroups(); + return; + } + if (auto main = App::main()) { + main->showWideSection(Profile::CommonGroups::SectionMemento(peer())); + } } } // namespace Profile diff --git a/Telegram/SourceFiles/profile/profile_block_shared_media.h b/Telegram/SourceFiles/profile/profile_block_shared_media.h index f225778b9..928472131 100644 --- a/Telegram/SourceFiles/profile/profile_block_shared_media.h +++ b/Telegram/SourceFiles/profile/profile_block_shared_media.h @@ -51,11 +51,18 @@ private: void refreshButtons(); void refreshButton(MediaOverviewType type); + void refreshCommonGroups(); void refreshVisibility(); + int getCommonGroupsCount() const; + void onShowCommonGroups(); + void slideCommonGroupsDown(); + void resizeButtons(int newWidth, int *top); Ui::LeftOutlineButton *_mediaButtons[OverviewCount] = { nullptr }; + object_ptr _commonGroups = { nullptr }; + History *_history; History *_migrated; diff --git a/Telegram/SourceFiles/profile/profile_common_groups_section.cpp b/Telegram/SourceFiles/profile/profile_common_groups_section.cpp index 274f9ce82..f7a6a6050 100644 --- a/Telegram/SourceFiles/profile/profile_common_groups_section.cpp +++ b/Telegram/SourceFiles/profile/profile_common_groups_section.cpp @@ -43,10 +43,10 @@ constexpr int kCommonGroupsPerPage = 40; } // namespace -Window::SectionWidget *SectionMemento::createWidget(QWidget *parent, const QRect &geometry) const { - auto result = new Widget(parent, _peer); +object_ptr SectionMemento::createWidget(QWidget *parent, const QRect &geometry) const { + auto result = object_ptr(parent, _peer); result->setInternalState(geometry, this); - return result; + return std_::move(result); } FixedBar::FixedBar(QWidget *parent) : TWidget(parent) @@ -333,7 +333,6 @@ InnerWidget::~InnerWidget() { Widget::Widget(QWidget *parent, PeerData *peer) : Window::SectionWidget(parent) , _scroll(this, st::settingsScroll) -, _inner(this, peer) , _fixedBar(this) , _fixedBarShadow(this, st::shadowColor) { _fixedBar->move(0, 0); @@ -344,7 +343,7 @@ Widget::Widget(QWidget *parent, PeerData *peer) : Window::SectionWidget(parent) updateAdaptiveLayout(); subscribe(Adaptive::Changed(), [this]() { updateAdaptiveLayout(); }); - _scroll->setOwnedWidget(_inner); + _inner = _scroll->setOwnedWidget(object_ptr(this, peer)); _scroll->move(0, _fixedBar->height()); _scroll->show(); diff --git a/Telegram/SourceFiles/profile/profile_common_groups_section.h b/Telegram/SourceFiles/profile/profile_common_groups_section.h index b6abf408c..8e8bd40ee 100644 --- a/Telegram/SourceFiles/profile/profile_common_groups_section.h +++ b/Telegram/SourceFiles/profile/profile_common_groups_section.h @@ -43,7 +43,7 @@ public: SectionMemento(PeerData *peer) : _peer(peer) { } - Window::SectionWidget *createWidget(QWidget *parent, const QRect &geometry) const override; + object_ptr createWidget(QWidget *parent, const QRect &geometry) const override; PeerData *getPeer() const { return _peer; @@ -86,7 +86,7 @@ public slots: void onBack(); private: - ChildWidget _backButton; + object_ptr _backButton; bool _animatingMode = false; @@ -205,10 +205,10 @@ private: void saveState(SectionMemento *memento) const; void restoreState(const SectionMemento *memento); - ChildWidget _scroll; - ChildWidget _inner; - ChildWidget _fixedBar; - ChildWidget _fixedBarShadow; + object_ptr _scroll; + QPointer _inner; + object_ptr _fixedBar; + object_ptr _fixedBarShadow; }; diff --git a/Telegram/SourceFiles/profile/profile_cover.cpp b/Telegram/SourceFiles/profile/profile_cover.cpp index 766ea6484..c4cfca623 100644 --- a/Telegram/SourceFiles/profile/profile_cover.cpp +++ b/Telegram/SourceFiles/profile/profile_cover.cpp @@ -280,7 +280,7 @@ void CoverWidget::dragEnterEvent(QDragEnterEvent *e) { } else { subtitle = lang(lng_profile_drop_area_subtitle_channel); } - _dropArea = new CoverDropArea(this, title, subtitle); + _dropArea.create(this, title, subtitle); resizeDropArea(width()); } _dropArea->showAnimated(); @@ -516,13 +516,12 @@ void CoverWidget::notifyFileQueryUpdated(const FileDialog::QueryUpdate &update) void CoverWidget::showSetPhotoBox(const QImage &img) { if (img.isNull() || img.width() > 10 * img.height() || img.height() > 10 * img.width()) { - Ui::showLayer(new InformBox(lang(lng_bad_photo))); + Ui::show(Box(lang(lng_bad_photo))); return; } - auto box = new PhotoCropBox(img, _peer); - connect(box, SIGNAL(closed(LayerWidget*)), this, SLOT(onPhotoUploadStatusChanged())); - Ui::showLayer(box); + auto box = Ui::show(Box(img, _peer)); + connect(box, SIGNAL(closed()), this, SLOT(onPhotoUploadStatusChanged())); } void CoverWidget::onPhotoUploadStatusChanged(PeerId peerId) { @@ -534,22 +533,22 @@ void CoverWidget::onPhotoUploadStatusChanged(PeerId peerId) { void CoverWidget::onAddMember() { if (_peerChat) { if (_peerChat->count >= Global::ChatSizeMax() && _peerChat->amCreator()) { - Ui::showLayer(new ConvertToSupergroupBox(_peerChat)); + Ui::show(Box(_peerChat)); } else { - Ui::showLayer(new ContactsBox(_peerChat, MembersFilter::Recent)); + Ui::show(Box(_peerChat, MembersFilter::Recent)); } } else if (_peerChannel && _peerChannel->mgInfo) { MembersAlreadyIn already; for_const (auto user, _peerChannel->mgInfo->lastParticipants) { already.insert(user); } - Ui::showLayer(new ContactsBox(_peerChannel, MembersFilter::Recent, already)); + Ui::show(Box(_peerChannel, MembersFilter::Recent, already)); } } void CoverWidget::onAddBotToGroup() { if (_peerUser && _peerUser->botInfo) { - Ui::showLayer(new ContactsBox(_peerUser)); + Ui::show(Box(_peerUser)); } } diff --git a/Telegram/SourceFiles/profile/profile_cover.h b/Telegram/SourceFiles/profile/profile_cover.h index db65d2e0c..48ec61d06 100644 --- a/Telegram/SourceFiles/profile/profile_cover.h +++ b/Telegram/SourceFiles/profile/profile_cover.h @@ -117,11 +117,11 @@ private: ChannelData *_peerChannel; ChannelData *_peerMegagroup; - ChildWidget _userpicButton; - ChildWidget _dropArea = { nullptr }; + object_ptr _userpicButton; + object_ptr _dropArea = { nullptr }; - ChildWidget _name; - ChildWidget _cancelPhotoUpload = { nullptr }; + object_ptr _name; + object_ptr _cancelPhotoUpload = { nullptr }; QPoint _statusPosition; QString _statusText; diff --git a/Telegram/SourceFiles/profile/profile_fixed_bar.cpp b/Telegram/SourceFiles/profile/profile_fixed_bar.cpp index 934e86dc5..79caa400a 100644 --- a/Telegram/SourceFiles/profile/profile_fixed_bar.cpp +++ b/Telegram/SourceFiles/profile/profile_fixed_bar.cpp @@ -151,22 +151,22 @@ void FixedBar::onBack() { } void FixedBar::onEditChannel() { - Ui::showLayer(new EditChannelBox(_peerMegagroup ? _peerMegagroup : _peerChannel)); + Ui::show(Box(_peerMegagroup ? _peerMegagroup : _peerChannel)); } void FixedBar::onEditGroup() { - Ui::showLayer(new EditNameTitleBox(_peerChat)); + Ui::show(Box(_peerChat)); } void FixedBar::onAddContact() { auto firstName = _peerUser->firstName; auto lastName = _peerUser->lastName; auto phone = _peerUser->phone().isEmpty() ? App::phoneFromSharedContact(peerToUser(_peer->id)) : _peerUser->phone(); - Ui::showLayer(new AddContactBox(firstName, lastName, phone)); + Ui::show(Box(firstName, lastName, phone)); } void FixedBar::onEditContact() { - Ui::showLayer(new AddContactBox(_peerUser)); + Ui::show(Box(_peerUser)); } void FixedBar::onShareContact() { @@ -174,27 +174,21 @@ void FixedBar::onShareContact() { } void FixedBar::onDeleteContact() { - ConfirmBox *box = new ConfirmBox(lng_sure_delete_contact(lt_contact, App::peerName(_peerUser)), lang(lng_box_delete)); - connect(box, SIGNAL(confirmed()), this, SLOT(onDeleteContactSure())); - Ui::showLayer(box); -} - -void FixedBar::onDeleteContactSure() { - Ui::showChatsList(); - Ui::hideLayer(); - MTP::send(MTPcontacts_DeleteContact(_peerUser->inputUser), App::main()->rpcDone(&MainWidget::deletedContact, _peerUser)); + auto text = lng_sure_delete_contact(lt_contact, App::peerName(_peerUser)); + Ui::show(Box(text, lang(lng_box_delete), base::lambda_guarded(this, [this] { + Ui::showChatsList(); + Ui::hideLayer(); + MTP::send(MTPcontacts_DeleteContact(_peerUser->inputUser), App::main()->rpcDone(&MainWidget::deletedContact, _peerUser)); + }))); } void FixedBar::onLeaveGroup() { - ConfirmBox *box = new ConfirmBox(lng_sure_delete_and_exit(lt_group, App::peerName(_peerChat)), lang(lng_box_leave), st::attentionBoxButton); - connect(box, SIGNAL(confirmed()), this, SLOT(onLeaveGroupSure())); - Ui::showLayer(box); -} - -void FixedBar::onLeaveGroupSure() { - Ui::showChatsList(); - Ui::hideLayer(); - App::main()->deleteAndExit(_peerChat); + auto text = lng_sure_delete_and_exit(lt_group, App::peerName(_peerChat)); + Ui::show(Box(text, lang(lng_box_leave), st::attentionBoxButton, base::lambda_guarded(this, [this] { + Ui::showChatsList(); + Ui::hideLayer(); + App::main()->deleteAndExit(_peerChat); + }))); } int FixedBar::resizeGetHeight(int newWidth) { diff --git a/Telegram/SourceFiles/profile/profile_fixed_bar.h b/Telegram/SourceFiles/profile/profile_fixed_bar.h index 18fa64d05..d78218120 100644 --- a/Telegram/SourceFiles/profile/profile_fixed_bar.h +++ b/Telegram/SourceFiles/profile/profile_fixed_bar.h @@ -61,9 +61,7 @@ private slots: void onEditContact(); void onShareContact(); void onDeleteContact(); - void onDeleteContactSure(); void onLeaveGroup(); - void onLeaveGroupSure(); private: void notifyPeerUpdate(const Notify::PeerUpdate &update); @@ -94,7 +92,7 @@ private: ChannelData *_peerChannel; ChannelData *_peerMegagroup; - ChildWidget _backButton; + object_ptr _backButton; int _currentAction = 0; struct RightAction { diff --git a/Telegram/SourceFiles/profile/profile_inner_widget.h b/Telegram/SourceFiles/profile/profile_inner_widget.h index 877ec6612..4a6d22783 100644 --- a/Telegram/SourceFiles/profile/profile_inner_widget.h +++ b/Telegram/SourceFiles/profile/profile_inner_widget.h @@ -102,7 +102,7 @@ private: int _visibleTop = 0; int _visibleBottom = 0; - ChildWidget _cover; + object_ptr _cover; int _blocksLeft = 0; // Caching countBlocksLeft() result. int _blocksTop = 0; diff --git a/Telegram/SourceFiles/profile/profile_section_memento.cpp b/Telegram/SourceFiles/profile/profile_section_memento.cpp index e64b23a2d..5ffa5813a 100644 --- a/Telegram/SourceFiles/profile/profile_section_memento.cpp +++ b/Telegram/SourceFiles/profile/profile_section_memento.cpp @@ -25,10 +25,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org namespace Profile { -Window::SectionWidget *SectionMemento::createWidget(QWidget *parent, const QRect &geometry) const { - auto result = new Widget(parent, _peer); +object_ptr SectionMemento::createWidget(QWidget *parent, const QRect &geometry) const { + auto result = object_ptr(parent, _peer); result->setInternalState(geometry, this); - return result; + return std_::move(result); } } // namespace Profile diff --git a/Telegram/SourceFiles/profile/profile_section_memento.h b/Telegram/SourceFiles/profile/profile_section_memento.h index 73505f023..d6bb9a660 100644 --- a/Telegram/SourceFiles/profile/profile_section_memento.h +++ b/Telegram/SourceFiles/profile/profile_section_memento.h @@ -31,7 +31,7 @@ public: SectionMemento(PeerData *peer) : _peer(peer) { } - Window::SectionWidget *createWidget(QWidget *parent, const QRect &geometry) const override; + object_ptr createWidget(QWidget *parent, const QRect &geometry) const override; PeerData *getPeer() const { return _peer; diff --git a/Telegram/SourceFiles/profile/profile_widget.cpp b/Telegram/SourceFiles/profile/profile_widget.cpp index 54120e3b5..6c712f003 100644 --- a/Telegram/SourceFiles/profile/profile_widget.cpp +++ b/Telegram/SourceFiles/profile/profile_widget.cpp @@ -27,6 +27,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "profile/profile_section_memento.h" #include "mainwindow.h" #include "application.h" +#include "ui/effects/widget_fade_wrap.h" #include "ui/widgets/scroll_area.h" #include "ui/widgets/shadow.h" @@ -34,19 +35,18 @@ namespace Profile { Widget::Widget(QWidget *parent, PeerData *peer) : Window::SectionWidget(parent) , _scroll(this, st::settingsScroll) -, _inner(this, peer) , _fixedBar(this, peer) -, _fixedBarShadow(this, st::shadowColor) { +, _fixedBarShadow(this, object_ptr(this, st::shadowColor)) { _fixedBar->move(0, 0); _fixedBar->resizeToWidth(width()); _fixedBar->show(); - _fixedBarShadow->setMode(Ui::ToggleableShadow::Mode::HiddenFast); + _fixedBarShadow->hideFast(); _fixedBarShadow->raise(); updateAdaptiveLayout(); subscribe(Adaptive::Changed(), [this]() { updateAdaptiveLayout(); }); - _scroll->setOwnedWidget(_inner); + _inner = _scroll->setOwnedWidget(object_ptr(this, peer)); _scroll->move(0, _fixedBar->height()); _scroll->show(); @@ -63,11 +63,11 @@ PeerData *Widget::peer() const { } bool Widget::hasTopBarShadow() const { - return _fixedBarShadow->isFullyShown(); + return !_fixedBarShadow->isHidden() && !_fixedBarShadow->animating(); } QPixmap Widget::grabForShowAnimation(const Window::SectionSlideParams ¶ms) { - if (params.withTopBarShadow) _fixedBarShadow->hide(); + if (params.withTopBarShadow || !_scroll->scrollTop()) _fixedBarShadow->hide(); auto result = myGrab(this); if (params.withTopBarShadow) _fixedBarShadow->show(); return result; @@ -108,7 +108,8 @@ void Widget::restoreState(const SectionMemento *memento) { _inner->restoreState(memento); auto scrollTop = memento->getScrollTop(); _scroll->scrollToY(scrollTop); - _fixedBarShadow->setMode((scrollTop > 0) ? Ui::ToggleableShadow::Mode::ShownFast : Ui::ToggleableShadow::Mode::HiddenFast); + updateScrollState(); + _fixedBarShadow->finishAnimation(); } void Widget::resizeEvent(QResizeEvent *e) { @@ -118,7 +119,7 @@ void Widget::resizeEvent(QResizeEvent *e) { int newScrollTop = _scroll->scrollTop() + topDelta(); _fixedBar->resizeToWidth(width()); - _fixedBarShadow->resize(width(), st::lineWidth); + _fixedBarShadow->entity()->resize(width(), st::lineWidth); QSize scrollSize(width(), height() - _fixedBar->height()); if (_scroll->size() != scrollSize) { @@ -131,16 +132,22 @@ void Widget::resizeEvent(QResizeEvent *e) { if (topDelta()) { _scroll->scrollToY(newScrollTop); } - int scrollTop = _scroll->scrollTop(); - _inner->setVisibleTopBottom(scrollTop, scrollTop + _scroll->height()); - _fixedBarShadow->setMode((scrollTop > 0) ? Ui::ToggleableShadow::Mode::Shown : Ui::ToggleableShadow::Mode::Hidden); + updateScrollState(); + } +} + +void Widget::updateScrollState() { + auto scrollTop = _scroll->scrollTop(); + _inner->setVisibleTopBottom(scrollTop, scrollTop + _scroll->height()); + if (scrollTop > 0) { + _fixedBarShadow->showAnimated(); + } else { + _fixedBarShadow->hideAnimated(); } } void Widget::onScroll() { - int scrollTop = _scroll->scrollTop(); - _inner->setVisibleTopBottom(scrollTop, scrollTop + _scroll->height()); - _fixedBarShadow->setMode((scrollTop > 0) ? Ui::ToggleableShadow::Mode::Shown : Ui::ToggleableShadow::Mode::Hidden); + updateScrollState(); } void Widget::showAnimatedHook() { @@ -149,6 +156,9 @@ void Widget::showAnimatedHook() { void Widget::showFinishedHook() { _fixedBar->setAnimatingMode(false); + if (!_scroll->scrollTop()) { + _fixedBarShadow->hide(); + } _inner->showFinished(); } diff --git a/Telegram/SourceFiles/profile/profile_widget.h b/Telegram/SourceFiles/profile/profile_widget.h index d3cade576..9a33fe82a 100644 --- a/Telegram/SourceFiles/profile/profile_widget.h +++ b/Telegram/SourceFiles/profile/profile_widget.h @@ -24,7 +24,9 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org namespace Ui { class ScrollArea; -class ToggleableShadow; +class PlainShadow; +template +class WidgetFadeWrap; } // namespace Ui namespace Profile { @@ -64,14 +66,15 @@ private slots: void onScroll(); private: + void updateScrollState(); void updateAdaptiveLayout(); void saveState(SectionMemento *memento) const; void restoreState(const SectionMemento *memento); - ChildWidget _scroll; - ChildWidget _inner; - ChildWidget _fixedBar; - ChildWidget _fixedBarShadow; + object_ptr _scroll; + QPointer _inner; + object_ptr _fixedBar; + object_ptr> _fixedBarShadow; }; diff --git a/Telegram/SourceFiles/settings/settings.style b/Telegram/SourceFiles/settings/settings.style index 3337fb70b..11d31930f 100644 --- a/Telegram/SourceFiles/settings/settings.style +++ b/Telegram/SourceFiles/settings/settings.style @@ -24,7 +24,7 @@ using "dialogs/dialogs.style"; using "ui/widgets/widgets.style"; using "boxes/boxes.style"; -settingsScroll: FlatScroll(defaultFlatScroll) { +settingsScroll: ScrollArea(defaultScrollArea) { bottomsh: 0px; topsh: 0px; } @@ -34,15 +34,12 @@ settingsMaxPadding: 48px; settingsMinPadding: 32px; settingsMargin: 48px; -settingsFixedBarHeight: 52px; -settingsFixedBarFont: font(14px semibold); -settingsFixedBarTextLeft: 20px; -settingsFixedBarTextTop: 16px; -settingsFixedBarClose: IconButton(boxBlockTitleClose) { +settingsFixedBarHeight: boxLayerTitleHeight; +settingsFixedBarFont: boxTitleFont; +settingsFixedBarTextPosition: boxLayerTitlePosition; +settingsFixedBarClose: IconButton(boxTitleClose) { width: settingsFixedBarHeight; height: settingsFixedBarHeight; - - rippleAreaPosition: point(6px, 6px); } settingsMarginTop: 34px; diff --git a/Telegram/SourceFiles/settings/settings_advanced_widget.cpp b/Telegram/SourceFiles/settings/settings_advanced_widget.cpp index 73ee6bd43..567276f6f 100644 --- a/Telegram/SourceFiles/settings/settings_advanced_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_advanced_widget.cpp @@ -72,37 +72,42 @@ void AdvancedWidget::createControls() { } void AdvancedWidget::onManageLocalStorage() { - Ui::showLayer(new LocalStorageBox()); + Ui::show(Box()); } #ifndef TDESKTOP_DISABLE_NETWORK_PROXY void AdvancedWidget::connectionTypeUpdated() { - QString connection; - switch (Global::ConnectionType()) { - case dbictAuto: { - QString transport = MTP::dctransport(); - connection = transport.isEmpty() ? lang(lng_connection_auto_connecting) : lng_connection_auto(lt_transport, transport); - } break; - case dbictHttpProxy: - case dbictTcpProxy: { - QString transport = MTP::dctransport(); - connection = transport.isEmpty() ? lang(lng_connection_proxy_connecting) : lng_connection_proxy(lt_transport, transport); - } break; - } - _connectionType->link()->setText(connection); + auto connection = [] { + switch (Global::ConnectionType()) { + case dbictHttpProxy: + case dbictTcpProxy: { + auto transport = MTP::dctransport(); + return transport.isEmpty() ? lang(lng_connection_proxy_connecting) : lng_connection_proxy(lt_transport, transport); + } break; + case dbictAuto: + default: { + auto transport = MTP::dctransport(); + return transport.isEmpty() ? lang(lng_connection_auto_connecting) : lng_connection_auto(lt_transport, transport); + } break; + } + }; + _connectionType->link()->setText(connection()); resizeToWidth(width()); } void AdvancedWidget::onConnectionType() { - Ui::showLayer(new ConnectionBox()); + Ui::show(Box()); } #endif // !TDESKTOP_DISABLE_NETWORK_PROXY void AdvancedWidget::onAskQuestion() { - ConfirmBox *box = new ConfirmBox(lang(lng_settings_ask_sure), lang(lng_settings_ask_ok), st::defaultBoxButton, lang(lng_settings_faq_button)); - connect(box, SIGNAL(confirmed()), this, SLOT(onAskQuestionSure())); - connect(box, SIGNAL(cancelPressed()), this, SLOT(onTelegramFAQ())); - Ui::showLayer(box); + auto box = Box(lang(lng_settings_ask_sure), lang(lng_settings_ask_ok), lang(lng_settings_faq_button), base::lambda_guarded(this, [this] { + onAskQuestionSure(); + }), base::lambda_guarded(this, [this] { + onTelegramFAQ(); + })); + box->setStrictCancel(true); + Ui::show(std_::move(box)); } void AdvancedWidget::onAskQuestionSure() { diff --git a/Telegram/SourceFiles/settings/settings_advanced_widget.h b/Telegram/SourceFiles/settings/settings_advanced_widget.h index 5b26f08e8..81786284e 100644 --- a/Telegram/SourceFiles/settings/settings_advanced_widget.h +++ b/Telegram/SourceFiles/settings/settings_advanced_widget.h @@ -48,13 +48,13 @@ private: #endif // !TDESKTOP_DISABLE_NETWORK_PROXY void supportGot(const MTPhelp_Support &support); - ChildWidget _manageLocalStorage = { nullptr }; + object_ptr _manageLocalStorage = { nullptr }; #ifndef TDESKTOP_DISABLE_NETWORK_PROXY - ChildWidget _connectionType = { nullptr }; + object_ptr _connectionType = { nullptr }; #endif // !TDESKTOP_DISABLE_NETWORK_PROXY - ChildWidget _askQuestion = { nullptr }; - ChildWidget _telegramFAQ = { nullptr }; - ChildWidget _logOut = { nullptr }; + object_ptr _askQuestion = { nullptr }; + object_ptr _telegramFAQ = { nullptr }; + object_ptr _logOut = { nullptr }; mtpRequestId _supportGetRequest = 0; diff --git a/Telegram/SourceFiles/settings/settings_background_widget.cpp b/Telegram/SourceFiles/settings/settings_background_widget.cpp index 737d87bed..699e553cf 100644 --- a/Telegram/SourceFiles/settings/settings_background_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_background_widget.cpp @@ -203,7 +203,7 @@ void BackgroundWidget::createControls() { } void BackgroundWidget::onChooseFromGallery() { - Ui::showLayer(new BackgroundBox()); + Ui::show(Box()); } void BackgroundWidget::needBackgroundUpdate(bool tile) { diff --git a/Telegram/SourceFiles/settings/settings_background_widget.h b/Telegram/SourceFiles/settings/settings_background_widget.h index 5f749dc1a..63e2129fb 100644 --- a/Telegram/SourceFiles/settings/settings_background_widget.h +++ b/Telegram/SourceFiles/settings/settings_background_widget.h @@ -52,8 +52,8 @@ private: void step_radial(TimeMs ms, bool timer); QPixmap _background; - ChildWidget _chooseFromGallery; - ChildWidget _chooseFromFile; + object_ptr _chooseFromGallery; + object_ptr _chooseFromFile; Ui::RadialAnimation _radial; @@ -76,9 +76,9 @@ private: void needBackgroundUpdate(bool tile); void notifyFileQueryUpdated(const FileDialog::QueryUpdate &update); - ChildWidget _background = { nullptr }; - ChildWidget _tile = { nullptr }; - ChildWidget> _adaptive = { nullptr }; + object_ptr _background = { nullptr }; + object_ptr _tile = { nullptr }; + object_ptr> _adaptive = { nullptr }; FileDialog::QueryId _chooseFromFileQueryId = 0; diff --git a/Telegram/SourceFiles/settings/settings_block_widget.cpp b/Telegram/SourceFiles/settings/settings_block_widget.cpp index 4ed134200..261b32586 100644 --- a/Telegram/SourceFiles/settings/settings_block_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_block_widget.cpp @@ -86,17 +86,17 @@ void BlockWidget::rowHeightUpdated() { } } -void BlockWidget::createChildRow(ChildWidget &child, style::margins &margin, const QString &text, const char *slot, bool checked) { +void BlockWidget::createChildRow(object_ptr &child, style::margins &margin, const QString &text, const char *slot, bool checked) { child.create(this, text, checked, st::defaultBoxCheckbox); connect(child, SIGNAL(changed()), this, slot); } -void BlockWidget::createChildRow(ChildWidget &child, style::margins &margin, const QString &group, int value, const QString &text, const char *slot, bool checked) { +void BlockWidget::createChildRow(object_ptr &child, style::margins &margin, const QString &group, int value, const QString &text, const char *slot, bool checked) { child .create(this, group, value, text, checked, st::defaultBoxCheckbox); connect(child, SIGNAL(changed()), this, slot); } -void BlockWidget::createChildRow(ChildWidget &child, style::margins &margin, const QString &text, const char *slot, const style::LinkButton &st) { +void BlockWidget::createChildRow(object_ptr &child, style::margins &margin, const QString &text, const char *slot, const style::LinkButton &st) { child .create(this, text, st); connect(child, SIGNAL(clicked()), this, slot); } diff --git a/Telegram/SourceFiles/settings/settings_block_widget.h b/Telegram/SourceFiles/settings/settings_block_widget.h index fcc55fc3c..f754b8b56 100644 --- a/Telegram/SourceFiles/settings/settings_block_widget.h +++ b/Telegram/SourceFiles/settings/settings_block_widget.h @@ -69,7 +69,7 @@ protected: } template - Widget *addChildRow(ChildWidget &child, style::margins margin, Args&&... args) { + Widget *addChildRow(object_ptr &child, style::margins margin, Args&&... args) { createChildRow(child, margin, std_::forward(args)...); addCreatedRow(child, margin); return child; @@ -77,20 +77,18 @@ protected: private: template - void createChildRow(ChildWidget> &child, style::margins &margin, const style::margins &padding, Args&&... args) { - ChildWidget plainChild = { nullptr }; - createChildRow(plainChild, margin, std_::forward(args)...); - child.create(this, plainChild, padding, [this]() { - rowHeightUpdated(); - }); + void createChildRow(object_ptr> &child, style::margins &margin, const style::margins &padding, Args&&... args) { + object_ptr entity = { nullptr }; + createChildRow(entity, margin, std_::forward(args)...); + child.create(this, std_::move(entity), padding, [this] { rowHeightUpdated(); }); margin.setLeft(margin.left() - padding.left()); margin.setTop(margin.top() - padding.top()); margin.setRight(margin.right() - padding.right()); margin.setBottom(margin.bottom() - padding.bottom()); } - void createChildRow(ChildWidget &child, style::margins &margin, const QString &text, const char *slot, bool checked); - void createChildRow(ChildWidget &child, style::margins &margin, const QString &group, int value, const QString &text, const char *slot, bool checked); - void createChildRow(ChildWidget &child, style::margins &margin, const QString &text, const char *slot, const style::LinkButton &st = st::boxLinkButton); + void createChildRow(object_ptr &child, style::margins &margin, const QString &text, const char *slot, bool checked); + void createChildRow(object_ptr &child, style::margins &margin, const QString &group, int value, const QString &text, const char *slot, bool checked); + void createChildRow(object_ptr &child, style::margins &margin, const QString &text, const char *slot, const style::LinkButton &st = st::boxLinkButton); void addCreatedRow(TWidget *child, const style::margins &margin); void rowHeightUpdated(); @@ -112,8 +110,8 @@ private: !std_::is_same::value>; template > - void createChildRow(ChildWidget &child, style::margins &margin, Args&&... args) { - child = new Widget(this, std_::forward(args)...); + void createChildRow(object_ptr &child, style::margins &margin, Args&&... args) { + child.create(this, std_::forward(args)...); } void paintTitle(Painter &p); diff --git a/Telegram/SourceFiles/settings/settings_chat_settings_widget.cpp b/Telegram/SourceFiles/settings/settings_chat_settings_widget.cpp index d1546d719..445998bb5 100644 --- a/Telegram/SourceFiles/settings/settings_chat_settings_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_chat_settings_widget.cpp @@ -48,6 +48,10 @@ void LabeledLink::setLink(const QString &text) { _link.create(this, text); } +Ui::LinkButton *LabeledLink::link() const { + return _link; +} + int LabeledLink::naturalWidth() const { return _label->naturalWidth() + st::normalFont->spacew + _link->naturalWidth(); } @@ -117,20 +121,16 @@ QString DownloadPathState::downloadPathText() const { }; void DownloadPathState::onDownloadPath() { - Ui::showLayer(new DownloadPathBox()); + Ui::show(Box()); } void DownloadPathState::onClear() { - ConfirmBox *box = new ConfirmBox(lang(lng_sure_clear_downloads)); - connect(box, SIGNAL(confirmed()), this, SLOT(onClearSure())); - Ui::showLayer(box); -} - -void DownloadPathState::onClearSure() { - Ui::hideLayer(); - App::wnd()->tempDirDelete(Local::ClearManagerDownloads); - _state = State::Clearing; - updateControls(); + Ui::show(Box(lang(lng_sure_clear_downloads), base::lambda_guarded(this, [this] { + Ui::hideLayer(); + App::wnd()->tempDirDelete(Local::ClearManagerDownloads); + _state = State::Clearing; + updateControls(); + }))); } void DownloadPathState::onTempDirCleared(int task) { @@ -189,7 +189,7 @@ void ChatSettingsWidget::onReplaceEmoji() { } void ChatSettingsWidget::onViewList() { - Ui::showLayer(new EmojiBox()); + Ui::show(Box()); } void ChatSettingsWidget::onDontAskDownloadPath() { @@ -219,11 +219,11 @@ void ChatSettingsWidget::onSendByCtrlEnter() { } void ChatSettingsWidget::onAutomaticMediaDownloadSettings() { - Ui::showLayer(new AutoDownloadBox()); + Ui::show(Box()); } void ChatSettingsWidget::onManageStickerSets() { - Ui::showLayer(new StickersBox()); + Ui::show(Box(StickersBox::Section::Installed)); } } // namespace Settings diff --git a/Telegram/SourceFiles/settings/settings_chat_settings_widget.h b/Telegram/SourceFiles/settings/settings_chat_settings_widget.h index a104ac1bf..ab4bce34b 100644 --- a/Telegram/SourceFiles/settings/settings_chat_settings_widget.h +++ b/Telegram/SourceFiles/settings/settings_chat_settings_widget.h @@ -38,9 +38,7 @@ public: void setLink(const QString &text); - Ui::LinkButton *link() { - return _link; - } + Ui::LinkButton *link() const; int naturalWidth() const override; @@ -48,8 +46,8 @@ protected: int resizeGetHeight(int newWidth) override; private: - ChildWidget _label; - ChildWidget _link; + object_ptr _label; + object_ptr _link; }; @@ -67,7 +65,6 @@ protected: private slots: void onDownloadPath(); void onClear(); - void onClearSure(); void onTempDirCleared(int task); void onTempDirClearFailed(int task); @@ -84,8 +81,8 @@ private: }; State _state = State::Empty; - ChildWidget _path; - ChildWidget _clear; + object_ptr _path; + object_ptr _clear; }; @@ -107,14 +104,14 @@ private slots: private: void createControls(); - ChildWidget _replaceEmoji = { nullptr }; - ChildWidget> _viewList = { nullptr }; - ChildWidget _dontAskDownloadPath = { nullptr }; - ChildWidget> _downloadPath = { nullptr }; - ChildWidget _sendByEnter = { nullptr }; - ChildWidget _sendByCtrlEnter = { nullptr }; - ChildWidget _automaticMediaDownloadSettings = { nullptr }; - ChildWidget _manageStickerSets = { nullptr }; + object_ptr _replaceEmoji = { nullptr }; + object_ptr> _viewList = { nullptr }; + object_ptr _dontAskDownloadPath = { nullptr }; + object_ptr> _downloadPath = { nullptr }; + object_ptr _sendByEnter = { nullptr }; + object_ptr _sendByCtrlEnter = { nullptr }; + object_ptr _automaticMediaDownloadSettings = { nullptr }; + object_ptr _manageStickerSets = { nullptr }; }; diff --git a/Telegram/SourceFiles/settings/settings_cover.cpp b/Telegram/SourceFiles/settings/settings_cover.cpp index ddfc1fb97..9be5fef37 100644 --- a/Telegram/SourceFiles/settings/settings_cover.cpp +++ b/Telegram/SourceFiles/settings/settings_cover.cpp @@ -210,7 +210,7 @@ void CoverWidget::dragEnterEvent(QDragEnterEvent *e) { if (!_dropArea) { auto title = lang(lng_profile_drop_area_title); auto subtitle = lang(lng_settings_drop_area_subtitle); - _dropArea = new Profile::CoverDropArea(this, title, subtitle); + _dropArea.create(this, title, subtitle); resizeDropArea(); } _dropArea->showAnimated(); @@ -308,7 +308,7 @@ void CoverWidget::onSetPhoto() { } void CoverWidget::onEditName() { - Ui::showLayer(new EditNameTitleBox(self())); + Ui::show(Box(self())); } void CoverWidget::notifyFileQueryUpdated(const FileDialog::QueryUpdate &update) { @@ -333,13 +333,12 @@ void CoverWidget::notifyFileQueryUpdated(const FileDialog::QueryUpdate &update) void CoverWidget::showSetPhotoBox(const QImage &img) { if (img.isNull() || img.width() > 10 * img.height() || img.height() > 10 * img.width()) { - Ui::showLayer(new InformBox(lang(lng_bad_photo))); + Ui::show(Box(lang(lng_bad_photo))); return; } - auto box = new PhotoCropBox(img, _self); - connect(box, SIGNAL(closed(LayerWidget*)), this, SLOT(onPhotoUploadStatusChanged())); - Ui::showLayer(box); + auto box = Ui::show(Box(img, _self)); + connect(box, SIGNAL(closed()), this, SLOT(onPhotoUploadStatusChanged())); } void CoverWidget::onPhotoUploadStatusChanged(PeerId peerId) { diff --git a/Telegram/SourceFiles/settings/settings_cover.h b/Telegram/SourceFiles/settings/settings_cover.h index b799d7c0f..a228026a5 100644 --- a/Telegram/SourceFiles/settings/settings_cover.h +++ b/Telegram/SourceFiles/settings/settings_cover.h @@ -42,7 +42,7 @@ class CoverDropArea; namespace Settings { -class CoverWidget final : public BlockWidget { +class CoverWidget : public BlockWidget { Q_OBJECT public: @@ -88,19 +88,19 @@ private: UserData *_self; - ChildWidget _userpicButton; - ChildWidget _dropArea = { nullptr }; + object_ptr _userpicButton; + object_ptr _dropArea = { nullptr }; - ChildWidget _name; - ChildWidget _editNameInline; - ChildWidget _cancelPhotoUpload = { nullptr }; + object_ptr _name; + object_ptr _editNameInline; + object_ptr _cancelPhotoUpload = { nullptr }; QPoint _statusPosition; QString _statusText; bool _statusTextIsOnline = false; - ChildWidget _setPhoto; - ChildWidget _editName; + object_ptr _setPhoto; + object_ptr _editName; bool _editNameVisible = true; int _dividerTop = 0; diff --git a/Telegram/SourceFiles/settings/settings_fixed_bar.cpp b/Telegram/SourceFiles/settings/settings_fixed_bar.cpp index a9aa941d3..80ca423fa 100644 --- a/Telegram/SourceFiles/settings/settings_fixed_bar.cpp +++ b/Telegram/SourceFiles/settings/settings_fixed_bar.cpp @@ -23,36 +23,27 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "styles/style_settings.h" #include "styles/style_boxes.h" -#include "ui/widgets/buttons.h" #include "mainwindow.h" #include "lang.h" namespace Settings { -FixedBar::FixedBar(QWidget *parent) : TWidget(parent) -, _close(this, st::settingsFixedBarClose) { +FixedBar::FixedBar(QWidget *parent) : TWidget(parent) { setAttribute(Qt::WA_OpaquePaintEvent); - _close->setClickedCallback([]() { - Ui::hideSettingsAndLayer(); - }); } int FixedBar::resizeGetHeight(int newWidth) { - return st::settingsFixedBarHeight; -} - -void FixedBar::resizeEvent(QResizeEvent *e) { - _close->moveToRight(0, 0); + return st::settingsFixedBarHeight - st::boxRadius; } void FixedBar::paintEvent(QPaintEvent *e) { Painter p(this); - p.fillRect(e->rect(), st::boxBlockTitleBg); + p.fillRect(e->rect(), st::boxBg); p.setFont(st::settingsFixedBarFont); p.setPen(st::windowFg); - p.drawTextLeft(st::settingsFixedBarTextLeft, st::settingsFixedBarTextTop, width(), lang(lng_menu_settings)); + p.drawTextLeft(st::settingsFixedBarTextPosition.x(), st::settingsFixedBarTextPosition.y() - st::boxRadius, width(), lang(lng_menu_settings)); } } // namespace Settings diff --git a/Telegram/SourceFiles/settings/settings_fixed_bar.h b/Telegram/SourceFiles/settings/settings_fixed_bar.h index 7ebc87e3d..b99e2afed 100644 --- a/Telegram/SourceFiles/settings/settings_fixed_bar.h +++ b/Telegram/SourceFiles/settings/settings_fixed_bar.h @@ -31,14 +31,10 @@ public: FixedBar(QWidget *parent); protected: - void resizeEvent(QResizeEvent *e) override; void paintEvent(QPaintEvent *e) override; int resizeGetHeight(int newWidth) override; -private: - ChildWidget _close; - }; } // namespace Settings diff --git a/Telegram/SourceFiles/settings/settings_general_widget.cpp b/Telegram/SourceFiles/settings/settings_general_widget.cpp index abc6ff3ce..3e870a06a 100644 --- a/Telegram/SourceFiles/settings/settings_general_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_general_widget.cpp @@ -221,14 +221,17 @@ void GeneralWidget::notifyFileQueryUpdated(const FileDialog::QueryUpdate &update LangLoaderPlain loader(_testLanguage, langLoaderRequest(lng_sure_save_language, lng_cancel, lng_box_ok)); if (loader.errors().isEmpty()) { LangLoaderResult result = loader.found(); - QString text = result.value(lng_sure_save_language, langOriginal(lng_sure_save_language)), + auto text = result.value(lng_sure_save_language, langOriginal(lng_sure_save_language)), save = result.value(lng_box_ok, langOriginal(lng_box_ok)), cancel = result.value(lng_cancel, langOriginal(lng_cancel)); - auto box = new ConfirmBox(text, save, st::defaultBoxButton, cancel); - connect(box, SIGNAL(confirmed()), this, SLOT(onSaveTestLanguage())); - Ui::showLayer(box); + Ui::show(Box(text, save, cancel, base::lambda_guarded(this, [this] { + cSetLangFile(_testLanguage); + cSetLang(languageTest); + Local::writeSettings(); + onRestart(); + }))); } else { - Ui::showLayer(new InformBox("Custom lang failed :(\n\nError: " + loader.errors())); + Ui::show(Box("Custom lang failed :(\n\nError: " + loader.errors())); } } @@ -236,17 +239,10 @@ void GeneralWidget::onChangeLanguage() { if ((_changeLanguage->clickModifiers() & Qt::ShiftModifier) && (_changeLanguage->clickModifiers() & Qt::AltModifier)) { chooseCustomLang(); } else { - Ui::showLayer(new LanguageBox()); + Ui::show(Box()); } } -void GeneralWidget::onSaveTestLanguage() { - cSetLangFile(_testLanguage); - cSetLang(languageTest); - Local::writeSettings(); - onRestart(); -} - void GeneralWidget::onRestart() { #ifndef TDESKTOP_DISABLE_AUTOUPDATE checkReadyUpdate(); diff --git a/Telegram/SourceFiles/settings/settings_general_widget.h b/Telegram/SourceFiles/settings/settings_general_widget.h index 48ab3cb2a..6b4d4f099 100644 --- a/Telegram/SourceFiles/settings/settings_general_widget.h +++ b/Telegram/SourceFiles/settings/settings_general_widget.h @@ -65,8 +65,8 @@ private: void setState(State state, bool force = false); void setDownloadProgress(qint64 ready, qint64 total); - ChildWidget _check; - ChildWidget _restart; + object_ptr _check; + object_ptr _restart; State _state = State::None; QString _downloadText; @@ -85,7 +85,6 @@ protected: private slots: void onChangeLanguage(); - void onSaveTestLanguage(); #ifndef TDESKTOP_DISABLE_AUTOUPDATE void onUpdateAutomatically(); @@ -106,16 +105,16 @@ private: void chooseCustomLang(); void notifyFileQueryUpdated(const FileDialog::QueryUpdate &update); - ChildWidget _changeLanguage; + object_ptr _changeLanguage; #ifndef TDESKTOP_DISABLE_AUTOUPDATE - ChildWidget _updateAutomatically = { nullptr }; - ChildWidget> _updateRow = { nullptr }; + object_ptr _updateAutomatically = { nullptr }; + object_ptr> _updateRow = { nullptr }; #endif // !TDESKTOP_DISABLE_AUTOUPDATE - ChildWidget _enableTrayIcon = { nullptr }; - ChildWidget _enableTaskbarIcon = { nullptr }; - ChildWidget _autoStart = { nullptr }; - ChildWidget> _startMinimized = { nullptr }; - ChildWidget _addInSendTo = { nullptr }; + object_ptr _enableTrayIcon = { nullptr }; + object_ptr _enableTaskbarIcon = { nullptr }; + object_ptr _autoStart = { nullptr }; + object_ptr> _startMinimized = { nullptr }; + object_ptr _addInSendTo = { nullptr }; FileDialog::QueryId _chooseLangFileQueryId = 0; QString _testLanguage; diff --git a/Telegram/SourceFiles/settings/settings_info_widget.cpp b/Telegram/SourceFiles/settings/settings_info_widget.cpp index 31c9a451a..8b00f0329 100644 --- a/Telegram/SourceFiles/settings/settings_info_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_info_widget.cpp @@ -84,7 +84,7 @@ void InfoWidget::refreshUsername() { setLabeledText(_username, lang(lng_profile_username), usernameText, TextWithEntities(), copyText); if (auto text = _username->entity()->textLabel()) { text->setClickHandlerHook([](const ClickHandlerPtr &handler, Qt::MouseButton button) { - Ui::showLayer(new UsernameBox()); + Ui::show(Box()); return false; }); } @@ -102,20 +102,20 @@ void InfoWidget::refreshLink() { setLabeledText(_link, lang(lng_profile_link), linkText, linkTextShort, QString()); if (auto text = _link->entity()->textLabel()) { text->setClickHandlerHook([](const ClickHandlerPtr &handler, Qt::MouseButton button) { - Ui::showLayer(new UsernameBox()); + Ui::show(Box()); return false; }); } if (auto shortText = _link->entity()->shortTextLabel()) { shortText->setExpandLinksMode(ExpandLinksUrlOnly); shortText->setClickHandlerHook([](const ClickHandlerPtr &handler, Qt::MouseButton button) { - Ui::showLayer(new UsernameBox()); + Ui::show(Box()); return false; }); } } -void InfoWidget::setLabeledText(ChildWidget &row, const QString &label, const TextWithEntities &textWithEntities, const TextWithEntities &shortTextWithEntities, const QString ©Text) { +void InfoWidget::setLabeledText(object_ptr &row, const QString &label, const TextWithEntities &textWithEntities, const TextWithEntities &shortTextWithEntities, const QString ©Text) { if (textWithEntities.text.isEmpty()) { row->slideUp(); } else { @@ -140,7 +140,15 @@ void InfoWidget::LabeledWidget::setLabeledText(const QString &label, const TextW resizeToWidth(width()); } -void InfoWidget::LabeledWidget::setLabelText(ChildWidget &text, const TextWithEntities &textWithEntities, const QString ©Text) { +Ui::FlatLabel *InfoWidget::LabeledWidget::textLabel() const { + return _text; +} + +Ui::FlatLabel *InfoWidget::LabeledWidget::shortTextLabel() const { + return _shortText; +} + +void InfoWidget::LabeledWidget::setLabelText(object_ptr &text, const TextWithEntities &textWithEntities, const QString ©Text) { text.destroy(); if (textWithEntities.text.isEmpty()) return; diff --git a/Telegram/SourceFiles/settings/settings_info_widget.h b/Telegram/SourceFiles/settings/settings_info_widget.h index 666350e9f..3fe1c4391 100644 --- a/Telegram/SourceFiles/settings/settings_info_widget.h +++ b/Telegram/SourceFiles/settings/settings_info_widget.h @@ -52,12 +52,8 @@ private: void setLabeledText(const QString &label, const TextWithEntities &textWithEntities, const TextWithEntities &shortTextWithEntities, const QString ©Text); - Ui::FlatLabel *textLabel() { - return _text; - } - Ui::FlatLabel *shortTextLabel() { - return _shortText; - } + Ui::FlatLabel *textLabel() const; + Ui::FlatLabel *shortTextLabel() const; int naturalWidth() const override; @@ -65,20 +61,20 @@ private: int resizeGetHeight(int newWidth) override; private: - void setLabelText(ChildWidget &text, const TextWithEntities &textWithEntities, const QString ©Text); + void setLabelText(object_ptr &text, const TextWithEntities &textWithEntities, const QString ©Text); - ChildWidget _label = { nullptr }; - ChildWidget _text = { nullptr }; - ChildWidget _shortText = { nullptr }; + object_ptr _label = { nullptr }; + object_ptr _text = { nullptr }; + object_ptr _shortText = { nullptr }; }; using LabeledWrap = Ui::WidgetSlideWrap; - void setLabeledText(ChildWidget &row, const QString &label, const TextWithEntities &textWithEntities, const TextWithEntities &shortTextWithEntities, const QString ©Text); + void setLabeledText(object_ptr &row, const QString &label, const TextWithEntities &textWithEntities, const TextWithEntities &shortTextWithEntities, const QString ©Text); - ChildWidget _mobileNumber = { nullptr }; - ChildWidget _username = { nullptr }; - ChildWidget _link = { nullptr }; + object_ptr _mobileNumber = { nullptr }; + object_ptr _username = { nullptr }; + object_ptr _link = { nullptr }; }; diff --git a/Telegram/SourceFiles/settings/settings_inner_widget.cpp b/Telegram/SourceFiles/settings/settings_inner_widget.cpp index 43f25bd3c..d0851c113 100644 --- a/Telegram/SourceFiles/settings/settings_inner_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_inner_widget.cpp @@ -68,7 +68,7 @@ void InnerWidget::refreshBlocks() { return; } if (_self) { - _cover = new CoverWidget(this, _self); + _cover.create(this, _self); _blocks.push_back(new InfoWidget(this, _self)); _blocks.push_back(new NotificationsWidget(this, _self)); } diff --git a/Telegram/SourceFiles/settings/settings_inner_widget.h b/Telegram/SourceFiles/settings/settings_inner_widget.h index 7091124e2..67aa4b0c2 100644 --- a/Telegram/SourceFiles/settings/settings_inner_widget.h +++ b/Telegram/SourceFiles/settings/settings_inner_widget.h @@ -56,7 +56,7 @@ private: // Returns the new height value. int refreshBlocksPositions(int newWidth); - ChildWidget _cover = { nullptr }; + object_ptr _cover = { nullptr }; QList _blocks; UserData *_self = nullptr; diff --git a/Telegram/SourceFiles/settings/settings_notifications_widget.cpp b/Telegram/SourceFiles/settings/settings_notifications_widget.cpp index 441b0c4f3..7d822720a 100644 --- a/Telegram/SourceFiles/settings/settings_notifications_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_notifications_widget.cpp @@ -173,7 +173,7 @@ void NotificationsWidget::onNativeNotifications() { } void NotificationsWidget::onAdvanced() { - Ui::showLayer(new NotificationsBox()); + Ui::show(Box()); } void NotificationsWidget::onPlaySound() { diff --git a/Telegram/SourceFiles/settings/settings_notifications_widget.h b/Telegram/SourceFiles/settings/settings_notifications_widget.h index 0a2b44e94..06a576514 100644 --- a/Telegram/SourceFiles/settings/settings_notifications_widget.h +++ b/Telegram/SourceFiles/settings/settings_notifications_widget.h @@ -45,13 +45,13 @@ private: void desktopEnabledUpdated(); void viewParamUpdated(); - ChildWidget _desktopNotifications = { nullptr }; - ChildWidget> _showSenderName = { nullptr }; - ChildWidget> _showMessagePreview = { nullptr }; - ChildWidget _nativeNotifications = { nullptr }; - ChildWidget _playSound = { nullptr }; - ChildWidget _includeMuted = { nullptr }; - ChildWidget> _advanced = { nullptr }; + object_ptr _desktopNotifications = { nullptr }; + object_ptr> _showSenderName = { nullptr }; + object_ptr> _showMessagePreview = { nullptr }; + object_ptr _nativeNotifications = { nullptr }; + object_ptr _playSound = { nullptr }; + object_ptr _includeMuted = { nullptr }; + object_ptr> _advanced = { nullptr }; }; diff --git a/Telegram/SourceFiles/settings/settings_privacy_widget.cpp b/Telegram/SourceFiles/settings/settings_privacy_widget.cpp index dbc6608c2..ca3a05d98 100644 --- a/Telegram/SourceFiles/settings/settings_privacy_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_privacy_widget.cpp @@ -49,11 +49,11 @@ int LocalPasscodeState::resizeGetHeight(int newWidth) { } void LocalPasscodeState::onEdit() { - Ui::showLayer(new PasscodeBox()); + Ui::show(Box(false)); } void LocalPasscodeState::onTurnOff() { - Ui::showLayer(new PasscodeBox(true)); + Ui::show(Box(true)); } void LocalPasscodeState::updateControls() { @@ -79,9 +79,8 @@ int CloudPasswordState::resizeGetHeight(int newWidth) { } void CloudPasswordState::onEdit() { - PasscodeBox *box = new PasscodeBox(_newPasswordSalt, _curPasswordSalt, _hasPasswordRecovery, _curPasswordHint); + auto box = Ui::show(Box(_newPasswordSalt, _curPasswordSalt, _hasPasswordRecovery, _curPasswordHint)); connect(box, SIGNAL(reloadPassword()), this, SLOT(onReloadPassword())); - Ui::showLayer(box); } void CloudPasswordState::onTurnOff() { @@ -92,9 +91,8 @@ void CloudPasswordState::onTurnOff() { MTPaccount_PasswordInputSettings settings(MTP_account_passwordInputSettings(MTP_flags(flags), MTP_bytes(QByteArray()), MTP_bytes(QByteArray()), MTP_string(QString()), MTP_string(QString()))); MTP::send(MTPaccount_UpdatePasswordSettings(MTP_bytes(QByteArray()), settings), rpcDone(&CloudPasswordState::offPasswordDone), rpcFail(&CloudPasswordState::offPasswordFail)); } else { - PasscodeBox *box = new PasscodeBox(_newPasswordSalt, _curPasswordSalt, _hasPasswordRecovery, _curPasswordHint, true); + auto box = Ui::show(Box(_newPasswordSalt, _curPasswordSalt, _hasPasswordRecovery, _curPasswordHint, true)); connect(box, SIGNAL(reloadPassword()), this, SLOT(onReloadPassword())); - Ui::showLayer(box); } } @@ -196,11 +194,11 @@ void PrivacyWidget::autoLockUpdated() { } void PrivacyWidget::onAutoLock() { - Ui::showLayer(new AutoLockBox()); + Ui::show(Box()); } void PrivacyWidget::onShowSessions() { - Ui::showLayer(new SessionsBox()); + Ui::show(Box()); } } // namespace Settings diff --git a/Telegram/SourceFiles/settings/settings_privacy_widget.h b/Telegram/SourceFiles/settings/settings_privacy_widget.h index 8bc1a947b..97b742c1a 100644 --- a/Telegram/SourceFiles/settings/settings_privacy_widget.h +++ b/Telegram/SourceFiles/settings/settings_privacy_widget.h @@ -41,8 +41,8 @@ private slots: private: void updateControls(); - ChildWidget _edit; - ChildWidget _turnOff; + object_ptr _edit; + object_ptr _turnOff; }; @@ -67,8 +67,8 @@ private: void offPasswordDone(const MTPBool &result); bool offPasswordFail(const RPCError &error); - ChildWidget _edit; - ChildWidget _turnOff; + object_ptr _edit; + object_ptr _turnOff; QString _waitingConfirm; QByteArray _curPasswordSalt; @@ -92,10 +92,10 @@ private: void createControls(); void autoLockUpdated(); - ChildWidget _localPasscodeState = { nullptr }; - ChildWidget> _autoLock = { nullptr }; - ChildWidget _cloudPasswordState = { nullptr }; - ChildWidget _showAllSessions = { nullptr }; + object_ptr _localPasscodeState = { nullptr }; + object_ptr> _autoLock = { nullptr }; + object_ptr _cloudPasswordState = { nullptr }; + object_ptr _showAllSessions = { nullptr }; }; diff --git a/Telegram/SourceFiles/settings/settings_scale_widget.cpp b/Telegram/SourceFiles/settings/settings_scale_widget.cpp index c3cca137a..8047847d5 100644 --- a/Telegram/SourceFiles/settings/settings_scale_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_scale_widget.cpp @@ -99,10 +99,15 @@ void ScaleWidget::setScale(DBIScale newScale) { } if (cEvalScale(newScale) != cEvalScale(cRealScale())) { - auto box = new ConfirmBox(lang(lng_settings_need_restart), lang(lng_settings_restart_now), st::defaultBoxButton, lang(lng_cancel)); - connect(box, SIGNAL(confirmed()), this, SLOT(onRestartNow())); - connect(box, SIGNAL(cancelled()), this, SLOT(onCancel())); - Ui::showLayer(box); + Ui::show(Box(lang(lng_settings_need_restart), lang(lng_settings_restart_now), base::lambda_guarded(this, [this] { + cSetConfigScale(_newScale); + Local::writeSettings(); + App::restart(); + }), base::lambda_guarded(this, [this] { + App::CallDelayed(st::boxDuration, this, [this] { + setScale(cRealScale()); + }); + }))); } else { cSetConfigScale(newScale); Local::writeSettings(); @@ -120,14 +125,4 @@ void ScaleWidget::scaleChanged() { setScale(newScale); } -void ScaleWidget::onRestartNow() { - cSetConfigScale(_newScale); - Local::writeSettings(); - App::restart(); -} - -void ScaleWidget::onCancel() { - App::CallDelayed(st::boxDuration, this, [this] { setScale(cRealScale()); }); -} - } // namespace Settings diff --git a/Telegram/SourceFiles/settings/settings_scale_widget.h b/Telegram/SourceFiles/settings/settings_scale_widget.h index 541339b69..da72f6e85 100644 --- a/Telegram/SourceFiles/settings/settings_scale_widget.h +++ b/Telegram/SourceFiles/settings/settings_scale_widget.h @@ -37,16 +37,14 @@ public: private slots: void onAutoChanged(); - void onRestartNow(); - void onCancel(); private: void scaleChanged(); void createControls(); void setScale(DBIScale newScale); - ChildWidget _auto = { nullptr }; - ChildWidget _scale = { nullptr }; + object_ptr _auto = { nullptr }; + object_ptr _scale = { nullptr }; DBIScale _newScale = dbisAuto; bool _inSetScale = false; diff --git a/Telegram/SourceFiles/settings/settings_widget.cpp b/Telegram/SourceFiles/settings/settings_widget.cpp index 602eb7a12..7e3f08d76 100644 --- a/Telegram/SourceFiles/settings/settings_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_widget.cpp @@ -26,8 +26,9 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "styles/style_settings.h" #include "styles/style_window.h" #include "styles/style_boxes.h" -#include "ui/widgets/shadow.h" +#include "ui/effects/widget_fade_wrap.h" #include "ui/widgets/scroll_area.h" +#include "ui/widgets/buttons.h" #include "mainwindow.h" #include "mainwidget.h" #include "localstorage.h" @@ -43,15 +44,15 @@ QMap> Codes; void fillCodes() { Codes.insert(qsl("debugmode"), []() { QString text = cDebug() ? qsl("Do you want to disable DEBUG logs?") : qsl("Do you want to enable DEBUG logs?\n\nAll network events will be logged."); - ConfirmBox *box = new ConfirmBox(text); - box->connect(box, SIGNAL(confirmed()), App::app(), SLOT(onSwitchDebugMode())); - Ui::showLayer(box); + Ui::show(Box(text, [] { + App::app()->onSwitchDebugMode(); + })); }); Codes.insert(qsl("testmode"), []() { - QString text = cTestMode() ? qsl("Do you want to disable TEST mode?") : qsl("Do you want to enable TEST mode?\n\nYou will be switched to test cloud."); - ConfirmBox *box = new ConfirmBox(text); - box->connect(box, SIGNAL(confirmed()), App::app(), SLOT(onSwitchTestMode())); - Ui::showLayer(box); + auto text = cTestMode() ? qsl("Do you want to disable TEST mode?") : qsl("Do you want to enable TEST mode?\n\nYou will be switched to test cloud."); + Ui::show(Box(text, [] { + App::app()->onSwitchTestMode(); + })); }); Codes.insert(qsl("loadlang"), []() { Global::RefChooseCustomLang().notify(); @@ -63,26 +64,24 @@ void fillCodes() { } else { Global::RefDebugLoggingFlags() |= DebugLogging::FileLoaderFlag; } - Ui::showLayer(new InformBox(DebugLogging::FileLoader() ? qsl("Enabled file download logging") : qsl("Disabled file download logging"))); + Ui::show(Box(DebugLogging::FileLoader() ? qsl("Enabled file download logging") : qsl("Disabled file download logging"))); }); Codes.insert(qsl("crashplease"), []() { t_assert(!"Crashed in Settings!"); }); Codes.insert(qsl("workmode"), []() { auto text = Global::DialogsModeEnabled() ? qsl("Disable work mode?") : qsl("Enable work mode?"); - auto box = std_::make_unique(text); - box->connect(box.get(), SIGNAL(confirmed()), App::app(), SLOT(onSwitchWorkMode())); - Ui::showLayer(box.release()); + Ui::show(Box(text, [] { + App::app()->onSwitchWorkMode(); + })); }); Codes.insert(qsl("moderate"), []() { auto text = Global::ModerateModeEnabled() ? qsl("Disable moderate mode?") : qsl("Enable moderate mode?"); - auto box = std_::make_unique(text); - box->setConfirmedCallback([]() { + Ui::show(Box(text, []() { Global::SetModerateModeEnabled(!Global::ModerateModeEnabled()); Local::writeUserSettings(); Ui::hideLayer(); - }); - Ui::showLayer(box.release()); + })); }); Codes.insert(qsl("getdifference"), []() { if (auto main = App::main()) { @@ -126,19 +125,35 @@ void codesFeedString(const QString &text) { Widget::Widget(QWidget *parent) : LayerWidget(parent) , _scroll(this, st::settingsScroll) -, _inner(this) , _fixedBar(this) -, _fixedBarShadow(this, st::boxBlockTitleShadow) { - _scroll->setOwnedWidget(_inner); - setAttribute(Qt::WA_OpaquePaintEvent); +, _fixedBarClose(this, st::settingsFixedBarClose) +, _fixedBarShadow(this, object_ptr(this)) { + _inner = _scroll->setOwnedWidget(object_ptr(this)); - _fixedBar->move(0, 0); - _fixedBarShadow->move(0, _fixedBar->y() + st::settingsFixedBarHeight); - _scroll->move(0, st::settingsFixedBarHeight); + _fixedBar->moveToLeft(0, st::boxRadius); + _fixedBarClose->moveToRight(0, 0); + _fixedBarShadow->entity()->resize(width(), st::lineWidth); + _fixedBarShadow->moveToLeft(0, _fixedBar->y() + _fixedBar->height()); + _fixedBarShadow->hideFast(); + _scroll->moveToLeft(0, st::settingsFixedBarHeight); + + connect(_scroll, SIGNAL(scrolled()), this, SLOT(onScroll())); + + _fixedBarClose->setClickedCallback([]() { + Ui::hideSettingsAndLayer(); + }); connect(_inner, SIGNAL(heightUpdated()), this, SLOT(onInnerHeightUpdated())); } +void Widget::onScroll() { + if (_scroll->scrollTop() > 0) { + _fixedBarShadow->showAnimated(); + } else { + _fixedBarShadow->hideAnimated(); + } +} + void Widget::parentResized() { auto parentSize = parentWidget()->size(); int windowWidth = parentSize.width(); @@ -180,7 +195,7 @@ void Widget::resizeUsingInnerHeight(int newWidth, int newContentLeft) { int windowWidth = parentSize.width(); int windowHeight = parentSize.height(); int maxHeight = st::settingsFixedBarHeight + _inner->height(); - int newHeight = maxHeight; + int newHeight = maxHeight + st::boxRadius; if (newHeight > windowHeight || newWidth >= windowWidth) { newHeight = windowHeight; } @@ -189,6 +204,9 @@ void Widget::resizeUsingInnerHeight(int newWidth, int newContentLeft) { _contentLeft = newContentLeft; } + _roundedCorners = (newHeight < windowHeight); + setAttribute(Qt::WA_OpaquePaintEvent, !_roundedCorners); + setGeometry((windowWidth - newWidth) / 2, (windowHeight - newHeight) / 2, newWidth, newHeight); update(); } @@ -199,7 +217,23 @@ void Widget::showFinished() { void Widget::paintEvent(QPaintEvent *e) { Painter p(this); - p.fillRect(e->rect(), st::boxBg); + auto clip = e->rect(); + if (_roundedCorners) { + auto paintTopRounded = clip.intersects(QRect(0, 0, width(), st::boxRadius)); + auto paintBottomRounded = clip.intersects(QRect(0, height() - st::boxRadius, width(), st::boxRadius)); + if (paintTopRounded || paintBottomRounded) { + auto parts = qFlags(App::RectPart::None); + if (paintTopRounded) parts |= App::RectPart::TopFull; + if (paintBottomRounded) parts |= App::RectPart::BottomFull; + App::roundRect(p, rect(), st::boxBg, BoxCorners, nullptr, parts); + } + auto other = clip.intersected(QRect(0, st::boxRadius, width(), height() - 2 * st::boxRadius)); + if (!other.isEmpty()) { + p.fillRect(other, st::boxBg); + } + } else { + p.fillRect(e->rect(), st::boxBg); + } } void Widget::resizeEvent(QResizeEvent *e) { @@ -209,15 +243,18 @@ void Widget::resizeEvent(QResizeEvent *e) { } _fixedBar->resizeToWidth(width()); - _fixedBarShadow->resize(width(), st::boxBlockTitleShadow.height()); + _fixedBar->moveToLeft(0, st::boxRadius); + _fixedBarClose->moveToRight(0, 0); + auto shadowTop = _fixedBar->y() + _fixedBar->height(); + _fixedBarShadow->entity()->resize(width(), st::lineWidth); + _fixedBarShadow->moveToLeft(0, shadowTop); - QSize scrollSize(width(), height() - _fixedBar->height()); + auto scrollSize = QSize(width(), height() - shadowTop - (_roundedCorners ? st::boxRadius : 0)); if (_scroll->size() != scrollSize) { _scroll->resize(scrollSize); } - if (!_scroll->isHidden()) { - int scrollTop = _scroll->scrollTop(); + auto scrollTop = _scroll->scrollTop(); _inner->setVisibleTopBottom(scrollTop, scrollTop + _scroll->height()); } } diff --git a/Telegram/SourceFiles/settings/settings_widget.h b/Telegram/SourceFiles/settings/settings_widget.h index 5eaa17247..7e7b6c294 100644 --- a/Telegram/SourceFiles/settings/settings_widget.h +++ b/Telegram/SourceFiles/settings/settings_widget.h @@ -22,9 +22,13 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "layerwidget.h" +class BoxLayerTitleShadow; + namespace Ui { class ScrollArea; -class GradientShadow; +class IconButton; +template +class WidgetFadeWrap; } // namespace Ui namespace Settings { @@ -48,16 +52,19 @@ protected: private slots: void onInnerHeightUpdated(); + void onScroll(); private: void resizeUsingInnerHeight(int newWidth, int newContentLeft); - ChildWidget _scroll; - ChildWidget _inner; - ChildWidget _fixedBar; - ChildWidget _fixedBarShadow; + object_ptr _scroll; + QPointer _inner; + object_ptr _fixedBar; + object_ptr _fixedBarClose; + object_ptr> _fixedBarShadow; int _contentLeft = 0; + bool _roundedCorners = false; }; diff --git a/Telegram/SourceFiles/stickers/emoji_pan.cpp b/Telegram/SourceFiles/stickers/emoji_pan.cpp index aaae3e6f9..4943761e4 100644 --- a/Telegram/SourceFiles/stickers/emoji_pan.cpp +++ b/Telegram/SourceFiles/stickers/emoji_pan.cpp @@ -41,14 +41,13 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org namespace internal { -EmojiColorPicker::EmojiColorPicker(QWidget *parent) : TWidget(parent) -, _shadow(st::defaultDropdownShadow) { +EmojiColorPicker::EmojiColorPicker(QWidget *parent) : TWidget(parent) { memset(_variants, 0, sizeof(_variants)); setMouseTracking(true); - int32 w = st::emojiPanSize.width() * (EmojiColorsCount + 1) + 4 * st::emojiColorsPadding + st::emojiColorsSep + st::defaultDropdownShadow.width() * 2; - int32 h = 2 * st::emojiColorsPadding + st::emojiPanSize.height() + st::defaultDropdownShadow.height() * 2; + auto w = st::emojiPanMargins.left() + st::emojiPanSize.width() * (EmojiColorsCount + 1) + 4 * st::emojiColorsPadding + st::emojiColorsSep + st::emojiPanMargins.right(); + auto h = st::emojiPanMargins.top() + 2 * st::emojiColorsPadding + st::emojiPanSize.height() + st::emojiPanMargins.bottom(); resize(w, h); _hideTimer.setSingleShot(true); @@ -88,25 +87,21 @@ void EmojiColorPicker::paintEvent(QPaintEvent *e) { p.setClipRect(e->rect()); } - auto w = st::defaultDropdownShadow.width(); - auto h = st::defaultDropdownShadow.height(); - auto r = QRect(w, h, width() - 2 * w, height() - 2 * h); - _shadow.paint(p, r, st::defaultDropdownShadowShift); + auto inner = rect().marginsRemoved(st::emojiPanMargins); + if (!_cache.isNull()) { + p.drawPixmap(0, 0, _cache); + return; + } + Ui::Shadow::paint(p, inner, width(), st::defaultRoundShadow); + App::roundRect(p, inner, st::boxBg, BoxCorners); - if (_cache.isNull()) { - p.fillRect(e->rect().intersected(r), st::emojiPanBg); + auto x = st::emojiPanMargins.left() + 2 * st::emojiColorsPadding + st::emojiPanSize.width(); + if (rtl()) x = width() - x - st::emojiColorsSep; + p.fillRect(x, st::emojiPanMargins.top() + st::emojiColorsPadding, st::emojiColorsSep, inner.height() - st::emojiColorsPadding * 2, st::emojiColorsSepColor); - int32 x = w + 2 * st::emojiColorsPadding + st::emojiPanSize.width(); - if (rtl()) x = width() - x - st::emojiColorsSep; - p.fillRect(x, h + st::emojiColorsPadding, st::emojiColorsSep, r.height() - st::emojiColorsPadding * 2, st::emojiColorsSepColor->b); - - if (!_variants[0]) return; - for (int i = 0; i < EmojiColorsCount + 1; ++i) { - drawVariant(p, i); - } - } else { - p.drawPixmap(r.left(), r.top(), _cache); - p.setOpacity(1.); + if (!_variants[0]) return; + for (int i = 0; i < EmojiColorsCount + 1; ++i) { + drawVariant(p, i); } } @@ -179,12 +174,11 @@ void EmojiColorPicker::hideFast() { void EmojiColorPicker::hideAnimated() { if (_cache.isNull()) { - auto w = st::defaultDropdownShadow.width(), h = st::defaultDropdownShadow.height(); - _cache = myGrab(this, QRect(w, h, width() - 2 * w, height() - 2 * h)); + _cache = myGrab(this); clearSelection(); } _hiding = true; - _a_opacity.start([this] { animationCallback(); }, 1., 0., st::defaultDropdownDuration); + _a_opacity.start([this] { animationCallback(); }, 1., 0., st::emojiPanDuration); } void EmojiColorPicker::showAnimated() { @@ -195,12 +189,11 @@ void EmojiColorPicker::showAnimated() { } _hiding = false; if (_cache.isNull()) { - auto w = st::defaultDropdownShadow.width(), h = st::defaultDropdownShadow.height(); - _cache = myGrab(this, QRect(w, h, width() - 2 * w, height() - 2 * h)); + _cache = myGrab(this); clearSelection(); } show(); - _a_opacity.start([this] { animationCallback(); }, 0., 1., st::defaultDropdownDuration); + _a_opacity.start([this] { animationCallback(); }, 0., 1., st::emojiPanDuration); } void EmojiColorPicker::clearSelection() { @@ -212,9 +205,9 @@ void EmojiColorPicker::clearSelection() { void EmojiColorPicker::updateSelected() { auto newSelected = -1; auto p = mapFromGlobal(_lastMousePos); - int32 sx = rtl() ? (width() - p.x()) : p.x(), y = p.y() - st::defaultDropdownShadow.height() - st::emojiColorsPadding; + auto sx = rtl() ? (width() - p.x()) : p.x(), y = p.y() - st::emojiPanMargins.top() - st::emojiColorsPadding; if (y >= 0 && y < st::emojiPanSize.height()) { - int32 x = sx - st::defaultDropdownShadow.width() - st::emojiColorsPadding; + auto x = sx - st::emojiPanMargins.left() - st::emojiColorsPadding; if (x >= 0 && x < st::emojiPanSize.width()) { newSelected = 0; } else { @@ -234,7 +227,7 @@ void EmojiColorPicker::setSelected(int newSelected) { } auto updateSelectedRect = [this] { if (_selected < 0) return; - rtlupdate(st::defaultDropdownShadow.width() + st::emojiColorsPadding + _selected * st::emojiPanSize.width() + (_selected ? 2 * st::emojiColorsPadding + st::emojiColorsSep : 0), st::defaultDropdownShadow.height() + st::emojiColorsPadding, st::emojiPanSize.width(), st::emojiPanSize.height()); + rtlupdate(st::emojiPanMargins.left() + st::emojiColorsPadding + _selected * st::emojiPanSize.width() + (_selected ? 2 * st::emojiColorsPadding + st::emojiColorsSep : 0), st::emojiPanMargins.top() + st::emojiColorsPadding, st::emojiPanSize.width(), st::emojiPanSize.height()); }; updateSelectedRect(); _selected = newSelected; @@ -243,7 +236,7 @@ void EmojiColorPicker::setSelected(int newSelected) { } void EmojiColorPicker::drawVariant(Painter &p, int variant) { - QPoint w(st::defaultDropdownShadow.width() + st::emojiColorsPadding + variant * st::emojiPanSize.width() + (variant ? 2 * st::emojiColorsPadding + st::emojiColorsSep : 0), st::defaultDropdownShadow.height() + st::emojiColorsPadding); + QPoint w(st::emojiPanMargins.left() + st::emojiColorsPadding + variant * st::emojiPanSize.width() + (variant ? 2 * st::emojiColorsPadding + st::emojiColorsSep : 0), st::emojiPanMargins.top() + st::emojiColorsPadding); if (variant == _selected) { QPoint tl(w); if (rtl()) tl.setX(width() - tl.x() - st::emojiPanSize.width()); @@ -275,8 +268,8 @@ EmojiPanInner::EmojiPanInner(QWidget *parent) : TWidget(parent) connect(_picker, SIGNAL(hidden()), this, SLOT(onPickerHidden())); } -void EmojiPanInner::setMaxHeight(int32 h) { - _maxHeight = h; +void EmojiPanInner::setMaxHeight(int maxHeight) { + _maxHeight = maxHeight; resize(st::emojiPanWidth - st::emojiScroll.width, countHeight()); } @@ -732,8 +725,8 @@ StickerPanInner::StickerPanInner(QWidget *parent) : TWidget(parent) }); } -void StickerPanInner::setMaxHeight(int32 h) { - _maxHeight = h; +void StickerPanInner::setMaxHeight(int maxHeight) { + _maxHeight = maxHeight; resize(st::emojiPanWidth - st::emojiScroll.width - st::buttonRadius, countHeight()); _settings->moveToLeft((st::emojiPanWidth - _settings->width()) / 2, height() / 3); } @@ -2145,7 +2138,7 @@ void StickerPanInner::setSelected(int newSelected, int newSelectedFeaturedSet, i } void StickerPanInner::onSettings() { - Ui::showLayer(new StickersBox()); + Ui::show(Box(StickersBox::Section::Installed)); } void StickerPanInner::onPreview() { @@ -2664,10 +2657,8 @@ EmojiPan::EmojiPan(QWidget *parent) : TWidget(parent) , _symbols(this, st::emojiCategorySymbols) , _a_icons(animation(this, &EmojiPan::step_icons)) , e_scroll(this, st::emojiScroll) -, e_inner(this) , e_switch(e_scroll, true) , s_scroll(this, st::emojiScroll) -, s_inner(this) , s_switch(s_scroll, false) { resize(QRect(0, 0, st::emojiPanWidth, _contentHeight).marginsAdded(innerPadding()).size()); _width = width(); @@ -2678,9 +2669,9 @@ EmojiPan::EmojiPan(QWidget *parent) : TWidget(parent) s_scroll->resize(st::emojiPanWidth - st::buttonRadius, _contentHeightStickers); e_scroll->move(verticalRect().topLeft()); - e_scroll->setOwnedWidget(e_inner); + e_inner = e_scroll->setOwnedWidget(object_ptr(this)); s_scroll->move(verticalRect().topLeft()); - s_scroll->setOwnedWidget(s_inner); + s_inner = s_scroll->setOwnedWidget(object_ptr(this)); e_inner->moveToLeft(0, 0, e_scroll->width()); s_inner->moveToLeft(0, 0, s_scroll->width()); @@ -2749,8 +2740,8 @@ EmojiPan::EmojiPan(QWidget *parent) : TWidget(parent) setAttribute(Qt::WA_OpaquePaintEvent, false); } -void EmojiPan::setMaxHeight(int32 h) { - _maxHeight = h; +void EmojiPan::setMaxHeight(int maxHeight) { + _maxHeight = maxHeight - st::emojiPanMargins.top() - st::emojiPanMargins.bottom(); updateContentHeight(); } @@ -2952,7 +2943,7 @@ void EmojiPan::paintContent(Painter &p) { } } -void EmojiPan::moveBottom(int32 bottom, bool force) { +void EmojiPan::moveBottom(int bottom, bool force) { _bottom = bottom; if (isHidden() && !force) { move(x(), _bottom - height()); @@ -3008,7 +2999,7 @@ void EmojiPan::mousePressEvent(QMouseEvent *e) { updateSelected(); if (_iconOver == _icons.size()) { - Ui::showLayer(new StickersBox()); + Ui::show(Box(StickersBox::Section::Installed)); } else { _iconDown = _iconOver; _iconsMouseDown = _iconsMousePos; @@ -3188,8 +3179,8 @@ void EmojiPan::updateSelected() { void EmojiPan::updateIcons() { if (_emojiShown || !s_inner->showSectionIcons()) return; - QRect r(st::defaultDropdownPadding.left() + st::buttonRadius, st::defaultDropdownPadding.top(), _width - st::defaultDropdownPadding.left() - st::defaultDropdownPadding.right() - 2 * st::buttonRadius, _height - st::defaultDropdownPadding.top() - st::defaultDropdownPadding.bottom()); - update(r.left(), _iconsTop, r.width(), st::emojiCategory.height); + auto verticalInner = rect().marginsRemoved(st::emojiPanMargins).marginsRemoved(QMargins(st::buttonRadius, 0, st::buttonRadius, 0)); + update(verticalInner.left(), _iconsTop, verticalInner.width(), st::emojiCategory.height); } void EmojiPan::step_icons(TimeMs ms, bool timer) { @@ -3274,7 +3265,7 @@ void EmojiPan::startShowAnimation() { _cache = base::take(_cache); _showAnimation = std_::make_unique(st::emojiPanAnimation, _origin); - auto inner = rect().marginsRemoved(st::defaultDropdownPadding); + auto inner = rect().marginsRemoved(st::emojiPanMargins); _showAnimation->setFinalImage(std_::move(image), QRect(inner.topLeft() * cIntRetinaFactor(), inner.size() * cIntRetinaFactor())); auto corners = App::cornersMask(ImageRoundRadius::Small); _showAnimation->setCornerMasks(QImage(*corners[0]), QImage(*corners[1]), QImage(*corners[2]), QImage(*corners[3])); @@ -3560,7 +3551,7 @@ void EmojiPan::validateSelectedIcon(ValidateIconAnimations animations) { } style::margins EmojiPan::innerPadding() const { - return st::defaultDropdownPadding; + return st::emojiPanMargins; } QRect EmojiPan::innerRect() const { @@ -3597,7 +3588,7 @@ void EmojiPan::onSwitch() { auto direction = _emojiShown ? SlideAnimation::Direction::LeftToRight : SlideAnimation::Direction::RightToLeft; _slideAnimation = std_::make_unique(); - auto inner = rect().marginsRemoved(st::defaultDropdownPadding); + auto inner = rect().marginsRemoved(st::emojiPanMargins); _slideAnimation->setFinalImages(direction, std_::move(leftImage), std_::move(rightImage), QRect(inner.topLeft() * cIntRetinaFactor(), inner.size() * cIntRetinaFactor())); auto corners = App::cornersMask(ImageRoundRadius::Small); _slideAnimation->setCornerMasks(QImage(*corners[0]), QImage(*corners[1]), QImage(*corners[2]), QImage(*corners[3])); @@ -3642,9 +3633,8 @@ void EmojiPan::onDisplaySet(quint64 setId) { auto it = sets.constFind(setId); if (it != sets.cend()) { _displayingSetId = setId; - auto box = new StickerSetBox(Stickers::inputSetId(*it)); + auto box = Ui::show(Box(Stickers::inputSetId(*it)), KeepOtherLayers); connect(box, SIGNAL(destroyed(QObject*)), this, SLOT(onDelayedHide())); - Ui::showLayer(box, KeepOtherLayers); } } @@ -3678,44 +3668,43 @@ void EmojiPan::onRemoveSet(quint64 setId) { auto it = sets.constFind(setId); if (it != sets.cend() && !(it->flags & MTPDstickerSet::Flag::f_official)) { _removingSetId = it->id; - ConfirmBox *box = new ConfirmBox(lng_stickers_remove_pack(lt_sticker_pack, it->title), lang(lng_box_remove)); - connect(box, SIGNAL(confirmed()), this, SLOT(onRemoveSetSure())); - connect(box, SIGNAL(destroyed(QObject*)), this, SLOT(onDelayedHide())); - Ui::showLayer(box); - } -} - -void EmojiPan::onRemoveSetSure() { - Ui::hideLayer(); - auto &sets = Global::RefStickerSets(); - auto it = sets.find(_removingSetId); - if (it != sets.cend() && !(it->flags & MTPDstickerSet::Flag::f_official)) { - if (it->id && it->access) { - MTP::send(MTPmessages_UninstallStickerSet(MTP_inputStickerSetID(MTP_long(it->id), MTP_long(it->access)))); - } else if (!it->shortName.isEmpty()) { - MTP::send(MTPmessages_UninstallStickerSet(MTP_inputStickerSetShortName(MTP_string(it->shortName)))); - } - bool writeRecent = false; - RecentStickerPack &recent(cGetRecentStickers()); - for (RecentStickerPack::iterator i = recent.begin(); i != recent.cend();) { - if (it->stickers.indexOf(i->first) >= 0) { - i = recent.erase(i); - writeRecent = true; - } else { - ++i; + auto text = lng_stickers_remove_pack(lt_sticker_pack, it->title); + Ui::show(Box(text, lang(lng_box_remove), base::lambda_guarded(this, [this] { + Ui::hideLayer(); + auto &sets = Global::RefStickerSets(); + auto it = sets.find(_removingSetId); + if (it != sets.cend() && !(it->flags & MTPDstickerSet::Flag::f_official)) { + if (it->id && it->access) { + MTP::send(MTPmessages_UninstallStickerSet(MTP_inputStickerSetID(MTP_long(it->id), MTP_long(it->access)))); + } else if (!it->shortName.isEmpty()) { + MTP::send(MTPmessages_UninstallStickerSet(MTP_inputStickerSetShortName(MTP_string(it->shortName)))); + } + bool writeRecent = false; + RecentStickerPack &recent(cGetRecentStickers()); + for (RecentStickerPack::iterator i = recent.begin(); i != recent.cend();) { + if (it->stickers.indexOf(i->first) >= 0) { + i = recent.erase(i); + writeRecent = true; + } else { + ++i; + } + } + it->flags &= ~MTPDstickerSet::Flag::f_installed; + if (!(it->flags & MTPDstickerSet_ClientFlag::f_featured) && !(it->flags & MTPDstickerSet_ClientFlag::f_special)) { + sets.erase(it); + } + int removeIndex = Global::StickerSetsOrder().indexOf(_removingSetId); + if (removeIndex >= 0) Global::RefStickerSetsOrder().removeAt(removeIndex); + refreshStickers(); + Local::writeInstalledStickers(); + if (writeRecent) Local::writeUserSettings(); } - } - it->flags &= ~MTPDstickerSet::Flag::f_installed; - if (!(it->flags & MTPDstickerSet_ClientFlag::f_featured) && !(it->flags & MTPDstickerSet_ClientFlag::f_special)) { - sets.erase(it); - } - int removeIndex = Global::StickerSetsOrder().indexOf(_removingSetId); - if (removeIndex >= 0) Global::RefStickerSetsOrder().removeAt(removeIndex); - refreshStickers(); - Local::writeInstalledStickers(); - if (writeRecent) Local::writeUserSettings(); + _removingSetId = 0; + onDelayedHide(); + }), base::lambda_guarded(this, [this] { + onDelayedHide(); + }))); } - _removingSetId = 0; } void EmojiPan::onDelayedHide() { @@ -3732,6 +3721,15 @@ void EmojiPan::clearInlineBot() { e_switch->moveToRight(st::buttonRadius, 0, st::emojiPanWidth); } +bool EmojiPan::overlaps(const QRect &globalRect) const { + if (isHidden() || !_cache.isNull()) return false; + + auto testRect = QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size()); + auto inner = rect().marginsRemoved(st::emojiPanMargins); + return inner.marginsRemoved(QMargins(st::buttonRadius, 0, st::buttonRadius, 0)).contains(testRect) + || inner.marginsRemoved(QMargins(0, st::buttonRadius, 0, st::buttonRadius)).contains(testRect); +} + bool EmojiPan::hideOnNoInlineResults() { return _inlineBot && !_emojiShown && s_inner->inlineResultsShown() && (_shownFromInlineQuery || _inlineBot->username != cInlineGifBotUsername()); } @@ -3820,7 +3818,7 @@ void EmojiPan::queryInlineBot(UserData *bot, PeerData *peer, QString query) { _inlineBot = bot; force = true; //if (_inlineBot->isBotInlineGeo()) { - // Ui::showLayer(new InformBox(lang(lng_bot_inline_geo_unavailable))); + // Ui::show(Box(lang(lng_bot_inline_geo_unavailable))); //} } //if (_inlineBot && _inlineBot->isBotInlineGeo()) { diff --git a/Telegram/SourceFiles/stickers/emoji_pan.h b/Telegram/SourceFiles/stickers/emoji_pan.h index d4126d483..098dd82c2 100644 --- a/Telegram/SourceFiles/stickers/emoji_pan.h +++ b/Telegram/SourceFiles/stickers/emoji_pan.h @@ -21,7 +21,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #pragma once #include "ui/twidget.h" -#include "ui/effects/rect_shadow.h" #include "ui/abstract_button.h" #include "ui/effects/panel_animation.h" @@ -111,8 +110,6 @@ private: QTimer _hideTimer; - Ui::RectShadow _shadow; - }; class EmojiPanel; @@ -122,7 +119,7 @@ class EmojiPanInner : public TWidget { public: EmojiPanInner(QWidget *parent); - void setMaxHeight(int32 h); + void setMaxHeight(int maxHeight); void hideFinish(); @@ -190,7 +187,7 @@ private: int _pickerSel = -1; QPoint _lastMousePos; - ChildWidget _picker; + object_ptr _picker; QTimer _showPickerTimer; }; @@ -212,7 +209,7 @@ class StickerPanInner : public TWidget, private base::Subscriber { public: StickerPanInner(QWidget *parent); - void setMaxHeight(int32 h); + void setMaxHeight(int maxHeight); void hideFinish(bool completely); void showFinish(); @@ -367,7 +364,7 @@ private: QTimer _updateInlineItems; bool _inlineWithThumb = false; - ChildWidget _switchPmButton = { nullptr }; + object_ptr _switchPmButton = { nullptr }; QString _switchPmStartToken; typedef QVector InlineItems; @@ -410,7 +407,7 @@ private: QString _addText; int _addWidth; - ChildWidget _settings; + object_ptr _settings; QTimer _previewTimer; bool _previewShown = false; @@ -476,9 +473,9 @@ class EmojiPan : public TWidget, public RPCSender { public: EmojiPan(QWidget *parent); - void setMaxHeight(int32 h); + void setMaxHeight(int maxHeight); - void moveBottom(int32 bottom, bool force = false); + void moveBottom(int bottom, bool force = false); void hideFast(); bool hiding() const { @@ -494,15 +491,7 @@ public: void queryInlineBot(UserData *bot, PeerData *peer, QString query); void clearInlineBot(); - bool overlaps(const QRect &globalRect) { - if (isHidden() || !_cache.isNull()) return false; - - return QRect(st::defaultDropdownPadding.left() + st::buttonRadius, - st::defaultDropdownPadding.top(), - _width - st::defaultDropdownPadding.left() - st::defaultDropdownPadding.right() - 2 * st::buttonRadius, - _height - st::defaultDropdownPadding.top() - st::defaultDropdownPadding.bottom() - ).contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size())); - } + bool overlaps(const QRect &globalRect) const; void notify_inlineItemLayoutChanged(const InlineBots::Layout::ItemBase *layout); void ui_repaintInlineItem(const InlineBots::Layout::ItemBase *layout); @@ -545,7 +534,6 @@ private slots: void onDisplaySet(quint64 setId); void onInstallSet(quint64 setId); void onRemoveSet(quint64 setId); - void onRemoveSetSure(); void onDelayedHide(); void onRefreshIcons(bool scrollAnimation); @@ -619,10 +607,16 @@ private: void showAll(); void hideAll(); - int32 _maxHeight, _contentMaxHeight, _contentHeight, _contentHeightEmoji, _contentHeightStickers; + int _maxHeight = 0; + int _contentMaxHeight = 0; + int _contentHeight = 0; + int _contentHeightEmoji = 0; + int _contentHeightStickers = 0; bool _horizontal = false; - int32 _width, _height, _bottom; + int _width = 0; + int _height = 0; + int _bottom = 0; Ui::PanelAnimation::Origin _origin = Ui::PanelAnimation::Origin::BottomRight; std_::unique_ptr _showAnimation; @@ -638,14 +632,14 @@ private: std_::unique_ptr _slideAnimation; Animation _a_slide; - ChildWidget _recent; - ChildWidget _people; - ChildWidget _nature; - ChildWidget _food; - ChildWidget _activity; - ChildWidget _travel; - ChildWidget _objects; - ChildWidget _symbols; + object_ptr _recent; + object_ptr _people; + object_ptr _nature; + object_ptr _food; + object_ptr _activity; + object_ptr _travel; + object_ptr _objects; + object_ptr _symbols; QList _icons; int _iconOver = -1; @@ -665,14 +659,14 @@ private: bool _emojiShown = true; bool _shownFromInlineQuery = false; - ChildWidget e_scroll; - ChildWidget e_inner; + object_ptr e_scroll; + QPointer e_inner; QVector e_panels; - ChildWidget e_switch; - ChildWidget s_scroll; - ChildWidget s_inner; + object_ptr e_switch; + object_ptr s_scroll; + QPointer s_inner; QVector s_panels; - ChildWidget s_switch; + object_ptr s_switch; uint64 _displayingSetId = 0; uint64 _removingSetId = 0; diff --git a/Telegram/SourceFiles/stickers/stickers.cpp b/Telegram/SourceFiles/stickers/stickers.cpp index bd6564016..107611106 100644 --- a/Telegram/SourceFiles/stickers/stickers.cpp +++ b/Telegram/SourceFiles/stickers/stickers.cpp @@ -78,7 +78,7 @@ void applyArchivedResult(const MTPDmessages_stickerSetInstallResultArchive &d) { } Local::writeInstalledStickers(); Local::writeArchivedStickers(); - Ui::showLayer(new StickersBox(archived), KeepOtherLayers); + Ui::show(Box(archived), KeepOtherLayers); emit App::main()->stickersUpdated(); } @@ -164,7 +164,7 @@ void undoInstallLocally(uint64 setId) { Local::writeInstalledStickers(); emit App::main()->stickersUpdated(); - Ui::showLayer(new InformBox(lang(lng_stickers_not_found)), KeepOtherLayers); + Ui::show(Box(lang(lng_stickers_not_found)), KeepOtherLayers); } void markFeaturedAsRead(uint64 setId) { diff --git a/Telegram/SourceFiles/stickers/stickers.style b/Telegram/SourceFiles/stickers/stickers.style index 98a201c9f..591d2d5bc 100644 --- a/Telegram/SourceFiles/stickers/stickers.style +++ b/Telegram/SourceFiles/stickers/stickers.style @@ -67,6 +67,10 @@ stickersRemoveSkip: 4px; stickersReorderIcon: icon {{ "stickers_reorder", menuIconFg }}; stickersReorderSkip: 13px; +stickersTabs: SettingsSlider(defaultTabsSlider) { + rippleRoundRadius: boxRadius; +} + stickerEmojiSkip: 5px; stickersFeaturedBadgeFont: font(12px bold); @@ -82,11 +86,11 @@ stickersFeaturedUnreadSkip: 5px; stickersFeaturedUnreadTop: 7px; stickersFeaturedInstalled: icon {{ "send_control_save", lightButtonFg }}; -stickersMaxHeight: 440px; -stickersPadding: margins(19px, 17px, 19px, 17px); +stickersMaxHeight: 320px; +stickersPadding: margins(19px, 13px, 19px, 13px); stickersSize: size(64px, 64px); -stickersScroll: FlatScroll(boxScroll) { - deltat: 23px; +stickersScroll: ScrollArea(boxLayerScroll) { + deltat: 19px; deltab: 9px; } stickersReorderPadding: margins(0px, 12px, 0px, 12px); @@ -103,7 +107,9 @@ stickersTrendingActive: icon {{ "emoji_trending", emojiIconFgActive }}; stickersSettingsUnreadSize: 17px; stickersSettingsUnreadPosition: point(4px, 5px); -emojiScroll: FlatScroll(defaultSolidScroll) { +emojiPanMargins: margins(10px, 10px, 10px, 10px); + +emojiScroll: ScrollArea(defaultSolidScroll) { deltat: 48px; } emojiRecent: icon {{ "emoji_recent", emojiIconFg }}; diff --git a/Telegram/SourceFiles/structs.cpp b/Telegram/SourceFiles/structs.cpp index 086d84ab7..b2d513412 100644 --- a/Telegram/SourceFiles/structs.cpp +++ b/Telegram/SourceFiles/structs.cpp @@ -1690,7 +1690,7 @@ ClickHandlerPtr peerOpenClickHandler(PeerData *peer) { if (App::main()) { if (peer && peer->isChannel() && App::main()->historyPeer() != peer) { if (!peer->asChannel()->isPublic() && !peer->asChannel()->amIn()) { - Ui::showLayer(new InformBox(lang((peer->isMegagroup()) ? lng_group_not_accessible : lng_channel_not_accessible))); + Ui::show(Box(lang((peer->isMegagroup()) ? lng_group_not_accessible : lng_channel_not_accessible))); } else { Ui::showPeerHistory(peer, ShowAtUnreadMsgId, Ui::ShowWay::Forward); } diff --git a/Telegram/SourceFiles/ui/countryinput.cpp b/Telegram/SourceFiles/ui/countryinput.cpp index acab902a7..abe5e31bb 100644 --- a/Telegram/SourceFiles/ui/countryinput.cpp +++ b/Telegram/SourceFiles/ui/countryinput.cpp @@ -160,9 +160,8 @@ void CountryInput::mouseMoveEvent(QMouseEvent *e) { void CountryInput::mousePressEvent(QMouseEvent *e) { mouseMoveEvent(e); if (_active) { - CountrySelectBox *box = new CountrySelectBox(); + auto box = Ui::show(Box()); connect(box, SIGNAL(countryChosen(const QString&)), this, SLOT(onChooseCountry(const QString&))); - Ui::showLayer(box); } } @@ -213,21 +212,25 @@ void CountryInput::setText(const QString &newText) { _text = _st.font->elided(newText, width() - _st.textMargins.left() - _st.textMargins.right()); } -CountrySelectBox::CountrySelectBox() : ItemListBox(st::countriesScroll, st::boxWidth) -, _inner(this) -, _select(this, st::contactsMultiSelect, lang(lng_country_ph)) -, _topShadow(this) { +CountrySelectBox::CountrySelectBox(QWidget*) +: _select(this, st::contactsMultiSelect, lang(lng_country_ph)) { +} + +void CountrySelectBox::prepare() { + setTitle(lang(lng_country_select)); + _select->resizeToWidth(st::boxWidth); - setTitleText(lang(lng_country_select)); - - ItemListBox::init(_inner, st::boxScrollSkip, titleHeight() + _select->height()); - _select->setQueryChangedCallback([this](const QString &query) { onFilterUpdate(query); }); _select->setSubmittedCallback([this](bool) { onSubmit(); }); - connect(_inner, SIGNAL(mustScrollTo(int, int)), scrollArea(), SLOT(scrollToY(int, int))); - connect(_inner, SIGNAL(countryChosen(const QString&)), this, SIGNAL(countryChosen(const QString&))); - raiseShadow(); + _inner = setInnerWidget(object_ptr(this), st::countriesScroll, _select->height()); + + addButton(lang(lng_close), [this] { closeBox(); }); + + setDimensions(st::boxWidth, st::boxMaxListHeight); + + connect(_inner, SIGNAL(mustScrollTo(int, int)), this, SLOT(onScrollToY(int, int))); + connect(_inner, SIGNAL(countryChosen(const QString&)), this, SIGNAL(countryChosen(const QString&))); } void CountrySelectBox::onSubmit() { @@ -240,30 +243,29 @@ void CountrySelectBox::keyPressEvent(QKeyEvent *e) { } else if (e->key() == Qt::Key_Up) { _inner->selectSkip(-1); } else if (e->key() == Qt::Key_PageDown) { - _inner->selectSkipPage(scrollArea()->height(), 1); + _inner->selectSkipPage(height() - _select->height(), 1); } else if (e->key() == Qt::Key_PageUp) { - _inner->selectSkipPage(scrollArea()->height(), -1); + _inner->selectSkipPage(height() - _select->height(), -1); } else { - ItemListBox::keyPressEvent(e); + BoxContent::keyPressEvent(e); } } void CountrySelectBox::resizeEvent(QResizeEvent *e) { - ItemListBox::resizeEvent(e); + BoxContent::resizeEvent(e); _select->resizeToWidth(width()); - _select->moveToLeft(0, titleHeight()); + _select->moveToLeft(0, 0); _inner->resizeToWidth(width()); - _topShadow.setGeometry(0, titleHeight() + _select->height(), width(), st::lineWidth); } void CountrySelectBox::onFilterUpdate(const QString &query) { - scrollArea()->scrollToY(0); + onScrollToY(0); _inner->updateFilter(query); } -void CountrySelectBox::doSetInnerFocus() { +void CountrySelectBox::setInnerFocus() { _select->setInnerFocus(); } @@ -337,12 +339,12 @@ void CountrySelectBox::Inner::paintEvent(QPaintEvent *e) { } } - QString code = QString("+") + (*countriesNow)[i]->code; - int32 codeWidth = st::countryRowCodeFont->width(code); + auto code = QString("+") + (*countriesNow)[i]->code; + auto codeWidth = st::countryRowCodeFont->width(code); - QString name = QString::fromUtf8((*countriesNow)[i]->name); - int32 nameWidth = st::countryRowNameFont->width(name); - int32 availWidth = width() - st::countryRowPadding.left() - st::countryRowPadding.right() - codeWidth - st::contactsScroll.width; + auto name = QString::fromUtf8((*countriesNow)[i]->name); + auto nameWidth = st::countryRowNameFont->width(name); + auto availWidth = width() - st::countryRowPadding.left() - st::countryRowPadding.right() - codeWidth - st::boxLayerScroll.width; if (nameWidth > availWidth) { name = st::countryRowNameFont->elided(name, availWidth); nameWidth = st::countryRowNameFont->width(name); diff --git a/Telegram/SourceFiles/ui/countryinput.h b/Telegram/SourceFiles/ui/countryinput.h index 6eaf18575..85e2576c8 100644 --- a/Telegram/SourceFiles/ui/countryinput.h +++ b/Telegram/SourceFiles/ui/countryinput.h @@ -20,7 +20,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org */ #pragma once -#include "ui/effects/rect_shadow.h" #include "boxes/abstractbox.h" #include "styles/style_widgets.h" @@ -60,36 +59,32 @@ private: }; -namespace internal { -class CountrySelectInner; -} // namespace internal - -class CountrySelectBox : public ItemListBox { +class CountrySelectBox : public BoxContent { Q_OBJECT public: - CountrySelectBox(); + CountrySelectBox(QWidget*); signals: void countryChosen(const QString &iso); -public slots: - void onSubmit(); - protected: + void prepare() override; + void setInnerFocus() override; + void keyPressEvent(QKeyEvent *e) override; void resizeEvent(QResizeEvent *e) override; - void doSetInnerFocus() override; +private slots: + void onSubmit(); private: void onFilterUpdate(const QString &query); - class Inner; - ChildWidget _inner; - ChildWidget _select; + object_ptr _select; - ScrollableBoxShadow _topShadow; + class Inner; + QPointer _inner; }; diff --git a/Telegram/SourceFiles/ui/effects/rect_shadow.cpp b/Telegram/SourceFiles/ui/effects/rect_shadow.cpp deleted file mode 100644 index 92f9dd685..000000000 --- a/Telegram/SourceFiles/ui/effects/rect_shadow.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop version of Telegram messaging app, see https://telegram.org - -Telegram Desktop is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -It is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -In addition, as a special exception, the copyright holders give permission -to link the code of portions of this program with the OpenSSL library. - -Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE -Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org -*/ -#include "stdafx.h" -#include "ui/effects/rect_shadow.h" - -namespace Ui { - -RectShadow::RectShadow(const style::icon &topLeft) : _size(topLeft.width()), _pixsize(_size * cIntRetinaFactor()) { - if (!_size) return; - - QImage cornersImage(_pixsize * 2, _pixsize * 2, QImage::Format_ARGB32_Premultiplied); - cornersImage.setDevicePixelRatio(cRetinaFactor()); - { - Painter p(&cornersImage); - p.setCompositionMode(QPainter::CompositionMode_Source); - topLeft.paint(p, QPoint(0, 0), _size); - } - if (rtl()) cornersImage = cornersImage.mirrored(true, false); - { - QPainter p(&cornersImage); - p.setCompositionMode(QPainter::CompositionMode_Source); - QImage m = cornersImage.mirrored(); - m.setDevicePixelRatio(cRetinaFactor()); - p.drawImage(0, _size, m, 0, _pixsize, _pixsize, _pixsize); - } - { - QPainter p(&cornersImage); - p.setCompositionMode(QPainter::CompositionMode_Source); - QImage m = cornersImage.mirrored(true, false); - m.setDevicePixelRatio(cRetinaFactor()); - p.drawImage(_size, 0, m, _pixsize, 0, _pixsize, _pixsize * 2); - } - - uchar prev = 0; - for (int i = 0; i < _pixsize; ++i) { - uchar a = (cornersImage.pixel(QPoint(i, _pixsize - 1)) >> 24); - if (a < prev) break; - - ++_thickness; - prev = a; - } - - _left = App::pixmapFromImageInPlace(cornersImage.copy(0, _pixsize - 1, _thickness, 1)); - _left.setDevicePixelRatio(cRetinaFactor()); - _top = App::pixmapFromImageInPlace(cornersImage.copy(_pixsize - 1, 0, 1, _thickness)); - _top.setDevicePixelRatio(cRetinaFactor()); - _right = App::pixmapFromImageInPlace(cornersImage.copy(_pixsize * 2 - _thickness, _pixsize, _thickness, 1)); - _right.setDevicePixelRatio(cRetinaFactor()); - _bottom = App::pixmapFromImageInPlace(cornersImage.copy(_pixsize, _pixsize * 2 - _thickness, 1, _thickness)); - _bottom.setDevicePixelRatio(cRetinaFactor()); - - _corners = App::pixmapFromImageInPlace(std_::move(cornersImage)); - _corners.setDevicePixelRatio(cRetinaFactor()); -} - -void RectShadow::paint(Painter &p, const QRect &box, int shifty, Sides sides) { - if (!_size) return; - - int32 rshifty = shifty * cIntRetinaFactor(); - int32 count = _thickness, countsize = count / cIntRetinaFactor(), minus = _size - countsize + shifty; - bool left = (sides & Side::Left), top = (sides & Side::Top), right = (sides & Side::Right), bottom = (sides & Side::Bottom); - if (left && top) p.drawPixmap(box.left() - _size + minus, box.top() - _size + minus + shifty, _corners, 0, 0, _pixsize, _pixsize); - if (right && top) p.drawPixmap(box.left() + box.width() - minus, box.top() - _size + minus + shifty, _corners, _pixsize, 0, _pixsize, _pixsize); - if (right && bottom) p.drawPixmap(box.left() + box.width() - minus, box.top() + box.height() - minus + shifty, _corners, _pixsize, _pixsize, _pixsize, _pixsize); - if (left && bottom) p.drawPixmap(box.left() - _size + minus, box.top() + box.height() - minus + shifty, _corners, 0, _pixsize, _pixsize, _pixsize); - - PainterHighQualityEnabler hq(p); - if (left) p.drawPixmap(box.left() - countsize + shifty, box.top() + (top ? (minus + shifty) : 0), countsize - shifty, box.height() - (bottom ? (minus - shifty) : 0) - (top ? (minus + shifty) : 0), _left, 0, 0, count - rshifty, 1); - if (top) p.drawPixmap(box.left() + (left ? minus : 0), box.top() - countsize + 2 * shifty, box.width() - (right ? minus : 0) - (left ? minus : 0), countsize - 2 * shifty, _top, 0, 0, 1, count - 2 * rshifty); - if (right) p.drawPixmap(box.left() + box.width(), box.top() + (top ? (minus + shifty) : 0), countsize - shifty, box.height() - (bottom ? (minus - shifty) : 0) - (top ? (minus + shifty) : 0), _right, rshifty, 0, count - rshifty, 1); - if (bottom) p.drawPixmap(box.left() + (left ? minus : 0), box.top() + box.height(), box.width() - (right ? minus : 0) - (left ? minus : 0), countsize, _bottom, 0, 0, 1, count); -} - -style::margins RectShadow::getDimensions(int32 shifty) const { - if (!_size) return style::margins(0, 0, 0, 0); - - int d = _thickness / cIntRetinaFactor(); - return style::margins(d - shifty, d - 2 * shifty, d - shifty, d); -} - -} // namespace Ui diff --git a/Telegram/SourceFiles/ui/effects/rect_shadow.h b/Telegram/SourceFiles/ui/effects/rect_shadow.h deleted file mode 100644 index af1e28b13..000000000 --- a/Telegram/SourceFiles/ui/effects/rect_shadow.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop version of Telegram messaging app, see https://telegram.org - -Telegram Desktop is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -It is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -In addition, as a special exception, the copyright holders give permission -to link the code of portions of this program with the OpenSSL library. - -Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE -Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org -*/ -#pragma once - -#include "styles/style_widgets.h" - -namespace Ui { - -class RectShadow { -public: - enum class Side { - Left = 0x01, - Top = 0x02, - Right = 0x04, - Bottom = 0x08, - }; - Q_DECLARE_FLAGS(Sides, Side); - Q_DECLARE_FRIEND_OPERATORS_FOR_FLAGS(Sides); - - RectShadow(const style::icon &topLeft); - - void paint(Painter &p, const QRect &box, int shifty, Sides sides = Side::Left | Side::Top | Side::Right | Side::Bottom); - style::margins getDimensions(int shifty) const; - -private: - int _size, _pixsize; - int _thickness = 0; - QPixmap _corners, _left, _top, _right, _bottom; - -}; -Q_DECLARE_OPERATORS_FOR_FLAGS(RectShadow::Sides); - -} // namespace Ui diff --git a/Telegram/SourceFiles/ui/effects/widget_fade_wrap.cpp b/Telegram/SourceFiles/ui/effects/widget_fade_wrap.cpp index 3d3533f70..af35a59bd 100644 --- a/Telegram/SourceFiles/ui/effects/widget_fade_wrap.cpp +++ b/Telegram/SourceFiles/ui/effects/widget_fade_wrap.cpp @@ -118,10 +118,10 @@ void FadeAnimation::updateCallback() { } WidgetFadeWrap::WidgetFadeWrap(QWidget *parent -, TWidget *entity -, base::lambda &&updateCallback -, int duration) : TWidget(parent) -, _entity(entity) +, object_ptr entity +, int duration +, base::lambda &&updateCallback) : TWidget(parent) +, _entity(std_::move(entity)) , _duration(duration) , _updateCallback(std_::move(updateCallback)) , _animation(this) { diff --git a/Telegram/SourceFiles/ui/effects/widget_fade_wrap.h b/Telegram/SourceFiles/ui/effects/widget_fade_wrap.h index fb21cc296..9ff034d09 100644 --- a/Telegram/SourceFiles/ui/effects/widget_fade_wrap.h +++ b/Telegram/SourceFiles/ui/effects/widget_fade_wrap.h @@ -45,6 +45,14 @@ public: void fadeIn(int duration); void fadeOut(int duration); + void finish() { + _animation.finish(); + } + + bool animating() const { + return _animation.animating(); + } + private: void startAnimation(int duration); void stopAnimation(); @@ -67,16 +75,17 @@ class WidgetFadeWrap; template <> class WidgetFadeWrap : public TWidget { public: - WidgetFadeWrap(QWidget *parent, TWidget *entity - , base::lambda &&updateCallback - , int duration = st::widgetFadeDuration); + WidgetFadeWrap(QWidget *parent + , object_ptr entity + , int duration = st::widgetFadeDuration + , base::lambda &&updateCallback = base::lambda()); - void fadeOut() { - _animation.fadeOut(_duration); - } - void fadeIn() { + void showAnimated() { _animation.fadeIn(_duration); } + void hideAnimated() { + _animation.fadeOut(_duration); + } void showFast() { _animation.show(); if (_updateCallback) { @@ -89,6 +98,9 @@ public: _updateCallback(); } } + void finishAnimation() { + _animation.finish(); + } TWidget *entity() { return _entity; @@ -105,12 +117,16 @@ public: return _entity->naturalWidth(); } + bool animating() const { + return _animation.animating(); + } + protected: bool eventFilter(QObject *object, QEvent *event) override; void paintEvent(QPaintEvent *e) override; private: - TWidget *_entity; + object_ptr _entity; int _duration; base::lambda _updateCallback; @@ -121,9 +137,13 @@ private: template class WidgetFadeWrap : public WidgetFadeWrap { public: - WidgetFadeWrap(QWidget *parent, Widget *entity - , base::lambda &&updateCallback - , int duration = st::widgetFadeDuration) : WidgetFadeWrap(parent, entity, std_::move(updateCallback), duration) { + WidgetFadeWrap(QWidget *parent + , object_ptr entity + , int duration = st::widgetFadeDuration + , base::lambda &&updateCallback = base::lambda()) : WidgetFadeWrap(parent + , std_::move(entity) + , duration + , std_::move(updateCallback)) { } Widget *entity() { return static_cast(WidgetFadeWrap::entity()); diff --git a/Telegram/SourceFiles/ui/effects/widget_slide_wrap.cpp b/Telegram/SourceFiles/ui/effects/widget_slide_wrap.cpp index 690b401c2..d39b50722 100644 --- a/Telegram/SourceFiles/ui/effects/widget_slide_wrap.cpp +++ b/Telegram/SourceFiles/ui/effects/widget_slide_wrap.cpp @@ -24,11 +24,11 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org namespace Ui { WidgetSlideWrap::WidgetSlideWrap(QWidget *parent -, TWidget *entity +, object_ptr entity , style::margins entityPadding , base::lambda &&updateCallback , int duration) : TWidget(parent) -, _entity(entity) +, _entity(std_::move(entity)) , _padding(entityPadding) , _duration(duration) , _updateCallback(std_::move(updateCallback)) { diff --git a/Telegram/SourceFiles/ui/effects/widget_slide_wrap.h b/Telegram/SourceFiles/ui/effects/widget_slide_wrap.h index 8d0c3bd32..17b161df7 100644 --- a/Telegram/SourceFiles/ui/effects/widget_slide_wrap.h +++ b/Telegram/SourceFiles/ui/effects/widget_slide_wrap.h @@ -30,7 +30,8 @@ class WidgetSlideWrap; template <> class WidgetSlideWrap : public TWidget { public: - WidgetSlideWrap(QWidget *parent, TWidget *entity + WidgetSlideWrap(QWidget *parent + , object_ptr entity , style::margins entityPadding , base::lambda &&updateCallback , int duration = st::widgetSlideDuration); @@ -58,7 +59,7 @@ protected: private: void animationCallback(); - TWidget *_entity; + object_ptr _entity; bool _inResizeToWidth = false; style::margins _padding; int _duration; @@ -74,10 +75,15 @@ private: template class WidgetSlideWrap : public WidgetSlideWrap { public: - WidgetSlideWrap(QWidget *parent, Widget *entity + WidgetSlideWrap(QWidget *parent + , object_ptr entity , style::margins entityPadding , base::lambda &&updateCallback - , int duration = st::widgetSlideDuration) : WidgetSlideWrap(parent, entity, entityPadding, std_::move(updateCallback), duration) { + , int duration = st::widgetSlideDuration) : WidgetSlideWrap(parent + , std_::move(entity) + , entityPadding + , std_::move(updateCallback) + , duration) { } Widget *entity() { return static_cast(WidgetSlideWrap::entity()); diff --git a/Telegram/SourceFiles/ui/images.cpp b/Telegram/SourceFiles/ui/images.cpp index ade2ab023..ab705545a 100644 --- a/Telegram/SourceFiles/ui/images.cpp +++ b/Telegram/SourceFiles/ui/images.cpp @@ -279,8 +279,9 @@ QImage prepareOpaque(QImage image) { for (auto y = 0; y != height; ++y) { for (auto x = 0; x != width; ++x) { auto components = anim::shifted(*ints); - *ints = anim::unshifted(components * 256 + bg * (256 - anim::getAlpha(components))); + *ints++ = anim::unshifted(components * 256 + bg * (256 - anim::getAlpha(components))); } + ints += addPerLine; } } return std_::move(image); diff --git a/Telegram/SourceFiles/ui/toast/toast.cpp b/Telegram/SourceFiles/ui/toast/toast.cpp index 715ef1913..47264388b 100644 --- a/Telegram/SourceFiles/ui/toast/toast.cpp +++ b/Telegram/SourceFiles/ui/toast/toast.cpp @@ -50,7 +50,7 @@ void Instance::opacityAnimationCallback() { } } -void Instance::fadeOut() { +void Instance::hideAnimated() { _hiding = true; _a_opacity.start([this] { opacityAnimationCallback(); }, 1., 0., st::toastFadeOutDuration); } diff --git a/Telegram/SourceFiles/ui/toast/toast.h b/Telegram/SourceFiles/ui/toast/toast.h index 8e7b13761..4acc538cc 100644 --- a/Telegram/SourceFiles/ui/toast/toast.h +++ b/Telegram/SourceFiles/ui/toast/toast.h @@ -45,7 +45,7 @@ public: Instance(const Instance &other) = delete; Instance &operator=(const Instance &other) = delete; - void fadeOut(); + void hideAnimated(); void hide(); private: diff --git a/Telegram/SourceFiles/ui/toast/toast_manager.cpp b/Telegram/SourceFiles/ui/toast/toast_manager.cpp index 4026a29a6..e0e32accf 100644 --- a/Telegram/SourceFiles/ui/toast/toast_manager.cpp +++ b/Telegram/SourceFiles/ui/toast/toast_manager.cpp @@ -68,9 +68,9 @@ void Manager::onHideTimeout() { auto now = getms(true); for (auto i = _toastByHideTime.begin(); i != _toastByHideTime.cend();) { if (i.key() <= now) { - Instance *toast = i.value(); + auto toast = i.value(); i = _toastByHideTime.erase(i); - toast->fadeOut(); + toast->hideAnimated(); } else { break; } @@ -81,7 +81,7 @@ void Manager::onHideTimeout() { void Manager::onToastWidgetDestroyed(QObject *widget) { auto i = _toastByWidget.find(static_cast(widget)); if (i != _toastByWidget.cend()) { - Instance *toast = i.value(); + auto toast = i.value(); _toastByWidget.erase(i); toast->_widget.release(); @@ -94,7 +94,7 @@ void Manager::onToastWidgetDestroyed(QObject *widget) { } void Manager::onToastWidgetParentResized() { - QObject *resizedWidget = QObject::sender(); + auto resizedWidget = QObject::sender(); if (!resizedWidget) return; for (auto i = _toastByWidget.cbegin(), e = _toastByWidget.cend(); i != e; ++i) { diff --git a/Telegram/SourceFiles/ui/twidget.cpp b/Telegram/SourceFiles/ui/twidget.cpp index e31d3a339..65ef1f622 100644 --- a/Telegram/SourceFiles/ui/twidget.cpp +++ b/Telegram/SourceFiles/ui/twidget.cpp @@ -63,13 +63,15 @@ void myEnsureResized(QWidget *target) { } } -QPixmap myGrab(TWidget *target, QRect rect) { +QPixmap myGrab(TWidget *target, QRect rect, QColor bg) { myEnsureResized(target); if (rect.isNull()) rect = target->rect(); - auto result = QPixmap(rect.size() * cRetinaFactor()); + auto result = QPixmap(rect.size() * cIntRetinaFactor()); result.setDevicePixelRatio(cRetinaFactor()); - result.fill(Qt::transparent); + if (!target->testAttribute(Qt::WA_OpaquePaintEvent)) { + result.fill(bg); + } target->grabStart(); target->render(&result, QPoint(0, 0), rect, QWidget::DrawChildren | QWidget::IgnoreMask); @@ -78,14 +80,14 @@ QPixmap myGrab(TWidget *target, QRect rect) { return std_::move(result); } -QImage myGrabImage(TWidget *target, QRect rect) { +QImage myGrabImage(TWidget *target, QRect rect, QColor bg) { myEnsureResized(target); if (rect.isNull()) rect = target->rect(); - auto result = QImage(rect.size() * cRetinaFactor(), QImage::Format_ARGB32_Premultiplied); + auto result = QImage(rect.size() * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied); result.setDevicePixelRatio(cRetinaFactor()); if (!target->testAttribute(Qt::WA_OpaquePaintEvent)) { - result.fill(Qt::transparent); + result.fill(bg); } target->grabStart(); diff --git a/Telegram/SourceFiles/ui/twidget.h b/Telegram/SourceFiles/ui/twidget.h index 7dccc9026..990d81851 100644 --- a/Telegram/SourceFiles/ui/twidget.h +++ b/Telegram/SourceFiles/ui/twidget.h @@ -290,8 +290,8 @@ public: }; void myEnsureResized(QWidget *target); -QPixmap myGrab(TWidget *target, QRect rect = QRect()); -QImage myGrabImage(TWidget *target, QRect rect = QRect()); +QPixmap myGrab(TWidget *target, QRect rect = QRect(), QColor bg = QColor(255, 255, 255, 0)); +QImage myGrabImage(TWidget *target, QRect rect = QRect(), QColor bg = QColor(255, 255, 255, 0)); class SingleDelayedCall : public QObject { Q_OBJECT @@ -318,72 +318,107 @@ private: }; -// A simple wrap around T* to explicitly state ownership -template -class ChildObject { +// Smart pointer for QObject*, has move semantics, destroys object if it doesn't have a parent. +template +class object_ptr { public: - ChildObject(std_::nullptr_t) : _object(nullptr) { + object_ptr(std_::nullptr_t) { } // No default constructor, but constructors with at least // one argument are simply make functions. template - ChildObject(Parent &&parent, Args&&... args) : _object(new T(std_::forward(parent), std_::forward(args)...)) { + explicit object_ptr(Parent &&parent, Args&&... args) : _object(new Object(std_::forward(parent), std_::forward(args)...)) { } - ChildObject(const ChildObject &other) = delete; - ChildObject &operator=(const ChildObject &other) = delete; + object_ptr(const object_ptr &other) = delete; + object_ptr &operator=(const object_ptr &other) = delete; + object_ptr(object_ptr &&other) : _object(base::take(other._object)) { + } + object_ptr &operator=(object_ptr &&other) { + auto temp = std_::move(other); + destroy(); + std_::swap_moveable(_object, temp._object); + return *this; + } - ChildObject &operator=(std_::nullptr_t) { + template ::value>> + object_ptr(object_ptr &&other) : _object(base::take(other._object)) { + } + + template ::value>> + object_ptr &operator=(object_ptr &&other) { + _object = base::take(other._object); + return *this; + } + + object_ptr &operator=(std_::nullptr_t) { _object = nullptr; return *this; } - ChildObject &operator=(T *object) { - _object = object; - return *this; - } - - T *operator->() const { - return _object; - } - T &operator*() const { - return *_object; - } // So we can pass this pointer to methods like connect(). - T *ptr() const { - return _object; + Object *data() const { + return static_cast(_object); } - operator T*() const { - return ptr(); + operator Object*() const { + return data(); } - // Use that instead "= new T(parent, ...)" + explicit operator bool() const { + return _object != nullptr; + } + + Object *operator->() const { + return data(); + } + Object &operator*() const { + return *data(); + } + + // Use that instead "= new Object(parent, ...)" template void create(Parent &&parent, Args&&... args) { - delete _object; - _object = new T(std_::forward(parent), std_::forward(args)...); + destroy(); + _object = new Object(std_::forward(parent), std_::forward(args)...); } void destroy() { delete base::take(_object); } void destroyDelayed() { if (_object) { - if (auto widget = base::up_cast(_object)) { + if (auto widget = base::up_cast(data())) { widget->hide(); } - _object->deleteLater(); - _object = nullptr; + base::take(_object)->deleteLater(); } } + ~object_ptr() { + if (auto pointer = _object) { + if (!pointer->parent()) { + destroy(); + } + } + } + + template + friend object_ptr static_object_cast(object_ptr source); + private: - T *_object; + template + friend class object_ptr; + + QObject *_object = nullptr; }; -template -using ChildWidget = ChildObject; +template +inline object_ptr static_object_cast(object_ptr source) { + auto result = object_ptr(nullptr); + result._object = static_cast(base::take(source._object)); + return std_::move(result); +} void sendSynteticMouseEvent(QWidget *widget, QEvent::Type type, Qt::MouseButton button, const QPoint &globalPoint); diff --git a/Telegram/SourceFiles/ui/widgets/discrete_sliders.cpp b/Telegram/SourceFiles/ui/widgets/discrete_sliders.cpp index 8f33f58c6..fd11eb43a 100644 --- a/Telegram/SourceFiles/ui/widgets/discrete_sliders.cpp +++ b/Telegram/SourceFiles/ui/widgets/discrete_sliders.cpp @@ -200,12 +200,13 @@ int SettingsSlider::resizeGetHeight(int newWidth) { return _st.height; } -void SettingsSlider::startRipple(int index) { +void SettingsSlider::startRipple(int sectionIndex) { if (!_st.ripple.showDuration) return; - enumerateSections([this, &index](Section §ion) { - if (!index--) { + auto index = 0; + enumerateSections([this, &index, sectionIndex](Section §ion) { + if (index++ == sectionIndex) { if (!section.ripple) { - auto mask = RippleAnimation::rectMask(QSize(section.width, height() - _st.rippleBottomSkip)); + auto mask = prepareRippleMask(sectionIndex, section); section.ripple = MakeShared(_st.ripple, std_::move(mask), [this] { update(); }); } section.ripple->add(mapFromGlobal(QCursor::pos()) - QPoint(section.left, 0)); @@ -215,6 +216,23 @@ void SettingsSlider::startRipple(int index) { }); } +QImage SettingsSlider::prepareRippleMask(int sectionIndex, const Section §ion) { + auto size = QSize(section.width, height() - _st.rippleBottomSkip); + if (!_st.rippleRoundRadius || sectionIndex > 0 && sectionIndex + 1 < getSectionsCount()) { + return RippleAnimation::rectMask(size); + } + return RippleAnimation::maskByDrawer(size, false, [this, sectionIndex, width = section.width](QPainter &p) { + auto plusRadius = _st.rippleRoundRadius + 1; + p.drawRoundedRect(0, 0, width, height() + plusRadius, _st.rippleRoundRadius, _st.rippleRoundRadius); + if (sectionIndex > 0) { + p.fillRect(0, 0, plusRadius, plusRadius, p.brush()); + } + if (sectionIndex + 1 < getSectionsCount()) { + p.fillRect(width - plusRadius, 0, plusRadius, plusRadius, p.brush()); + } + }); +} + void SettingsSlider::paintEvent(QPaintEvent *e) { Painter p(this); diff --git a/Telegram/SourceFiles/ui/widgets/discrete_sliders.h b/Telegram/SourceFiles/ui/widgets/discrete_sliders.h index b0d600e37..1ed11b42a 100644 --- a/Telegram/SourceFiles/ui/widgets/discrete_sliders.h +++ b/Telegram/SourceFiles/ui/widgets/discrete_sliders.h @@ -67,7 +67,7 @@ protected: template void enumerateSections(Lambda callback); - virtual void startRipple(int index) { + virtual void startRipple(int sectionIndex) { } void stopAnimation() { @@ -108,11 +108,12 @@ protected: int resizeGetHeight(int newWidth) override; - void startRipple(int index) override; + void startRipple(int sectionIndex) override; private: const style::font &getLabelFont() const override; int getAnimationDuration() const override; + QImage prepareRippleMask(int sectionIndex, const Section §ion); void resizeSections(int newWidth); diff --git a/Telegram/SourceFiles/ui/widgets/dropdown_menu.h b/Telegram/SourceFiles/ui/widgets/dropdown_menu.h index 7502b6292..37e6ea899 100644 --- a/Telegram/SourceFiles/ui/widgets/dropdown_menu.h +++ b/Telegram/SourceFiles/ui/widgets/dropdown_menu.h @@ -18,7 +18,6 @@ #pragma once #include "styles/style_widgets.h" -#include "ui/effects/rect_shadow.h" #include "ui/widgets/inner_dropdown.h" #include "ui/widgets/menu.h" @@ -101,7 +100,7 @@ private: const style::DropdownMenu &_st; base::lambda _hiddenCallback; - ChildWidget _menu; + object_ptr _menu; // Not ready with submenus yet. //using Submenus = QMap; diff --git a/Telegram/SourceFiles/ui/widgets/inner_dropdown.cpp b/Telegram/SourceFiles/ui/widgets/inner_dropdown.cpp index af45eaf8b..83d343422 100644 --- a/Telegram/SourceFiles/ui/widgets/inner_dropdown.cpp +++ b/Telegram/SourceFiles/ui/widgets/inner_dropdown.cpp @@ -51,9 +51,8 @@ InnerDropdown::InnerDropdown(QWidget *parent, const style::InnerDropdown &st) : } void InnerDropdown::setOwnedWidget(TWidget *widget) { - auto container = new Container(_scroll, widget, _st); connect(widget, SIGNAL(heightUpdated()), this, SLOT(onWidgetHeightUpdated())); - _scroll->setOwnedWidget(container); + auto container = _scroll->setOwnedWidget(object_ptr(_scroll, widget, _st)); container->resizeToWidth(_scroll->width()); container->moveToLeft(0, 0); container->show(); diff --git a/Telegram/SourceFiles/ui/widgets/inner_dropdown.h b/Telegram/SourceFiles/ui/widgets/inner_dropdown.h index a3683238e..4267f142c 100644 --- a/Telegram/SourceFiles/ui/widgets/inner_dropdown.h +++ b/Telegram/SourceFiles/ui/widgets/inner_dropdown.h @@ -120,7 +120,7 @@ private: base::lambda _hideStartCallback; base::lambda _hiddenCallback; - ChildWidget _scroll; + object_ptr _scroll; int _maxHeight = 0; diff --git a/Telegram/SourceFiles/ui/widgets/input_fields.cpp b/Telegram/SourceFiles/ui/widgets/input_fields.cpp index 65c225117..decd457c1 100644 --- a/Telegram/SourceFiles/ui/widgets/input_fields.cpp +++ b/Telegram/SourceFiles/ui/widgets/input_fields.cpp @@ -1934,13 +1934,8 @@ void InputArea::Inner::focusInEvent(QFocusEvent *e) { } void InputArea::focusInInner(bool focusByMouse) { - if (!_focused) { - _focused = true; - _borderAnimationStart = focusByMouse ? mapFromGlobal(QCursor::pos()).x() : (width() / 2); - _a_focused.start([this] { update(); }, 0., 1., _st.duration); - startPlaceholderAnimation(); - startBorderAnimation(); - } + _borderAnimationStart = focusByMouse ? mapFromGlobal(QCursor::pos()).x() : (width() / 2); + setFocused(true); } void InputArea::Inner::focusOutEvent(QFocusEvent *e) { @@ -1950,9 +1945,13 @@ void InputArea::Inner::focusOutEvent(QFocusEvent *e) { } void InputArea::focusOutInner() { - if (_focused) { - _focused = false; - _a_focused.start([this] { update(); }, 1., 0., _st.duration); + setFocused(false); +} + +void InputArea::setFocused(bool focused) { + if (_focused != focused) { + _focused = focused; + _a_focused.start([this] { update(); }, _focused ? 0. : 1., _focused ? 1. : 0., _st.duration); startPlaceholderAnimation(); startBorderAnimation(); } @@ -2275,6 +2274,11 @@ void InputArea::onRedoAvailable(bool avail) { if (App::wnd()) App::wnd()->updateGlobalMenu(); } +void InputArea::setDisplayFocused(bool focused) { + setFocused(focused); + finishAnimations(); +} + void InputArea::finishAnimations() { _a_focused.finish(); _a_error.finish(); @@ -2631,13 +2635,8 @@ void InputField::Inner::focusInEvent(QFocusEvent *e) { } void InputField::focusInInner(bool focusByMouse) { - if (!_focused) { - _focused = true; - _borderAnimationStart = focusByMouse ? mapFromGlobal(QCursor::pos()).x() : (width() / 2); - _a_focused.start([this] { update(); }, 0., 1., _st.duration); - startPlaceholderAnimation(); - startBorderAnimation(); - } + _borderAnimationStart = focusByMouse ? mapFromGlobal(QCursor::pos()).x() : (width() / 2); + setFocused(true); } void InputField::Inner::focusOutEvent(QFocusEvent *e) { @@ -2647,9 +2646,13 @@ void InputField::Inner::focusOutEvent(QFocusEvent *e) { } void InputField::focusOutInner() { - if (_focused) { - _focused = false; - _a_focused.start([this] { update(); }, 1., 0., _st.duration); + setFocused(false); +} + +void InputField::setFocused(bool focused) { + if (_focused != focused) { + _focused = focused; + _a_focused.start([this] { update(); }, _focused ? 0. : 1., _focused ? 1. : 0., _st.duration); startPlaceholderAnimation(); startBorderAnimation(); } @@ -3027,6 +3030,11 @@ void InputField::selectAll() { _inner->setTextCursor(cursor); } +void InputField::setDisplayFocused(bool focused) { + setFocused(focused); + finishAnimations(); +} + void InputField::finishAnimations() { _a_focused.finish(); _a_error.finish(); @@ -3383,26 +3391,25 @@ void MaskedInputField::startBorderAnimation() { } void MaskedInputField::focusInEvent(QFocusEvent *e) { - if (!_focused) { - _focused = true; - _borderAnimationStart = (e->reason() == Qt::MouseFocusReason) ? mapFromGlobal(QCursor::pos()).x() : (width() / 2); - _a_focused.start([this] { update(); }, 0., 1., _st.duration); - startPlaceholderAnimation(); - startBorderAnimation(); - } + _borderAnimationStart = (e->reason() == Qt::MouseFocusReason) ? mapFromGlobal(QCursor::pos()).x() : (width() / 2); + setFocused(true); QLineEdit::focusInEvent(e); emit focused(); } void MaskedInputField::focusOutEvent(QFocusEvent *e) { - if (_focused) { - _focused = false; - _a_focused.start([this] { update(); }, 1., 0., _st.duration); + setFocused(false); + QLineEdit::focusOutEvent(e); + emit blurred(); +} + +void MaskedInputField::setFocused(bool focused) { + if (_focused != focused) { + _focused = focused; + _a_focused.start([this] { update(); }, _focused ? 0. : 1., _focused ? 1. : 0., _st.duration); startPlaceholderAnimation(); startBorderAnimation(); } - QLineEdit::focusOutEvent(e); - emit blurred(); } void MaskedInputField::resizeEvent(QResizeEvent *e) { @@ -3456,6 +3463,11 @@ QSize MaskedInputField::minimumSizeHint() const { return geometry().size(); } +void MaskedInputField::setDisplayFocused(bool focused) { + setFocused(focused); + finishAnimations(); +} + void MaskedInputField::finishAnimations() { _a_focused.finish(); _a_error.finish(); diff --git a/Telegram/SourceFiles/ui/widgets/input_fields.h b/Telegram/SourceFiles/ui/widgets/input_fields.h index 557fc8fce..a59444902 100644 --- a/Telegram/SourceFiles/ui/widgets/input_fields.h +++ b/Telegram/SourceFiles/ui/widgets/input_fields.h @@ -342,6 +342,7 @@ public: const QString &getLastText() const { return _oldtext; } + void setDisplayFocused(bool focused); void finishAnimations(); QSize sizeHint() const override; @@ -452,6 +453,7 @@ private: void focusInInner(bool focusByMouse); void focusOutInner(); + void setFocused(bool focused); void processDocumentContentsChange(int position, int charsAdded); @@ -459,7 +461,7 @@ private: int _maxLength = -1; - ChildWidget _inner; + object_ptr _inner; QString _oldtext; @@ -513,6 +515,7 @@ public: return _oldtext; } void setPlaceholderHidden(bool forcePlaceholderHidden); + void setDisplayFocused(bool focused); void finishAnimations(); QSize sizeHint() const override; @@ -630,6 +633,7 @@ private: void focusInInner(bool focusByMouse); void focusOutInner(); + void setFocused(bool focused); void processDocumentContentsChange(int position, int charsAdded); @@ -638,7 +642,7 @@ private: int _maxLength = -1; bool _forcePlaceholderHidden = false; - ChildWidget _inner; + object_ptr _inner; QString _oldtext; @@ -692,6 +696,7 @@ public: return _oldtext; } void setPlaceholderHidden(bool forcePlaceholderHidden); + void setDisplayFocused(bool focused); void finishAnimations(); void setText(const QString &text) { @@ -764,6 +769,8 @@ private: void createPlaceholderPath(); void setErrorShown(bool error); + void setFocused(bool focused); + int _maxLength = -1; bool _forcePlaceholderHidden = false; diff --git a/Telegram/SourceFiles/ui/widgets/labels.cpp b/Telegram/SourceFiles/ui/widgets/labels.cpp index 84d36b6dc..87bab310b 100644 --- a/Telegram/SourceFiles/ui/widgets/labels.cpp +++ b/Telegram/SourceFiles/ui/widgets/labels.cpp @@ -610,10 +610,7 @@ std_::unique_ptr FlatLabel::CrossFade(FlatLabel *from, FlatL }; auto prepareData = [&bg](FlatLabel *label) { auto result = Data(); - result.full = QImage(label->size() * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied); - result.full.setDevicePixelRatio(cRetinaFactor()); - result.full.fill(bg->c); - Painter(&result.full).drawImage(0, 0, myGrabImage(label)); + result.full = myGrabImage(label, QRect(), bg->c); auto textWidth = label->width() - label->_st.margin.left() - label->_st.margin.right(); label->_text.countLineWidths(textWidth, &result.lineWidths); result.lineHeight = label->_st.font->height; diff --git a/Telegram/SourceFiles/ui/widgets/multi_select.cpp b/Telegram/SourceFiles/ui/widgets/multi_select.cpp index 01da8e788..13f01a649 100644 --- a/Telegram/SourceFiles/ui/widgets/multi_select.cpp +++ b/Telegram/SourceFiles/ui/widgets/multi_select.cpp @@ -328,9 +328,10 @@ void MultiSelect::Inner::Item::setOver(bool over) { MultiSelect::MultiSelect(QWidget *parent, const style::MultiSelect &st, const QString &placeholder) : TWidget(parent) , _st(st) -, _scroll(this, _st.scroll) -, _inner(this, st, placeholder, [this](int activeTop, int activeBottom) { scrollTo(activeTop, activeBottom); }) { - _scroll->setOwnedWidget(_inner); +, _scroll(this, _st.scroll) { + _inner = _scroll->setOwnedWidget(object_ptr(this, st, placeholder, [this](int activeTop, int activeBottom) { + scrollTo(activeTop, activeBottom); + })); _scroll->installEventFilter(this); _inner->setResizedCallback([this](int innerHeightDelta) { auto newHeight = resizeGetHeight(width()); diff --git a/Telegram/SourceFiles/ui/widgets/multi_select.h b/Telegram/SourceFiles/ui/widgets/multi_select.h index 41a57bce9..32fc912b1 100644 --- a/Telegram/SourceFiles/ui/widgets/multi_select.h +++ b/Telegram/SourceFiles/ui/widgets/multi_select.h @@ -60,10 +60,10 @@ private: const style::MultiSelect &_st; - ChildWidget _scroll; + object_ptr _scroll; class Inner; - ChildWidget _inner; + QPointer _inner; base::lambda _resizedCallback; base::lambda _queryChangedCallback; @@ -153,8 +153,8 @@ private: int _fieldLeft = 0; int _fieldTop = 0; int _fieldWidth = 0; - ChildWidget _field; - ChildWidget _cancel; + object_ptr _field; + object_ptr _cancel; int _newHeight = 0; Animation _height; diff --git a/Telegram/SourceFiles/ui/widgets/popup_menu.h b/Telegram/SourceFiles/ui/widgets/popup_menu.h index 7428fd5a5..86271dfaa 100644 --- a/Telegram/SourceFiles/ui/widgets/popup_menu.h +++ b/Telegram/SourceFiles/ui/widgets/popup_menu.h @@ -105,7 +105,7 @@ private: const style::PopupMenu &_st; - ChildWidget _menu; + object_ptr _menu; using Submenus = QMap; Submenus _submenus; diff --git a/Telegram/SourceFiles/ui/widgets/scroll_area.cpp b/Telegram/SourceFiles/ui/widgets/scroll_area.cpp index d0af59c9d..99e55ae96 100644 --- a/Telegram/SourceFiles/ui/widgets/scroll_area.cpp +++ b/Telegram/SourceFiles/ui/widgets/scroll_area.cpp @@ -25,7 +25,7 @@ namespace Ui { // flick scroll taken from http://qt-project.org/doc/qt-4.8/demos-embedded-anomaly-src-flickcharm-cpp.html -ScrollShadow::ScrollShadow(ScrollArea *parent, const style::FlatScroll *st) : QWidget(parent), _st(st) { +ScrollShadow::ScrollShadow(ScrollArea *parent, const style::ScrollArea *st) : QWidget(parent), _st(st) { setVisible(false); } @@ -38,7 +38,7 @@ void ScrollShadow::changeVisibility(bool shown) { setVisible(shown); } -ScrollBar::ScrollBar(ScrollArea *parent, bool vert, const style::FlatScroll *st) : QWidget(parent) +ScrollBar::ScrollBar(ScrollArea *parent, bool vert, const style::ScrollArea *st) : QWidget(parent) , _st(st) , _vertical(vert) , _hiding(_st->hiding != 0) @@ -313,7 +313,7 @@ void SplittedWidgetOther::paintEvent(QPaintEvent *e) { } } -ScrollArea::ScrollArea(QWidget *parent, const style::FlatScroll &st, bool handleTouch) : QScrollArea(parent) +ScrollArea::ScrollArea(QWidget *parent, const style::ScrollArea &st, bool handleTouch) : QScrollArea(parent) , _st(st) , _horizontalBar(this, false, &_st) , _verticalBar(this, true, &_st) @@ -699,39 +699,34 @@ void ScrollArea::scrollToY(int toTop, int toBottom) { verticalScrollBar()->setValue(scToTop); } -void ScrollArea::setWidget(QWidget *w) { - SplittedWidget *splitted = qobject_cast(w); +void ScrollArea::doSetOwnedWidget(object_ptr w) { + auto splitted = qobject_cast(w.data()); if (widget() && _touchEnabled) { widget()->removeEventFilter(this); if (!_widgetAcceptsTouch) widget()->setAttribute(Qt::WA_AcceptTouchEvents, false); } if (_other && !splitted) { - delete _other; - _other = 0; + _other.destroy(); disconnect(verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(onVerticalScroll())); } else if (!_other && splitted) { - _other = new SplittedWidgetOther(this); - _other->setAttribute(Qt::WA_OpaquePaintEvent); + _other.create(this); _other->resize(_verticalBar->width(), _other->height()); connect(verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(onVerticalScroll())); _horizontalBar->raise(); _verticalBar->raise(); } - if (_ownsWidget) { - _ownsWidget = false; - delete takeWidget(); - } - QScrollArea::setWidget(w); - if (w) { - w->setAutoFillBackground(false); + _widget = std_::move(w); + QScrollArea::setWidget(_widget); + if (_widget) { + _widget->setAutoFillBackground(false); if (_touchEnabled) { - w->installEventFilter(this); - _widgetAcceptsTouch = w->testAttribute(Qt::WA_AcceptTouchEvents); - w->setAttribute(Qt::WA_AcceptTouchEvents); + _widget->installEventFilter(this); + _widgetAcceptsTouch = _widget->testAttribute(Qt::WA_AcceptTouchEvents); + _widget->setAttribute(Qt::WA_AcceptTouchEvents); } if (splitted) { splitted->setOtherWidth(_verticalBar->width()); - w->setGeometry(rtl() ? splitted->otherWidth() : 0, 0, width() - splitted->otherWidth(), w->height()); + _widget->setGeometry(rtl() ? splitted->otherWidth() : 0, 0, width() - splitted->otherWidth(), _widget->height()); connect(splitted, SIGNAL(resizeOther()), this, SLOT(onResizeOther())); connect(splitted, SIGNAL(updateOther(const QRect&)), this, SLOT(onUpdateOther(const QRect&))); connect(splitted, SIGNAL(updateOther(const QRegion&)), this, SLOT(onUpdateOther(const QRegion&))); @@ -741,18 +736,13 @@ void ScrollArea::setWidget(QWidget *w) { } } -void ScrollArea::setOwnedWidget(QWidget *widget) { - setWidget(widget); - _ownsWidget = true; -} - -QWidget *ScrollArea::takeWidget() { +object_ptr ScrollArea::doTakeWidget() { if (_other) { - delete _other; - _other = 0; + _other.destroy(); disconnect(verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(onVerticalScroll())); } - return QScrollArea::takeWidget(); + QScrollArea::takeWidget(); + return std_::move(_widget); } void ScrollArea::onResizeOther() { @@ -792,10 +782,4 @@ void ScrollArea::setMovingByScrollBar(bool movingByScrollBar) { _movingByScrollBar = movingByScrollBar; } -ScrollArea::~ScrollArea() { - if (!_ownsWidget) { - takeWidget(); - } -} - } // namespace Ui diff --git a/Telegram/SourceFiles/ui/widgets/scroll_area.h b/Telegram/SourceFiles/ui/widgets/scroll_area.h index c2463b796..002daf6a6 100644 --- a/Telegram/SourceFiles/ui/widgets/scroll_area.h +++ b/Telegram/SourceFiles/ui/widgets/scroll_area.h @@ -37,7 +37,7 @@ class ScrollShadow : public QWidget { public: - ScrollShadow(ScrollArea *parent, const style::FlatScroll *st); + ScrollShadow(ScrollArea *parent, const style::ScrollArea *st); void paintEvent(QPaintEvent *e); @@ -47,7 +47,7 @@ public slots: private: - const style::FlatScroll *_st; + const style::ScrollArea *_st; }; @@ -55,7 +55,7 @@ class ScrollBar : public QWidget { Q_OBJECT public: - ScrollBar(ScrollArea *parent, bool vertical, const style::FlatScroll *st); + ScrollBar(ScrollArea *parent, bool vertical, const style::ScrollArea *st); void recountSize(); @@ -86,7 +86,7 @@ private: void setOverBar(bool overbar); void setMoving(bool moving); - const style::FlatScroll *_st; + const style::ScrollArea *_st; bool _vertical = true; bool _hiding = false; @@ -174,7 +174,7 @@ class ScrollArea : public QScrollArea { T_WIDGET public: - ScrollArea(QWidget *parent, const style::FlatScroll &st = st::defaultFlatScroll, bool handleTouch = true); + ScrollArea(QWidget *parent, const style::ScrollArea &st = st::defaultScrollArea, bool handleTouch = true); int scrollWidth() const; int scrollHeight() const; @@ -183,9 +183,16 @@ public: int scrollLeft() const; int scrollTop() const; - void setWidget(QWidget *widget); - void setOwnedWidget(QWidget *widget); - QWidget *takeWidget(); + template + QPointer setOwnedWidget(object_ptr widget) { + auto result = QPointer(widget); + doSetOwnedWidget(std_::move(widget)); + return result; + } + template + object_ptr takeWidget() { + return static_object_cast(doTakeWidget()); + } void rangeChanged(int oldMax, int newMax, bool vertical); @@ -201,8 +208,6 @@ public: return QMargins(); } - ~ScrollArea(); - protected: bool eventFilter(QObject *obj, QEvent *e) override; @@ -236,6 +241,11 @@ protected: void scrollContentsBy(int dx, int dy) override; private: + void doSetOwnedWidget(object_ptr widget); + object_ptr doTakeWidget(); + + void setWidget(QWidget *widget); + bool touchScroll(const QPoint &delta); void touchScrollUpdated(const QPoint &screenPos); @@ -245,12 +255,11 @@ private: void touchDeaccelerate(int32 elapsed); bool _disabled = false; - bool _ownsWidget = false; // if true, the widget is deleted in destructor. bool _movingByScrollBar = false; - const style::FlatScroll &_st; - ChildWidget _horizontalBar, _verticalBar; - ChildWidget _topShadow, _bottomShadow; + const style::ScrollArea &_st; + object_ptr _horizontalBar, _verticalBar; + object_ptr _topShadow, _bottomShadow; int _horizontalValue, _verticalValue; bool _touchEnabled; @@ -272,13 +281,16 @@ private: bool _widgetAcceptsTouch = false; friend class SplittedWidgetOther; - SplittedWidgetOther *_other = nullptr; + object_ptr _other = { nullptr }; + + object_ptr _widget = { nullptr }; }; class SplittedWidgetOther : public TWidget { public: SplittedWidgetOther(ScrollArea *parent) : TWidget(parent) { + setAttribute(Qt::WA_OpaquePaintEvent); } protected: diff --git a/Telegram/SourceFiles/ui/widgets/shadow.cpp b/Telegram/SourceFiles/ui/widgets/shadow.cpp index 13fd54eb3..a20cfa364 100644 --- a/Telegram/SourceFiles/ui/widgets/shadow.cpp +++ b/Telegram/SourceFiles/ui/widgets/shadow.cpp @@ -23,36 +23,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org namespace Ui { -void ToggleableShadow::setMode(Mode mode) { - if (mode == Mode::ShownFast || mode == Mode::HiddenFast) { - if (_a_opacity.animating()) { - _a_opacity.finish(); - update(); - } - } - if (_shown && (mode == Mode::Hidden || mode == Mode::HiddenFast)) { - _shown = false; - if (mode == Mode::Hidden) { - _a_opacity.start([this] { update(); }, 1., 0., st::shadowToggleDuration); - } - } else if (!_shown && (mode == Mode::Shown || mode == Mode::ShownFast)) { - _shown = true; - if (mode == Mode::Shown) { - _a_opacity.start([this] { update(); }, 0., 1., st::shadowToggleDuration); - } - } -} - -void ToggleableShadow::paintEvent(QPaintEvent *e) { - Painter p(this); - if (_a_opacity.animating(getms())) { - p.setOpacity(_a_opacity.current()); - } else if (!_shown) { - return; - } - p.fillRect(e->rect(), _color); -} - void Shadow::paint(Painter &p, const QRect &box, int outerWidth, const style::Shadow &st, Sides sides) { auto left = (sides & Side::Left); auto top = (sides & Side::Top); @@ -108,4 +78,27 @@ void Shadow::paint(Painter &p, const QRect &box, int outerWidth, const style::Sh } } +QPixmap Shadow::grab(TWidget *target, const style::Shadow &shadow, Sides sides) { + myEnsureResized(target); + auto rect = target->rect(); + auto extend = QMargins( + (sides & Side::Left) ? shadow.extend.left() : 0, + (sides & Side::Top) ? shadow.extend.top() : 0, + (sides & Side::Right) ? shadow.extend.right() : 0, + (sides & Side::Bottom) ? shadow.extend.bottom() : 0 + ); + auto full = QRect(0, 0, extend.left() + rect.width() + extend.right(), extend.top() + rect.height() + extend.bottom()); + auto result = QPixmap(full.size() * cIntRetinaFactor()); + result.setDevicePixelRatio(cRetinaFactor()); + result.fill(Qt::transparent); + { + Painter p(&result); + Ui::Shadow::paint(p, full.marginsRemoved(extend), full.width(), shadow); + target->grabStart(); + target->render(&p, QPoint(extend.left(), extend.top()), rect, QWidget::DrawChildren | QWidget::IgnoreMask); + target->grabFinish(); + } + return std_::move(result); +} + } // namespace Ui diff --git a/Telegram/SourceFiles/ui/widgets/shadow.h b/Telegram/SourceFiles/ui/widgets/shadow.h index f09fc5129..a5a20f810 100644 --- a/Telegram/SourceFiles/ui/widgets/shadow.h +++ b/Telegram/SourceFiles/ui/widgets/shadow.h @@ -36,53 +36,6 @@ private: }; -class ToggleableShadow : public TWidget { -public: - ToggleableShadow(QWidget *parent, const style::color &color) : TWidget(parent), _color(color) { - } - - enum class Mode { - Shown, - ShownFast, - Hidden, - HiddenFast - }; - void setMode(Mode mode); - - bool isFullyShown() const { - return _shown && !_a_opacity.animating(); - } - -protected: - void paintEvent(QPaintEvent *e) override; - -private: - const style::color &_color; - Animation _a_opacity; - bool _shown = true; - -}; - -class GradientShadow : public TWidget { -public: - GradientShadow(QWidget *parent, const style::icon &icon) : TWidget(parent), _icon(icon) { - } - -protected: - int resizeGetHeight(int newWidth) override { - return _icon.height(); - } - void paintEvent(QPaintEvent *e) override { - Painter p(this); - auto clip = e->rect(); - _icon.fill(p, QRect(clip.x(), 0, clip.width(), height())); - } - -private: - const style::icon &_icon; - -}; - class Shadow : public TWidget { public: enum class Side { @@ -101,6 +54,8 @@ public: static void paint(Painter &p, const QRect &box, int outerWidth, const style::Shadow &st, Sides sides = Side::Left | Side::Top | Side::Right | Side::Bottom); + static QPixmap grab(TWidget *target, const style::Shadow &shadow, Sides sides = Side::Left | Side::Top | Side::Right | Side::Bottom); + protected: void paintEvent(QPaintEvent *e) override { Painter p(this); diff --git a/Telegram/SourceFiles/ui/widgets/widgets.style b/Telegram/SourceFiles/ui/widgets/widgets.style index 19a2e7d68..3f1bc3b8a 100644 --- a/Telegram/SourceFiles/ui/widgets/widgets.style +++ b/Telegram/SourceFiles/ui/widgets/widgets.style @@ -118,7 +118,7 @@ Checkbox { ripple: RippleAnimation; } -FlatScroll { +ScrollArea { barColor: color; bgColor: color; barOverColor: color; @@ -339,7 +339,7 @@ MultiSelect { bg: color; padding: margins; maxHeight: pixels; - scroll: FlatScroll; + scroll: ScrollArea; item: MultiSelectItem; itemSkip: pixels; @@ -414,7 +414,7 @@ InnerDropdown { width: pixels; bg: color; - scroll: FlatScroll; + scroll: ScrollArea; scrollMargin: margins; scrollPadding: margins; } @@ -481,6 +481,8 @@ defaultActiveButton: RoundButton { defaultLightButton: RoundButton(defaultActiveButton) { textFg: lightButtonFg; textFgOver: lightButtonFgOver; + secondaryTextFg: lightButtonFg; + secondaryTextFgOver: lightButtonFgOver; textBg: lightButtonBg; textBgOver: lightButtonBgOver; @@ -489,7 +491,7 @@ defaultLightButton: RoundButton(defaultActiveButton) { } } -defaultFlatScroll: FlatScroll { +defaultScrollArea: ScrollArea { barColor: #00000053; bgColor: #0000001a; barOverColor: #0000007a; @@ -511,7 +513,7 @@ defaultFlatScroll: FlatScroll { hiding: 1000; } -defaultSolidScroll: FlatScroll(defaultFlatScroll) { +defaultSolidScroll: ScrollArea(defaultScrollArea) { deltax: 5px; width: 14px; deltat: 6px; @@ -660,6 +662,7 @@ SettingsSlider { labelFgActive: color; duration: int; rippleBottomSkip: pixels; + rippleRoundRadius: pixels; rippleBg: color; rippleBgActive: color; ripple: RippleAnimation; diff --git a/Telegram/SourceFiles/window/main_window.h b/Telegram/SourceFiles/window/main_window.h index d287a0370..306881e57 100644 --- a/Telegram/SourceFiles/window/main_window.h +++ b/Telegram/SourceFiles/window/main_window.h @@ -51,7 +51,7 @@ public: virtual ~MainWindow(); TWidget *bodyWidget() { - return _body; + return _body.data(); } protected: @@ -86,11 +86,11 @@ private: void updateUnreadCounter(); void initSize(); - ChildObject _positionUpdatedTimer; + object_ptr _positionUpdatedTimer; bool _positionInited = false; - ChildWidget _title = { nullptr }; - ChildWidget _body; + object_ptr _title = { nullptr }; + object_ptr _body; QString _titleText; diff --git a/Telegram/SourceFiles/window/notifications_manager_default.cpp b/Telegram/SourceFiles/window/notifications_manager_default.cpp index 3d7d0181e..dee5d70d1 100644 --- a/Telegram/SourceFiles/window/notifications_manager_default.cpp +++ b/Telegram/SourceFiles/window/notifications_manager_default.cpp @@ -561,7 +561,7 @@ void Notification::onReplyCancel() { void Notification::updateGeometry(int x, int y, int width, int height) { if (height > st::notifyMinHeight) { if (!_background) { - _background = new Background(this); + _background.create(this); } _background->setGeometry(0, st::notifyMinHeight, width, height - st::notifyMinHeight); } else if (_background) { diff --git a/Telegram/SourceFiles/window/notifications_manager_default.h b/Telegram/SourceFiles/window/notifications_manager_default.h index 84f1e8531..c99451c17 100644 --- a/Telegram/SourceFiles/window/notifications_manager_default.h +++ b/Telegram/SourceFiles/window/notifications_manager_default.h @@ -192,7 +192,7 @@ public: return !_history; } bool isReplying() const { - return (_replyArea != nullptr) && !isUnlinked(); + return _replyArea && !isUnlinked(); } // Called only by Manager. @@ -243,11 +243,11 @@ private: PeerData *_author; HistoryItem *_item; int _forwardedCount; - ChildWidget _close; - ChildWidget _reply; - ChildWidget _background = { nullptr }; - ChildWidget _replyArea = { nullptr }; - ChildWidget _replySend = { nullptr }; + object_ptr _close; + object_ptr _reply; + object_ptr _background = { nullptr }; + object_ptr _replyArea = { nullptr }; + object_ptr _replySend = { nullptr }; bool _waitingForInput = true; QTimer _hideTimer; diff --git a/Telegram/SourceFiles/window/player_wrap_widget.cpp b/Telegram/SourceFiles/window/player_wrap_widget.cpp index 4c7120760..6c307eb7d 100644 --- a/Telegram/SourceFiles/window/player_wrap_widget.cpp +++ b/Telegram/SourceFiles/window/player_wrap_widget.cpp @@ -26,7 +26,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org namespace Window { PlayerWrapWidget::PlayerWrapWidget(QWidget *parent, base::lambda &&updateCallback) : Parent(parent - , new Media::Player::Widget(parent) + , object_ptr(parent) , style::margins(0, 0, 0, 0) , std_::move(updateCallback)) { } diff --git a/Telegram/SourceFiles/window/section_memento.h b/Telegram/SourceFiles/window/section_memento.h index 5f288349d..78c329b3a 100644 --- a/Telegram/SourceFiles/window/section_memento.h +++ b/Telegram/SourceFiles/window/section_memento.h @@ -26,7 +26,7 @@ class SectionWidget; class SectionMemento { public: - virtual SectionWidget *createWidget(QWidget *parent, const QRect &geometry) const = 0; + virtual object_ptr createWidget(QWidget *parent, const QRect &geometry) const = 0; virtual ~SectionMemento() { } diff --git a/Telegram/SourceFiles/window/top_bar_widget.cpp b/Telegram/SourceFiles/window/top_bar_widget.cpp index 9d840524f..d954e8152 100644 --- a/Telegram/SourceFiles/window/top_bar_widget.cpp +++ b/Telegram/SourceFiles/window/top_bar_widget.cpp @@ -106,19 +106,19 @@ void TopBarWidget::showMenu() { if (auto peer = main->peer()) { if (!_menu) { _menu.create(App::main()); - _menu->setHiddenCallback([that = weak(), menu = _menu.ptr()] { + _menu->setHiddenCallback([that = weak(), menu = _menu.data()] { menu->deleteLater(); if (that && that->_menu == menu) { that->_menu = nullptr; that->_menuToggle->setForceRippled(false); } }); - _menu->setShowStartCallback(base::lambda_guarded(this, [this, menu = _menu.ptr()] { + _menu->setShowStartCallback(base::lambda_guarded(this, [this, menu = _menu.data()] { if (_menu == menu) { _menuToggle->setForceRippled(true); } })); - _menu->setHideStartCallback(base::lambda_guarded(this, [this, menu = _menu.ptr()] { + _menu->setHideStartCallback(base::lambda_guarded(this, [this, menu = _menu.data()] { if (_menu == menu) { _menuToggle->setForceRippled(false); } @@ -312,7 +312,7 @@ void TopBarWidget::updateMembersShowArea() { } return; } else if (!_membersShowArea) { - _membersShowArea = new TWidget(this); + _membersShowArea.create(this); _membersShowArea->show(); _membersShowArea->installEventFilter(this); } diff --git a/Telegram/SourceFiles/window/top_bar_widget.h b/Telegram/SourceFiles/window/top_bar_widget.h index 792bd4280..8af590e37 100644 --- a/Telegram/SourceFiles/window/top_bar_widget.h +++ b/Telegram/SourceFiles/window/top_bar_widget.h @@ -76,17 +76,17 @@ private: bool _animating = false; - ChildWidget _clearSelection; - ChildWidget _forward, _delete; + object_ptr _clearSelection; + object_ptr _forward, _delete; - ChildWidget _info; - ChildWidget _mediaType; + object_ptr _info; + object_ptr _mediaType; - ChildWidget _search; - ChildWidget _menuToggle; - ChildWidget _menu = { nullptr }; + object_ptr _search; + object_ptr _menuToggle; + object_ptr _menu = { nullptr }; - ChildWidget _membersShowArea = { nullptr }; + object_ptr _membersShowArea = { nullptr }; int _unreadCounterSubscription = 0; diff --git a/Telegram/SourceFiles/window/window.style b/Telegram/SourceFiles/window/window.style index 7c1a2b0fa..2020a877f 100644 --- a/Telegram/SourceFiles/window/window.style +++ b/Telegram/SourceFiles/window/window.style @@ -73,6 +73,9 @@ notifyReplyArea: InputField(defaultInputField) { textMargins: margins(8px, 8px, 8px, 6px); heightMin: 36px; heightMax: 72px; + placeholderFgActive: #aaaaaa; + placeholderFgError: #aaaaaa; + placeholderMargins: margins(2px, 0px, 2px, 0px); placeholderScale: 0.; placeholderFont: normalFont; border: 0px; diff --git a/Telegram/SourceFiles/window/window_main_menu.cpp b/Telegram/SourceFiles/window/window_main_menu.cpp index d7a38f89d..1b7573796 100644 --- a/Telegram/SourceFiles/window/window_main_menu.cpp +++ b/Telegram/SourceFiles/window/window_main_menu.cpp @@ -56,7 +56,7 @@ MainMenu::MainMenu(QWidget *parent) : TWidget(parent) App::wnd()->onShowNewChannel(); }, &st::mainMenuNewChannel, &st::mainMenuNewChannelOver); _menu->addAction(lang(lng_menu_contacts), [] { - Ui::showLayer(new ContactsBox()); + Ui::show(Box()); }, &st::mainMenuContacts, &st::mainMenuContactsOver); _menu->addAction(lang(lng_menu_settings), [] { App::wnd()->showSettings(); @@ -69,7 +69,7 @@ MainMenu::MainMenu(QWidget *parent) : TWidget(parent) _telegram->setLink(1, MakeShared(qsl("https://desktop.telegram.org"))); _version->setRichText(textcmdLink(1, lng_settings_current_version(lt_version, currentVersionText())) + QChar(' ') + QChar(8211) + QChar(' ') + textcmdLink(2, lang(lng_menu_about))); _version->setLink(1, MakeShared(qsl("https://desktop.telegram.org/?_hash=changelog"))); - _version->setLink(2, MakeShared([] { Ui::showLayer(new AboutBox()); })); + _version->setLink(2, MakeShared([] { Ui::show(Box()); })); subscribe(FileDownload::ImageLoaded(), [this] { update(); }); subscribe(Global::RefConnectionTypeChanged(), [this] { updateConnectionState(); }); diff --git a/Telegram/SourceFiles/window/window_main_menu.h b/Telegram/SourceFiles/window/window_main_menu.h index 5d23119d5..b38ea9141 100644 --- a/Telegram/SourceFiles/window/window_main_menu.h +++ b/Telegram/SourceFiles/window/window_main_menu.h @@ -20,8 +20,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org */ #pragma once -#include "ui/effects/rect_shadow.h" - namespace Ui { class FlatLabel; class Menu; @@ -51,10 +49,10 @@ private: void updateControlsGeometry(); void updateConnectionState(); - ChildWidget _userpicButton = { nullptr }; - ChildWidget _menu; - ChildWidget _telegram; - ChildWidget _version; + object_ptr _userpicButton = { nullptr }; + object_ptr _menu; + object_ptr _telegram; + object_ptr _version; bool _showFinished = false; QString _connectionText; diff --git a/Telegram/SourceFiles/window/window_theme_warning.cpp b/Telegram/SourceFiles/window/window_theme_warning.cpp index 7e84788b6..f52855174 100644 --- a/Telegram/SourceFiles/window/window_theme_warning.cpp +++ b/Telegram/SourceFiles/window/window_theme_warning.cpp @@ -23,6 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "styles/style_boxes.h" #include "ui/widgets/buttons.h" +#include "ui/widgets/shadow.h" #include "window/window_theme.h" #include "lang.h" @@ -36,7 +37,6 @@ constexpr int kWaitBeforeRevertMs = 15999; WarningWidget::WarningWidget(QWidget *parent) : TWidget(parent) , _secondsLeft(kWaitBeforeRevertMs / 1000) -, _shadow(st::themeWarningShadow) , _keepChanges(this, lang(lng_theme_keep_changes), st::defaultBoxButton) , _revert(this, lang(lng_theme_revert), st::cancelBoxButton) { _keepChanges->setClickedCallback([] { Window::Theme::KeepApplied(); }); @@ -71,8 +71,8 @@ void WarningWidget::paintEvent(QPaintEvent *e) { return; } - _shadow.paint(p, _inner, st::themeWarningShadowShift); - p.fillRect(_inner, st::boxBg); + Ui::Shadow::paint(p, _inner, width(), st::boxRoundShadow); + App::roundRect(p, _inner, st::boxBg, BoxCorners); p.setFont(st::boxTitleFont); p.setPen(st::boxTitleFg); @@ -85,7 +85,7 @@ void WarningWidget::paintEvent(QPaintEvent *e) { void WarningWidget::resizeEvent(QResizeEvent *e) { _inner = QRect((width() - st::themeWarningWidth) / 2, (height() - st::themeWarningHeight) / 2, st::themeWarningWidth, st::themeWarningHeight); - _outer = _inner.marginsAdded(_shadow.getDimensions(st::themeWarningShadowShift)); + _outer = _inner.marginsAdded(st::boxRoundShadow.extend); auto left = _inner.x() + _inner.width() - st::boxButtonPadding.right() - _keepChanges->width(); _keepChanges->moveToLeft(left, _inner.y() + _inner.height() - st::boxButtonPadding.bottom() - _keepChanges->height()); _revert->moveToLeft(left - st::boxButtonPadding.left() - _revert->width(), _keepChanges->y()); diff --git a/Telegram/SourceFiles/window/window_theme_warning.h b/Telegram/SourceFiles/window/window_theme_warning.h index a5ee31a6c..2b793ed88 100644 --- a/Telegram/SourceFiles/window/window_theme_warning.h +++ b/Telegram/SourceFiles/window/window_theme_warning.h @@ -20,8 +20,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org */ #pragma once -#include "ui/effects/rect_shadow.h" - namespace Ui { class RoundButton; } // namespace Ui @@ -61,9 +59,8 @@ private: int _secondsLeft = 0; QString _text; - Ui::RectShadow _shadow; - ChildWidget _keepChanges; - ChildWidget _revert; + object_ptr _keepChanges; + object_ptr _revert; base::lambda _hiddenCallback; diff --git a/Telegram/build/version b/Telegram/build/version index 0b546acd0..91a62546d 100644 --- a/Telegram/build/version +++ b/Telegram/build/version @@ -3,4 +3,4 @@ AppVersionStrMajor 0.10 AppVersionStrSmall 0.10.20 AppVersionStr 0.10.20 AlphaChannel 0 -BetaVersion 10019014 +BetaVersion 10020001 diff --git a/Telegram/gyp/Telegram.gyp b/Telegram/gyp/Telegram.gyp index b16993665..5c746da56 100644 --- a/Telegram/gyp/Telegram.gyp +++ b/Telegram/gyp/Telegram.gyp @@ -470,8 +470,6 @@ '<(src_loc)/ui/effects/panel_animation.h', '<(src_loc)/ui/effects/radial_animation.cpp', '<(src_loc)/ui/effects/radial_animation.h', - '<(src_loc)/ui/effects/rect_shadow.cpp', - '<(src_loc)/ui/effects/rect_shadow.h', '<(src_loc)/ui/effects/ripple_animation.cpp', '<(src_loc)/ui/effects/ripple_animation.h', '<(src_loc)/ui/effects/round_checkbox.cpp',