mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Support dynamic search tabs with emoji.
This commit is contained in:
parent
7b7438cd7b
commit
279db771cf
9 changed files with 158 additions and 60 deletions
|
@ -48,7 +48,8 @@ class DefaultIconEmoji final : public Ui::Text::CustomEmoji {
|
||||||
public:
|
public:
|
||||||
DefaultIconEmoji(
|
DefaultIconEmoji(
|
||||||
rpl::producer<DefaultIcon> value,
|
rpl::producer<DefaultIcon> value,
|
||||||
Fn<void()> repaint);
|
Fn<void()> repaint,
|
||||||
|
Data::CustomEmojiSizeTag tag);
|
||||||
|
|
||||||
int width() override;
|
int width() override;
|
||||||
QString entityData() override;
|
QString entityData() override;
|
||||||
|
@ -61,14 +62,17 @@ public:
|
||||||
private:
|
private:
|
||||||
DefaultIcon _icon = {};
|
DefaultIcon _icon = {};
|
||||||
QImage _image;
|
QImage _image;
|
||||||
|
Data::CustomEmojiSizeTag _tag = {};
|
||||||
|
|
||||||
rpl::lifetime _lifetime;
|
rpl::lifetime _lifetime;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
DefaultIconEmoji::DefaultIconEmoji(
|
DefaultIconEmoji::DefaultIconEmoji(
|
||||||
rpl::producer<DefaultIcon> value,
|
rpl::producer<DefaultIcon> value,
|
||||||
Fn<void()> repaint) {
|
Fn<void()> repaint,
|
||||||
|
Data::CustomEmojiSizeTag tag)
|
||||||
|
: _tag(tag) {
|
||||||
std::move(value) | rpl::start_with_next([=](DefaultIcon value) {
|
std::move(value) | rpl::start_with_next([=](DefaultIcon value) {
|
||||||
_icon = value;
|
_icon = value;
|
||||||
_image = QImage();
|
_image = QImage();
|
||||||
|
@ -85,19 +89,22 @@ QString DefaultIconEmoji::entityData() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DefaultIconEmoji::paint(QPainter &p, const Context &context) {
|
void DefaultIconEmoji::paint(QPainter &p, const Context &context) {
|
||||||
|
const auto &st = (_tag == Data::CustomEmojiSizeTag::Normal)
|
||||||
|
? st::normalForumTopicIcon
|
||||||
|
: st::defaultForumTopicIcon;
|
||||||
if (_image.isNull()) {
|
if (_image.isNull()) {
|
||||||
_image = Data::IsForumGeneralIconTitle(_icon.title)
|
_image = Data::IsForumGeneralIconTitle(_icon.title)
|
||||||
? Data::ForumTopicGeneralIconFrame(
|
? Data::ForumTopicGeneralIconFrame(
|
||||||
st::defaultForumTopicIcon.size,
|
st.size,
|
||||||
Data::ParseForumGeneralIconColor(_icon.colorId))
|
Data::ParseForumGeneralIconColor(_icon.colorId))
|
||||||
: Data::ForumTopicIconFrame(
|
: Data::ForumTopicIconFrame(_icon.colorId, _icon.title, st);
|
||||||
_icon.colorId,
|
|
||||||
_icon.title,
|
|
||||||
st::defaultForumTopicIcon);
|
|
||||||
}
|
}
|
||||||
const auto esize = Ui::Emoji::GetSizeLarge() / style::DevicePixelRatio();
|
const auto full = (_tag == Data::CustomEmojiSizeTag::Normal)
|
||||||
|
? Ui::Emoji::GetSizeNormal()
|
||||||
|
: Ui::Emoji::GetSizeLarge();
|
||||||
|
const auto esize = full / style::DevicePixelRatio();
|
||||||
const auto customSize = Ui::Text::AdjustCustomEmojiSize(esize);
|
const auto customSize = Ui::Text::AdjustCustomEmojiSize(esize);
|
||||||
const auto skip = (customSize - st::defaultForumTopicIcon.size) / 2;
|
const auto skip = (customSize - st.size) / 2;
|
||||||
p.drawImage(context.position + QPoint(skip, skip), _image);
|
p.drawImage(context.position + QPoint(skip, skip), _image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,7 +269,8 @@ struct IconSelector {
|
||||||
if (id == kDefaultIconId) {
|
if (id == kDefaultIconId) {
|
||||||
return std::make_unique<DefaultIconEmoji>(
|
return std::make_unique<DefaultIconEmoji>(
|
||||||
rpl::duplicate(defaultIcon),
|
rpl::duplicate(defaultIcon),
|
||||||
std::move(repaint));
|
std::move(repaint),
|
||||||
|
tag);
|
||||||
}
|
}
|
||||||
return manager->create(id, std::move(repaint), tag);
|
return manager->create(id, std::move(repaint), tag);
|
||||||
};
|
};
|
||||||
|
@ -576,8 +584,10 @@ void EditForumTopicBox(
|
||||||
|
|
||||||
std::unique_ptr<Ui::Text::CustomEmoji> MakeTopicIconEmoji(
|
std::unique_ptr<Ui::Text::CustomEmoji> MakeTopicIconEmoji(
|
||||||
Data::TopicIconDescriptor descriptor,
|
Data::TopicIconDescriptor descriptor,
|
||||||
Fn<void()> repaint) {
|
Fn<void()> repaint,
|
||||||
|
Data::CustomEmojiSizeTag tag) {
|
||||||
return std::make_unique<DefaultIconEmoji>(
|
return std::make_unique<DefaultIconEmoji>(
|
||||||
rpl::single(descriptor),
|
rpl::single(descriptor),
|
||||||
std::move(repaint));
|
std::move(repaint),
|
||||||
|
tag);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ class History;
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
struct TopicIconDescriptor;
|
struct TopicIconDescriptor;
|
||||||
|
enum class CustomEmojiSizeTag : uchar;
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
||||||
namespace Window {
|
namespace Window {
|
||||||
|
@ -32,4 +33,5 @@ void EditForumTopicBox(
|
||||||
|
|
||||||
[[nodiscard]] std::unique_ptr<Ui::Text::CustomEmoji> MakeTopicIconEmoji(
|
[[nodiscard]] std::unique_ptr<Ui::Text::CustomEmoji> MakeTopicIconEmoji(
|
||||||
Data::TopicIconDescriptor descriptor,
|
Data::TopicIconDescriptor descriptor,
|
||||||
Fn<void()> repaint);
|
Fn<void()> repaint,
|
||||||
|
Data::CustomEmojiSizeTag tag);
|
||||||
|
|
|
@ -542,7 +542,7 @@ std::unique_ptr<Ui::Text::CustomEmoji> CustomEmojiManager::create(
|
||||||
const auto size = EmojiSizeFromTag(tag) / ratio;
|
const auto size = EmojiSizeFromTag(tag) / ratio;
|
||||||
return userpic(data, std::move(update), size);
|
return userpic(data, std::move(update), size);
|
||||||
} else if (const auto parsed = Data::ParseTopicIconEmojiEntity(data)) {
|
} else if (const auto parsed = Data::ParseTopicIconEmojiEntity(data)) {
|
||||||
return MakeTopicIconEmoji(parsed, std::move(update));
|
return MakeTopicIconEmoji(parsed, std::move(update), tag);
|
||||||
}
|
}
|
||||||
const auto parsed = ParseCustomEmojiData(data);
|
const auto parsed = ParseCustomEmojiData(data);
|
||||||
return parsed
|
return parsed
|
||||||
|
|
|
@ -46,6 +46,11 @@ defaultForumTopicIcon: ForumTopicIcon {
|
||||||
font: font(bold 11px);
|
font: font(bold 11px);
|
||||||
textTop: 2px;
|
textTop: 2px;
|
||||||
}
|
}
|
||||||
|
normalForumTopicIcon: ForumTopicIcon {
|
||||||
|
size: 19px;
|
||||||
|
font: font(bold 10px);
|
||||||
|
textTop: 2px;
|
||||||
|
}
|
||||||
largeForumTopicIcon: ForumTopicIcon {
|
largeForumTopicIcon: ForumTopicIcon {
|
||||||
size: 26px;
|
size: 26px;
|
||||||
font: font(bold 13px);
|
font: font(bold 13px);
|
||||||
|
|
|
@ -47,6 +47,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
#include "base/event_filter.h"
|
#include "base/event_filter.h"
|
||||||
#include "core/application.h"
|
#include "core/application.h"
|
||||||
|
#include "core/ui_integration.h"
|
||||||
#include "core/update_checker.h"
|
#include "core/update_checker.h"
|
||||||
#include "core/shortcuts.h"
|
#include "core/shortcuts.h"
|
||||||
#include "boxes/peer_list_box.h"
|
#include "boxes/peer_list_box.h"
|
||||||
|
@ -1230,9 +1231,17 @@ void Widget::updateSearchTabs() {
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else if (!_searchTabs) {
|
} else if (!_searchTabs) {
|
||||||
|
const auto savedSession = &session();
|
||||||
|
const auto markedTextContext = [=](Fn<void()> repaint) {
|
||||||
|
return Core::MarkedTextContext{
|
||||||
|
.session = savedSession,
|
||||||
|
.customEmojiRepaint = std::move(repaint),
|
||||||
|
};
|
||||||
|
};
|
||||||
_searchTabs = std::make_unique<ChatSearchTabs>(
|
_searchTabs = std::make_unique<ChatSearchTabs>(
|
||||||
this,
|
this,
|
||||||
_searchState.tab);
|
_searchState.tab,
|
||||||
|
std::move(markedTextContext));
|
||||||
_searchTabs->setVisible(!_showAnimation);
|
_searchTabs->setVisible(!_showAnimation);
|
||||||
_searchTabs->tabChanges(
|
_searchTabs->tabChanges(
|
||||||
) | rpl::filter([=](ChatSearchTab tab) {
|
) | rpl::filter([=](ChatSearchTab tab) {
|
||||||
|
@ -1250,16 +1259,19 @@ void Widget::updateSearchTabs() {
|
||||||
: _openedForum
|
: _openedForum
|
||||||
? _openedForum->channel().get()
|
? _openedForum->channel().get()
|
||||||
: nullptr;
|
: nullptr;
|
||||||
const auto topicShortLabel = topic
|
const auto topicShortLabel = !topic
|
||||||
? Ui::Text::SingleCustomEmoji(Data::TopicIconEmojiEntity({
|
? TextWithEntities()
|
||||||
|
: topic->iconId()
|
||||||
|
? Ui::Text::SingleCustomEmoji(
|
||||||
|
Data::SerializeCustomEmojiId(topic->iconId()))
|
||||||
|
: Ui::Text::SingleCustomEmoji(Data::TopicIconEmojiEntity({
|
||||||
.title = (topic->isGeneral()
|
.title = (topic->isGeneral()
|
||||||
? Data::ForumGeneralIconTitle()
|
? Data::ForumGeneralIconTitle()
|
||||||
: topic->title()),
|
: topic->title()),
|
||||||
.colorId = (topic->isGeneral()
|
.colorId = (topic->isGeneral()
|
||||||
? Data::ForumGeneralIconColor(st::windowSubTextFg->c)
|
? Data::ForumGeneralIconColor(st::windowSubTextFg->c)
|
||||||
: topic->colorId()),
|
: topic->colorId()),
|
||||||
}))
|
}));
|
||||||
: TextWithEntities();
|
|
||||||
const auto peerShortLabel = peer
|
const auto peerShortLabel = peer
|
||||||
? Ui::Text::SingleCustomEmoji(
|
? Ui::Text::SingleCustomEmoji(
|
||||||
session().data().customEmojiManager().peerUserpicEmojiData(
|
session().data().customEmojiManager().peerUserpicEmojiData(
|
||||||
|
|
|
@ -97,31 +97,19 @@ bool IsHashtagSearchQuery(const QString &query) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatSearchTabs::ChatSearchTabs(QWidget *parent, ChatSearchTab active)
|
ChatSearchTabs::ChatSearchTabs(
|
||||||
|
QWidget *parent,
|
||||||
|
ChatSearchTab active,
|
||||||
|
Fn<std::any(Fn<void()>)> markedTextContext)
|
||||||
: RpWidget(parent)
|
: RpWidget(parent)
|
||||||
, _tabs(std::make_unique<Ui::SettingsSlider>(this, st::dialogsSearchTabs))
|
, _tabs(std::make_unique<Ui::SettingsSlider>(this, st::dialogsSearchTabs))
|
||||||
, _shadow(std::make_unique<Ui::PlainShadow>(this))
|
, _shadow(std::make_unique<Ui::PlainShadow>(this))
|
||||||
|
, _markedTextContext(std::move(markedTextContext))
|
||||||
, _active(active) {
|
, _active(active) {
|
||||||
for (const auto tab : {
|
|
||||||
ChatSearchTab::ThisTopic,
|
|
||||||
ChatSearchTab::ThisPeer,
|
|
||||||
ChatSearchTab::MyMessages,
|
|
||||||
ChatSearchTab::PublicPosts,
|
|
||||||
}) {
|
|
||||||
_list.push_back({ tab, TabLabel(tab) });
|
|
||||||
}
|
|
||||||
_tabs->move(st::dialogsSearchTabsPadding, 0);
|
_tabs->move(st::dialogsSearchTabsPadding, 0);
|
||||||
_tabs->sectionActivated(
|
_tabs->sectionActivated(
|
||||||
) | rpl::start_with_next([=](int index) {
|
) | rpl::start_with_next([=](int index) {
|
||||||
for (const auto &tab : _list) {
|
_active = _list[index].value;
|
||||||
if (tab.shortLabel.empty()) {
|
|
||||||
continue;
|
|
||||||
} else if (!index) {
|
|
||||||
_active = tab.value;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
--index;
|
|
||||||
}
|
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,40 +119,73 @@ void ChatSearchTabs::setTabShortLabels(
|
||||||
std::vector<ShortLabel> labels,
|
std::vector<ShortLabel> labels,
|
||||||
ChatSearchTab active,
|
ChatSearchTab active,
|
||||||
ChatSearchPeerTabType peerTabType) {
|
ChatSearchPeerTabType peerTabType) {
|
||||||
for (const auto &label : labels) {
|
const auto &st = st::dialogsSearchTabs;
|
||||||
const auto i = ranges::find(_list, label.tab, &Tab::value);
|
const auto &font = st.labelStyle.font;
|
||||||
Assert(i != end(_list));
|
_list.clear();
|
||||||
i->shortLabel = std::move(label.label);
|
_list.reserve(labels.size());
|
||||||
if (i->value == ChatSearchTab::ThisPeer) {
|
|
||||||
i->label = TabLabel(label.tab, peerTabType);
|
auto widthTotal = 0;
|
||||||
|
for (const auto tab : {
|
||||||
|
ChatSearchTab::ThisTopic,
|
||||||
|
ChatSearchTab::ThisPeer,
|
||||||
|
ChatSearchTab::MyMessages,
|
||||||
|
ChatSearchTab::PublicPosts,
|
||||||
|
}) {
|
||||||
|
const auto i = ranges::find(labels, tab, &ShortLabel::tab);
|
||||||
|
if (i != end(labels) && !i->label.empty()) {
|
||||||
|
const auto label = TabLabel(tab, peerTabType);
|
||||||
|
const auto widthFull = font->width(label) + st.strictSkip;
|
||||||
|
_list.push_back({
|
||||||
|
.value = tab,
|
||||||
|
.label = label,
|
||||||
|
.shortLabel = i->label,
|
||||||
|
.widthFull = widthFull,
|
||||||
|
});
|
||||||
|
widthTotal += widthFull;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
refreshTabs(active);
|
const auto widthSingleEmoji = st::emojiSize + st.strictSkip;
|
||||||
|
for (const auto tab : {
|
||||||
|
ChatSearchTab::PublicPosts,
|
||||||
|
ChatSearchTab::ThisTopic,
|
||||||
|
ChatSearchTab::ThisPeer,
|
||||||
|
ChatSearchTab::MyMessages,
|
||||||
|
}) {
|
||||||
|
const auto i = ranges::find(_list, tab, &Tab::value);
|
||||||
|
if (i != end(_list)) {
|
||||||
|
i->widthThresholdForShort = widthTotal;
|
||||||
|
widthTotal -= i->widthFull;
|
||||||
|
widthTotal += widthSingleEmoji;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
refillTabs(active, width());
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<ChatSearchTab> ChatSearchTabs::tabChanges() const {
|
rpl::producer<ChatSearchTab> ChatSearchTabs::tabChanges() const {
|
||||||
return _active.changes();
|
return _active.changes();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatSearchTabs::refreshTabs(ChatSearchTab active) {
|
void ChatSearchTabs::refillTabs(
|
||||||
auto index = 0;
|
ChatSearchTab active,
|
||||||
auto labels = std::vector<QString>();
|
int newWidth) {
|
||||||
|
auto labels = std::vector<TextWithEntities>();
|
||||||
|
const auto available = newWidth - 2 * st::dialogsSearchTabsPadding;
|
||||||
for (const auto &tab : _list) {
|
for (const auto &tab : _list) {
|
||||||
if (tab.value == active) {
|
auto label = (available < tab.widthThresholdForShort)
|
||||||
index = int(labels.size());
|
? tab.shortLabel
|
||||||
Assert(!tab.shortLabel.empty());
|
: TextWithEntities{ tab.label };
|
||||||
labels.push_back(tab.label);
|
labels.push_back(std::move(label));
|
||||||
} else if (!tab.shortLabel.empty()) {
|
|
||||||
labels.push_back(tab.label);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_tabs->setSections(labels);
|
_tabs->setSections(labels, _markedTextContext([=] { update(); }));
|
||||||
_tabs->setActiveSectionFast(index);
|
|
||||||
resizeToWidth(width());
|
const auto i = ranges::find(_list, active, &Tab::value);
|
||||||
|
Assert(i != end(_list));
|
||||||
|
_tabs->setActiveSectionFast(i - begin(_list));
|
||||||
|
_tabs->resizeToWidth(newWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ChatSearchTabs::resizeGetHeight(int newWidth) {
|
int ChatSearchTabs::resizeGetHeight(int newWidth) {
|
||||||
_tabs->resizeToWidth(newWidth);
|
refillTabs(_active.current(), newWidth);
|
||||||
_shadow->setGeometry(
|
_shadow->setGeometry(
|
||||||
0,
|
0,
|
||||||
_tabs->y() + _tabs->height() - st::lineWidth,
|
_tabs->y() + _tabs->height() - st::lineWidth,
|
||||||
|
|
|
@ -34,7 +34,10 @@ enum class ChatSearchPeerTabType : uchar {
|
||||||
|
|
||||||
class ChatSearchTabs final : public Ui::RpWidget {
|
class ChatSearchTabs final : public Ui::RpWidget {
|
||||||
public:
|
public:
|
||||||
ChatSearchTabs(QWidget *parent, ChatSearchTab active);
|
ChatSearchTabs(
|
||||||
|
QWidget *parent,
|
||||||
|
ChatSearchTab active,
|
||||||
|
Fn<std::any(Fn<void()>)> markedTextContext);
|
||||||
~ChatSearchTabs();
|
~ChatSearchTabs();
|
||||||
|
|
||||||
// A [custom] emoji to use when there is not enough space for text.
|
// A [custom] emoji to use when there is not enough space for text.
|
||||||
|
@ -55,14 +58,18 @@ private:
|
||||||
ChatSearchTab value = {};
|
ChatSearchTab value = {};
|
||||||
QString label;
|
QString label;
|
||||||
TextWithEntities shortLabel;
|
TextWithEntities shortLabel;
|
||||||
|
int widthFull = 0;
|
||||||
|
int widthThresholdForShort = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
void refreshTabs(ChatSearchTab active);
|
void refreshTabs(ChatSearchTab active);
|
||||||
|
void refillTabs(ChatSearchTab active, int newWidth);
|
||||||
int resizeGetHeight(int newWidth) override;
|
int resizeGetHeight(int newWidth) override;
|
||||||
void paintEvent(QPaintEvent *e) override;
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
|
||||||
const std::unique_ptr<Ui::SettingsSlider> _tabs;
|
const std::unique_ptr<Ui::SettingsSlider> _tabs;
|
||||||
const std::unique_ptr<Ui::PlainShadow> _shadow;
|
const std::unique_ptr<Ui::PlainShadow> _shadow;
|
||||||
|
const Fn<std::any(Fn<void()>)> _markedTextContext;
|
||||||
|
|
||||||
std::vector<Tab> _list;
|
std::vector<Tab> _list;
|
||||||
rpl::variable<ChatSearchTab> _active;
|
rpl::variable<ChatSearchTab> _active;
|
||||||
|
|
|
@ -66,6 +66,13 @@ void DiscreteSlider::addSection(const QString &label) {
|
||||||
resizeToWidth(width());
|
resizeToWidth(width());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DiscreteSlider::addSection(
|
||||||
|
const TextWithEntities &label,
|
||||||
|
const std::any &context) {
|
||||||
|
_sections.push_back(Section(label, getLabelStyle(), context));
|
||||||
|
resizeToWidth(width());
|
||||||
|
}
|
||||||
|
|
||||||
void DiscreteSlider::setSections(const std::vector<QString> &labels) {
|
void DiscreteSlider::setSections(const std::vector<QString> &labels) {
|
||||||
Assert(!labels.empty());
|
Assert(!labels.empty());
|
||||||
|
|
||||||
|
@ -73,6 +80,22 @@ void DiscreteSlider::setSections(const std::vector<QString> &labels) {
|
||||||
for (const auto &label : labels) {
|
for (const auto &label : labels) {
|
||||||
_sections.push_back(Section(label, getLabelStyle()));
|
_sections.push_back(Section(label, getLabelStyle()));
|
||||||
}
|
}
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DiscreteSlider::setSections(
|
||||||
|
const std::vector<TextWithEntities> &labels,
|
||||||
|
const std::any &context) {
|
||||||
|
Assert(!labels.empty());
|
||||||
|
|
||||||
|
_sections.clear();
|
||||||
|
for (const auto &label : labels) {
|
||||||
|
_sections.push_back(Section(label, getLabelStyle(), context));
|
||||||
|
}
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DiscreteSlider::refresh() {
|
||||||
stopAnimation();
|
stopAnimation();
|
||||||
if (_activeIndex >= _sections.size()) {
|
if (_activeIndex >= _sections.size()) {
|
||||||
_activeIndex = 0;
|
_activeIndex = 0;
|
||||||
|
@ -182,6 +205,13 @@ DiscreteSlider::Section::Section(
|
||||||
: label(st, label) {
|
: label(st, label) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DiscreteSlider::Section::Section(
|
||||||
|
const TextWithEntities &label,
|
||||||
|
const style::TextStyle &st,
|
||||||
|
const std::any &context) {
|
||||||
|
this->label.setMarkedText(st, label, kMarkupTextOptions, context);
|
||||||
|
}
|
||||||
|
|
||||||
SettingsSlider::SettingsSlider(
|
SettingsSlider::SettingsSlider(
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
const style::SettingsSlider &st)
|
const style::SettingsSlider &st)
|
||||||
|
|
|
@ -22,7 +22,13 @@ public:
|
||||||
~DiscreteSlider();
|
~DiscreteSlider();
|
||||||
|
|
||||||
void addSection(const QString &label);
|
void addSection(const QString &label);
|
||||||
|
void addSection(
|
||||||
|
const TextWithEntities &label,
|
||||||
|
const std::any &context = {});
|
||||||
void setSections(const std::vector<QString> &labels);
|
void setSections(const std::vector<QString> &labels);
|
||||||
|
void setSections(
|
||||||
|
const std::vector<TextWithEntities> &labels,
|
||||||
|
const std::any &context = {});
|
||||||
int activeSection() const {
|
int activeSection() const {
|
||||||
return _activeIndex;
|
return _activeIndex;
|
||||||
}
|
}
|
||||||
|
@ -44,6 +50,10 @@ protected:
|
||||||
|
|
||||||
struct Section {
|
struct Section {
|
||||||
Section(const QString &label, const style::TextStyle &st);
|
Section(const QString &label, const style::TextStyle &st);
|
||||||
|
Section(
|
||||||
|
const TextWithEntities &label,
|
||||||
|
const style::TextStyle &st,
|
||||||
|
const std::any &context);
|
||||||
|
|
||||||
int left = 0;
|
int left = 0;
|
||||||
int width = 0;
|
int width = 0;
|
||||||
|
@ -75,6 +85,7 @@ protected:
|
||||||
_a_left.stop();
|
_a_left.stop();
|
||||||
_a_width.stop();
|
_a_width.stop();
|
||||||
}
|
}
|
||||||
|
void refresh();
|
||||||
|
|
||||||
void setSelectOnPress(bool selectOnPress);
|
void setSelectOnPress(bool selectOnPress);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue