Files
chatterino2/src/messages/layouts/MessageLayoutElement.cpp
Rasmus Karlsson 0f44a2e0f4 re-enable link resolver, but fix the underlying issue in the "link changed" signal.
The feature itself still doesn't work for me, but this code does the same thing.
only thing that's really different is it also disconnects the signal properly once
the TextLayoutElement is deleted
2018-10-23 10:32:13 +02:00

366 lines
8.1 KiB
C++

#include "messages/layouts/MessageLayoutElement.hpp"
#include "Application.hpp"
#include "messages/Emote.hpp"
#include "messages/Image.hpp"
#include "messages/MessageElement.hpp"
#include "singletons/Theme.hpp"
#include "util/DebugCount.hpp"
#include <QDebug>
#include <QPainter>
namespace chatterino {
const QRect &MessageLayoutElement::getRect() const
{
return this->rect_;
}
MessageLayoutElement::MessageLayoutElement(MessageElement &creator,
const QSize &size)
: creator_(creator)
{
this->rect_.setSize(size);
DebugCount::increase("message layout elements");
}
MessageLayoutElement::~MessageLayoutElement()
{
DebugCount::decrease("message layout elements");
}
MessageElement &MessageLayoutElement::getCreator() const
{
return this->creator_;
}
void MessageLayoutElement::setPosition(QPoint point)
{
this->rect_.moveTopLeft(point);
}
bool MessageLayoutElement::hasTrailingSpace() const
{
return this->trailingSpace;
}
MessageLayoutElement *MessageLayoutElement::setTrailingSpace(bool value)
{
this->trailingSpace = value;
return this;
}
MessageLayoutElement *MessageLayoutElement::setLink(const Link &_link)
{
this->link_ = _link;
return this;
}
MessageLayoutElement *MessageLayoutElement::setText(const QString &_text)
{
this->text_ = _text;
return this;
}
const Link &MessageLayoutElement::getLink() const
{
return this->link_;
}
const QString &MessageLayoutElement::getText() const
{
return this->text_;
}
FlagsEnum<MessageElementFlag> MessageLayoutElement::getFlags() const
{
return this->creator_.getFlags();
}
//
// IMAGE
//
ImageLayoutElement::ImageLayoutElement(MessageElement &creator, ImagePtr image,
const QSize &size)
: MessageLayoutElement(creator, size)
, image_(image)
{
this->trailingSpace = creator.hasTrailingSpace();
}
void ImageLayoutElement::addCopyTextToString(QString &str, int from,
int to) const
{
const auto *emoteElement =
dynamic_cast<EmoteElement *>(&this->getCreator());
if (emoteElement)
{
str += emoteElement->getEmote()->getCopyString();
if (this->hasTrailingSpace())
{
str += " ";
}
}
}
int ImageLayoutElement::getSelectionIndexCount() const
{
return this->trailingSpace ? 2 : 1;
}
void ImageLayoutElement::paint(QPainter &painter)
{
if (this->image_ == nullptr)
{
return;
}
auto pixmap = this->image_->pixmap();
if (pixmap && !this->image_->animated())
{
// fourtf: make it use qreal values
painter.drawPixmap(QRectF(this->getRect()), *pixmap, QRectF());
}
}
void ImageLayoutElement::paintAnimated(QPainter &painter, int yOffset)
{
if (this->image_ == nullptr)
{
return;
}
if (this->image_->animated())
{
if (auto pixmap = this->image_->pixmap())
{
auto rect = this->getRect();
rect.moveTop(rect.y() + yOffset);
painter.drawPixmap(QRectF(rect), *pixmap, QRectF());
}
}
}
int ImageLayoutElement::getMouseOverIndex(const QPoint &abs) const
{
return 0;
}
int ImageLayoutElement::getXFromIndex(int index)
{
if (index <= 0)
{
return this->getRect().left();
}
else if (index == 1)
{
// fourtf: remove space width
return this->getRect().right();
}
else
{
return this->getRect().right();
}
}
//
// TEXT
//
TextLayoutElement::TextLayoutElement(MessageElement &_creator, QString &_text,
const QSize &_size, QColor _color,
FontStyle _style, float _scale)
: MessageLayoutElement(_creator, _size)
, color(_color)
, style(_style)
, scale(_scale)
{
this->setText(_text);
}
void TextLayoutElement::listenToLinkChanges()
{
this->managedConnections_.emplace_back(
static_cast<TextElement &>(this->getCreator())
.linkChanged.connect([this]() {
// log("Old link: {}", this->getCreator().getLink().value);
// log("This link: {}", this->getLink().value);
this->setLink(this->getCreator().getLink()); //
}));
}
void TextLayoutElement::addCopyTextToString(QString &str, int from,
int to) const
{
str += this->getText().mid(from, to - from);
if (this->hasTrailingSpace())
{
str += " ";
}
}
int TextLayoutElement::getSelectionIndexCount() const
{
return this->getText().length() + (this->trailingSpace ? 1 : 0);
}
void TextLayoutElement::paint(QPainter &painter)
{
auto app = getApp();
painter.setPen(this->color);
painter.setFont(app->fonts->getFont(this->style, this->scale));
painter.drawText(
QRectF(this->getRect().x(), this->getRect().y(), 10000, 10000),
this->getText(), QTextOption(Qt::AlignLeft | Qt::AlignTop));
}
void TextLayoutElement::paintAnimated(QPainter &, int)
{
}
int TextLayoutElement::getMouseOverIndex(const QPoint &abs) const
{
if (abs.x() < this->getRect().left())
{
return 0;
}
auto app = getApp();
QFontMetrics metrics = app->fonts->getFontMetrics(this->style, this->scale);
int x = this->getRect().left();
for (int i = 0; i < this->getText().size(); i++)
{
auto &text = this->getText();
auto width = metrics.width(this->getText()[i]);
if (x + width > abs.x())
{
if (text.size() > i + 1 &&
QChar::isLowSurrogate(text[i].unicode())) //
{
i++;
}
return i;
}
x += width;
}
return this->getSelectionIndexCount();
}
int TextLayoutElement::getXFromIndex(int index)
{
auto app = getApp();
QFontMetrics metrics = app->fonts->getFontMetrics(this->style, this->scale);
if (index <= 0)
{
return this->getRect().left();
}
else if (index < this->getText().size())
{
int x = 0;
for (int i = 0; i < index; i++)
{
x += metrics.width(this->getText()[i]);
}
return x + this->getRect().left();
}
else
{
return this->getRect().right();
}
}
// TEXT ICON
TextIconLayoutElement::TextIconLayoutElement(MessageElement &creator,
const QString &_line1,
const QString &_line2,
float _scale, const QSize &size)
: MessageLayoutElement(creator, size)
, scale(_scale)
, line1(_line1)
, line2(_line2)
{
}
void TextIconLayoutElement::addCopyTextToString(QString &str, int from,
int to) const
{
}
int TextIconLayoutElement::getSelectionIndexCount() const
{
return this->trailingSpace ? 2 : 1;
}
void TextIconLayoutElement::paint(QPainter &painter)
{
auto app = getApp();
QFont font = app->fonts->getFont(FontStyle::Tiny, this->scale);
painter.setPen(app->themes->messages.textColors.system);
painter.setFont(font);
QTextOption option;
option.setAlignment(Qt::AlignHCenter);
if (this->line2.isEmpty())
{
QRect _rect(this->getRect());
painter.drawText(_rect, this->line1, option);
}
else
{
painter.drawText(
QPoint(this->getRect().x(),
this->getRect().y() + this->getRect().height() / 2),
this->line1);
painter.drawText(QPoint(this->getRect().x(),
this->getRect().y() + this->getRect().height()),
this->line2);
}
}
void TextIconLayoutElement::paintAnimated(QPainter &painter, int yOffset)
{
}
int TextIconLayoutElement::getMouseOverIndex(const QPoint &abs) const
{
return 0;
}
int TextIconLayoutElement::getXFromIndex(int index)
{
if (index <= 0)
{
return this->getRect().left();
}
else if (index == 1)
{
// fourtf: remove space width
return this->getRect().right();
}
else
{
return this->getRect().right();
}
}
} // namespace chatterino