info_downloads_inner_widget.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #include "info/downloads/info_downloads_inner_widget.h"
  8. #include "info/downloads/info_downloads_widget.h"
  9. #include "info/media/info_media_list_widget.h"
  10. #include "info/info_controller.h"
  11. #include "ui/widgets/labels.h"
  12. #include "ui/search_field_controller.h"
  13. #include "lang/lang_keys.h"
  14. #include "styles/style_info.h"
  15. namespace Info::Downloads {
  16. class EmptyWidget : public Ui::RpWidget {
  17. public:
  18. EmptyWidget(QWidget *parent);
  19. void setFullHeight(rpl::producer<int> fullHeightValue);
  20. void setSearchQuery(const QString &query);
  21. protected:
  22. int resizeGetHeight(int newWidth) override;
  23. void paintEvent(QPaintEvent *e) override;
  24. private:
  25. object_ptr<Ui::FlatLabel> _text;
  26. int _height = 0;
  27. };
  28. EmptyWidget::EmptyWidget(QWidget *parent)
  29. : RpWidget(parent)
  30. , _text(this, st::infoEmptyLabel) {
  31. }
  32. void EmptyWidget::setFullHeight(rpl::producer<int> fullHeightValue) {
  33. std::move(
  34. fullHeightValue
  35. ) | rpl::start_with_next([this](int fullHeight) {
  36. // Make icon center be on 1/3 height.
  37. auto iconCenter = fullHeight / 3;
  38. auto iconHeight = st::infoEmptyFile.height();
  39. auto iconTop = iconCenter - iconHeight / 2;
  40. _height = iconTop + st::infoEmptyIconTop;
  41. resizeToWidth(width());
  42. }, lifetime());
  43. }
  44. void EmptyWidget::setSearchQuery(const QString &query) {
  45. _text->setText(query.isEmpty()
  46. ? tr::lng_media_file_empty(tr::now)
  47. : tr::lng_media_file_empty_search(tr::now));
  48. resizeToWidth(width());
  49. }
  50. int EmptyWidget::resizeGetHeight(int newWidth) {
  51. auto labelTop = _height - st::infoEmptyLabelTop;
  52. auto labelWidth = newWidth - 2 * st::infoEmptyLabelSkip;
  53. _text->resizeToNaturalWidth(labelWidth);
  54. auto labelLeft = (newWidth - _text->width()) / 2;
  55. _text->moveToLeft(labelLeft, labelTop, newWidth);
  56. update();
  57. return _height;
  58. }
  59. void EmptyWidget::paintEvent(QPaintEvent *e) {
  60. auto p = QPainter(this);
  61. const auto iconLeft = (width() - st::infoEmptyFile.width()) / 2;
  62. const auto iconTop = height() - st::infoEmptyIconTop;
  63. st::infoEmptyFile.paint(p, iconLeft, iconTop, width());
  64. }
  65. InnerWidget::InnerWidget(
  66. QWidget *parent,
  67. not_null<Controller*> controller)
  68. : RpWidget(parent)
  69. , _controller(controller)
  70. , _empty(this) {
  71. _empty->heightValue(
  72. ) | rpl::start_with_next(
  73. [this] { refreshHeight(); },
  74. _empty->lifetime());
  75. _list = setupList();
  76. }
  77. void InnerWidget::visibleTopBottomUpdated(
  78. int visibleTop,
  79. int visibleBottom) {
  80. setChildVisibleTopBottom(_list, visibleTop, visibleBottom);
  81. }
  82. bool InnerWidget::showInternal(not_null<Memento*> memento) {
  83. if (memento->section().type() == Section::Type::Downloads) {
  84. restoreState(memento);
  85. return true;
  86. }
  87. return false;
  88. }
  89. object_ptr<Media::ListWidget> InnerWidget::setupList() {
  90. auto result = object_ptr<Media::ListWidget>(this, _controller);
  91. result->heightValue(
  92. ) | rpl::start_with_next(
  93. [this] { refreshHeight(); },
  94. result->lifetime());
  95. using namespace rpl::mappers;
  96. result->scrollToRequests(
  97. ) | rpl::map([widget = result.data()](int to) {
  98. return Ui::ScrollToRequest {
  99. widget->y() + to,
  100. -1
  101. };
  102. }) | rpl::start_to_stream(
  103. _scrollToRequests,
  104. result->lifetime());
  105. _selectedLists.fire(result->selectedListValue());
  106. _listTops.fire(result->topValue());
  107. _controller->searchQueryValue(
  108. ) | rpl::start_with_next([this](const QString &query) {
  109. _empty->setSearchQuery(query);
  110. }, result->lifetime());
  111. return result;
  112. }
  113. void InnerWidget::saveState(not_null<Memento*> memento) {
  114. _list->saveState(&memento->media());
  115. }
  116. void InnerWidget::restoreState(not_null<Memento*> memento) {
  117. _list->restoreState(&memento->media());
  118. }
  119. rpl::producer<SelectedItems> InnerWidget::selectedListValue() const {
  120. return _selectedLists.events_starting_with(
  121. _list->selectedListValue()
  122. ) | rpl::flatten_latest();
  123. }
  124. void InnerWidget::selectionAction(SelectionAction action) {
  125. _list->selectionAction(action);
  126. }
  127. InnerWidget::~InnerWidget() = default;
  128. int InnerWidget::resizeGetHeight(int newWidth) {
  129. _inResize = true;
  130. auto guard = gsl::finally([this] { _inResize = false; });
  131. _list->resizeToWidth(newWidth);
  132. _empty->resizeToWidth(newWidth);
  133. return recountHeight();
  134. }
  135. void InnerWidget::refreshHeight() {
  136. if (_inResize) {
  137. return;
  138. }
  139. resize(width(), recountHeight());
  140. }
  141. int InnerWidget::recountHeight() {
  142. auto top = 0;
  143. auto listHeight = 0;
  144. if (_list) {
  145. _list->moveToLeft(0, top);
  146. listHeight = _list->heightNoMargins();
  147. top += listHeight;
  148. }
  149. if (listHeight > 0) {
  150. _empty->hide();
  151. } else {
  152. _empty->show();
  153. _empty->moveToLeft(0, top);
  154. top += _empty->heightNoMargins();
  155. }
  156. return top;
  157. }
  158. void InnerWidget::setScrollHeightValue(rpl::producer<int> value) {
  159. using namespace rpl::mappers;
  160. _empty->setFullHeight(rpl::combine(
  161. std::move(value),
  162. _listTops.events_starting_with(
  163. _list->topValue()
  164. ) | rpl::flatten_latest(),
  165. _1 - _2));
  166. }
  167. rpl::producer<Ui::ScrollToRequest> InnerWidget::scrollToRequests() const {
  168. return _scrollToRequests.events();
  169. }
  170. } // namespace Info::Downloads