Huge refactor

- Remove some underscore-prefixes
 - Start using this-> more
 - Remove a few of the singletons (We pass references to managers to
         things that need it now. Might not be much better, but for now
         it works. It also shows what places might be slightly wrong
         designed)
This commit is contained in:
Rasmus Karlsson 2017-06-13 21:13:58 +02:00
parent 55b04ee7eb
commit 59d383c161
37 changed files with 630 additions and 523 deletions

View file

@ -47,6 +47,7 @@ win32 {
SOURCES += \
src/main.cpp \
src/application.cpp \
src/channel.cpp \
src/colorscheme.cpp \
src/emojis.cpp \

42
src/application.cpp Normal file
View file

@ -0,0 +1,42 @@
#include "application.hpp"
#include "colorscheme.hpp"
#include "settingsmanager.hpp"
namespace chatterino {
Application::Application()
: windowManager(this->channelManager)
, emoteManager(this->windowManager, this->resources)
, resources(this->emoteManager, this->windowManager)
, channelManager(this->windowManager, this->emoteManager, this->ircManager)
, ircManager(this->channelManager, this->resources, this->emoteManager, this->windowManager)
{
// TODO(pajlada): Get rid of all singletons
ColorScheme::getInstance().init(this->windowManager);
// Initialize everything we need
this->emoteManager.loadGlobalEmotes();
// XXX
SettingsManager::getInstance().updateWordTypeMask();
this->windowManager.load();
}
Application::~Application()
{
this->windowManager.save();
}
int Application::run(QApplication &qtApp)
{
// Start connecting to the IRC Servers (Twitch only for now)
this->ircManager.connect();
// Show main window
this->windowManager.getMainWindow().show();
return qtApp.exec();
}
} // namespace chatterino

28
src/application.hpp Normal file
View file

@ -0,0 +1,28 @@
#pragma once
#include "channelmanager.hpp"
#include "emotemanager.hpp"
#include "ircmanager.hpp"
#include "resources.hpp"
#include "windowmanager.hpp"
#include <QApplication>
namespace chatterino {
class Application
{
public:
Application();
~Application();
int run(QApplication &qtApp);
WindowManager windowManager;
EmoteManager emoteManager;
Resources resources;
ChannelManager channelManager;
IrcManager ircManager;
};
} // namespace chatterino

View file

@ -3,7 +3,6 @@
#include "ircmanager.hpp"
#include "logging/loggingmanager.hpp"
#include "messages/message.hpp"
#include "util/urlfetch.hpp"
#include "windowmanager.hpp"
#include <QDebug>
@ -21,8 +20,12 @@ using namespace chatterino::messages;
namespace chatterino {
Channel::Channel(const QString &channel)
: _messages()
Channel::Channel(WindowManager &_windowManager, EmoteManager &_emoteManager,
IrcManager &_ircManager, const QString &channel, bool isSpecial)
: windowManager(_windowManager)
, emoteManager(_emoteManager)
, ircManager(_ircManager)
, _messages()
, _name((channel.length() > 0 && channel[0] == '#') ? channel.mid(1) : channel)
, _bttvChannelEmotes()
, _ffzChannelEmotes()
@ -33,7 +36,9 @@ Channel::Channel(const QString &channel)
{
qDebug() << "Open channel:" << channel << ". Name: " << _name;
printf("Channel pointer: %p\n", this);
reloadChannelEmotes();
if (!isSpecial) {
this->reloadChannelEmotes();
}
}
//
@ -121,82 +126,21 @@ void Channel::addMessage(std::shared_ptr<Message> message)
this->messageAppended(message);
WindowManager::getInstance().repaintVisibleChatWidgets(this);
this->windowManager.repaintVisibleChatWidgets(this);
}
// private methods
void Channel::reloadChannelEmotes()
{
reloadBttvEmotes();
reloadFfzEmotes();
printf("[Channel:%s] Reloading channel emotes\n", qPrintable(this->_name));
this->emoteManager.reloadBTTVChannelEmotes(this->_name, this->_bttvChannelEmotes);
this->emoteManager.reloadFFZChannelEmotes(this->_name, this->_ffzChannelEmotes);
}
void Channel::sendMessage(const QString &message)
{
qDebug() << "Channel send message: " << message;
IrcManager &instance = IrcManager::getInstance();
instance.sendMessage(_name, message);
}
void Channel::reloadBttvEmotes()
{
util::urlJsonFetch(
"https://api.betterttv.net/2/channels/" + _name, [this](QJsonObject &rootNode) {
auto emotesNode = rootNode.value("emotes").toArray();
QString linkTemplate = "https:" + rootNode.value("urlTemplate").toString();
for (const QJsonValue &emoteNode : emotesNode) {
QJsonObject emoteObject = emoteNode.toObject();
QString id = emoteObject.value("id").toString();
QString code = emoteObject.value("code").toString();
// emoteObject.value("imageType").toString();
QString link = linkTemplate;
link.detach();
link = link.replace("{{id}}", id).replace("{{image}}", "1x");
auto emote = EmoteManager::getInstance().getBttvChannelEmoteFromCaches().getOrAdd(
id, [&code, &link] {
return new LazyLoadedImage(link, 1, code, code + "\nChannel Bttv Emote");
});
this->getBttvChannelEmotes().insert(code, emote);
}
});
}
void Channel::reloadFfzEmotes()
{
util::urlJsonFetch("http://api.frankerfacez.com/v1/room/" + _name, [this](
QJsonObject &rootNode) {
auto setsNode = rootNode.value("sets").toObject();
for (const QJsonValue &setNode : setsNode) {
auto emotesNode = setNode.toObject().value("emoticons").toArray();
for (const QJsonValue &emoteNode : emotesNode) {
QJsonObject emoteObject = emoteNode.toObject();
// margins
int id = emoteObject.value("id").toInt();
QString code = emoteObject.value("name").toString();
QJsonObject urls = emoteObject.value("urls").toObject();
QString url1 = "http:" + urls.value("1").toString();
auto emote = EmoteManager::getInstance().getFfzChannelEmoteFromCaches().getOrAdd(
id, [&code, &url1] {
return new LazyLoadedImage(url1, 1, code, code + "\nGlobal Ffz Emote");
});
getFfzChannelEmotes().insert(code, emote);
}
}
});
this->ircManager.sendMessage(_name, message);
}
} // namespace chatterino

View file

@ -18,12 +18,15 @@ namespace messages {
class Message;
}
class ChannelManager;
class WindowManager;
class EmoteManager;
class IrcManager;
class Channel
{
public:
Channel(const QString &channel);
explicit Channel(WindowManager &_windowManager, EmoteManager &_emoteManager,
IrcManager &_ircManager, const QString &channel, bool isSpecial = false);
boost::signals2::signal<void(messages::SharedMessage &)> messageRemovedFromStart;
boost::signals2::signal<void(messages::SharedMessage &)> messageAppended;
@ -51,6 +54,10 @@ public:
void sendMessage(const QString &message);
private:
WindowManager &windowManager;
EmoteManager &emoteManager;
IrcManager &ircManager;
// variabeles
messages::LimitedQueue<messages::SharedMessage> _messages;
@ -69,10 +76,6 @@ private:
QString _streamStatus;
QString _streamGame;
// std::shared_ptr<logging::Channel> _loggingChannel;
// methods
void reloadBttvEmotes();
void reloadFfzEmotes();
};
} // namespace chatterino

View file

@ -3,14 +3,14 @@
namespace chatterino {
ChannelManager ChannelManager::instance;
ChannelManager::ChannelManager()
: _channels()
, _channelsMutex()
, _whispers(new Channel(QString("/whispers")))
, _mentions(new Channel(QString("/mentions")))
, _empty(new Channel(QString("")))
ChannelManager::ChannelManager(WindowManager &_windowManager, EmoteManager &_emoteManager,
IrcManager &_ircManager)
: windowManager(_windowManager)
, emoteManager(_emoteManager)
, ircManager(_ircManager)
, _whispers(new Channel(_windowManager, _emoteManager, _ircManager, "/whispers", true))
, _mentions(new Channel(_windowManager, _emoteManager, _ircManager, "/mentions", true))
, _empty(new Channel(_windowManager, _emoteManager, _ircManager, QString(), true))
{
}
@ -55,10 +55,11 @@ std::shared_ptr<Channel> ChannelManager::addChannel(const QString &channel)
auto it = _channels.find(channelName);
if (it == _channels.end()) {
auto channel = std::shared_ptr<Channel>(new Channel(channelName));
auto channel = std::shared_ptr<Channel>(
new Channel(this->windowManager, this->emoteManager, this->ircManager, channelName));
_channels.insert(channelName, std::make_tuple(channel, 1));
IrcManager::getInstance().joinChannel(channelName);
this->ircManager.joinChannel(channelName);
return channel;
}
@ -114,7 +115,7 @@ void ChannelManager::removeChannel(const QString &channel)
std::get<1>(a.value())--;
if (std::get<1>(a.value()) == 0) {
IrcManager::getInstance().partChannel(c);
this->ircManager.partChannel(c);
_channels.remove(c);
}
}

View file

@ -4,13 +4,15 @@
namespace chatterino {
class WindowManager;
class EmoteManager;
class IrcManager;
class ChannelManager
{
public:
static ChannelManager &getInstance()
{
return instance;
}
explicit ChannelManager(WindowManager &_windowManager, EmoteManager &_emoteManager,
IrcManager &_ircManager);
std::shared_ptr<Channel> getWhispers();
std::shared_ptr<Channel> getMentions();
@ -23,9 +25,9 @@ public:
void removeChannel(const QString &channel);
private:
static ChannelManager instance;
ChannelManager();
WindowManager &windowManager;
EmoteManager &emoteManager;
IrcManager &ircManager;
QMap<QString, std::tuple<std::shared_ptr<Channel>, int>> _channels;
QMutex _channelsMutex;

View file

@ -8,20 +8,25 @@
namespace chatterino {
void ColorScheme::init()
void ColorScheme::init(WindowManager &windowManager)
{
static bool initiated = false;
if (!initiated) {
initiated = true;
ColorScheme::getInstance().update();
SettingsManager::getInstance().theme.valueChanged.connect(
[](const QString &) { ColorScheme::getInstance().update(); });
SettingsManager::getInstance().themeHue.valueChanged.connect(
[](const float &) { ColorScheme::getInstance().update(); });
ColorScheme::getInstance().updated.connect(
[] { WindowManager::getInstance().repaintVisibleChatWidgets(); });
SettingsManager::getInstance().theme.valueChanged.connect([](const QString &) {
ColorScheme::getInstance().update(); //
});
SettingsManager::getInstance().themeHue.valueChanged.connect([](const float &) {
ColorScheme::getInstance().update(); //
});
ColorScheme::getInstance().updated.connect([&windowManager] {
windowManager.repaintVisibleChatWidgets(); //
});
}
}

View file

@ -6,6 +6,8 @@
namespace chatterino {
class WindowManager;
class ColorScheme
{
public:
@ -67,7 +69,7 @@ public:
return instance;
}
void init();
void init(WindowManager &windowManager);
void normalizeColor(QColor &color);
void update();

View file

@ -46,8 +46,14 @@ void Emojis::parseEmojis(std::vector<std::tuple<messages::LazyLoadedImage *, QSt
}
vector.push_back(std::tuple<messages::LazyLoadedImage *, QString>(
imageCache.getOrAdd(
url, [&url] { return new messages::LazyLoadedImage(url, 0.35); }),
imageCache.getOrAdd(url,
[/*&url*/] {
/* TODO: re-implement
return new messages::LazyLoadedImage(url,
0.35); //
*/
return nullptr;
}),
QString()));
i += j - 1;

View file

@ -1,5 +1,7 @@
#include "emotemanager.hpp"
#include "resources.hpp"
#include "util/urlfetch.hpp"
#include "windowmanager.hpp"
#include <QDebug>
#include <QJsonArray>
@ -18,22 +20,92 @@ using namespace chatterino::messages;
namespace chatterino {
EmoteManager EmoteManager::instance;
EmoteManager::EmoteManager()
: _twitchEmotes()
, _bttvEmotes()
, _ffzEmotes()
, _chatterinoEmotes()
, _bttvChannelEmoteFromCaches()
, _ffzChannelEmoteFromCaches()
, _twitchEmoteFromCache()
, _miscImageFromCache()
, _gifUpdateTimerSignal()
, _gifUpdateTimer()
, _gifUpdateTimerInitiated(false)
, _generation(0)
EmoteManager::EmoteManager(WindowManager &_windowManager, Resources &_resources)
: windowManager(_windowManager)
, resources(_resources)
{
// Note: Do not use this->resources in ctor
}
void EmoteManager::loadGlobalEmotes()
{
this->loadBTTVEmotes();
this->loadFFZEmotes();
}
void EmoteManager::reloadBTTVChannelEmotes(const QString &channelName,
BTTVEmoteMap &channelEmoteMap)
{
printf("[EmoteManager] Reload BTTV Channel Emotes for channel %s\n", qPrintable(channelName));
QString url("https://api.betterttv.net/2/channels/" + channelName);
util::urlJsonFetch(url, [this, &channelEmoteMap](QJsonObject &rootNode) {
channelEmoteMap.clear();
auto emotesNode = rootNode.value("emotes").toArray();
QString linkTemplate = "https:" + rootNode.value("urlTemplate").toString();
for (const QJsonValue &emoteNode : emotesNode) {
QJsonObject emoteObject = emoteNode.toObject();
QString id = emoteObject.value("id").toString();
QString code = emoteObject.value("code").toString();
// emoteObject.value("imageType").toString();
QString link = linkTemplate;
link.detach();
link = link.replace("{{id}}", id).replace("{{image}}", "1x");
auto emote = this->getBTTVChannelEmoteFromCaches().getOrAdd(id, [this, &code, &link] {
return new LazyLoadedImage(*this, this->windowManager, link, 1, code,
code + "\nChannel BTTV Emote");
});
this->bttvChannelEmotes.insert(code, emote);
channelEmoteMap.insert(code, emote);
}
});
}
void EmoteManager::reloadFFZChannelEmotes(
const QString &channelName,
ConcurrentMap<QString, messages::LazyLoadedImage *> &channelEmoteMap)
{
printf("[EmoteManager] Reload FFZ Channel Emotes for channel %s\n", qPrintable(channelName));
QString url("http://api.frankerfacez.com/v1/room/" + channelName);
util::urlJsonFetch(url, [this, &channelEmoteMap](QJsonObject &rootNode) {
channelEmoteMap.clear();
auto setsNode = rootNode.value("sets").toObject();
for (const QJsonValue &setNode : setsNode) {
auto emotesNode = setNode.toObject().value("emoticons").toArray();
for (const QJsonValue &emoteNode : emotesNode) {
QJsonObject emoteObject = emoteNode.toObject();
// margins
int id = emoteObject.value("id").toInt();
QString code = emoteObject.value("name").toString();
QJsonObject urls = emoteObject.value("urls").toObject();
QString url1 = "http:" + urls.value("1").toString();
auto emote =
this->getFFZChannelEmoteFromCaches().getOrAdd(id, [this, &code, &url1] {
return new LazyLoadedImage(*this, this->windowManager, url1, 1, code,
code + "\nGlobal FFZ Emote");
});
this->ffzChannelEmotes.insert(code, emote);
channelEmoteMap.insert(code, emote);
}
}
});
}
ConcurrentMap<QString, twitch::EmoteValue *> &EmoteManager::getTwitchEmotes()
@ -41,12 +113,12 @@ ConcurrentMap<QString, twitch::EmoteValue *> &EmoteManager::getTwitchEmotes()
return _twitchEmotes;
}
ConcurrentMap<QString, messages::LazyLoadedImage *> &EmoteManager::getBttvEmotes()
ConcurrentMap<QString, messages::LazyLoadedImage *> &EmoteManager::getBTTVEmotes()
{
return _bttvEmotes;
}
ConcurrentMap<QString, messages::LazyLoadedImage *> &EmoteManager::getFfzEmotes()
ConcurrentMap<QString, messages::LazyLoadedImage *> &EmoteManager::getFFZEmotes()
{
return _ffzEmotes;
}
@ -56,12 +128,12 @@ ConcurrentMap<QString, messages::LazyLoadedImage *> &EmoteManager::getChatterino
return _chatterinoEmotes;
}
ConcurrentMap<QString, messages::LazyLoadedImage *> &EmoteManager::getBttvChannelEmoteFromCaches()
ConcurrentMap<QString, messages::LazyLoadedImage *> &EmoteManager::getBTTVChannelEmoteFromCaches()
{
return _bttvChannelEmoteFromCaches;
}
ConcurrentMap<int, messages::LazyLoadedImage *> &EmoteManager::getFfzChannelEmoteFromCaches()
ConcurrentMap<int, messages::LazyLoadedImage *> &EmoteManager::getFFZChannelEmoteFromCaches()
{
return _ffzChannelEmoteFromCaches;
}
@ -76,13 +148,7 @@ ConcurrentMap<QString, messages::LazyLoadedImage *> &EmoteManager::getMiscImageF
return _miscImageFromCache;
}
void EmoteManager::loadGlobalEmotes()
{
loadBttvEmotes();
loadFfzEmotes();
}
void EmoteManager::loadBttvEmotes()
void EmoteManager::loadBTTVEmotes()
{
// bttv
QNetworkAccessManager *manager = new QNetworkAccessManager();
@ -111,8 +177,9 @@ void EmoteManager::loadBttvEmotes()
tmp.detach();
QString url = tmp.replace("{{id}}", id).replace("{{image}}", "1x");
EmoteManager::getBttvEmotes().insert(
code, new LazyLoadedImage(url, 1, code, code + "\nGlobal Bttv Emote"));
EmoteManager::getBTTVEmotes().insert(
code, new LazyLoadedImage(*this, this->windowManager, url, 1, code,
code + "\nGlobal BTTV Emote"));
}
}
@ -121,7 +188,7 @@ void EmoteManager::loadBttvEmotes()
});
}
void EmoteManager::loadFfzEmotes()
void EmoteManager::loadFFZEmotes()
{
// ffz
QNetworkAccessManager *manager = new QNetworkAccessManager();
@ -153,8 +220,9 @@ void EmoteManager::loadFfzEmotes()
QJsonObject urls = object.value("urls").toObject();
QString url1 = "http:" + urls.value("1").toString();
EmoteManager::getBttvEmotes().insert(
code, new LazyLoadedImage(url1, 1, code, code + "\nGlobal Ffz Emote"));
EmoteManager::getBTTVEmotes().insert(
code, new LazyLoadedImage(*this, this->windowManager, url1, 1, code,
code + "\nGlobal FFZ Emote"));
}
}
}
@ -166,11 +234,12 @@ void EmoteManager::loadFfzEmotes()
LazyLoadedImage *EmoteManager::getTwitchEmoteById(const QString &name, long id)
{
return EmoteManager::_twitchEmoteFromCache.getOrAdd(id, [&name, &id] {
return EmoteManager::_twitchEmoteFromCache.getOrAdd(id, [this, &name, &id] {
qDebug() << "added twitch emote: " << id;
qreal scale;
QString url = getTwitchEmoteLink(id, scale);
return new LazyLoadedImage(url, scale, name, name + "\nTwitch Emote");
return new LazyLoadedImage(*this, this->windowManager, url, scale, name,
name + "\nTwitch Emote");
});
}
@ -188,24 +257,41 @@ QString EmoteManager::getTwitchEmoteLink(long id, qreal &scale)
LazyLoadedImage *EmoteManager::getCheerImage(long long amount, bool animated)
{
// TODO: fix this xD
return getCheerBadge(amount);
return this->getCheerBadge(amount);
}
LazyLoadedImage *EmoteManager::getCheerBadge(long long amount)
{
if (amount >= 100000) {
return Resources::getCheerBadge100000();
return this->resources.cheerBadge100000;
} else if (amount >= 10000) {
return Resources::getCheerBadge10000();
return this->resources.cheerBadge10000;
} else if (amount >= 5000) {
return Resources::getCheerBadge5000();
return this->resources.cheerBadge5000;
} else if (amount >= 1000) {
return Resources::getCheerBadge1000();
return this->resources.cheerBadge1000;
} else if (amount >= 100) {
return Resources::getCheerBadge100();
return this->resources.cheerBadge100;
} else {
return Resources::getCheerBadge1();
return this->resources.cheerBadge1;
}
}
boost::signals2::signal<void()> &EmoteManager::getGifUpdateSignal()
{
if (!_gifUpdateTimerInitiated) {
_gifUpdateTimerInitiated = true;
_gifUpdateTimer.setInterval(30);
_gifUpdateTimer.start();
QObject::connect(&_gifUpdateTimer, &QTimer::timeout, [this] {
_gifUpdateTimerSignal();
this->windowManager.repaintGifEmotes();
});
}
return _gifUpdateTimerSignal;
}
} // namespace chatterino

View file

@ -5,7 +5,6 @@
#include "concurrentmap.hpp"
#include "messages/lazyloadedimage.hpp"
#include "twitch/emotevalue.hpp"
#include "windowmanager.hpp"
#include <QMap>
#include <QMutex>
@ -13,25 +12,33 @@
#include <boost/signals2.hpp>
namespace chatterino {
class WindowManager;
class Resources;
class EmoteManager
{
public:
static EmoteManager &getInstance()
{
return instance;
}
using FFZEmoteMap = ConcurrentMap<QString, messages::LazyLoadedImage *>;
using BTTVEmoteMap = ConcurrentMap<QString, messages::LazyLoadedImage *>;
using ChatterinoEmoteMap = ConcurrentMap<QString, messages::LazyLoadedImage *>;
ConcurrentMap<QString, twitch::EmoteValue *> &getTwitchEmotes();
ConcurrentMap<QString, messages::LazyLoadedImage *> &getBttvEmotes();
ConcurrentMap<QString, messages::LazyLoadedImage *> &getFfzEmotes();
ConcurrentMap<QString, messages::LazyLoadedImage *> &getChatterinoEmotes();
ConcurrentMap<QString, messages::LazyLoadedImage *> &getBttvChannelEmoteFromCaches();
ConcurrentMap<int, messages::LazyLoadedImage *> &getFfzChannelEmoteFromCaches();
ConcurrentMap<long, messages::LazyLoadedImage *> &getTwitchEmoteFromCache();
ConcurrentMap<QString, messages::LazyLoadedImage *> &getMiscImageFromCache();
EmoteManager(WindowManager &_windowManager, Resources &_resources);
void loadGlobalEmotes();
void reloadBTTVChannelEmotes(const QString &channelName, BTTVEmoteMap &channelEmoteMap);
void reloadFFZChannelEmotes(const QString &channelName, FFZEmoteMap &channelEmoteMap);
ConcurrentMap<QString, twitch::EmoteValue *> &getTwitchEmotes();
ConcurrentMap<QString, messages::LazyLoadedImage *> &getBTTVEmotes();
ConcurrentMap<QString, messages::LazyLoadedImage *> &getFFZEmotes();
ConcurrentMap<QString, messages::LazyLoadedImage *> &getChatterinoEmotes();
ConcurrentMap<QString, messages::LazyLoadedImage *> &getBTTVChannelEmoteFromCaches();
ConcurrentMap<int, messages::LazyLoadedImage *> &getFFZChannelEmoteFromCaches();
ConcurrentMap<long, messages::LazyLoadedImage *> &getTwitchEmoteFromCache();
ConcurrentMap<QString, messages::LazyLoadedImage *> &getMiscImageFromCache();
messages::LazyLoadedImage *getCheerImage(long long int amount, bool animated);
messages::LazyLoadedImage *getCheerBadge(long long int amount);
@ -47,29 +54,15 @@ public:
_generation++;
}
boost::signals2::signal<void()> &getGifUpdateSignal()
{
if (!_gifUpdateTimerInitiated) {
_gifUpdateTimerInitiated = true;
_gifUpdateTimer.setInterval(30);
_gifUpdateTimer.start();
QObject::connect(&_gifUpdateTimer, &QTimer::timeout, [this] {
_gifUpdateTimerSignal();
WindowManager::getInstance().repaintGifEmotes();
});
}
return _gifUpdateTimerSignal;
}
boost::signals2::signal<void()> &getGifUpdateSignal();
private:
static EmoteManager instance;
WindowManager &windowManager;
Resources &resources;
EmoteManager();
ConcurrentMap<QString, messages::LazyLoadedImage *> bttvChannelEmotes;
ConcurrentMap<QString, messages::LazyLoadedImage *> ffzChannelEmotes;
// variables
ConcurrentMap<QString, twitch::EmoteValue *> _twitchEmotes;
ConcurrentMap<QString, messages::LazyLoadedImage *> _bttvEmotes;
ConcurrentMap<QString, messages::LazyLoadedImage *> _ffzEmotes;
@ -81,15 +74,15 @@ private:
boost::signals2::signal<void()> _gifUpdateTimerSignal;
QTimer _gifUpdateTimer;
bool _gifUpdateTimerInitiated;
bool _gifUpdateTimerInitiated = false;
int _generation;
int _generation = 0;
// methods
static QString getTwitchEmoteLink(long id, qreal &scale);
void loadFfzEmotes();
void loadBttvEmotes();
void loadFFZEmotes();
void loadBTTVEmotes();
};
} // namespace chatterino

View file

@ -3,14 +3,15 @@
#include "asyncexec.hpp"
#include "channel.hpp"
#include "channelmanager.hpp"
#include "emotemanager.hpp"
#include "messages/messageparseargs.hpp"
#include "twitch/twitchmessagebuilder.hpp"
#include "twitch/twitchparsemessage.hpp"
#include "twitch/twitchuser.hpp"
#include "windowmanager.hpp"
#include <irccommand.h>
#include <ircconnection.h>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
@ -23,12 +24,15 @@ using namespace chatterino::messages;
namespace chatterino {
IrcManager IrcManager::instance;
const QString IrcManager::defaultClientId("7ue61iz46fz11y3cugd0l3tawb4taal");
IrcManager::IrcManager()
: _account(AccountManager::getInstance().getTwitchUser())
IrcManager::IrcManager(ChannelManager &_channelManager, Resources &_resources,
EmoteManager &_emoteManager, WindowManager &_windowManager)
: channelManager(_channelManager)
, resources(_resources)
, emoteManager(_emoteManager)
, windowManager(_windowManager)
, _account(AccountManager::getInstance().getTwitchUser())
{
}
@ -168,7 +172,7 @@ void IrcManager::beginConnecting()
this->writeConnection->moveToThread(QCoreApplication::instance()->thread());
this->readConnection->moveToThread(QCoreApplication::instance()->thread());
for (auto &channel : ChannelManager::getInstance().getItems()) {
for (auto &channel : this->channelManager.getItems()) {
this->writeConnection->sendRaw("JOIN #" + channel->getName());
this->readConnection->sendRaw("JOIN #" + channel->getName());
}
@ -231,12 +235,14 @@ void IrcManager::partChannel(const QString &channelName)
void IrcManager::messageReceived(Communi::IrcMessage *message)
{
/*
qDebug() << "Message received: " << message->command();
// qInfo(message->command().toStdString().c_str());
//
for (const auto &param : message->parameters()) {
qDebug() << "Param: " << param;
}
*/
/*
const QString &command = message->command();
@ -252,12 +258,13 @@ void IrcManager::messageReceived(Communi::IrcMessage *message)
void IrcManager::privateMessageReceived(Communi::IrcPrivateMessage *message)
{
auto c = ChannelManager::getInstance().getChannel(message->target().mid(1));
auto c = this->channelManager.getChannel(message->target().mid(1));
if (c != nullptr) {
messages::MessageParseArgs args;
c->addMessage(twitch::TwitchMessageBuilder::parse(message, c.get(), args));
c->addMessage(twitch::TwitchMessageBuilder::parse(message, c.get(), args, this->resources,
this->emoteManager, this->windowManager));
}
}

View file

@ -16,15 +16,18 @@
namespace chatterino {
class ChannelManager;
class Resources;
class EmoteManager;
class WindowManager;
class IrcManager : public QObject
{
Q_OBJECT
public:
static IrcManager &getInstance()
{
return instance;
}
IrcManager(ChannelManager &_channelManager, Resources &_resources, EmoteManager &_emoteManager,
WindowManager &_windowManager);
static const QString defaultClientId;
@ -48,8 +51,10 @@ public:
void setUser(const twitch::TwitchUser &account);
private:
static IrcManager instance;
IrcManager();
ChannelManager &channelManager;
Resources &resources;
EmoteManager &emoteManager;
WindowManager &windowManager;
// variables
twitch::TwitchUser _account;

View file

@ -1,3 +1,4 @@
#include "application.hpp"
#include "channelmanager.hpp"
#include "colorscheme.hpp"
#include "emojis.hpp"
@ -16,9 +17,6 @@
#include <boost/signals2.hpp>
#include <pajlada/settings/settingmanager.hpp>
using namespace chatterino;
using namespace chatterino::widgets;
namespace {
inline bool initSettings(bool portable)
@ -68,28 +66,25 @@ int main(int argc, char *argv[])
}
chatterino::logging::init();
SettingsManager::getInstance().load();
Resources::load();
Emojis::loadEmojis();
EmoteManager::getInstance().loadGlobalEmotes();
chatterino::SettingsManager::getInstance().load();
chatterino::Emojis::loadEmojis();
ColorScheme::getInstance().init();
int ret = 0;
WindowManager::getInstance().load();
{
// Initialize application
chatterino::Application app;
MainWindow &w = WindowManager::getInstance().getMainWindow();
w.show();
// Start the application
ret = app.run(a);
IrcManager::getInstance().connect();
// Application will go out of scope here and deinitialize itself
}
int ret = a.exec();
SettingsManager::getInstance().save();
chatterino::SettingsManager::getInstance().save();
// Save settings
pajlada::Settings::SettingManager::save();
WindowManager::getInstance().save();
return ret;
}

View file

@ -1,5 +1,4 @@
#include "messages/lazyloadedimage.hpp"
#include "asyncexec.hpp"
#include "emotemanager.hpp"
#include "ircmanager.hpp"
@ -18,15 +17,15 @@
namespace chatterino {
namespace messages {
LazyLoadedImage::LazyLoadedImage(const QString &url, qreal scale, const QString &name,
LazyLoadedImage::LazyLoadedImage(EmoteManager &_emoteManager, WindowManager &_windowManager,
const QString &url, qreal scale, const QString &name,
const QString &tooltip, const QMargins &margin, bool isHat)
: _currentPixmap(nullptr)
, _currentFrame(0)
, _currentFrameOffset(0)
: emoteManager(_emoteManager)
, windowManager(_windowManager)
, _currentPixmap(nullptr)
, _url(url)
, _name(name)
, _tooltip(tooltip)
, _animated(false)
, _margin(margin)
, _ishat(isHat)
, _scale(scale)
@ -34,14 +33,14 @@ LazyLoadedImage::LazyLoadedImage(const QString &url, qreal scale, const QString
{
}
LazyLoadedImage::LazyLoadedImage(QPixmap *image, qreal scale, const QString &name,
LazyLoadedImage::LazyLoadedImage(EmoteManager &_emoteManager, WindowManager &_windowManager,
QPixmap *image, qreal scale, const QString &name,
const QString &tooltip, const QMargins &margin, bool isHat)
: _currentPixmap(image)
, _currentFrame(0)
, _currentFrameOffset(0)
: emoteManager(_emoteManager)
, windowManager(_windowManager)
, _currentPixmap(image)
, _name(name)
, _tooltip(tooltip)
, _animated(false)
, _margin(margin)
, _ishat(isHat)
, _scale(scale)
@ -81,11 +80,13 @@ void LazyLoadedImage::loadImage()
if (_allFrames.size() > 1) {
_animated = true;
EmoteManager::getInstance().getGifUpdateSignal().connect([this] { gifUpdateTimout(); });
this->emoteManager.getGifUpdateSignal().connect([this] {
gifUpdateTimout(); //
});
}
EmoteManager::getInstance().incGeneration();
WindowManager::getInstance().layoutVisibleChatWidgets();
this->emoteManager.incGeneration();
this->windowManager.layoutVisibleChatWidgets();
});
}

View file

@ -4,15 +4,24 @@
#include <QString>
namespace chatterino {
class EmoteManager;
class WindowManager;
namespace messages {
class LazyLoadedImage : QObject
{
public:
explicit LazyLoadedImage(const QString &_url, qreal _scale = 1, const QString &_name = "",
LazyLoadedImage() = delete;
explicit LazyLoadedImage(EmoteManager &_emoteManager, WindowManager &_windowManager,
const QString &_url, qreal _scale = 1, const QString &_name = "",
const QString &_tooltip = "", const QMargins &_margin = QMargins(),
bool isHat = false);
explicit LazyLoadedImage(QPixmap *_currentPixmap, qreal _scale = 1, const QString &_name = "",
explicit LazyLoadedImage(EmoteManager &_emoteManager, WindowManager &_windowManager,
QPixmap *_currentPixmap, qreal _scale = 1, const QString &_name = "",
const QString &_tooltip = "", const QMargins &_margin = QMargins(),
bool isHat = false);
@ -78,6 +87,9 @@ public:
}
private:
EmoteManager &emoteManager;
WindowManager &windowManager;
struct FrameData {
QPixmap *image;
int duration;
@ -85,13 +97,13 @@ private:
QPixmap *_currentPixmap;
std::vector<FrameData> _allFrames;
int _currentFrame;
int _currentFrameOffset;
int _currentFrame = 0;
int _currentFrameOffset = 0;
QString _url;
QString _name;
QString _tooltip;
bool _animated;
bool _animated = false;
QMargins _margin;
bool _ishat;
qreal _scale;

View file

@ -21,16 +21,16 @@ namespace chatterino {
namespace messages {
Message::Message(const QString &text)
: _words()
, _text(text)
: _text(text)
, _words()
{
_words.push_back(
Word(text, Word::Text, ColorScheme::getInstance().SystemMessageColor, text, QString()));
}
Message::Message(const QString &text, const std::vector<Word> &words)
: _words(words)
, _text(text)
: _text(text)
, _words(words)
{
}

View file

@ -23,8 +23,8 @@ typedef std::shared_ptr<Message> SharedMessage;
class Message
{
public:
Message(const QString &text);
Message(const QString &text, const std::vector<messages::Word> &words);
explicit Message(const QString &text);
explicit Message(const QString &text, const std::vector<messages::Word> &words);
bool getCanHighlightTab() const;
const QString &getTimeoutUser() const;

View file

@ -41,7 +41,11 @@ bool MessageRef::layout(int width, bool enableEmoteMargins)
int mediumTextLineHeight =
FontManager::getInstance().getFontMetrics(FontManager::Medium).height();
/* TODO(pajlada): Re-implement
bool recalculateImages = _emoteGeneration != EmoteManager::getInstance().getGeneration();
*/
bool recalculateImages = true;
bool recalculateText = _fontGeneration != FontManager::getInstance().getGeneration();
bool newWordTypes = _currentWordTypes != SettingsManager::getInstance().getWordTypeMask();
@ -53,7 +57,7 @@ bool MessageRef::layout(int width, bool enableEmoteMargins)
return false;
}
_emoteGeneration = EmoteManager::getInstance().getGeneration();
// _emoteGeneration = EmoteManager::getInstance().getGeneration();
_fontGeneration = FontManager::getInstance().getGeneration();
for (auto &word : _message->getWords()) {

View file

@ -1,60 +1,39 @@
#include "resources.hpp"
#include "emotemanager.hpp"
#include "windowmanager.hpp"
#include <QPixmap>
namespace chatterino {
messages::LazyLoadedImage *Resources::badgeStaff(nullptr);
messages::LazyLoadedImage *Resources::badgeAdmin(nullptr);
messages::LazyLoadedImage *Resources::badgeModerator(nullptr);
messages::LazyLoadedImage *Resources::badgeGlobalmod(nullptr);
messages::LazyLoadedImage *Resources::badgeTurbo(nullptr);
messages::LazyLoadedImage *Resources::badgeBroadcaster(nullptr);
messages::LazyLoadedImage *Resources::badgePremium(nullptr);
namespace {
messages::LazyLoadedImage *Resources::cheerBadge100000(nullptr);
messages::LazyLoadedImage *Resources::cheerBadge10000(nullptr);
messages::LazyLoadedImage *Resources::cheerBadge5000(nullptr);
messages::LazyLoadedImage *Resources::cheerBadge1000(nullptr);
messages::LazyLoadedImage *Resources::cheerBadge100(nullptr);
messages::LazyLoadedImage *Resources::cheerBadge1(nullptr);
messages::LazyLoadedImage *Resources::buttonBan(nullptr);
messages::LazyLoadedImage *Resources::buttonTimeout(nullptr);
Resources::Resources()
inline messages::LazyLoadedImage *lli(EmoteManager &emoteManager, WindowManager &windowManager,
const char *pixmapPath, qreal scale = 1)
{
return new messages::LazyLoadedImage(emoteManager, windowManager, new QPixmap(pixmapPath),
scale);
}
void Resources::load()
} // namespace
Resources::Resources(EmoteManager &emoteManager, WindowManager &windowManager)
: badgeStaff(lli(emoteManager, windowManager, ":/images/staff_bg.png"))
, badgeAdmin(lli(emoteManager, windowManager, ":/images/admin_bg.png"))
, badgeGlobalModerator(lli(emoteManager, windowManager, ":/images/globalmod_bg.png"))
, badgeModerator(lli(emoteManager, windowManager, ":/images/moderator_bg.png"))
, badgeTurbo(lli(emoteManager, windowManager, ":/images/turbo_bg.png"))
, badgeBroadcaster(lli(emoteManager, windowManager, ":/images/broadcaster_bg.png"))
, badgePremium(lli(emoteManager, windowManager, ":/images/twitchprime_bg.png"))
, cheerBadge100000(lli(emoteManager, windowManager, ":/images/cheer100000"))
, cheerBadge10000(lli(emoteManager, windowManager, ":/images/cheer10000"))
, cheerBadge5000(lli(emoteManager, windowManager, ":/images/cheer5000"))
, cheerBadge1000(lli(emoteManager, windowManager, ":/images/cheer1000"))
, cheerBadge100(lli(emoteManager, windowManager, ":/images/cheer100"))
, cheerBadge1(lli(emoteManager, windowManager, ":/images/cheer1"))
, buttonBan(lli(emoteManager, windowManager, ":/images/button_ban.png", 0.25))
, buttonTimeout(lli(emoteManager, windowManager, ":/images/button_timeout.png", 0.25))
{
// badges
Resources::badgeStaff = new messages::LazyLoadedImage(new QPixmap(":/images/staff_bg.png"));
Resources::badgeAdmin = new messages::LazyLoadedImage(new QPixmap(":/images/admin_bg.png"));
Resources::badgeModerator =
new messages::LazyLoadedImage(new QPixmap(":/images/moderator_bg.png"));
Resources::badgeGlobalmod =
new messages::LazyLoadedImage(new QPixmap(":/images/globalmod_bg.png"));
Resources::badgeTurbo = new messages::LazyLoadedImage(new QPixmap(":/images/turbo_bg.png"));
Resources::badgeBroadcaster =
new messages::LazyLoadedImage(new QPixmap(":/images/broadcaster_bg.png"));
Resources::badgePremium =
new messages::LazyLoadedImage(new QPixmap(":/images/twitchprime_bg.png"));
// cheer badges
Resources::cheerBadge100000 =
new messages::LazyLoadedImage(new QPixmap(":/images/cheer100000"));
Resources::cheerBadge10000 = new messages::LazyLoadedImage(new QPixmap(":/images/cheer10000"));
Resources::cheerBadge5000 = new messages::LazyLoadedImage(new QPixmap(":/images/cheer5000"));
Resources::cheerBadge1000 = new messages::LazyLoadedImage(new QPixmap(":/images/cheer1000"));
Resources::cheerBadge100 = new messages::LazyLoadedImage(new QPixmap(":/images/cheer100"));
Resources::cheerBadge1 = new messages::LazyLoadedImage(new QPixmap(":/images/cheer1"));
// button
Resources::buttonBan =
new messages::LazyLoadedImage(new QPixmap(":/images/button_ban.png"), 0.25);
Resources::buttonTimeout =
new messages::LazyLoadedImage(new QPixmap(":/images/button_timeout.png"), 0.25);
}
} // namespace chatterino

View file

@ -4,108 +4,31 @@
namespace chatterino {
class EmoteManager;
class WindowManager;
class Resources
{
public:
static void load();
explicit Resources(EmoteManager &emoteManager, WindowManager &windowManager);
// badges
static messages::LazyLoadedImage *getBadgeStaff()
{
return badgeStaff;
}
messages::LazyLoadedImage *badgeStaff;
messages::LazyLoadedImage *badgeAdmin;
messages::LazyLoadedImage *badgeGlobalModerator;
messages::LazyLoadedImage *badgeModerator;
messages::LazyLoadedImage *badgeTurbo;
messages::LazyLoadedImage *badgeBroadcaster;
messages::LazyLoadedImage *badgePremium;
static messages::LazyLoadedImage *getBadgeAdmin()
{
return badgeAdmin;
}
messages::LazyLoadedImage *cheerBadge100000;
messages::LazyLoadedImage *cheerBadge10000;
messages::LazyLoadedImage *cheerBadge5000;
messages::LazyLoadedImage *cheerBadge1000;
messages::LazyLoadedImage *cheerBadge100;
messages::LazyLoadedImage *cheerBadge1;
static messages::LazyLoadedImage *getBadgeGlobalmod()
{
return badgeGlobalmod;
}
static messages::LazyLoadedImage *getBadgeModerator()
{
return badgeModerator;
}
static messages::LazyLoadedImage *getBadgeTurbo()
{
return badgeTurbo;
}
static messages::LazyLoadedImage *getBadgeBroadcaster()
{
return badgeBroadcaster;
}
static messages::LazyLoadedImage *getBadgePremium()
{
return badgePremium;
}
// cheer badges
static messages::LazyLoadedImage *getCheerBadge100000()
{
return cheerBadge100000;
}
static messages::LazyLoadedImage *getCheerBadge10000()
{
return cheerBadge10000;
}
static messages::LazyLoadedImage *getCheerBadge5000()
{
return cheerBadge5000;
}
static messages::LazyLoadedImage *getCheerBadge1000()
{
return cheerBadge1000;
}
static messages::LazyLoadedImage *getCheerBadge100()
{
return cheerBadge100;
}
static messages::LazyLoadedImage *getCheerBadge1()
{
return cheerBadge1;
}
static messages::LazyLoadedImage *getButtonBan()
{
return buttonBan;
}
static messages::LazyLoadedImage *getButtonTimeout()
{
return buttonTimeout;
}
private:
Resources();
static messages::LazyLoadedImage *badgeStaff;
static messages::LazyLoadedImage *badgeAdmin;
static messages::LazyLoadedImage *badgeGlobalmod;
static messages::LazyLoadedImage *badgeModerator;
static messages::LazyLoadedImage *badgeTurbo;
static messages::LazyLoadedImage *badgeBroadcaster;
static messages::LazyLoadedImage *badgePremium;
static messages::LazyLoadedImage *cheerBadge100000;
static messages::LazyLoadedImage *cheerBadge10000;
static messages::LazyLoadedImage *cheerBadge5000;
static messages::LazyLoadedImage *cheerBadge1000;
static messages::LazyLoadedImage *cheerBadge100;
static messages::LazyLoadedImage *cheerBadge1;
static messages::LazyLoadedImage *buttonBan;
static messages::LazyLoadedImage *buttonTimeout;
messages::LazyLoadedImage *buttonBan;
messages::LazyLoadedImage *buttonTimeout;
};
} // namespace chatterino

View file

@ -34,6 +34,7 @@ private:
messages::Word::Type _wordTypeMask = messages::Word::Default;
// methods
public: // temporary
void updateWordTypeMask();
public:

View file

@ -4,6 +4,7 @@
#include "emotemanager.hpp"
#include "ircmanager.hpp"
#include "resources.hpp"
#include "windowmanager.hpp"
using namespace chatterino::messages;
@ -17,45 +18,15 @@ TwitchMessageBuilder::TwitchMessageBuilder()
{
}
void TwitchMessageBuilder::appendTwitchBadges(const QStringList &badges)
{
for (QString badge : badges) {
if (badge.startsWith("bits/")) {
long long int cheer = std::strtoll(badge.mid(5).toStdString().c_str(), nullptr, 10);
appendWord(Word(EmoteManager::getInstance().getCheerBadge(cheer), Word::BadgeCheer,
QString(), QString("Twitch Cheer" + QString::number(cheer))));
} else if (badge == "staff/1") {
appendWord(Word(Resources::getBadgeStaff(), Word::BadgeStaff, QString(),
QString("Twitch Staff")));
} else if (badge == "admin/1") {
appendWord(Word(Resources::getBadgeAdmin(), Word::BadgeAdmin, QString(),
QString("Twitch Admin")));
} else if (badge == "global_mod/1") {
appendWord(Word(Resources::getBadgeGlobalmod(), Word::BadgeGlobalMod, QString(),
QString("Global Moderator")));
} else if (badge == "moderator/1") {
// TODO: implement this xD
appendWord(Word(Resources::getBadgeTurbo(), Word::BadgeModerator, QString(),
QString("Channel Moderator"))); // custom badge
} else if (badge == "turbo/1") {
appendWord(Word(Resources::getBadgeStaff(), Word::BadgeTurbo, QString(),
QString("Turbo Subscriber")));
} else if (badge == "broadcaster/1") {
appendWord(Word(Resources::getBadgeBroadcaster(), Word::BadgeBroadcaster, QString(),
QString("Channel Broadcaster")));
} else if (badge == "premium/1") {
appendWord(Word(Resources::getBadgePremium(), Word::BadgePremium, QString(),
QString("Twitch Prime")));
}
}
}
SharedMessage TwitchMessageBuilder::parse(const Communi::IrcPrivateMessage *ircMessage,
Channel *channel, const MessageParseArgs &args)
Channel *channel, const MessageParseArgs &args,
const Resources &resources, EmoteManager &emoteManager,
WindowManager &windowManager)
{
TwitchMessageBuilder b;
// timestamp
// The timestamp is always appended to the builder
// Whether or not will be rendered is decided/checked later
b.appendTimestamp();
auto tags = ircMessage->tags();
@ -69,14 +40,7 @@ SharedMessage TwitchMessageBuilder::parse(const Communi::IrcPrivateMessage *ircM
// timestamps
iterator = tags.find("tmi-sent-ts");
// mod buttons
static QString buttonBanTooltip("Ban user");
static QString buttonTimeoutTooltip("Timeout user");
b.appendWord(Word(Resources::getButtonBan(), Word::ButtonBan, QString(), buttonBanTooltip,
Link(Link::UserBan, ircMessage->account())));
b.appendWord(Word(Resources::getButtonTimeout(), Word::ButtonTimeout, QString(),
buttonTimeoutTooltip, Link(Link::UserTimeout, ircMessage->account())));
b.appendModerationWords(ircMessage, resources);
// badges
iterator = tags.find("badges");
@ -84,7 +48,7 @@ SharedMessage TwitchMessageBuilder::parse(const Communi::IrcPrivateMessage *ircM
if (iterator != tags.end()) {
auto badges = iterator.value().toString().split(',');
b.appendTwitchBadges(badges);
b.appendTwitchBadges(badges, resources, emoteManager);
}
// color
@ -124,11 +88,13 @@ SharedMessage TwitchMessageBuilder::parse(const Communi::IrcPrivateMessage *ircM
displayName + (hasLocalizedName ? (" (" + ircMessage->account() + ")") : QString());
if (args.isSentWhisper) {
userDisplayString += IrcManager::getInstance().getUser().getUserName();
// TODO(pajlada): Re-implement
// userDisplayString += IrcManager::getInstance().getUser().getUserName();
}
if (args.isReceivedWhisper) {
userDisplayString += " -> " + IrcManager::getInstance().getUser().getUserName();
// TODO(pajlada): Re-implement
// userDisplayString += " -> " + IrcManager::getInstance().getUser().getUserName();
}
if (!ircMessage->isAction()) {
@ -153,40 +119,11 @@ SharedMessage TwitchMessageBuilder::parse(const Communi::IrcPrivateMessage *ircM
std::vector<std::pair<long int, LazyLoadedImage *>> twitchEmotes;
iterator = tags.find("emotes");
if (iterator != tags.end()) {
auto emotes = iterator.value().toString().split('/');
QStringList emoteString = iterator.value().toString().split('/');
for (QString emote : emotes) {
if (!emote.contains(':'))
continue;
QStringList parameters = emote.split(':');
if (parameters.length() < 2)
continue;
long int id = std::stol(parameters.at(0).toStdString(), nullptr, 10);
QStringList occurences = parameters.at(1).split(',');
for (QString occurence : occurences) {
QStringList coords = occurence.split('-');
if (coords.length() < 2)
continue;
long int start = std::stol(coords.at(0).toStdString(), nullptr, 10);
long int end = std::stol(coords.at(1).toStdString(), nullptr, 10);
if (start >= end || start < 0 || end > ircMessage->content().length())
continue;
QString name = ircMessage->content().mid(start, end - start + 1);
twitchEmotes.push_back(std::pair<long int, LazyLoadedImage *>(
start, EmoteManager::getInstance().getTwitchEmoteById(name, id)));
}
for (QString emote : emoteString) {
b.appendTwitchEmote(ircMessage, emote, twitchEmotes, emoteManager);
}
struct {
@ -270,13 +207,15 @@ SharedMessage TwitchMessageBuilder::parse(const Communi::IrcPrivateMessage *ircM
QString bitsLink =
QString("http://static-cdn.jtvnw.net/bits/dark/static/" + color + "/1");
LazyLoadedImage *imageAnimated =
EmoteManager::getInstance().getMiscImageFromCache().getOrAdd(
bitsLinkAnimated,
[&bitsLinkAnimated] { return new LazyLoadedImage(bitsLinkAnimated); });
LazyLoadedImage *image =
EmoteManager::getInstance().getMiscImageFromCache().getOrAdd(
bitsLink, [&bitsLink] { return new LazyLoadedImage(bitsLink); });
LazyLoadedImage *imageAnimated = emoteManager.getMiscImageFromCache().getOrAdd(
bitsLinkAnimated, [&emoteManager, &windowManager, &bitsLinkAnimated] {
return new LazyLoadedImage(emoteManager, windowManager,
bitsLinkAnimated);
});
LazyLoadedImage *image = emoteManager.getMiscImageFromCache().getOrAdd(
bitsLink, [&emoteManager, &windowManager, &bitsLink] {
return new LazyLoadedImage(emoteManager, windowManager, bitsLink);
});
b.appendWord(Word(imageAnimated, Word::BitsAnimated, QString("cheer"),
QString("Twitch Cheer"),
@ -302,11 +241,11 @@ SharedMessage TwitchMessageBuilder::parse(const Communi::IrcPrivateMessage *ircM
LazyLoadedImage *bttvEmote;
// TODO: Implement this (ignored emotes)
if (EmoteManager::getInstance().getBttvEmotes().tryGet(string, bttvEmote) ||
if (emoteManager.getBTTVEmotes().tryGet(string, bttvEmote) ||
channel->getBttvChannelEmotes().tryGet(string, bttvEmote) ||
EmoteManager::getInstance().getFfzEmotes().tryGet(string, bttvEmote) ||
emoteManager.getFFZEmotes().tryGet(string, bttvEmote) ||
channel->getFfzChannelEmotes().tryGet(string, bttvEmote) ||
EmoteManager::getInstance().getChatterinoEmotes().tryGet(string, bttvEmote)) {
emoteManager.getChatterinoEmotes().tryGet(string, bttvEmote)) {
b.appendWord(Word(bttvEmote, Word::BttvEmoteImage, bttvEmote->getName(),
bttvEmote->getTooltip(),
Link(Link::Url, bttvEmote->getUrl())));
@ -340,6 +279,92 @@ SharedMessage TwitchMessageBuilder::parse(const Communi::IrcPrivateMessage *ircM
return b.build();
}
void TwitchMessageBuilder::appendModerationWords(const Communi::IrcPrivateMessage *ircMessage,
const Resources &resources)
{
// mod buttons
static QString buttonBanTooltip("Ban user");
static QString buttonTimeoutTooltip("Timeout user");
this->appendWord(Word(resources.buttonBan, Word::ButtonBan, QString(), buttonBanTooltip,
Link(Link::UserBan, ircMessage->account())));
this->appendWord(Word(resources.buttonTimeout, Word::ButtonTimeout, QString(),
buttonTimeoutTooltip, Link(Link::UserTimeout, ircMessage->account())));
}
void TwitchMessageBuilder::appendTwitchEmote(
const Communi::IrcPrivateMessage *ircMessage, const QString &emote,
std::vector<std::pair<long int, messages::LazyLoadedImage *>> &vec, EmoteManager &emoteManager)
{
if (!emote.contains(':')) {
return;
}
QStringList parameters = emote.split(':');
if (parameters.length() < 2) {
return;
}
long int id = std::stol(parameters.at(0).toStdString(), nullptr, 10);
QStringList occurences = parameters.at(1).split(',');
for (QString occurence : occurences) {
QStringList coords = occurence.split('-');
if (coords.length() < 2) {
return;
}
long int start = std::stol(coords.at(0).toStdString(), nullptr, 10);
long int end = std::stol(coords.at(1).toStdString(), nullptr, 10);
if (start >= end || start < 0 || end > ircMessage->content().length()) {
return;
}
QString name = ircMessage->content().mid(start, end - start + 1);
vec.push_back(std::pair<long int, LazyLoadedImage *>(
start, emoteManager.getTwitchEmoteById(name, id)));
}
}
void TwitchMessageBuilder::appendTwitchBadges(const QStringList &badges, const Resources &resources,
EmoteManager &emoteManager)
{
for (QString badge : badges) {
if (badge.startsWith("bits/")) {
long long int cheer = std::strtoll(badge.mid(5).toStdString().c_str(), nullptr, 10);
appendWord(Word(emoteManager.getCheerBadge(cheer), Word::BadgeCheer, QString(),
QString("Twitch Cheer" + QString::number(cheer))));
} else if (badge == "staff/1") {
appendWord(
Word(resources.badgeStaff, Word::BadgeStaff, QString(), QString("Twitch Staff")));
} else if (badge == "admin/1") {
appendWord(
Word(resources.badgeAdmin, Word::BadgeAdmin, QString(), QString("Twitch Admin")));
} else if (badge == "global_mod/1") {
appendWord(Word(resources.badgeGlobalModerator, Word::BadgeGlobalMod, QString(),
QString("Global Moderator")));
} else if (badge == "moderator/1") {
// TODO: implement this xD
appendWord(Word(resources.badgeTurbo, Word::BadgeModerator, QString(),
QString("Channel Moderator"))); // custom badge
} else if (badge == "turbo/1") {
appendWord(Word(resources.badgeStaff, Word::BadgeTurbo, QString(),
QString("Turbo Subscriber")));
} else if (badge == "broadcaster/1") {
appendWord(Word(resources.badgeBroadcaster, Word::BadgeBroadcaster, QString(),
QString("Channel Broadcaster")));
} else if (badge == "premium/1") {
appendWord(Word(resources.badgePremium, Word::BadgePremium, QString(),
QString("Twitch Prime")));
}
}
}
// bool
// sortTwitchEmotes(const std::pair<long int, LazyLoadedImage *> &a,
// const std::pair<long int, LazyLoadedImage *> &b)

View file

@ -4,8 +4,14 @@
#include "messages/messagebuilder.hpp"
#include <QString>
#include <QVariant>
namespace chatterino {
class Resources;
class EmoteManager;
class WindowManager;
namespace twitch {
class TwitchMessageBuilder : public messages::MessageBuilder
@ -13,17 +19,26 @@ class TwitchMessageBuilder : public messages::MessageBuilder
public:
TwitchMessageBuilder();
void appendTwitchBadges(const QStringList &badges);
QString messageId;
QString userName;
static messages::SharedMessage parse(const Communi::IrcPrivateMessage *ircMessage,
Channel *channel, const messages::MessageParseArgs &args);
Channel *channel, const messages::MessageParseArgs &args,
const Resources &resources, EmoteManager &emoteManager,
WindowManager &windowManager);
// static bool sortTwitchEmotes(
// const std::pair<long int, messages::LazyLoadedImage *> &a,
// const std::pair<long int, messages::LazyLoadedImage *> &b);
private:
void appendModerationWords(const Communi::IrcPrivateMessage *ircMessage,
const Resources &resources);
void appendTwitchEmote(const Communi::IrcPrivateMessage *ircMessage, const QString &emote,
std::vector<std::pair<long int, messages::LazyLoadedImage *>> &vec,
EmoteManager &emoteManager);
void appendTwitchBadges(const QStringList &badges, const Resources &resources,
EmoteManager &emoteManager);
};
} // namespace twitch

View file

@ -30,9 +30,10 @@ inline void ezShortcut(ChatWidget *w, const char *key, T t)
} // namespace
ChatWidget::ChatWidget(QWidget *parent)
ChatWidget::ChatWidget(ChannelManager &_channelManager, QWidget *parent)
: QWidget(parent)
, channel(ChannelManager::getInstance().getEmpty())
, channelManager(_channelManager)
, channel(_channelManager.getEmpty())
, vbox(this)
, header(this)
, view(this)
@ -90,7 +91,7 @@ void ChatWidget::setChannelName(const QString &_newChannelName)
// remove current channel
if (!this->channelName.isEmpty()) {
ChannelManager::getInstance().removeChannel(this->channelName);
this->channelManager.removeChannel(this->channelName);
this->detachChannel();
}
@ -104,7 +105,7 @@ void ChatWidget::setChannelName(const QString &_newChannelName)
if (newChannelName.isEmpty()) {
this->channel = nullptr;
} else {
this->setChannel(ChannelManager::getInstance().addChannel(newChannelName));
this->setChannel(this->channelManager.addChannel(newChannelName));
}
// update header
@ -240,7 +241,7 @@ void ChatWidget::doChangeChannel()
void ChatWidget::doPopup()
{
// TODO: Copy signals and stuff too
auto widget = new ChatWidget();
auto widget = new ChatWidget(this->channelManager);
widget->setChannelName(this->getChannelName());
widget->show();
}

View file

@ -17,6 +17,9 @@
#include <boost/signals2/connection.hpp>
namespace chatterino {
class ChannelManager;
namespace widgets {
// Each ChatWidget consists of three sub-elements that handle their own part of the chat widget:
@ -34,7 +37,7 @@ class ChatWidget : public QWidget
Q_OBJECT
public:
ChatWidget(QWidget *parent = nullptr);
ChatWidget(ChannelManager &_channelManager, QWidget *parent = nullptr);
~ChatWidget();
std::shared_ptr<Channel> getChannel() const;
@ -53,6 +56,8 @@ protected:
void paintEvent(QPaintEvent *) override;
private:
ChannelManager &channelManager;
void setChannel(std::shared_ptr<Channel> newChannel);
void detachChannel();

View file

@ -1,4 +1,5 @@
#include "widgets/mainwindow.hpp"
#include "channelmanager.hpp"
#include "colorscheme.hpp"
#include "settingsmanager.hpp"
#include "widgets/chatwidget.hpp"
@ -18,9 +19,10 @@
namespace chatterino {
namespace widgets {
MainWindow::MainWindow(QWidget *parent)
MainWindow::MainWindow(ChannelManager &_channelManager, QWidget *parent)
: QWidget(parent)
, _notebook(this)
, channelManager(_channelManager)
, notebook(this->channelManager, this)
, _loaded(false)
, _titleBar()
{
@ -31,7 +33,7 @@ MainWindow::MainWindow(QWidget *parent)
// layout->addWidget(&_titleBar);
// }
layout->addWidget(&_notebook);
layout->addWidget(&this->notebook);
setLayout(layout);
// set margin
@ -63,7 +65,7 @@ MainWindow::~MainWindow()
void MainWindow::layoutVisibleChatWidgets(Channel *channel)
{
auto *page = _notebook.getSelectedPage();
auto *page = this->notebook.getSelectedPage();
if (page == nullptr) {
return;
@ -82,7 +84,7 @@ void MainWindow::layoutVisibleChatWidgets(Channel *channel)
void MainWindow::repaintVisibleChatWidgets(Channel *channel)
{
auto *page = _notebook.getSelectedPage();
auto *page = this->notebook.getSelectedPage();
if (page == nullptr) {
return;
@ -101,7 +103,7 @@ void MainWindow::repaintVisibleChatWidgets(Channel *channel)
void MainWindow::repaintGifEmotes()
{
auto *page = _notebook.getSelectedPage();
auto *page = this->notebook.getSelectedPage();
if (page == nullptr) {
return;
@ -118,7 +120,7 @@ void MainWindow::repaintGifEmotes()
void MainWindow::load(const boost::property_tree::ptree &tree)
{
this->_notebook.load(tree);
this->notebook.load(tree);
_loaded = true;
}
@ -129,14 +131,14 @@ boost::property_tree::ptree MainWindow::save()
child.put("type", "main");
_notebook.save(child);
this->notebook.save(child);
return child;
}
void MainWindow::loadDefaults()
{
_notebook.loadDefaults();
this->notebook.loadDefaults();
_loaded = true;
}
@ -148,7 +150,7 @@ bool MainWindow::isLoaded() const
Notebook &MainWindow::getNotebook()
{
return _notebook;
return this->notebook;
}
} // namespace widgets

View file

@ -11,6 +11,9 @@
#include <boost/property_tree/ptree.hpp>
namespace chatterino {
class ChannelManager;
namespace widgets {
class MainWindow : public QWidget
@ -18,7 +21,7 @@ class MainWindow : public QWidget
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
explicit MainWindow(ChannelManager &_channelManager, QWidget *parent = nullptr);
~MainWindow();
void layoutVisibleChatWidgets(Channel *channel = nullptr);
@ -34,7 +37,9 @@ public:
Notebook &getNotebook();
private:
Notebook _notebook;
ChannelManager &channelManager;
Notebook notebook;
bool _loaded;
TitleBar _titleBar;
};

View file

@ -18,8 +18,9 @@
namespace chatterino {
namespace widgets {
Notebook::Notebook(QWidget *parent)
Notebook::Notebook(ChannelManager &_channelManager, QWidget *parent)
: QWidget(parent)
, channelManager(_channelManager)
, _addButton(this)
, _settingsButton(this)
, _userButton(this)
@ -47,7 +48,7 @@ Notebook::Notebook(QWidget *parent)
NotebookPage *Notebook::addPage(bool select)
{
auto tab = new NotebookTab(this);
auto page = new NotebookPage(this, tab);
auto page = new NotebookPage(this->channelManager, this, tab);
tab->show();

View file

@ -9,6 +9,9 @@
#include <boost/property_tree/ptree.hpp>
namespace chatterino {
class ChannelManager;
namespace widgets {
class Notebook : public QWidget
@ -18,7 +21,7 @@ class Notebook : public QWidget
public:
enum HighlightType { none, highlighted, newMessage };
Notebook(QWidget *parent);
Notebook(ChannelManager &_channelManager, QWidget *parent);
NotebookPage *addPage(bool select = false);
@ -46,6 +49,8 @@ public slots:
void addPageButtonClicked();
private:
ChannelManager &channelManager;
QList<NotebookPage *> _pages;
NotebookButton _addButton;

View file

@ -19,9 +19,10 @@ bool NotebookPage::isDraggingSplit = false;
ChatWidget *NotebookPage::draggingSplit = nullptr;
std::pair<int, int> NotebookPage::dropPosition = std::pair<int, int>(-1, -1);
NotebookPage::NotebookPage(QWidget *parent, NotebookTab *tab)
NotebookPage::NotebookPage(ChannelManager &_channelManager, QWidget *parent, NotebookTab *_tab)
: QWidget(parent)
, _tab(tab)
, channelManager(_channelManager)
, tab(_tab)
, _parentbox(this)
, _chatWidgets()
, _preview(this)
@ -46,12 +47,12 @@ const std::vector<ChatWidget *> &NotebookPage::getChatWidgets() const
NotebookTab *NotebookPage::getTab() const
{
return _tab;
return this->tab;
}
void NotebookPage::addChat(bool openChannelNameDialog)
{
ChatWidget *w = new ChatWidget();
ChatWidget *w = new ChatWidget(this->channelManager);
if (openChannelNameDialog) {
w->showChangeChannelPopup();
@ -143,7 +144,7 @@ void NotebookPage::mouseReleaseEvent(QMouseEvent *event)
{
if (_hbox.count() == 0 && event->button() == Qt::LeftButton) {
// "Add Chat" was clicked
addToLayout(new ChatWidget(), std::pair<int, int>(-1, -1));
addToLayout(new ChatWidget(this->channelManager), std::pair<int, int>(-1, -1));
setCursor(QCursor(Qt::ArrowCursor));
}
@ -275,7 +276,7 @@ void NotebookPage::load(const boost::property_tree::ptree &tree)
for (const auto &v : tree.get_child("columns.")) {
int row = 0;
for (const auto &innerV : v.second.get_child("")) {
auto widget = new ChatWidget();
auto widget = new ChatWidget(this->channelManager);
widget->load(innerV.second);
addToLayout(widget, std::pair<int, int>(column, row));
++row;

View file

@ -15,6 +15,9 @@
#include <boost/signals2.hpp>
namespace chatterino {
class ChannelManager;
namespace widgets {
class NotebookPage : public QWidget
@ -22,7 +25,7 @@ class NotebookPage : public QWidget
Q_OBJECT
public:
NotebookPage(QWidget *parent, NotebookTab *_tab);
NotebookPage(ChannelManager &_channelManager, QWidget *parent, NotebookTab *_tab);
std::pair<int, int> removeFromLayout(ChatWidget *widget);
void addToLayout(ChatWidget *widget, std::pair<int, int> position);
@ -49,6 +52,8 @@ protected:
void dropEvent(QDropEvent *event) override;
private:
ChannelManager &channelManager;
struct DropRegion {
QRect rect;
std::pair<int, int> position;
@ -60,7 +65,7 @@ private:
}
};
NotebookTab *_tab;
NotebookTab *tab;
QVBoxLayout _parentbox;
QHBoxLayout _hbox;

View file

@ -153,7 +153,9 @@ void SettingsDialog::addTabs()
QObject::connect(slider, &QSlider::valueChanged, this, [&settings](int value) {
settings.themeHue.set(value / 1000.0);
WindowManager::getInstance().updateAll();
// TODO(pajlada): re-implement
// this->windowManager.updateAll();
});
group->setLayout(form);

View file

@ -17,6 +17,7 @@
#include <pajlada/settings/setting.hpp>
namespace chatterino {
namespace widgets {
class SettingsDialog : public QWidget

View file

@ -1,5 +1,6 @@
#include "windowmanager.hpp"
#include "appdatapath.hpp"
#include "channelmanager.hpp"
#include <QDebug>
#include <QStandardPaths>
@ -7,10 +8,9 @@
#include <boost/property_tree/json_parser.hpp>
namespace chatterino {
WindowManager WindowManager::instance;
WindowManager::WindowManager()
: _mainWindow(nullptr)
WindowManager::WindowManager(ChannelManager &_channelManager)
: channelManager(_channelManager)
{
}
@ -23,41 +23,41 @@ static const std::string &getSettingsPath()
void WindowManager::layoutVisibleChatWidgets(Channel *channel)
{
if (_mainWindow != nullptr) {
_mainWindow->layoutVisibleChatWidgets(channel);
if (this->mainWindow != nullptr) {
this->mainWindow->layoutVisibleChatWidgets(channel);
}
}
void WindowManager::repaintVisibleChatWidgets(Channel *channel)
{
if (_mainWindow != nullptr) {
_mainWindow->repaintVisibleChatWidgets(channel);
if (this->mainWindow != nullptr) {
this->mainWindow->repaintVisibleChatWidgets(channel);
}
}
void WindowManager::repaintGifEmotes()
{
if (_mainWindow != nullptr) {
_mainWindow->repaintGifEmotes();
if (this->mainWindow != nullptr) {
this->mainWindow->repaintGifEmotes();
}
}
void WindowManager::updateAll()
{
if (_mainWindow != nullptr) {
_mainWindow->update();
if (this->mainWindow != nullptr) {
this->mainWindow->update();
}
}
widgets::MainWindow &WindowManager::getMainWindow()
{
std::lock_guard<std::mutex> lock(_windowMutex);
std::lock_guard<std::mutex> lock(this->windowMutex);
if (_mainWindow == nullptr) {
_mainWindow = new widgets::MainWindow();
if (this->mainWindow == nullptr) {
this->mainWindow = new widgets::MainWindow(this->channelManager);
}
return *_mainWindow;
return *this->mainWindow;
}
void WindowManager::load()

View file

@ -6,13 +6,12 @@
namespace chatterino {
class ChannelManager;
class WindowManager
{
public:
static WindowManager &getInstance()
{
return instance;
}
explicit WindowManager(ChannelManager &_channelManager);
void layoutVisibleChatWidgets(Channel *channel = nullptr);
void repaintVisibleChatWidgets(Channel *channel = nullptr);
@ -25,12 +24,12 @@ public:
void save();
private:
static WindowManager instance;
ChannelManager &channelManager;
WindowManager();
std::mutex windowMutex;
std::mutex _windowMutex;
widgets::MainWindow *_mainWindow;
// TODO(pajlada): Store as a value instead of a pointer
widgets::MainWindow *mainWindow = nullptr;
};
} // namespace chatterino