tdesktop/Telegram/SourceFiles/info/downloads/info_downloads_inner_widget...

206 lines
5.0 KiB
C++

/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "info/downloads/info_downloads_inner_widget.h"
#include "info/downloads/info_downloads_widget.h"
#include "info/media/info_media_list_widget.h"
#include "info/info_controller.h"
#include "ui/widgets/labels.h"
#include "ui/search_field_controller.h"
#include "lang/lang_keys.h"
#include "styles/style_info.h"
namespace Info::Downloads {
class EmptyWidget : public Ui::RpWidget {
public:
EmptyWidget(QWidget *parent);
void setFullHeight(rpl::producer<int> fullHeightValue);
void setSearchQuery(const QString &query);
protected:
int resizeGetHeight(int newWidth) override;
void paintEvent(QPaintEvent *e) override;
private:
object_ptr<Ui::FlatLabel> _text;
int _height = 0;
};
EmptyWidget::EmptyWidget(QWidget *parent)
: RpWidget(parent)
, _text(this, st::infoEmptyLabel) {
}
void EmptyWidget::setFullHeight(rpl::producer<int> fullHeightValue) {
std::move(
fullHeightValue
) | rpl::start_with_next([this](int fullHeight) {
// Make icon center be on 1/3 height.
auto iconCenter = fullHeight / 3;
auto iconHeight = st::infoEmptyFile.height();
auto iconTop = iconCenter - iconHeight / 2;
_height = iconTop + st::infoEmptyIconTop;
resizeToWidth(width());
}, lifetime());
}
void EmptyWidget::setSearchQuery(const QString &query) {
_text->setText(query.isEmpty()
? tr::lng_media_file_empty(tr::now)
: tr::lng_media_file_empty_search(tr::now));
resizeToWidth(width());
}
int EmptyWidget::resizeGetHeight(int newWidth) {
auto labelTop = _height - st::infoEmptyLabelTop;
auto labelWidth = newWidth - 2 * st::infoEmptyLabelSkip;
_text->resizeToNaturalWidth(labelWidth);
auto labelLeft = (newWidth - _text->width()) / 2;
_text->moveToLeft(labelLeft, labelTop, newWidth);
update();
return _height;
}
void EmptyWidget::paintEvent(QPaintEvent *e) {
auto p = QPainter(this);
const auto iconLeft = (width() - st::infoEmptyFile.width()) / 2;
const auto iconTop = height() - st::infoEmptyIconTop;
st::infoEmptyFile.paint(p, iconLeft, iconTop, width());
}
InnerWidget::InnerWidget(
QWidget *parent,
not_null<Controller*> controller)
: RpWidget(parent)
, _controller(controller)
, _empty(this) {
_empty->heightValue(
) | rpl::start_with_next(
[this] { refreshHeight(); },
_empty->lifetime());
_list = setupList();
}
void InnerWidget::visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) {
setChildVisibleTopBottom(_list, visibleTop, visibleBottom);
}
bool InnerWidget::showInternal(not_null<Memento*> memento) {
if (memento->section().type() == Section::Type::Downloads) {
restoreState(memento);
return true;
}
return false;
}
object_ptr<Media::ListWidget> InnerWidget::setupList() {
auto result = object_ptr<Media::ListWidget>(
this,
_controller);
result->heightValue(
) | rpl::start_with_next(
[this] { refreshHeight(); },
result->lifetime());
using namespace rpl::mappers;
result->scrollToRequests(
) | rpl::map([widget = result.data()](int to) {
return Ui::ScrollToRequest {
widget->y() + to,
-1
};
}) | rpl::start_to_stream(
_scrollToRequests,
result->lifetime());
_selectedLists.fire(result->selectedListValue());
_listTops.fire(result->topValue());
_controller->searchQueryValue(
) | rpl::start_with_next([this](const QString &query) {
_empty->setSearchQuery(query);
}, result->lifetime());
return result;
}
void InnerWidget::saveState(not_null<Memento*> memento) {
_list->saveState(&memento->media());
}
void InnerWidget::restoreState(not_null<Memento*> memento) {
_list->restoreState(&memento->media());
}
rpl::producer<SelectedItems> InnerWidget::selectedListValue() const {
return _selectedLists.events_starting_with(
_list->selectedListValue()
) | rpl::flatten_latest();
}
void InnerWidget::selectionAction(SelectionAction action) {
_list->selectionAction(action);
}
InnerWidget::~InnerWidget() = default;
int InnerWidget::resizeGetHeight(int newWidth) {
_inResize = true;
auto guard = gsl::finally([this] { _inResize = false; });
_list->resizeToWidth(newWidth);
_empty->resizeToWidth(newWidth);
return recountHeight();
}
void InnerWidget::refreshHeight() {
if (_inResize) {
return;
}
resize(width(), recountHeight());
}
int InnerWidget::recountHeight() {
auto top = 0;
auto listHeight = 0;
if (_list) {
_list->moveToLeft(0, top);
listHeight = _list->heightNoMargins();
top += listHeight;
}
if (listHeight > 0) {
_empty->hide();
} else {
_empty->show();
_empty->moveToLeft(0, top);
top += _empty->heightNoMargins();
}
return top;
}
void InnerWidget::setScrollHeightValue(rpl::producer<int> value) {
using namespace rpl::mappers;
_empty->setFullHeight(rpl::combine(
std::move(value),
_listTops.events_starting_with(
_list->topValue()
) | rpl::flatten_latest(),
_1 - _2));
}
rpl::producer<Ui::ScrollToRequest> InnerWidget::scrollToRequests() const {
return _scrollToRequests.events();
}
} // namespace Info::Downloads