mirror-chatterino2/src/messages/messageelement.cpp

264 lines
7.3 KiB
C++
Raw Normal View History

#include "messages/messageelement.hpp"
#include "messages/layouts/messagelayoutcontainer.hpp"
#include "messages/layouts/messagelayoutelement.hpp"
#include "singletons/settingsmanager.hpp"
#include "util/benchmark.hpp"
#include "util/emotemap.hpp"
namespace chatterino {
namespace messages {
MessageElement::MessageElement(Flags _flags)
: flags(_flags)
{
}
MessageElement *MessageElement::setLink(const Link &_link)
{
this->link = _link;
return this;
}
MessageElement *MessageElement::setTooltip(const QString &_tooltip)
{
this->tooltip = _tooltip;
return this;
}
MessageElement *MessageElement::setTrailingSpace(bool value)
{
this->trailingSpace = value;
return this;
}
const QString &MessageElement::getTooltip() const
{
return this->tooltip;
}
const Link &MessageElement::getLink() const
{
return this->link;
}
bool MessageElement::hasTrailingSpace() const
{
return this->trailingSpace;
}
MessageElement::Flags MessageElement::getFlags() const
{
return this->flags;
}
// IMAGE
ImageElement::ImageElement(Image &_image, MessageElement::Flags flags)
: MessageElement(flags)
, image(_image)
{
this->setTooltip(_image.getTooltip());
}
void ImageElement::addToContainer(MessageLayoutContainer &container, MessageElement::Flags _flags)
{
QSize size(this->image.getWidth() * this->image.getScale() * container.scale,
this->image.getHeight() * this->image.getScale() * container.scale);
container.addElement(new ImageLayoutElement(*this, this->image, size));
}
void ImageElement::update(UpdateFlags _flags)
{
}
// EMOTE
EmoteElement::EmoteElement(const util::EmoteData &_data, MessageElement::Flags flags)
: MessageElement(flags)
, data(_data)
{
if (_data.isValid()) {
this->setTooltip(data.image1x->getTooltip());
}
}
void EmoteElement::addToContainer(MessageLayoutContainer &container, MessageElement::Flags _flags)
{
if (!this->data.isValid()) {
qDebug() << "EmoteElement::data is invalid xD";
return;
}
int quality = singletons::SettingManager::getInstance().preferredEmoteQuality;
Image *_image;
if (quality == 3 && this->data.image3x != nullptr) {
_image = this->data.image3x;
} else if (quality >= 2 && this->data.image2x != nullptr) {
_image = this->data.image2x;
} else {
_image = this->data.image1x;
}
QSize size((int)(container.scale * _image->getScaledWidth()),
(int)(container.scale * _image->getScaledHeight()));
container.addElement(new ImageLayoutElement(*this, *_image, size));
}
void EmoteElement::update(UpdateFlags _flags)
{
}
// TEXT
TextElement::TextElement(const QString &text, MessageElement::Flags flags,
const MessageColor &_color, FontStyle _style)
: MessageElement(flags)
, color(_color)
, style(_style)
{
for (QString word : text.split(' ')) {
this->words.push_back({word, -1});
// fourtf: add logic to store mutliple spaces after message
}
}
void TextElement::addToContainer(MessageLayoutContainer &container, MessageElement::Flags _flags)
{
QFontMetrics &metrics =
singletons::FontManager::getInstance().getFontMetrics(this->style, container.scale);
singletons::ThemeManager &themeManager = singletons::ThemeManager::ThemeManager::getInstance();
for (Word &word : this->words) {
2018-01-16 00:56:17 +01:00
auto getTextLayoutElement = [&](QString text, int width, bool trailingSpace) {
auto e = new TextLayoutElement(*this, text, QSize(width, metrics.height()),
this->color.getColor(themeManager), this->style,
container.scale);
e->setTrailingSpace(trailingSpace);
return e;
};
if (word.width == -1) {
word.width = metrics.width(word.text);
}
// see if the text fits in the current line
if (container.fitsInLine(word.width)) {
2018-01-16 00:56:17 +01:00
container.addElementNoLineBreak(
getTextLayoutElement(word.text, word.width, this->hasTrailingSpace()));
continue;
}
// see if the text fits in the next line
if (!container.atStartOfLine()) {
container.breakLine();
if (container.fitsInLine(word.width)) {
2018-01-16 00:56:17 +01:00
container.addElementNoLineBreak(
getTextLayoutElement(word.text, word.width, this->hasTrailingSpace()));
continue;
}
}
// we done goofed, we need to wrap the text
QString text = word.text;
int textLength = text.length();
int wordStart = 0;
int width = metrics.width(text[0]);
int lastWidth = 0;
for (int i = 1; i < textLength; i++) {
2018-01-16 00:56:17 +01:00
int charWidth = metrics.width(text[i]);
2018-01-16 00:56:17 +01:00
if (!container.fitsInLine(width + charWidth)) {
container.addElementNoLineBreak(getTextLayoutElement(
text.mid(wordStart, i - wordStart), width - lastWidth, false));
container.breakLine();
wordStart = i;
lastWidth = width;
2018-01-16 00:56:17 +01:00
width = 0;
if (textLength > i + 2) {
width += metrics.width(text[i]);
width += metrics.width(text[i + 1]);
i += 1;
}
continue;
}
2018-01-16 00:56:17 +01:00
width += charWidth;
}
2018-01-16 00:56:17 +01:00
container.addElement(getTextLayoutElement(text.mid(wordStart), word.width - lastWidth,
this->hasTrailingSpace()));
container.breakLine();
}
}
void TextElement::update(UpdateFlags _flags)
{
if (_flags & UpdateFlags::Update_Text) {
for (Word &word : this->words) {
word.width = -1;
}
}
}
// TIMESTAMP
TimestampElement::TimestampElement()
: TimestampElement(QTime::currentTime())
{
}
TimestampElement::TimestampElement(QTime _time)
: MessageElement(MessageElement::Timestamp)
, time(_time)
, element(formatTime(_time))
{
assert(this->element != nullptr);
}
TimestampElement::~TimestampElement()
{
delete this->element;
}
void TimestampElement::addToContainer(MessageLayoutContainer &container,
MessageElement::Flags _flags)
{
2018-01-12 23:09:05 +01:00
if (singletons::SettingManager::getInstance().timestampFormat != this->format) {
2018-01-16 22:37:06 +01:00
this->format = singletons::SettingManager::getInstance().timestampFormat.getValue();
2018-01-12 23:09:05 +01:00
delete this->element;
this->element = TimestampElement::formatTime(this->time);
}
this->element->addToContainer(container, _flags);
}
void TimestampElement::update(UpdateFlags _flags)
{
2018-01-12 23:09:05 +01:00
this->element->update(_flags);
}
TextElement *TimestampElement::formatTime(const QTime &time)
{
2018-01-12 23:09:05 +01:00
QString format = time.toString(singletons::SettingManager::getInstance().timestampFormat);
2018-01-12 23:09:05 +01:00
return new TextElement(format, Flags::Timestamp, MessageColor::System, FontStyle::Medium);
}
// TWITCH MODERATION
TwitchModerationElement::TwitchModerationElement()
: MessageElement(MessageElement::ModeratorTools)
{
}
void TwitchModerationElement::addToContainer(MessageLayoutContainer &container,
MessageElement::Flags _flags)
{
}
void TwitchModerationElement::update(UpdateFlags _flags)
{
}
} // namespace messages
} // namespace chatterino