mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-21 22:24:07 +01:00
added spicy new segfaults
This commit is contained in:
parent
a8c2b1151f
commit
580a411e9d
22 changed files with 472 additions and 111 deletions
BIN
.vs/chatterino/v14/.suo
Normal file
BIN
.vs/chatterino/v14/.suo
Normal file
Binary file not shown.
|
@ -11,6 +11,17 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isIgnoredEmote(const QString& emote);
|
static bool isIgnoredEmote(const QString& emote);
|
||||||
|
static qreal emoteScale() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static qreal badgeScale() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool scaleEmotesByLineHeight() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AppSettings();
|
AppSettings();
|
||||||
|
|
21
channel.cpp
21
channel.cpp
|
@ -1,8 +1,10 @@
|
||||||
#include "channel.h"
|
#include "channel.h"
|
||||||
#include "message.h"
|
#include "message.h"
|
||||||
|
|
||||||
Channel Channel::whispers = Channel(QString("/whispers"));
|
#include <memory>
|
||||||
Channel Channel::mentions = Channel(QString("/mentions"));
|
|
||||||
|
Channel Channel::whispers(QString("/whispers"));
|
||||||
|
Channel Channel::mentions(QString("/mentions"));
|
||||||
|
|
||||||
QMap<QString, Channel*> Channel::channels = QMap<QString, Channel*>();
|
QMap<QString, Channel*> Channel::channels = QMap<QString, Channel*>();
|
||||||
|
|
||||||
|
@ -30,7 +32,7 @@ Channel* Channel::addChannel(const QString &channel)
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
c->referenceCount++;
|
c->m_referenceCount++;
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
@ -60,25 +62,26 @@ void Channel::removeChannel(const QString &channel)
|
||||||
|
|
||||||
if (c == NULL) return;
|
if (c == NULL) return;
|
||||||
|
|
||||||
c->referenceCount--;
|
c->m_referenceCount--;
|
||||||
|
|
||||||
if (c->referenceCount == 0) {
|
if (c->m_referenceCount == 0) {
|
||||||
channels.remove(channel);
|
channels.remove(channel);
|
||||||
delete c;
|
delete c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<Message*> Channel::getMessagesClone()
|
QVector<std::shared_ptr<Message>> Channel::getMessagesClone()
|
||||||
{
|
{
|
||||||
m_messageMutex.lock();
|
m_messageMutex.lock();
|
||||||
QVector M = QVector<Message*>(*m_messages);
|
QVector<std::shared_ptr<Message>> M(m_messages);
|
||||||
|
M.detach();
|
||||||
m_messageMutex.unlock();
|
m_messageMutex.unlock();
|
||||||
return M;
|
return M;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Channel::addMessage(Message *message)
|
void Channel::addMessage(std::shared_ptr<Message> message)
|
||||||
{
|
{
|
||||||
m_messageMutex.lock();
|
m_messageMutex.lock();
|
||||||
// messages
|
m_messages.append(message);
|
||||||
m_messageMutex.unlock();
|
m_messageMutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
class Message;
|
class Message;
|
||||||
|
|
||||||
|
@ -48,9 +49,9 @@ public:
|
||||||
const QString& streamGame() const { return m_streamGame; }
|
const QString& streamGame() const { return m_streamGame; }
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
void addMessage(Message* message);
|
void addMessage(std::shared_ptr<Message> message);
|
||||||
|
|
||||||
QVector<Message*> getMessagesClone();
|
QVector<std::shared_ptr<Message>> getMessagesClone();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Channel(QString channel);
|
Channel(QString channel);
|
||||||
|
@ -61,7 +62,7 @@ private:
|
||||||
|
|
||||||
int m_referenceCount = 0;
|
int m_referenceCount = 0;
|
||||||
|
|
||||||
QVector<Message*> m_messages;
|
QVector<std::shared_ptr<Message>> m_messages;
|
||||||
|
|
||||||
QString m_name;
|
QString m_name;
|
||||||
int m_roomID;
|
int m_roomID;
|
||||||
|
|
|
@ -56,7 +56,8 @@ SOURCES += main.cpp\
|
||||||
link.cpp \
|
link.cpp \
|
||||||
fonts.cpp \
|
fonts.cpp \
|
||||||
appsettings.cpp \
|
appsettings.cpp \
|
||||||
emojis.cpp
|
emojis.cpp \
|
||||||
|
wordpart.cpp
|
||||||
|
|
||||||
HEADERS += mainwindow.h \
|
HEADERS += mainwindow.h \
|
||||||
chatwidget.h \
|
chatwidget.h \
|
||||||
|
@ -87,11 +88,12 @@ HEADERS += mainwindow.h \
|
||||||
word.h \
|
word.h \
|
||||||
link.h \
|
link.h \
|
||||||
fonts.h \
|
fonts.h \
|
||||||
common.h \
|
|
||||||
appsettings.h \
|
appsettings.h \
|
||||||
emojis.h
|
emojis.h \
|
||||||
|
wordpart.h \
|
||||||
|
common.h
|
||||||
|
|
||||||
PRECOMPILED_HEADER = common.h
|
PRECOMPILED_HEADER =
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
dialog.ui
|
dialog.ui
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
#include "chatwidgetview.h"
|
#include "chatwidgetview.h"
|
||||||
#include "QScroller"
|
#include "word.h"
|
||||||
#include "QPainter"
|
#include "wordpart.h"
|
||||||
|
#include "message.h"
|
||||||
|
|
||||||
|
#include <QScroller>
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
ChatWidgetView::ChatWidgetView()
|
ChatWidgetView::ChatWidgetView()
|
||||||
: QWidget(),
|
: QWidget(),
|
||||||
|
@ -18,6 +22,17 @@ void ChatWidgetView::resizeEvent(QResizeEvent *)
|
||||||
{
|
{
|
||||||
scrollbar.resize(scrollbar.width(), height());
|
scrollbar.resize(scrollbar.width(), height());
|
||||||
scrollbar.move(width() - scrollbar.width(), 0);
|
scrollbar.move(width() - scrollbar.width(), 0);
|
||||||
|
|
||||||
|
auto c = channel();
|
||||||
|
|
||||||
|
if (c == NULL) return;
|
||||||
|
|
||||||
|
auto messages = c->getMessagesClone();
|
||||||
|
|
||||||
|
for (std::shared_ptr<Message>& message : messages)
|
||||||
|
{
|
||||||
|
message.get()->layout(width(), true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatWidgetView::paintEvent(QPaintEvent *)
|
void ChatWidgetView::paintEvent(QPaintEvent *)
|
||||||
|
@ -28,7 +43,34 @@ void ChatWidgetView::paintEvent(QPaintEvent *)
|
||||||
|
|
||||||
if (c == NULL) return;
|
if (c == NULL) return;
|
||||||
|
|
||||||
auto M = c->getMessagesClone();
|
auto messages = c->getMessagesClone();
|
||||||
|
|
||||||
|
int y = 0;
|
||||||
|
|
||||||
|
for (std::shared_ptr<Message> const& message : messages)
|
||||||
|
{
|
||||||
|
for (WordPart const& wordPart : message.get()->wordParts())
|
||||||
|
{
|
||||||
|
// image
|
||||||
|
if (wordPart.word().isImage())
|
||||||
|
{
|
||||||
|
LazyLoadedImage& lli = wordPart.word().getImage();
|
||||||
|
|
||||||
|
const QImage* image = lli.image();
|
||||||
|
|
||||||
|
if (image != NULL)
|
||||||
|
{
|
||||||
|
painter.drawImage(QRect(wordPart.x(), wordPart.y() + y, wordPart.width(), wordPart.height()), *image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// text
|
||||||
|
else
|
||||||
|
{
|
||||||
|
painter.drawText(wordPart.x(), wordPart.y() + y, wordPart.getText());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
y += message.get()->height();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
16
common.h.cpp
Normal file
16
common.h.cpp
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
/*--------------------------------------------------------------------
|
||||||
|
* Precompiled header source file used by Visual Studio.NET to generate
|
||||||
|
* the .pch file.
|
||||||
|
*
|
||||||
|
* Due to issues with the dependencies checker within the IDE, it
|
||||||
|
* sometimes fails to recompile the PCH file, if we force the IDE to
|
||||||
|
* create the PCH file directly from the header file.
|
||||||
|
*
|
||||||
|
* This file is auto-generated by qmake since no PRECOMPILED_SOURCE was
|
||||||
|
* specified, and is used as the common stdafx.cpp. The file is only
|
||||||
|
* generated when creating .vcxproj project files, and is not used for
|
||||||
|
* command line compilations by nmake.
|
||||||
|
*
|
||||||
|
* WARNING: All changes made in this file will be lost.
|
||||||
|
--------------------------------------------------------------------*/
|
||||||
|
#include "common.h"
|
|
@ -14,7 +14,7 @@ public:
|
||||||
map = new QMap<TKey, TValue>();
|
map = new QMap<TKey, TValue>();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tryGet(const TKey &name, TValue& value) {
|
bool tryGet(const TKey &name, TValue& value) const {
|
||||||
mutex->lock();
|
mutex->lock();
|
||||||
auto a = map->find(name);
|
auto a = map->find(name);
|
||||||
if (a == map->end()) {
|
if (a == map->end()) {
|
||||||
|
|
|
@ -15,7 +15,7 @@ ConcurrentMap<QString, LazyLoadedImage*>* Emojis::imageCache = new ConcurrentMap
|
||||||
|
|
||||||
QString Emojis::replaceShortCodes(const QString &text)
|
QString Emojis::replaceShortCodes(const QString &text)
|
||||||
{
|
{
|
||||||
#warning "xD"
|
#pragma message WARN("xD")
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,14 +23,14 @@ Emotes::Emotes()
|
||||||
|
|
||||||
LazyLoadedImage* Emotes::getTwitchEmoteById(const QString &name, long id)
|
LazyLoadedImage* Emotes::getTwitchEmoteById(const QString &name, long id)
|
||||||
{
|
{
|
||||||
#warning "xD"
|
#pragma message WARN("xD")
|
||||||
return new LazyLoadedImage(NULL);
|
return new LazyLoadedImage(NULL);
|
||||||
// return m_twitchEmoteFromCache->getOrAdd()
|
// return m_twitchEmoteFromCache->getOrAdd()
|
||||||
}
|
}
|
||||||
|
|
||||||
LazyLoadedImage* Emotes::getCheerImage(long long amount, bool animated)
|
LazyLoadedImage* Emotes::getCheerImage(long long amount, bool animated)
|
||||||
{
|
{
|
||||||
#warning "xD"
|
#pragma message WARN("xD")
|
||||||
return getCheerBadge(amount);
|
return getCheerBadge(amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
19
fonts.cpp
19
fonts.cpp
|
@ -9,6 +9,13 @@ QFont* Fonts::small = new QFont(DEFAULT_FONT);
|
||||||
QFont* Fonts::large = new QFont(DEFAULT_FONT);
|
QFont* Fonts::large = new QFont(DEFAULT_FONT);
|
||||||
QFont* Fonts::veryLarge = new QFont(DEFAULT_FONT);
|
QFont* Fonts::veryLarge = new QFont(DEFAULT_FONT);
|
||||||
|
|
||||||
|
QFontMetrics* Fonts::metricsMedium = new QFontMetrics(*medium );
|
||||||
|
QFontMetrics* Fonts::metricsMediumBold = new QFontMetrics(*mediumBold );
|
||||||
|
QFontMetrics* Fonts::metricsMediumItalic = new QFontMetrics(*mediumItalic);
|
||||||
|
QFontMetrics* Fonts::metricsSmall = new QFontMetrics(*small );
|
||||||
|
QFontMetrics* Fonts::metricsLarge = new QFontMetrics(*large );
|
||||||
|
QFontMetrics* Fonts::metricsVeryLarge = new QFontMetrics(*veryLarge );
|
||||||
|
|
||||||
Fonts::Fonts()
|
Fonts::Fonts()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -25,3 +32,15 @@ QFont& Fonts::getFont(Type type)
|
||||||
|
|
||||||
return *medium;
|
return *medium;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QFontMetrics& Fonts::getFontMetrics(Type type)
|
||||||
|
{
|
||||||
|
if (type == Medium ) return *metricsMedium ;
|
||||||
|
if (type == MediumBold ) return *metricsMediumBold ;
|
||||||
|
if (type == MediumItalic) return *metricsMediumItalic;
|
||||||
|
if (type == Small ) return *metricsSmall ;
|
||||||
|
if (type == Large ) return *metricsLarge ;
|
||||||
|
if (type == VeryLarge ) return *metricsVeryLarge ;
|
||||||
|
|
||||||
|
return *metricsMedium;
|
||||||
|
}
|
||||||
|
|
11
fonts.h
11
fonts.h
|
@ -1,7 +1,8 @@
|
||||||
#ifndef FONTS_H
|
#ifndef FONTS_H
|
||||||
#define FONTS_H
|
#define FONTS_H
|
||||||
|
|
||||||
#include "QFont"
|
#include <QFont>
|
||||||
|
#include <QFontMetrics>
|
||||||
|
|
||||||
class Fonts
|
class Fonts
|
||||||
{
|
{
|
||||||
|
@ -16,6 +17,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
static QFont& getFont(Type type);
|
static QFont& getFont(Type type);
|
||||||
|
static QFontMetrics& getFontMetrics(Type type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Fonts();
|
Fonts();
|
||||||
|
@ -26,6 +28,13 @@ private:
|
||||||
static QFont* small;
|
static QFont* small;
|
||||||
static QFont* large;
|
static QFont* large;
|
||||||
static QFont* veryLarge;
|
static QFont* veryLarge;
|
||||||
|
|
||||||
|
static QFontMetrics* metricsMedium;
|
||||||
|
static QFontMetrics* metricsMediumBold;
|
||||||
|
static QFontMetrics* metricsMediumItalic;
|
||||||
|
static QFontMetrics* metricsSmall;
|
||||||
|
static QFontMetrics* metricsLarge;
|
||||||
|
static QFontMetrics* metricsVeryLarge;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FONTS_H
|
#endif // FONTS_H
|
||||||
|
|
|
@ -22,7 +22,7 @@ QMutex* IrcManager::twitchBlockedUsersMutex = new QMutex();
|
||||||
|
|
||||||
IrcManager::IrcManager()
|
IrcManager::IrcManager()
|
||||||
{
|
{
|
||||||
// account = Account::anon();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IrcManager::connect()
|
void IrcManager::connect()
|
||||||
|
@ -160,7 +160,7 @@ void IrcManager::privateMessageReceived(IrcPrivateMessage *message)
|
||||||
auto c = Channel::getChannel(message->target().mid(1));
|
auto c = Channel::getChannel(message->target().mid(1));
|
||||||
|
|
||||||
if (c != NULL) {
|
if (c != NULL) {
|
||||||
c->addMessage(new Message(*message, *c));
|
c->addMessage(std::shared_ptr<Message>(new Message(*message, *c)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#include "lazyloadedimage.h"
|
#include "lazyloadedimage.h"
|
||||||
|
|
||||||
LazyLoadedImage::LazyLoadedImage(const QString& url, qreal scale, const QString& name, const QString& tooltip, const QMargins& margin, bool isHat)
|
LazyLoadedImage::LazyLoadedImage(const QString& url, qreal scale, const QString& name, const QString& tooltip, const QMargins& margin, bool isHat)
|
||||||
: m_url(url)
|
: m_image(NULL)
|
||||||
|
, m_url(url)
|
||||||
, m_name(name)
|
, m_name(name)
|
||||||
, m_tooltip(tooltip)
|
, m_tooltip(tooltip)
|
||||||
, m_animated(false)
|
, m_animated(false)
|
||||||
|
|
|
@ -25,8 +25,22 @@ public:
|
||||||
bool animated() const { return m_animated; }
|
bool animated() const { return m_animated; }
|
||||||
bool isHat() const { return m_ishat; }
|
bool isHat() const { return m_ishat; }
|
||||||
|
|
||||||
|
const long width() const {
|
||||||
|
if (m_image == NULL) {
|
||||||
|
return 16;
|
||||||
|
}
|
||||||
|
return m_image->width();
|
||||||
|
}
|
||||||
|
|
||||||
|
const long height() const {
|
||||||
|
if (m_image == NULL) {
|
||||||
|
return 16;
|
||||||
|
}
|
||||||
|
return m_image->height();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QImage* m_image = NULL;
|
QImage* m_image;
|
||||||
qreal m_scale;
|
qreal m_scale;
|
||||||
|
|
||||||
QString m_url;
|
QString m_url;
|
||||||
|
|
3
main.cpp
3
main.cpp
|
@ -1,8 +1,9 @@
|
||||||
#include <QApplication>
|
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "colorscheme.h"
|
#include "colorscheme.h"
|
||||||
#include "ircmanager.h"
|
#include "ircmanager.h"
|
||||||
#include "emojis.h"
|
#include "emojis.h"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
|
|
210
message.cpp
210
message.cpp
|
@ -6,11 +6,18 @@
|
||||||
#include "link.h"
|
#include "link.h"
|
||||||
#include "appsettings.h"
|
#include "appsettings.h"
|
||||||
#include "ircmanager.h"
|
#include "ircmanager.h"
|
||||||
|
#include "fonts.h"
|
||||||
|
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
#include <list>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
|
||||||
|
#define MARGIN_LEFT 8
|
||||||
|
#define MARGIN_RIGHT 8
|
||||||
|
#define MARGIN_TOP 8
|
||||||
|
#define MARGIN_BOTTOM 8
|
||||||
|
|
||||||
LazyLoadedImage* Message::badgeStaff = new LazyLoadedImage(new QImage(":/images/staff_bg.png"));
|
LazyLoadedImage* Message::badgeStaff = new LazyLoadedImage(new QImage(":/images/staff_bg.png"));
|
||||||
LazyLoadedImage* Message::badgeAdmin = new LazyLoadedImage(new QImage(":/images/admin_bg.png"));
|
LazyLoadedImage* Message::badgeAdmin = new LazyLoadedImage(new QImage(":/images/admin_bg.png"));
|
||||||
LazyLoadedImage* Message::badgeModerator = new LazyLoadedImage(new QImage(":/images/moderator_bg.png"));
|
LazyLoadedImage* Message::badgeModerator = new LazyLoadedImage(new QImage(":/images/moderator_bg.png"));
|
||||||
|
@ -22,29 +29,33 @@ LazyLoadedImage* Message::badgePremium = new LazyLoadedImage(new QImage(":/i
|
||||||
QRegularExpression* Message::cheerRegex = new QRegularExpression("cheer[1-9][0-9]*");
|
QRegularExpression* Message::cheerRegex = new QRegularExpression("cheer[1-9][0-9]*");
|
||||||
|
|
||||||
Message::Message(const QString &text)
|
Message::Message(const QString &text)
|
||||||
|
: m_wordParts(new std::list<WordPart>())
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Message::Message(const IrcPrivateMessage& ircMessage, const Channel& channel, bool enablePingSound,
|
Message::Message(const IrcPrivateMessage& ircMessage, const Channel& channel, bool enablePingSound,
|
||||||
bool isReceivedWhisper, bool isSentWhisper, bool includeChannel )
|
bool isReceivedWhisper, bool isSentWhisper, bool includeChannel )
|
||||||
|
: m_wordParts(new std::list<WordPart>())
|
||||||
{
|
{
|
||||||
m_parseTime = std::chrono::system_clock::now();
|
m_parseTime = std::chrono::system_clock::now();
|
||||||
|
|
||||||
auto words = new QList<Word>();
|
auto words = std::vector<Word>();
|
||||||
|
|
||||||
auto iterator = ircMessage.tags().find("id");
|
auto tags = ircMessage.tags();
|
||||||
|
|
||||||
if (iterator != ircMessage.tags().end())
|
auto iterator = tags.find("id");
|
||||||
|
|
||||||
|
if (iterator != tags.end())
|
||||||
{
|
{
|
||||||
m_id = iterator.value().toString();
|
m_id = iterator.value().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
// timestamps
|
// timestamps
|
||||||
iterator = ircMessage.tags().find("tmi-sent-ts");
|
iterator = tags.find("tmi-sent-ts");
|
||||||
std::time_t time = std::time(NULL);
|
std::time_t time = std::time(NULL);
|
||||||
|
|
||||||
if (iterator != ircMessage.tags().end())
|
if (iterator != tags.end())
|
||||||
{
|
{
|
||||||
time = strtoll(iterator.value().toString().toStdString().c_str(), NULL, 10);
|
time = strtoll(iterator.value().toString().toStdString().c_str(), NULL, 10);
|
||||||
}
|
}
|
||||||
|
@ -57,13 +68,13 @@ Message::Message(const IrcPrivateMessage& ircMessage, const Channel& channel, bo
|
||||||
strftime(timeStampBuffer, 69, "%H:%M:%S", localtime(&time));
|
strftime(timeStampBuffer, 69, "%H:%M:%S", localtime(&time));
|
||||||
QString timestampWithSeconds = QString(timeStampBuffer);
|
QString timestampWithSeconds = QString(timeStampBuffer);
|
||||||
|
|
||||||
words->append(Word(timestamp, Word::TimestampNoSeconds, ColorScheme::instance().SystemMessageColor, QString(), QString()));
|
words.push_back(Word(timestamp, Word::TimestampNoSeconds, ColorScheme::instance().SystemMessageColor, QString(), QString()));
|
||||||
words->append(Word(timestampWithSeconds, Word::TimestampWithSeconds, ColorScheme::instance().SystemMessageColor, QString(), QString()));
|
words.push_back(Word(timestampWithSeconds, Word::TimestampWithSeconds, ColorScheme::instance().SystemMessageColor, QString(), QString()));
|
||||||
|
|
||||||
// badges
|
// badges
|
||||||
iterator = ircMessage.tags().find("badges");
|
iterator = tags.find("badges");
|
||||||
|
|
||||||
if (iterator != ircMessage.tags().end())
|
if (iterator != tags.end())
|
||||||
{
|
{
|
||||||
auto badges = iterator.value().toString().split(',');
|
auto badges = iterator.value().toString().split(',');
|
||||||
|
|
||||||
|
@ -72,36 +83,36 @@ Message::Message(const IrcPrivateMessage& ircMessage, const Channel& channel, bo
|
||||||
if (badge.startsWith("bits/"))
|
if (badge.startsWith("bits/"))
|
||||||
{
|
{
|
||||||
long long int cheer = strtoll(badge.mid(5).toStdString().c_str(), NULL, 10);
|
long long int cheer = strtoll(badge.mid(5).toStdString().c_str(), NULL, 10);
|
||||||
words->append(Word(Emotes::getCheerBadge(cheer), Word::BadgeCheer, QString(), QString("Twitch Cheer" + QString::number(cheer))));
|
words.push_back(Word(Emotes::getCheerBadge(cheer), Word::BadgeCheer, QString(), QString("Twitch Cheer" + QString::number(cheer))));
|
||||||
}
|
}
|
||||||
else if (badge == "staff/1")
|
else if (badge == "staff/1")
|
||||||
{
|
{
|
||||||
words->append(Word(badgeStaff, Word::BadgeStaff, QString(), QString("Twitch Staff")));
|
words.push_back(Word(badgeStaff, Word::BadgeStaff, QString(), QString("Twitch Staff")));
|
||||||
}
|
}
|
||||||
else if (badge == "admin/1")
|
else if (badge == "admin/1")
|
||||||
{
|
{
|
||||||
words->append(Word(badgeAdmin, Word::BadgeAdmin, QString(), QString("Twitch Admin")));
|
words.push_back(Word(badgeAdmin, Word::BadgeAdmin, QString(), QString("Twitch Admin")));
|
||||||
}
|
}
|
||||||
else if (badge == "global_mod/1")
|
else if (badge == "global_mod/1")
|
||||||
{
|
{
|
||||||
words->append(Word(badgeGlobalmod, Word::BadgeGlobalMod, QString(), QString("Global Moderator")));
|
words.push_back(Word(badgeGlobalmod, Word::BadgeGlobalMod, QString(), QString("Global Moderator")));
|
||||||
}
|
}
|
||||||
else if (badge == "moderator/1")
|
else if (badge == "moderator/1")
|
||||||
{
|
{
|
||||||
#warning "xD"
|
#pragma message WARN("xD")
|
||||||
words->append(Word(badgeTurbo, Word::BadgeModerator, QString(), QString("Channel Moderator"))); // custom badge
|
words.push_back(Word(badgeTurbo, Word::BadgeModerator, QString(), QString("Channel Moderator"))); // custom badge
|
||||||
}
|
}
|
||||||
else if (badge == "turbo/1")
|
else if (badge == "turbo/1")
|
||||||
{
|
{
|
||||||
words->append(Word(badgeStaff, Word::BadgeTurbo, QString(), QString("Turbo Subscriber")));
|
words.push_back(Word(badgeStaff, Word::BadgeTurbo, QString(), QString("Turbo Subscriber")));
|
||||||
}
|
}
|
||||||
else if (badge == "broadcaster/1")
|
else if (badge == "broadcaster/1")
|
||||||
{
|
{
|
||||||
words->append(Word(badgeBroadcaster, Word::BadgeBroadcaster, QString(), QString("Channel Broadcaster")));
|
words.push_back(Word(badgeBroadcaster, Word::BadgeBroadcaster, QString(), QString("Channel Broadcaster")));
|
||||||
}
|
}
|
||||||
else if (badge == "premium/1")
|
else if (badge == "premium/1")
|
||||||
{
|
{
|
||||||
words->append(Word(badgePremium, Word::BadgePremium, QString(), QString("Twitch Prime")));
|
words.push_back(Word(badgePremium, Word::BadgePremium, QString(), QString("Twitch Prime")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,8 +120,8 @@ Message::Message(const IrcPrivateMessage& ircMessage, const Channel& channel, bo
|
||||||
// color
|
// color
|
||||||
QColor usernameColor = ColorScheme::instance().SystemMessageColor;
|
QColor usernameColor = ColorScheme::instance().SystemMessageColor;
|
||||||
|
|
||||||
iterator = ircMessage.tags().find("color");
|
iterator = tags.find("color");
|
||||||
if (iterator != ircMessage.tags().end())
|
if (iterator != tags.end())
|
||||||
{
|
{
|
||||||
usernameColor = QColor(iterator.value().toString());
|
usernameColor = QColor(iterator.value().toString());
|
||||||
}
|
}
|
||||||
|
@ -119,7 +130,7 @@ Message::Message(const IrcPrivateMessage& ircMessage, const Channel& channel, bo
|
||||||
if (includeChannel)
|
if (includeChannel)
|
||||||
{
|
{
|
||||||
QString channelName("#" + channel.name());
|
QString channelName("#" + channel.name());
|
||||||
words->append(Word(channelName, Word::Misc, ColorScheme::instance().SystemMessageColor, QString(channelName), QString(), Link(Link::Url, channel.name() + "\n" + m_id)));
|
words.push_back(Word(channelName, Word::Misc, ColorScheme::instance().SystemMessageColor, QString(channelName), QString(), Link(Link::Url, channel.name() + "\n" + m_id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// username
|
// username
|
||||||
|
@ -127,9 +138,9 @@ Message::Message(const IrcPrivateMessage& ircMessage, const Channel& channel, bo
|
||||||
|
|
||||||
if (m_userName.isEmpty())
|
if (m_userName.isEmpty())
|
||||||
{
|
{
|
||||||
auto iterator = ircMessage.tags().find("login");
|
auto iterator = tags.find("login");
|
||||||
|
|
||||||
if (iterator != ircMessage.tags().end())
|
if (iterator != tags.end())
|
||||||
{
|
{
|
||||||
m_userName = iterator.value().toString();
|
m_userName = iterator.value().toString();
|
||||||
}
|
}
|
||||||
|
@ -137,8 +148,8 @@ Message::Message(const IrcPrivateMessage& ircMessage, const Channel& channel, bo
|
||||||
|
|
||||||
QString displayName;
|
QString displayName;
|
||||||
|
|
||||||
iterator = ircMessage.tags().find("display-name");
|
iterator = tags.find("display-name");
|
||||||
if (iterator == ircMessage.tags().end()) {
|
if (iterator == tags.end()) {
|
||||||
displayName = ircMessage.account();
|
displayName = ircMessage.account();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -163,7 +174,7 @@ Message::Message(const IrcPrivateMessage& ircMessage, const Channel& channel, bo
|
||||||
userDisplayString += ": ";
|
userDisplayString += ": ";
|
||||||
}
|
}
|
||||||
|
|
||||||
words->append(Word(userDisplayString, Word::Username, usernameColor, userDisplayString, QString()));
|
words.push_back(Word(userDisplayString, Word::Username, usernameColor, userDisplayString, QString()));
|
||||||
|
|
||||||
// highlights
|
// highlights
|
||||||
#pragma message WARN("xD")
|
#pragma message WARN("xD")
|
||||||
|
@ -171,18 +182,18 @@ Message::Message(const IrcPrivateMessage& ircMessage, const Channel& channel, bo
|
||||||
// bits
|
// bits
|
||||||
QString bits = "";
|
QString bits = "";
|
||||||
|
|
||||||
iterator = ircMessage.tags().find("bits");
|
iterator = tags.find("bits");
|
||||||
if (iterator != ircMessage.tags().end())
|
if (iterator != tags.end())
|
||||||
{
|
{
|
||||||
bits = iterator.value().toString();
|
bits = iterator.value().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
// twitch emotes
|
// twitch emotes
|
||||||
QVector<std::pair<long int, LazyLoadedImage*>> twitchEmotes;
|
std::vector<std::pair<long int, LazyLoadedImage*>> twitchEmotes;
|
||||||
|
|
||||||
iterator = ircMessage.tags().find("emotes");
|
iterator = tags.find("emotes");
|
||||||
|
|
||||||
if (iterator != ircMessage.tags().end())
|
if (iterator != tags.end())
|
||||||
{
|
{
|
||||||
auto emotes = iterator.value().toString().split('/');
|
auto emotes = iterator.value().toString().split('/');
|
||||||
|
|
||||||
|
@ -211,7 +222,7 @@ Message::Message(const IrcPrivateMessage& ircMessage, const Channel& channel, bo
|
||||||
|
|
||||||
QString name = ircMessage.content().mid(start, end - start);
|
QString name = ircMessage.content().mid(start, end - start);
|
||||||
|
|
||||||
twitchEmotes.append(std::pair<long int, LazyLoadedImage*>(start, Emotes::getTwitchEmoteById(name, id)));
|
twitchEmotes.push_back(std::pair<long int, LazyLoadedImage*>(start, Emotes::getTwitchEmoteById(name, id)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,8 +245,8 @@ Message::Message(const IrcPrivateMessage& ircMessage, const Channel& channel, bo
|
||||||
|
|
||||||
if (currentTwitchEmote->first == i)
|
if (currentTwitchEmote->first == i)
|
||||||
{
|
{
|
||||||
words->append(Word(currentTwitchEmote->second, Word::TwitchEmoteImage, currentTwitchEmote->second->name(), currentTwitchEmote->second->name() + QString("\nTwitch Emote")));
|
words.push_back(Word(currentTwitchEmote->second, Word::TwitchEmoteImage, currentTwitchEmote->second->name(), currentTwitchEmote->second->name() + QString("\nTwitch Emote")));
|
||||||
words->append(Word(currentTwitchEmote->second->name(), Word::TwitchEmoteText, textColor, currentTwitchEmote->second->name(), currentTwitchEmote->second->name() + QString("\nTwitch Emote")));
|
words.push_back(Word(currentTwitchEmote->second->name(), Word::TwitchEmoteText, textColor, currentTwitchEmote->second->name(), currentTwitchEmote->second->name() + QString("\nTwitch Emote")));
|
||||||
|
|
||||||
i += split.length() + 1;
|
i += split.length() + 1;
|
||||||
currentTwitchEmote = std::next(currentTwitchEmote);
|
currentTwitchEmote = std::next(currentTwitchEmote);
|
||||||
|
@ -296,26 +307,26 @@ Message::Message(const IrcPrivateMessage& ircMessage, const Channel& channel, bo
|
||||||
LazyLoadedImage* imageAnimated = Emotes::miscImageFromCache().getOrAdd(bitsLinkAnimated, [&bitsLinkAnimated]{ return new LazyLoadedImage(bitsLinkAnimated); });
|
LazyLoadedImage* imageAnimated = Emotes::miscImageFromCache().getOrAdd(bitsLinkAnimated, [&bitsLinkAnimated]{ return new LazyLoadedImage(bitsLinkAnimated); });
|
||||||
LazyLoadedImage* image = Emotes::miscImageFromCache().getOrAdd(bitsLink, [&bitsLink]{ return new LazyLoadedImage(bitsLink); });
|
LazyLoadedImage* image = Emotes::miscImageFromCache().getOrAdd(bitsLink, [&bitsLink]{ return new LazyLoadedImage(bitsLink); });
|
||||||
|
|
||||||
words->append(Word(imageAnimated, Word::BitsAnimated, QString("cheer"), QString("Twitch Cheer"), Link(Link::Url, QString("https://blog.twitch.tv/introducing-cheering-celebrate-together-da62af41fac6"))));
|
words.push_back(Word(imageAnimated, Word::BitsAnimated, QString("cheer"), QString("Twitch Cheer"), Link(Link::Url, QString("https://blog.twitch.tv/introducing-cheering-celebrate-together-da62af41fac6"))));
|
||||||
words->append(Word(image, Word::Bits, QString("cheer"), QString("Twitch Cheer"), Link(Link::Url, QString("https://blog.twitch.tv/introducing-cheering-celebrate-together-da62af41fac6"))));
|
words.push_back(Word(image, Word::Bits, QString("cheer"), QString("Twitch Cheer"), Link(Link::Url, QString("https://blog.twitch.tv/introducing-cheering-celebrate-together-da62af41fac6"))));
|
||||||
|
|
||||||
words->append(Word(QString("x" + string.mid(5)), Word::BitsAmount, bitsColor, QString(string.mid(5)), QString("Twitch Cheer"), Link(Link::Url, QString("https://blog.twitch.tv/introducing-cheering-celebrate-together-da62af41fac6"))));
|
words.push_back(Word(QString("x" + string.mid(5)), Word::BitsAmount, bitsColor, QString(string.mid(5)), QString("Twitch Cheer"), Link(Link::Url, QString("https://blog.twitch.tv/introducing-cheering-celebrate-together-da62af41fac6"))));
|
||||||
|
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// bttv / ffz emotes
|
// bttv / ffz emotes
|
||||||
LazyLoadedImage* bttvEmote;
|
LazyLoadedImage* bttvEmote;
|
||||||
|
|
||||||
|
#pragma message WARN( "xD ignored emotes")
|
||||||
if (
|
if (
|
||||||
#warning "xD ignored emotes"
|
|
||||||
Emotes::bttvEmotes().tryGet(string, bttvEmote) ||
|
Emotes::bttvEmotes().tryGet(string, bttvEmote) ||
|
||||||
channel.bttvChannelEmotes().tryGet(string, bttvEmote) ||
|
channel.bttvChannelEmotes().tryGet(string, bttvEmote) ||
|
||||||
Emotes::ffzEmotes().tryGet(string, bttvEmote) ||
|
Emotes::ffzEmotes().tryGet(string, bttvEmote) ||
|
||||||
channel.ffzChannelEmotes().tryGet(string, bttvEmote) ||
|
channel.ffzChannelEmotes().tryGet(string, bttvEmote) ||
|
||||||
Emotes::chatterinoEmotes().tryGet(string, bttvEmote))
|
Emotes::chatterinoEmotes().tryGet(string, bttvEmote))
|
||||||
{
|
{
|
||||||
words->append(Word(bttvEmote, Word::BttvEmoteImage, bttvEmote->name(), bttvEmote->tooltip(), Link(Link::Url, bttvEmote->url())));
|
words.push_back(Word(bttvEmote, Word::BttvEmoteImage, bttvEmote->name(), bttvEmote->tooltip(), Link(Link::Url, bttvEmote->url())));
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -323,22 +334,131 @@ Message::Message(const IrcPrivateMessage& ircMessage, const Channel& channel, bo
|
||||||
// actually just a word
|
// actually just a word
|
||||||
QString link = matchLink(string);
|
QString link = matchLink(string);
|
||||||
|
|
||||||
words->append(Word(string, Word::Text, textColor, string, QString(), link.isEmpty() ? Link() : Link(Link::Url, link)));
|
words.push_back(Word(string, Word::Text, textColor, string, QString(), link.isEmpty() ? Link() : Link(Link::Url, link)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i += split.length() + 1;
|
i += split.length() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->words() = words;
|
this->m_words = words;
|
||||||
|
|
||||||
#warning "xD"
|
#pragma message WARN("xD")
|
||||||
// if (!isReceivedWhisper && AppSettings.HighlightIgnoredUsers.ContainsKey(Username))
|
// if (!isReceivedWhisper && AppSettings.HighlightIgnoredUsers.ContainsKey(Username))
|
||||||
// {
|
// {
|
||||||
// HighlightTab = false;
|
// HighlightTab = false;
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//static void normalize
|
||||||
|
|
||||||
|
bool Message::layout(int width, bool enableEmoteMargins)
|
||||||
|
{
|
||||||
|
width = width - (width % 2);
|
||||||
|
|
||||||
|
int mediumTextLineHeight = Fonts::getFontMetrics(Fonts::Medium).height();
|
||||||
|
|
||||||
|
bool redraw = width != m_currentLayoutWidth || m_relayoutRequested;
|
||||||
|
|
||||||
|
if (m_recalculateImages || m_recalculateText)
|
||||||
|
{
|
||||||
|
redraw = true;
|
||||||
|
|
||||||
|
for (auto& word : m_words)
|
||||||
|
{
|
||||||
|
if (word.isImage())
|
||||||
|
{
|
||||||
|
if (m_recalculateImages)
|
||||||
|
{
|
||||||
|
auto& image = word.getImage();
|
||||||
|
|
||||||
|
qreal w = image.width();
|
||||||
|
qreal h = image.height();
|
||||||
|
|
||||||
|
if (AppSettings::scaleEmotesByLineHeight())
|
||||||
|
{
|
||||||
|
word.setSize(w * mediumTextLineHeight / h * AppSettings::emoteScale(), mediumTextLineHeight * AppSettings::emoteScale());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
word.setSize(w * image.scale() * AppSettings::emoteScale(), h * image.scale() * AppSettings::emoteScale());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (m_recalculateText)
|
||||||
|
{
|
||||||
|
QFontMetrics& metrics = word.getFontMetrics();
|
||||||
|
word.setSize(metrics.width(word.getText()), metrics.height());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_recalculateImages = false;
|
||||||
|
m_recalculateText = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (redraw)
|
||||||
|
{
|
||||||
|
int x = MARGIN_LEFT;
|
||||||
|
int y = MARGIN_TOP;
|
||||||
|
|
||||||
|
int right = width - MARGIN_RIGHT;
|
||||||
|
|
||||||
|
std::list<WordPart>* parts;
|
||||||
|
|
||||||
|
auto lineStart = m_wordParts->begin();
|
||||||
|
int lineHeight = 0;
|
||||||
|
|
||||||
|
for (auto it = m_words.begin(); it != m_words.end(); ++it)
|
||||||
|
{
|
||||||
|
Word& word = *it;
|
||||||
|
|
||||||
|
int xOffset = 0, yOffset = 0;
|
||||||
|
|
||||||
|
if (enableEmoteMargins)
|
||||||
|
{
|
||||||
|
if (word.isImage() && word.getImage().isHat())
|
||||||
|
{
|
||||||
|
xOffset = -word.width() + 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xOffset = word.xOffset();
|
||||||
|
yOffset = word.yOffset();
|
||||||
|
}
|
||||||
|
|
||||||
|
lineHeight = std::max(word.height(), lineHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x + word.width() + xOffset <= right)
|
||||||
|
{
|
||||||
|
parts->push_back(WordPart(word, x, y, QStringRef(&word.copyText())));
|
||||||
|
x += word.width() + xOffset;
|
||||||
|
}
|
||||||
|
// else if (word.isText() && word.getText().length() > 2)
|
||||||
|
// {
|
||||||
|
|
||||||
|
// }
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parts->push_back(WordPart(word, x, y, QStringRef(&word.copyText())));
|
||||||
|
|
||||||
|
lineHeight = std::max(word.height(), lineHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto tmp = m_wordParts;
|
||||||
|
m_wordParts = parts;
|
||||||
|
delete tmp;
|
||||||
|
|
||||||
|
m_height = y + lineHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
return redraw;
|
||||||
|
}
|
||||||
|
|
||||||
bool Message::sortTwitchEmotes(const std::pair<long int, LazyLoadedImage*>& a, const std::pair<long int, LazyLoadedImage*>& b)
|
bool Message::sortTwitchEmotes(const std::pair<long int, LazyLoadedImage*>& a, const std::pair<long int, LazyLoadedImage*>& b)
|
||||||
{
|
{
|
||||||
return a.first < b.first;
|
return a.first < b.first;
|
||||||
|
@ -346,6 +466,6 @@ bool Message::sortTwitchEmotes(const std::pair<long int, LazyLoadedImage*>& a, c
|
||||||
|
|
||||||
QString Message::matchLink(const QString &string)
|
QString Message::matchLink(const QString &string)
|
||||||
{
|
{
|
||||||
#warning "xD"
|
#pragma message WARN("xD")
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
50
message.h
50
message.h
|
@ -1,29 +1,27 @@
|
||||||
#ifndef MESSAGE_H
|
#ifndef MESSAGE_H
|
||||||
#define MESSAGE_H
|
#define MESSAGE_H
|
||||||
|
|
||||||
#include "IrcMessage"
|
|
||||||
#include "word.h"
|
#include "word.h"
|
||||||
#include "chrono"
|
#include "wordpart.h"
|
||||||
#include "channel.h"
|
#include "channel.h"
|
||||||
|
|
||||||
|
#include <IrcMessage>
|
||||||
|
#include <QVector>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
class Message
|
class Message
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// enum Badges : char {
|
|
||||||
// None = 0,
|
|
||||||
// Mod = 1,
|
|
||||||
// Turbo = 2,
|
|
||||||
// Sub = 4,
|
|
||||||
// Staff = 8,
|
|
||||||
// GlobalMod = 16,
|
|
||||||
// Admin = 32,
|
|
||||||
// Broadcaster = 64,
|
|
||||||
// };
|
|
||||||
|
|
||||||
Message(const QString& text);
|
Message(const QString& text);
|
||||||
Message(const IrcPrivateMessage& ircMessage, const Channel& Channel, bool enablePingSound = true,
|
Message(const IrcPrivateMessage& ircMessage, const Channel& Channel, bool enablePingSound = true,
|
||||||
bool isReceivedWhisper = false, bool isSentWhisper = false, bool includeChannel = false);
|
bool isReceivedWhisper = false, bool isSentWhisper = false, bool includeChannel = false);
|
||||||
|
|
||||||
|
~Message() {
|
||||||
|
if (m_wordParts != NULL) {
|
||||||
|
delete m_wordParts;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool canHighlightTab() const {
|
bool canHighlightTab() const {
|
||||||
return m_highlightTab;
|
return m_highlightTab;
|
||||||
}
|
}
|
||||||
|
@ -44,10 +42,14 @@ public:
|
||||||
return m_displayName;
|
return m_displayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<Word> words() const {
|
const std::vector<Word> words() const {
|
||||||
return m_words;
|
return m_words;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::list<WordPart> wordParts() const {
|
||||||
|
return *m_wordParts;
|
||||||
|
}
|
||||||
|
|
||||||
bool disabled() const {
|
bool disabled() const {
|
||||||
return m_disabled;
|
return m_disabled;
|
||||||
}
|
}
|
||||||
|
@ -56,6 +58,16 @@ public:
|
||||||
return m_id;
|
return m_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int height() const {
|
||||||
|
return m_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool layout(int width, bool enableEmoteMargins = true);
|
||||||
|
|
||||||
|
void requestRelayout() { m_relayoutRequested = true; }
|
||||||
|
void requestTextRecalculation() { m_recalculateText = true; }
|
||||||
|
void requestImageRecalculation() { m_recalculateImages = true; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static LazyLoadedImage* badgeStaff;
|
static LazyLoadedImage* badgeStaff;
|
||||||
static LazyLoadedImage* badgeAdmin;
|
static LazyLoadedImage* badgeAdmin;
|
||||||
|
@ -77,7 +89,15 @@ private:
|
||||||
QString m_displayName = "";
|
QString m_displayName = "";
|
||||||
QString m_id = "";
|
QString m_id = "";
|
||||||
|
|
||||||
QList<Word> m_words;
|
int m_height = 0;
|
||||||
|
|
||||||
|
std::vector<Word> m_words;
|
||||||
|
std::list<WordPart>* m_wordParts;
|
||||||
|
|
||||||
|
long m_currentLayoutWidth = -1;
|
||||||
|
bool m_relayoutRequested = true;
|
||||||
|
bool m_recalculateText = true;
|
||||||
|
bool m_recalculateImages = true;
|
||||||
|
|
||||||
static QString matchLink(const QString& string);
|
static QString matchLink(const QString& string);
|
||||||
|
|
||||||
|
|
5
word.cpp
5
word.cpp
|
@ -11,13 +11,14 @@ Word::Word(LazyLoadedImage* image, Type type, const QString& copytext, const QSt
|
||||||
, m_color()
|
, m_color()
|
||||||
, m_link(link)
|
, m_link(link)
|
||||||
{
|
{
|
||||||
|
image->width(); // professional segfault test
|
||||||
}
|
}
|
||||||
|
|
||||||
// Text word
|
// Text word
|
||||||
Word::Word(const QString& text, Type type, const QColor& color, const QString& copytext, const QString& tooltip, const Link& link)
|
Word::Word(const QString& text, Type type, const QColor& color, const QString& copytext, const QString& tooltip, const Link& link)
|
||||||
: m_image(nullptr)
|
: m_image(NULL)
|
||||||
, m_text(text)
|
, m_text(text)
|
||||||
, m_isImage(true)
|
, m_isImage(false)
|
||||||
, m_type(type)
|
, m_type(type)
|
||||||
, m_copyText(copytext)
|
, m_copyText(copytext)
|
||||||
, m_tooltip(tooltip)
|
, m_tooltip(tooltip)
|
||||||
|
|
49
word.h
49
word.h
|
@ -27,6 +27,7 @@ public:
|
||||||
BttvGifEmoteText = 0x200,
|
BttvGifEmoteText = 0x200,
|
||||||
FfzEmoteImage = 0x400,
|
FfzEmoteImage = 0x400,
|
||||||
FfzEmoteText = 0x800,
|
FfzEmoteText = 0x800,
|
||||||
|
EmoteImages = TwitchEmoteImage | BttvEmoteImage | BttvGifEmoteImage | FfzEmoteImage,
|
||||||
|
|
||||||
Bits = 0x1000,
|
Bits = 0x1000,
|
||||||
BitsAnimated = 0x2000,
|
BitsAnimated = 0x2000,
|
||||||
|
@ -75,30 +76,19 @@ public:
|
||||||
return m_height;
|
return m_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
int x() const {
|
void setSize(int width, int height) {
|
||||||
return m_x;
|
m_width = width;
|
||||||
}
|
m_height = height;
|
||||||
|
|
||||||
int y() const {
|
|
||||||
return m_y;
|
|
||||||
}
|
|
||||||
|
|
||||||
int right() const {
|
|
||||||
return m_x + m_width;
|
|
||||||
}
|
|
||||||
|
|
||||||
int bottom() const {
|
|
||||||
return m_y + m_height;
|
|
||||||
}
|
|
||||||
|
|
||||||
QRect rect() const {
|
|
||||||
return QRect(m_x, m_y, m_width, m_height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isImage() const {
|
bool isImage() const {
|
||||||
return m_isImage;
|
return m_isImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isText() const {
|
||||||
|
return !m_isImage;
|
||||||
|
}
|
||||||
|
|
||||||
const QString& copyText() const {
|
const QString& copyText() const {
|
||||||
return m_copyText;
|
return m_copyText;
|
||||||
}
|
}
|
||||||
|
@ -111,6 +101,10 @@ public:
|
||||||
return Fonts::getFont(m_font);
|
return Fonts::getFont(m_font);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QFontMetrics& getFontMetrics() const {
|
||||||
|
return Fonts::getFontMetrics(m_font);
|
||||||
|
}
|
||||||
|
|
||||||
Type type() const {
|
Type type() const {
|
||||||
return m_type;
|
return m_type;
|
||||||
}
|
}
|
||||||
|
@ -127,6 +121,19 @@ public:
|
||||||
return m_link;
|
return m_link;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int xOffset() const {
|
||||||
|
return m_xOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
int yOffset() const {
|
||||||
|
return m_yOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setOffset(int xOffset, int yOffset) {
|
||||||
|
m_xOffset = std::max(0, xOffset);
|
||||||
|
m_yOffset = std::max(0, yOffset);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LazyLoadedImage* m_image;
|
LazyLoadedImage* m_image;
|
||||||
QString m_text;
|
QString m_text;
|
||||||
|
@ -136,10 +143,12 @@ private:
|
||||||
Type m_type;
|
Type m_type;
|
||||||
QString m_copyText;
|
QString m_copyText;
|
||||||
QString m_tooltip;
|
QString m_tooltip;
|
||||||
int m_x;
|
|
||||||
int m_y;
|
|
||||||
int m_width;
|
int m_width;
|
||||||
int m_height;
|
int m_height;
|
||||||
|
int m_xOffset;
|
||||||
|
int m_yOffset;
|
||||||
|
|
||||||
bool m_hasTrailingSpace;
|
bool m_hasTrailingSpace;
|
||||||
Fonts::Type m_font = Fonts::Medium;
|
Fonts::Type m_font = Fonts::Medium;
|
||||||
Link m_link;
|
Link m_link;
|
||||||
|
|
18
wordpart.cpp
Normal file
18
wordpart.cpp
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#include "wordpart.h"
|
||||||
|
#include "word.h"
|
||||||
|
|
||||||
|
WordPart::WordPart(Word& word, int x, int y, const QStringRef& copyText, bool allowTrailingSpace)
|
||||||
|
: m_word(word)
|
||||||
|
, m_copyText(copyText)
|
||||||
|
, m_x(x)
|
||||||
|
, m_y(y)
|
||||||
|
, m_width(word.width())
|
||||||
|
, m_height(word.height())
|
||||||
|
, m_trailingSpace(word.hasTrailingSpace() & allowTrailingSpace)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString& WordPart::getText() const
|
||||||
|
{
|
||||||
|
return m_word.getText();
|
||||||
|
}
|
74
wordpart.h
Normal file
74
wordpart.h
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
#ifndef WORDPART_H
|
||||||
|
#define WORDPART_H
|
||||||
|
|
||||||
|
#include <QRect>
|
||||||
|
#include <QStringRef>
|
||||||
|
|
||||||
|
class Word;
|
||||||
|
|
||||||
|
class WordPart
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WordPart(Word& word, int x, int y, const QStringRef& copyText, bool allowTrailingSpace = true);
|
||||||
|
|
||||||
|
const Word& word() const {
|
||||||
|
return m_word;
|
||||||
|
}
|
||||||
|
|
||||||
|
int width() const {
|
||||||
|
return m_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
int height() const {
|
||||||
|
return m_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
int x() const {
|
||||||
|
return m_x;
|
||||||
|
}
|
||||||
|
|
||||||
|
int y() const {
|
||||||
|
return m_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPosition(int x, int y) {
|
||||||
|
m_x = x;
|
||||||
|
m_y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
int right() const {
|
||||||
|
return m_x + m_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bottom() const {
|
||||||
|
return m_y + m_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect rect() const {
|
||||||
|
return QRect(m_x, m_y, m_width, m_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
const QStringRef copyText() const {
|
||||||
|
return m_copyText;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hasTrailingSpace() const {
|
||||||
|
return m_trailingSpace;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString& getText() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Word& m_word;
|
||||||
|
|
||||||
|
QStringRef m_copyText;
|
||||||
|
|
||||||
|
int m_x;
|
||||||
|
int m_y;
|
||||||
|
int m_width;
|
||||||
|
int m_height;
|
||||||
|
|
||||||
|
bool m_trailingSpace;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // WORDPART_H
|
Loading…
Reference in a new issue