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 qreal emoteScale() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static qreal badgeScale() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool scaleEmotesByLineHeight() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
AppSettings();
|
||||
|
|
21
channel.cpp
21
channel.cpp
|
@ -1,8 +1,10 @@
|
|||
#include "channel.h"
|
||||
#include "message.h"
|
||||
|
||||
Channel Channel::whispers = Channel(QString("/whispers"));
|
||||
Channel Channel::mentions = Channel(QString("/mentions"));
|
||||
#include <memory>
|
||||
|
||||
Channel Channel::whispers(QString("/whispers"));
|
||||
Channel Channel::mentions(QString("/mentions"));
|
||||
|
||||
QMap<QString, Channel*> Channel::channels = QMap<QString, Channel*>();
|
||||
|
||||
|
@ -30,7 +32,7 @@ Channel* Channel::addChannel(const QString &channel)
|
|||
return c;
|
||||
}
|
||||
|
||||
c->referenceCount++;
|
||||
c->m_referenceCount++;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
@ -60,25 +62,26 @@ void Channel::removeChannel(const QString &channel)
|
|||
|
||||
if (c == NULL) return;
|
||||
|
||||
c->referenceCount--;
|
||||
c->m_referenceCount--;
|
||||
|
||||
if (c->referenceCount == 0) {
|
||||
if (c->m_referenceCount == 0) {
|
||||
channels.remove(channel);
|
||||
delete c;
|
||||
}
|
||||
}
|
||||
|
||||
QVector<Message*> Channel::getMessagesClone()
|
||||
QVector<std::shared_ptr<Message>> Channel::getMessagesClone()
|
||||
{
|
||||
m_messageMutex.lock();
|
||||
QVector M = QVector<Message*>(*m_messages);
|
||||
QVector<std::shared_ptr<Message>> M(m_messages);
|
||||
M.detach();
|
||||
m_messageMutex.unlock();
|
||||
return M;
|
||||
}
|
||||
|
||||
void Channel::addMessage(Message *message)
|
||||
void Channel::addMessage(std::shared_ptr<Message> message)
|
||||
{
|
||||
m_messageMutex.lock();
|
||||
// messages
|
||||
m_messages.append(message);
|
||||
m_messageMutex.unlock();
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <QMap>
|
||||
#include <QMutex>
|
||||
#include <QVector>
|
||||
#include <memory>
|
||||
|
||||
class Message;
|
||||
|
||||
|
@ -48,9 +49,9 @@ public:
|
|||
const QString& streamGame() const { return m_streamGame; }
|
||||
|
||||
// methods
|
||||
void addMessage(Message* message);
|
||||
void addMessage(std::shared_ptr<Message> message);
|
||||
|
||||
QVector<Message*> getMessagesClone();
|
||||
QVector<std::shared_ptr<Message>> getMessagesClone();
|
||||
|
||||
private:
|
||||
Channel(QString channel);
|
||||
|
@ -61,7 +62,7 @@ private:
|
|||
|
||||
int m_referenceCount = 0;
|
||||
|
||||
QVector<Message*> m_messages;
|
||||
QVector<std::shared_ptr<Message>> m_messages;
|
||||
|
||||
QString m_name;
|
||||
int m_roomID;
|
||||
|
|
|
@ -56,7 +56,8 @@ SOURCES += main.cpp\
|
|||
link.cpp \
|
||||
fonts.cpp \
|
||||
appsettings.cpp \
|
||||
emojis.cpp
|
||||
emojis.cpp \
|
||||
wordpart.cpp
|
||||
|
||||
HEADERS += mainwindow.h \
|
||||
chatwidget.h \
|
||||
|
@ -87,11 +88,12 @@ HEADERS += mainwindow.h \
|
|||
word.h \
|
||||
link.h \
|
||||
fonts.h \
|
||||
common.h \
|
||||
appsettings.h \
|
||||
emojis.h
|
||||
emojis.h \
|
||||
wordpart.h \
|
||||
common.h
|
||||
|
||||
PRECOMPILED_HEADER = common.h
|
||||
PRECOMPILED_HEADER =
|
||||
|
||||
FORMS += \
|
||||
dialog.ui
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
#include "chatwidgetview.h"
|
||||
#include "QScroller"
|
||||
#include "QPainter"
|
||||
#include "word.h"
|
||||
#include "wordpart.h"
|
||||
#include "message.h"
|
||||
|
||||
#include <QScroller>
|
||||
#include <QPainter>
|
||||
|
||||
ChatWidgetView::ChatWidgetView()
|
||||
: QWidget(),
|
||||
|
@ -18,6 +22,17 @@ void ChatWidgetView::resizeEvent(QResizeEvent *)
|
|||
{
|
||||
scrollbar.resize(scrollbar.width(), height());
|
||||
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 *)
|
||||
|
@ -28,7 +43,34 @@ void ChatWidgetView::paintEvent(QPaintEvent *)
|
|||
|
||||
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>();
|
||||
}
|
||||
|
||||
bool tryGet(const TKey &name, TValue& value) {
|
||||
bool tryGet(const TKey &name, TValue& value) const {
|
||||
mutex->lock();
|
||||
auto a = map->find(name);
|
||||
if (a == map->end()) {
|
||||
|
|
|
@ -15,7 +15,7 @@ ConcurrentMap<QString, LazyLoadedImage*>* Emojis::imageCache = new ConcurrentMap
|
|||
|
||||
QString Emojis::replaceShortCodes(const QString &text)
|
||||
{
|
||||
#warning "xD"
|
||||
#pragma message WARN("xD")
|
||||
return text;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,14 +23,14 @@ Emotes::Emotes()
|
|||
|
||||
LazyLoadedImage* Emotes::getTwitchEmoteById(const QString &name, long id)
|
||||
{
|
||||
#warning "xD"
|
||||
#pragma message WARN("xD")
|
||||
return new LazyLoadedImage(NULL);
|
||||
// return m_twitchEmoteFromCache->getOrAdd()
|
||||
}
|
||||
|
||||
LazyLoadedImage* Emotes::getCheerImage(long long amount, bool animated)
|
||||
{
|
||||
#warning "xD"
|
||||
#pragma message WARN("xD")
|
||||
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::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()
|
||||
{
|
||||
|
||||
|
@ -25,3 +32,15 @@ QFont& Fonts::getFont(Type type)
|
|||
|
||||
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
|
||||
#define FONTS_H
|
||||
|
||||
#include "QFont"
|
||||
#include <QFont>
|
||||
#include <QFontMetrics>
|
||||
|
||||
class Fonts
|
||||
{
|
||||
|
@ -16,6 +17,7 @@ public:
|
|||
};
|
||||
|
||||
static QFont& getFont(Type type);
|
||||
static QFontMetrics& getFontMetrics(Type type);
|
||||
|
||||
private:
|
||||
Fonts();
|
||||
|
@ -26,6 +28,13 @@ private:
|
|||
static QFont* small;
|
||||
static QFont* large;
|
||||
static QFont* veryLarge;
|
||||
|
||||
static QFontMetrics* metricsMedium;
|
||||
static QFontMetrics* metricsMediumBold;
|
||||
static QFontMetrics* metricsMediumItalic;
|
||||
static QFontMetrics* metricsSmall;
|
||||
static QFontMetrics* metricsLarge;
|
||||
static QFontMetrics* metricsVeryLarge;
|
||||
};
|
||||
|
||||
#endif // FONTS_H
|
||||
|
|
|
@ -22,7 +22,7 @@ QMutex* IrcManager::twitchBlockedUsersMutex = new QMutex();
|
|||
|
||||
IrcManager::IrcManager()
|
||||
{
|
||||
// account = Account::anon();
|
||||
|
||||
}
|
||||
|
||||
void IrcManager::connect()
|
||||
|
@ -160,7 +160,7 @@ void IrcManager::privateMessageReceived(IrcPrivateMessage *message)
|
|||
auto c = Channel::getChannel(message->target().mid(1));
|
||||
|
||||
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"
|
||||
|
||||
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_tooltip(tooltip)
|
||||
, m_animated(false)
|
||||
|
|
|
@ -25,8 +25,22 @@ public:
|
|||
bool animated() const { return m_animated; }
|
||||
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:
|
||||
QImage* m_image = NULL;
|
||||
QImage* m_image;
|
||||
qreal m_scale;
|
||||
|
||||
QString m_url;
|
||||
|
|
3
main.cpp
3
main.cpp
|
@ -1,8 +1,9 @@
|
|||
#include <QApplication>
|
||||
#include "mainwindow.h"
|
||||
#include "colorscheme.h"
|
||||
#include "ircmanager.h"
|
||||
#include "emojis.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QClipboard>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
|
208
message.cpp
208
message.cpp
|
@ -6,11 +6,18 @@
|
|||
#include "link.h"
|
||||
#include "appsettings.h"
|
||||
#include "ircmanager.h"
|
||||
#include "fonts.h"
|
||||
|
||||
#include <ctime>
|
||||
#include <tuple>
|
||||
#include <list>
|
||||
#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::badgeAdmin = new LazyLoadedImage(new QImage(":/images/admin_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]*");
|
||||
|
||||
Message::Message(const QString &text)
|
||||
: m_wordParts(new std::list<WordPart>())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Message::Message(const IrcPrivateMessage& ircMessage, const Channel& channel, bool enablePingSound,
|
||||
bool isReceivedWhisper, bool isSentWhisper, bool includeChannel )
|
||||
: m_wordParts(new std::list<WordPart>())
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
// timestamps
|
||||
iterator = ircMessage.tags().find("tmi-sent-ts");
|
||||
iterator = tags.find("tmi-sent-ts");
|
||||
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);
|
||||
}
|
||||
|
@ -57,13 +68,13 @@ Message::Message(const IrcPrivateMessage& ircMessage, const Channel& channel, bo
|
|||
strftime(timeStampBuffer, 69, "%H:%M:%S", localtime(&time));
|
||||
QString timestampWithSeconds = QString(timeStampBuffer);
|
||||
|
||||
words->append(Word(timestamp, Word::TimestampNoSeconds, ColorScheme::instance().SystemMessageColor, QString(), QString()));
|
||||
words->append(Word(timestampWithSeconds, Word::TimestampWithSeconds, ColorScheme::instance().SystemMessageColor, QString(), QString()));
|
||||
words.push_back(Word(timestamp, Word::TimestampNoSeconds, ColorScheme::instance().SystemMessageColor, QString(), QString()));
|
||||
words.push_back(Word(timestampWithSeconds, Word::TimestampWithSeconds, ColorScheme::instance().SystemMessageColor, QString(), QString()));
|
||||
|
||||
// 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(',');
|
||||
|
||||
|
@ -72,36 +83,36 @@ Message::Message(const IrcPrivateMessage& ircMessage, const Channel& channel, bo
|
|||
if (badge.startsWith("bits/"))
|
||||
{
|
||||
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")
|
||||
{
|
||||
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")
|
||||
{
|
||||
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")
|
||||
{
|
||||
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")
|
||||
{
|
||||
#warning "xD"
|
||||
words->append(Word(badgeTurbo, Word::BadgeModerator, QString(), QString("Channel Moderator"))); // custom badge
|
||||
#pragma message WARN("xD")
|
||||
words.push_back(Word(badgeTurbo, Word::BadgeModerator, QString(), QString("Channel Moderator"))); // custom badge
|
||||
}
|
||||
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")
|
||||
{
|
||||
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")
|
||||
{
|
||||
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
|
||||
QColor usernameColor = ColorScheme::instance().SystemMessageColor;
|
||||
|
||||
iterator = ircMessage.tags().find("color");
|
||||
if (iterator != ircMessage.tags().end())
|
||||
iterator = tags.find("color");
|
||||
if (iterator != tags.end())
|
||||
{
|
||||
usernameColor = QColor(iterator.value().toString());
|
||||
}
|
||||
|
@ -119,7 +130,7 @@ Message::Message(const IrcPrivateMessage& ircMessage, const Channel& channel, bo
|
|||
if (includeChannel)
|
||||
{
|
||||
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
|
||||
|
@ -127,9 +138,9 @@ Message::Message(const IrcPrivateMessage& ircMessage, const Channel& channel, bo
|
|||
|
||||
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();
|
||||
}
|
||||
|
@ -137,8 +148,8 @@ Message::Message(const IrcPrivateMessage& ircMessage, const Channel& channel, bo
|
|||
|
||||
QString displayName;
|
||||
|
||||
iterator = ircMessage.tags().find("display-name");
|
||||
if (iterator == ircMessage.tags().end()) {
|
||||
iterator = tags.find("display-name");
|
||||
if (iterator == tags.end()) {
|
||||
displayName = ircMessage.account();
|
||||
}
|
||||
else {
|
||||
|
@ -163,7 +174,7 @@ Message::Message(const IrcPrivateMessage& ircMessage, const Channel& channel, bo
|
|||
userDisplayString += ": ";
|
||||
}
|
||||
|
||||
words->append(Word(userDisplayString, Word::Username, usernameColor, userDisplayString, QString()));
|
||||
words.push_back(Word(userDisplayString, Word::Username, usernameColor, userDisplayString, QString()));
|
||||
|
||||
// highlights
|
||||
#pragma message WARN("xD")
|
||||
|
@ -171,18 +182,18 @@ Message::Message(const IrcPrivateMessage& ircMessage, const Channel& channel, bo
|
|||
// bits
|
||||
QString bits = "";
|
||||
|
||||
iterator = ircMessage.tags().find("bits");
|
||||
if (iterator != ircMessage.tags().end())
|
||||
iterator = tags.find("bits");
|
||||
if (iterator != tags.end())
|
||||
{
|
||||
bits = iterator.value().toString();
|
||||
}
|
||||
|
||||
// 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('/');
|
||||
|
||||
|
@ -211,7 +222,7 @@ Message::Message(const IrcPrivateMessage& ircMessage, const Channel& channel, bo
|
|||
|
||||
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)
|
||||
{
|
||||
words->append(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, Word::TwitchEmoteImage, 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;
|
||||
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* 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->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(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(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;
|
||||
}
|
||||
|
||||
// bttv / ffz emotes
|
||||
LazyLoadedImage* bttvEmote;
|
||||
|
||||
#pragma message WARN( "xD ignored emotes")
|
||||
if (
|
||||
#warning "xD ignored emotes"
|
||||
Emotes::bttvEmotes().tryGet(string, bttvEmote) ||
|
||||
channel.bttvChannelEmotes().tryGet(string, bttvEmote) ||
|
||||
Emotes::ffzEmotes().tryGet(string, bttvEmote) ||
|
||||
channel.ffzChannelEmotes().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;
|
||||
}
|
||||
|
@ -323,22 +334,131 @@ Message::Message(const IrcPrivateMessage& ircMessage, const Channel& channel, bo
|
|||
// actually just a word
|
||||
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;
|
||||
}
|
||||
|
||||
this->words() = words;
|
||||
this->m_words = words;
|
||||
|
||||
#warning "xD"
|
||||
#pragma message WARN("xD")
|
||||
// if (!isReceivedWhisper && AppSettings.HighlightIgnoredUsers.ContainsKey(Username))
|
||||
// {
|
||||
// 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
#warning "xD"
|
||||
#pragma message WARN("xD")
|
||||
return QString();
|
||||
}
|
||||
|
|
50
message.h
50
message.h
|
@ -1,29 +1,27 @@
|
|||
#ifndef MESSAGE_H
|
||||
#define MESSAGE_H
|
||||
|
||||
#include "IrcMessage"
|
||||
#include "word.h"
|
||||
#include "chrono"
|
||||
#include "wordpart.h"
|
||||
#include "channel.h"
|
||||
|
||||
#include <IrcMessage>
|
||||
#include <QVector>
|
||||
#include <chrono>
|
||||
|
||||
class Message
|
||||
{
|
||||
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 IrcPrivateMessage& ircMessage, const Channel& Channel, bool enablePingSound = true,
|
||||
bool isReceivedWhisper = false, bool isSentWhisper = false, bool includeChannel = false);
|
||||
|
||||
~Message() {
|
||||
if (m_wordParts != NULL) {
|
||||
delete m_wordParts;
|
||||
}
|
||||
}
|
||||
|
||||
bool canHighlightTab() const {
|
||||
return m_highlightTab;
|
||||
}
|
||||
|
@ -44,10 +42,14 @@ public:
|
|||
return m_displayName;
|
||||
}
|
||||
|
||||
QList<Word> words() const {
|
||||
const std::vector<Word> words() const {
|
||||
return m_words;
|
||||
}
|
||||
|
||||
const std::list<WordPart> wordParts() const {
|
||||
return *m_wordParts;
|
||||
}
|
||||
|
||||
bool disabled() const {
|
||||
return m_disabled;
|
||||
}
|
||||
|
@ -56,6 +58,16 @@ public:
|
|||
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:
|
||||
static LazyLoadedImage* badgeStaff;
|
||||
static LazyLoadedImage* badgeAdmin;
|
||||
|
@ -77,7 +89,15 @@ private:
|
|||
QString m_displayName = "";
|
||||
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);
|
||||
|
||||
|
|
5
word.cpp
5
word.cpp
|
@ -11,13 +11,14 @@ Word::Word(LazyLoadedImage* image, Type type, const QString& copytext, const QSt
|
|||
, m_color()
|
||||
, m_link(link)
|
||||
{
|
||||
image->width(); // professional segfault test
|
||||
}
|
||||
|
||||
// Text word
|
||||
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_isImage(true)
|
||||
, m_isImage(false)
|
||||
, m_type(type)
|
||||
, m_copyText(copytext)
|
||||
, m_tooltip(tooltip)
|
||||
|
|
49
word.h
49
word.h
|
@ -27,6 +27,7 @@ public:
|
|||
BttvGifEmoteText = 0x200,
|
||||
FfzEmoteImage = 0x400,
|
||||
FfzEmoteText = 0x800,
|
||||
EmoteImages = TwitchEmoteImage | BttvEmoteImage | BttvGifEmoteImage | FfzEmoteImage,
|
||||
|
||||
Bits = 0x1000,
|
||||
BitsAnimated = 0x2000,
|
||||
|
@ -75,30 +76,19 @@ public:
|
|||
return m_height;
|
||||
}
|
||||
|
||||
int x() const {
|
||||
return m_x;
|
||||
}
|
||||
|
||||
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);
|
||||
void setSize(int width, int height) {
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
}
|
||||
|
||||
bool isImage() const {
|
||||
return m_isImage;
|
||||
}
|
||||
|
||||
bool isText() const {
|
||||
return !m_isImage;
|
||||
}
|
||||
|
||||
const QString& copyText() const {
|
||||
return m_copyText;
|
||||
}
|
||||
|
@ -111,6 +101,10 @@ public:
|
|||
return Fonts::getFont(m_font);
|
||||
}
|
||||
|
||||
QFontMetrics& getFontMetrics() const {
|
||||
return Fonts::getFontMetrics(m_font);
|
||||
}
|
||||
|
||||
Type type() const {
|
||||
return m_type;
|
||||
}
|
||||
|
@ -127,6 +121,19 @@ public:
|
|||
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:
|
||||
LazyLoadedImage* m_image;
|
||||
QString m_text;
|
||||
|
@ -136,10 +143,12 @@ private:
|
|||
Type m_type;
|
||||
QString m_copyText;
|
||||
QString m_tooltip;
|
||||
int m_x;
|
||||
int m_y;
|
||||
|
||||
int m_width;
|
||||
int m_height;
|
||||
int m_xOffset;
|
||||
int m_yOffset;
|
||||
|
||||
bool m_hasTrailingSpace;
|
||||
Fonts::Type m_font = Fonts::Medium;
|
||||
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