mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-21 22:24:07 +01:00
ChatWidgetView -> ChannelView, added Emote Picker
This commit is contained in:
parent
84c23a5d00
commit
c7b3480aaf
37 changed files with 532 additions and 407 deletions
|
@ -62,7 +62,6 @@ SOURCES += \
|
||||||
src/widgets/chatwidgetheader.cpp \
|
src/widgets/chatwidgetheader.cpp \
|
||||||
src/widgets/chatwidgetheaderbutton.cpp \
|
src/widgets/chatwidgetheaderbutton.cpp \
|
||||||
src/widgets/chatwidgetinput.cpp \
|
src/widgets/chatwidgetinput.cpp \
|
||||||
src/widgets/chatwidgetview.cpp \
|
|
||||||
src/widgets/mainwindow.cpp \
|
src/widgets/mainwindow.cpp \
|
||||||
src/widgets/notebook.cpp \
|
src/widgets/notebook.cpp \
|
||||||
src/widgets/notebookbutton.cpp \
|
src/widgets/notebookbutton.cpp \
|
||||||
|
@ -97,7 +96,9 @@ SOURCES += \
|
||||||
src/completionmanager.cpp \
|
src/completionmanager.cpp \
|
||||||
src/widgets/logindialog.cpp \
|
src/widgets/logindialog.cpp \
|
||||||
src/widgets/qualitypopup.cpp \
|
src/widgets/qualitypopup.cpp \
|
||||||
src/widgets/emotepopup.cpp
|
src/widgets/emotepopup.cpp \
|
||||||
|
src/widgets/channelview.cpp \
|
||||||
|
src/twitch/twitchchannel.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
src/asyncexec.hpp \
|
src/asyncexec.hpp \
|
||||||
|
@ -118,7 +119,6 @@ HEADERS += \
|
||||||
src/widgets/chatwidgetheader.hpp \
|
src/widgets/chatwidgetheader.hpp \
|
||||||
src/widgets/chatwidgetheaderbutton.hpp \
|
src/widgets/chatwidgetheaderbutton.hpp \
|
||||||
src/widgets/chatwidgetinput.hpp \
|
src/widgets/chatwidgetinput.hpp \
|
||||||
src/widgets/chatwidgetview.hpp \
|
|
||||||
src/widgets/mainwindow.hpp \
|
src/widgets/mainwindow.hpp \
|
||||||
src/widgets/notebook.hpp \
|
src/widgets/notebook.hpp \
|
||||||
src/widgets/notebookbutton.hpp \
|
src/widgets/notebookbutton.hpp \
|
||||||
|
@ -159,7 +159,9 @@ HEADERS += \
|
||||||
src/widgets/basewidget.hpp \
|
src/widgets/basewidget.hpp \
|
||||||
src/completionmanager.hpp \
|
src/completionmanager.hpp \
|
||||||
src/widgets/qualitypopup.h \
|
src/widgets/qualitypopup.h \
|
||||||
src/widgets/emotepopup.h
|
src/widgets/emotepopup.h \
|
||||||
|
src/widgets/channelview.hpp \
|
||||||
|
src/twitch/twitchchannel.hpp
|
||||||
|
|
||||||
PRECOMPILED_HEADER =
|
PRECOMPILED_HEADER =
|
||||||
|
|
||||||
|
|
|
@ -18,55 +18,14 @@ using namespace chatterino::messages;
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
Channel::Channel(WindowManager &_windowManager, EmoteManager &_emoteManager,
|
Channel::Channel()
|
||||||
IrcManager &_ircManager, const QString &channelName, bool isSpecial)
|
|
||||||
: windowManager(_windowManager)
|
|
||||||
, emoteManager(_emoteManager)
|
|
||||||
, ircManager(_ircManager)
|
|
||||||
, name(channelName)
|
|
||||||
, bttvChannelEmotes(this->emoteManager.bttvChannels[channelName])
|
|
||||||
, ffzChannelEmotes(this->emoteManager.ffzChannels[channelName])
|
|
||||||
, _subLink("https://www.twitch.tv/" + name + "/subscribe?ref=in_chat_subscriber_link")
|
|
||||||
, _channelLink("https://twitch.tv/" + name)
|
|
||||||
, _popoutPlayerLink("https://player.twitch.tv/?channel=" + name)
|
|
||||||
, isLive(false)
|
|
||||||
// , _loggingChannel(logging::get(_name))
|
// , _loggingChannel(logging::get(_name))
|
||||||
{
|
{
|
||||||
qDebug() << "Open channel:" << this->name;
|
|
||||||
|
|
||||||
if (!isSpecial) {
|
|
||||||
this->reloadChannelEmotes();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// properties
|
|
||||||
//
|
|
||||||
|
|
||||||
bool Channel::isEmpty() const
|
bool Channel::isEmpty() const
|
||||||
{
|
{
|
||||||
return name.isEmpty();
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
const QString &Channel::getSubLink() const
|
|
||||||
{
|
|
||||||
return _subLink;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString &Channel::getChannelLink() const
|
|
||||||
{
|
|
||||||
return _channelLink;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString &Channel::getPopoutPlayerLink() const
|
|
||||||
{
|
|
||||||
return _popoutPlayerLink;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Channel::setRoomID(std::string id)
|
|
||||||
{
|
|
||||||
this->roomID = id;
|
|
||||||
this->roomIDchanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
messages::LimitedQueueSnapshot<messages::SharedMessage> Channel::getMessageSnapshot()
|
messages::LimitedQueueSnapshot<messages::SharedMessage> Channel::getMessageSnapshot()
|
||||||
|
@ -74,9 +33,6 @@ messages::LimitedQueueSnapshot<messages::SharedMessage> Channel::getMessageSnaps
|
||||||
return _messages.getSnapshot();
|
return _messages.getSnapshot();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// methods
|
|
||||||
//
|
|
||||||
void Channel::addMessage(std::shared_ptr<Message> message)
|
void Channel::addMessage(std::shared_ptr<Message> message)
|
||||||
{
|
{
|
||||||
std::shared_ptr<Message> deleted;
|
std::shared_ptr<Message> deleted;
|
||||||
|
@ -90,26 +46,15 @@ void Channel::addMessage(std::shared_ptr<Message> message)
|
||||||
}
|
}
|
||||||
|
|
||||||
this->messageAppended(message);
|
this->messageAppended(message);
|
||||||
|
|
||||||
this->windowManager.repaintVisibleChatWidgets(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// private methods
|
bool Channel::canSendMessage() const
|
||||||
void Channel::reloadChannelEmotes()
|
|
||||||
{
|
{
|
||||||
printf("[Channel:%s] Reloading channel emotes\n", qPrintable(this->name));
|
return false;
|
||||||
this->emoteManager.reloadBTTVChannelEmotes(this->name);
|
|
||||||
this->emoteManager.reloadFFZChannelEmotes(this->name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Channel::sendMessage(const QString &message)
|
void Channel::sendMessage(const QString &message)
|
||||||
{
|
{
|
||||||
qDebug() << "Channel send message: " << message;
|
|
||||||
|
|
||||||
// Do last message processing
|
|
||||||
QString parsedMessage = this->emoteManager.replaceShortCodes(message);
|
|
||||||
|
|
||||||
this->ircManager.sendMessage(name, parsedMessage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -19,58 +19,30 @@ namespace messages {
|
||||||
class Message;
|
class Message;
|
||||||
}
|
}
|
||||||
|
|
||||||
class WindowManager;
|
|
||||||
class IrcManager;
|
class IrcManager;
|
||||||
|
|
||||||
class Channel
|
class Channel
|
||||||
{
|
{
|
||||||
WindowManager &windowManager;
|
|
||||||
EmoteManager &emoteManager;
|
|
||||||
IrcManager &ircManager;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Channel(WindowManager &_windowManager, EmoteManager &_emoteManager,
|
explicit Channel();
|
||||||
IrcManager &_ircManager, const QString &channelName, bool isSpecial = false);
|
|
||||||
|
|
||||||
boost::signals2::signal<void(messages::SharedMessage &)> messageRemovedFromStart;
|
boost::signals2::signal<void(messages::SharedMessage &)> messageRemovedFromStart;
|
||||||
boost::signals2::signal<void(messages::SharedMessage &)> messageAppended;
|
boost::signals2::signal<void(messages::SharedMessage &)> messageAppended;
|
||||||
|
|
||||||
bool isEmpty() const;
|
virtual bool isEmpty() const;
|
||||||
const QString &getSubLink() const;
|
|
||||||
const QString &getChannelLink() const;
|
|
||||||
const QString &getPopoutPlayerLink() const;
|
|
||||||
messages::LimitedQueueSnapshot<messages::SharedMessage> getMessageSnapshot();
|
messages::LimitedQueueSnapshot<messages::SharedMessage> getMessageSnapshot();
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
void addMessage(messages::SharedMessage message);
|
void addMessage(messages::SharedMessage message);
|
||||||
void reloadChannelEmotes();
|
QString name;
|
||||||
|
|
||||||
void sendMessage(const QString &message);
|
virtual bool canSendMessage() const;
|
||||||
|
virtual void sendMessage(const QString &message);
|
||||||
std::string roomID;
|
|
||||||
const QString name;
|
|
||||||
bool isLive;
|
|
||||||
QString streamViewerCount;
|
|
||||||
QString streamStatus;
|
|
||||||
QString streamGame;
|
|
||||||
QString streamUptime;
|
|
||||||
|
|
||||||
void setRoomID(std::string id);
|
|
||||||
boost::signals2::signal<void()> roomIDchanged;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// variables
|
// variables
|
||||||
messages::LimitedQueue<messages::SharedMessage> _messages;
|
messages::LimitedQueue<messages::SharedMessage> _messages;
|
||||||
|
|
||||||
public:
|
|
||||||
const EmoteManager::EmoteMap &bttvChannelEmotes;
|
|
||||||
const EmoteManager::EmoteMap &ffzChannelEmotes;
|
|
||||||
|
|
||||||
private:
|
|
||||||
QString _subLink;
|
|
||||||
QString _channelLink;
|
|
||||||
QString _popoutPlayerLink;
|
|
||||||
|
|
||||||
// std::shared_ptr<logging::Channel> _loggingChannel;
|
// std::shared_ptr<logging::Channel> _loggingChannel;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "channelmanager.hpp"
|
#include "channelmanager.hpp"
|
||||||
#include "ircmanager.hpp"
|
#include "ircmanager.hpp"
|
||||||
|
|
||||||
|
using namespace chatterino::twitch;
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
ChannelManager::ChannelManager(WindowManager &_windowManager, EmoteManager &_emoteManager,
|
ChannelManager::ChannelManager(WindowManager &_windowManager, EmoteManager &_emoteManager,
|
||||||
|
@ -8,9 +10,9 @@ ChannelManager::ChannelManager(WindowManager &_windowManager, EmoteManager &_emo
|
||||||
: windowManager(_windowManager)
|
: windowManager(_windowManager)
|
||||||
, emoteManager(_emoteManager)
|
, emoteManager(_emoteManager)
|
||||||
, ircManager(_ircManager)
|
, ircManager(_ircManager)
|
||||||
, whispersChannel(new Channel(_windowManager, _emoteManager, _ircManager, "/whispers", true))
|
, whispersChannel(new TwitchChannel(_emoteManager, _ircManager, "/whispers", true))
|
||||||
, mentionsChannel(new Channel(_windowManager, _emoteManager, _ircManager, "/mentions", true))
|
, mentionsChannel(new TwitchChannel(_emoteManager, _ircManager, "/mentions", true))
|
||||||
, emptyChannel(new Channel(_windowManager, _emoteManager, _ircManager, "", true))
|
, emptyChannel(new TwitchChannel(_emoteManager, _ircManager, "", true))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,19 +22,19 @@ const std::vector<std::shared_ptr<Channel>> ChannelManager::getItems()
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Channel>> items;
|
std::vector<std::shared_ptr<Channel>> items;
|
||||||
|
|
||||||
for (auto &item : this->channels.values()) {
|
for (auto &item : this->twitchChannels.values()) {
|
||||||
items.push_back(std::get<0>(item));
|
items.push_back(std::get<0>(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Channel> ChannelManager::addChannel(const QString &rawChannelName)
|
std::shared_ptr<TwitchChannel> ChannelManager::addTwitchChannel(const QString &rawChannelName)
|
||||||
{
|
{
|
||||||
QString channelName = rawChannelName.toLower();
|
QString channelName = rawChannelName.toLower();
|
||||||
|
|
||||||
if (channelName.length() > 1 && channelName.at(0) == '/') {
|
if (channelName.length() > 1 && channelName.at(0) == '/') {
|
||||||
return this->getChannel(channelName);
|
return this->getTwitchChannel(channelName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (channelName.length() > 0 && channelName.at(0) == '#') {
|
if (channelName.length() > 0 && channelName.at(0) == '#') {
|
||||||
|
@ -41,12 +43,13 @@ std::shared_ptr<Channel> ChannelManager::addChannel(const QString &rawChannelNam
|
||||||
|
|
||||||
QMutexLocker locker(&this->channelsMutex);
|
QMutexLocker locker(&this->channelsMutex);
|
||||||
|
|
||||||
auto it = this->channels.find(channelName);
|
auto it = this->twitchChannels.find(channelName);
|
||||||
|
|
||||||
if (it == this->channels.end()) {
|
if (it == this->twitchChannels.end()) {
|
||||||
auto channel = std::make_shared<Channel>(this->windowManager, this->emoteManager,
|
auto channel =
|
||||||
this->ircManager, channelName);
|
std::make_shared<TwitchChannel>(this->emoteManager, this->ircManager, channelName);
|
||||||
this->channels.insert(channelName, std::make_tuple(channel, 1));
|
|
||||||
|
this->twitchChannels.insert(channelName, std::make_tuple(channel, 1));
|
||||||
|
|
||||||
this->ircManager.joinChannel(channelName);
|
this->ircManager.joinChannel(channelName);
|
||||||
|
|
||||||
|
@ -58,7 +61,7 @@ std::shared_ptr<Channel> ChannelManager::addChannel(const QString &rawChannelNam
|
||||||
return std::get<0>(it.value());
|
return std::get<0>(it.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Channel> ChannelManager::getChannel(const QString &channel)
|
std::shared_ptr<TwitchChannel> ChannelManager::getTwitchChannel(const QString &channel)
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&this->channelsMutex);
|
QMutexLocker locker(&this->channelsMutex);
|
||||||
|
|
||||||
|
@ -76,16 +79,16 @@ std::shared_ptr<Channel> ChannelManager::getChannel(const QString &channel)
|
||||||
return emptyChannel;
|
return emptyChannel;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto a = this->channels.find(c);
|
auto a = this->twitchChannels.find(c);
|
||||||
|
|
||||||
if (a == this->channels.end()) {
|
if (a == this->twitchChannels.end()) {
|
||||||
return emptyChannel;
|
return emptyChannel;
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::get<0>(a.value());
|
return std::get<0>(a.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChannelManager::removeChannel(const QString &channel)
|
void ChannelManager::removeTwitchChannel(const QString &channel)
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&this->channelsMutex);
|
QMutexLocker locker(&this->channelsMutex);
|
||||||
|
|
||||||
|
@ -95,9 +98,9 @@ void ChannelManager::removeChannel(const QString &channel)
|
||||||
|
|
||||||
QString c = channel.toLower();
|
QString c = channel.toLower();
|
||||||
|
|
||||||
auto a = this->channels.find(c);
|
auto a = this->twitchChannels.find(c);
|
||||||
|
|
||||||
if (a == this->channels.end()) {
|
if (a == this->twitchChannels.end()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +108,7 @@ void ChannelManager::removeChannel(const QString &channel)
|
||||||
|
|
||||||
if (std::get<1>(a.value()) == 0) {
|
if (std::get<1>(a.value()) == 0) {
|
||||||
this->ircManager.partChannel(c);
|
this->ircManager.partChannel(c);
|
||||||
this->channels.remove(c);
|
this->twitchChannels.remove(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,4 +126,9 @@ const std::string &ChannelManager::getUserID(const std::string &username)
|
||||||
return temporary;
|
return temporary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EmoteManager &ChannelManager::getEmoteManager()
|
||||||
|
{
|
||||||
|
return this->emoteManager;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "channel.hpp"
|
#include "channel.hpp"
|
||||||
#include "channeldata.hpp"
|
#include "channeldata.hpp"
|
||||||
|
#include "twitch/twitchchannel.hpp"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
@ -23,23 +24,24 @@ public:
|
||||||
|
|
||||||
const std::vector<std::shared_ptr<Channel>> getItems();
|
const std::vector<std::shared_ptr<Channel>> getItems();
|
||||||
|
|
||||||
std::shared_ptr<Channel> addChannel(const QString &channel);
|
std::shared_ptr<twitch::TwitchChannel> addTwitchChannel(const QString &channel);
|
||||||
std::shared_ptr<Channel> getChannel(const QString &channel);
|
std::shared_ptr<twitch::TwitchChannel> getTwitchChannel(const QString &channel);
|
||||||
void removeChannel(const QString &channel);
|
void removeTwitchChannel(const QString &channel);
|
||||||
|
|
||||||
const std::string &getUserID(const std::string &username);
|
const std::string &getUserID(const std::string &username);
|
||||||
|
EmoteManager &getEmoteManager();
|
||||||
|
|
||||||
// Special channels
|
// Special channels
|
||||||
const std::shared_ptr<Channel> whispersChannel;
|
const std::shared_ptr<twitch::TwitchChannel> whispersChannel;
|
||||||
const std::shared_ptr<Channel> mentionsChannel;
|
const std::shared_ptr<twitch::TwitchChannel> mentionsChannel;
|
||||||
const std::shared_ptr<Channel> emptyChannel;
|
const std::shared_ptr<twitch::TwitchChannel> emptyChannel;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<std::string, std::string> usernameToID;
|
std::map<std::string, std::string> usernameToID;
|
||||||
std::map<std::string, ChannelData> channelDatas;
|
std::map<std::string, ChannelData> channelDatas;
|
||||||
|
|
||||||
QMutex channelsMutex;
|
QMutex channelsMutex;
|
||||||
QMap<QString, std::tuple<std::shared_ptr<Channel>, int>> channels;
|
QMap<QString, std::tuple<std::shared_ptr<twitch::TwitchChannel>, int>> twitchChannels;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -20,7 +20,7 @@ public:
|
||||||
|
|
||||||
bool tryGet(const TKey &name, TValue &value) const
|
bool tryGet(const TKey &name, TValue &value) const
|
||||||
{
|
{
|
||||||
QMutexLocker lock(this->mutex.get());
|
QMutexLocker lock(&this->mutex);
|
||||||
|
|
||||||
auto a = this->data.find(name);
|
auto a = this->data.find(name);
|
||||||
if (a == this->data.end()) {
|
if (a == this->data.end()) {
|
||||||
|
@ -34,7 +34,7 @@ public:
|
||||||
|
|
||||||
TValue getOrAdd(const TKey &name, std::function<TValue()> addLambda)
|
TValue getOrAdd(const TKey &name, std::function<TValue()> addLambda)
|
||||||
{
|
{
|
||||||
QMutexLocker lock(this->mutex.get());
|
QMutexLocker lock(&this->mutex);
|
||||||
|
|
||||||
auto a = this->data.find(name);
|
auto a = this->data.find(name);
|
||||||
if (a == this->data.end()) {
|
if (a == this->data.end()) {
|
||||||
|
@ -48,42 +48,28 @@ public:
|
||||||
|
|
||||||
TValue &operator[](const TKey &name)
|
TValue &operator[](const TKey &name)
|
||||||
{
|
{
|
||||||
QMutexLocker lock(this->mutex.get());
|
QMutexLocker lock(&this->mutex);
|
||||||
|
|
||||||
return this->data[name];
|
return this->data[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
ConcurrentMap(const ConcurrentMap &o)
|
|
||||||
: mutex(std::move(o.mutex))
|
|
||||||
, data(std::move(o.data))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ConcurrentMap &operator=(const ConcurrentMap &rhs)
|
|
||||||
{
|
|
||||||
this->mutex = std::move(rhs.mutex);
|
|
||||||
this->data = std::move(rhs.data);
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
QMutexLocker lock(this->mutex.get());
|
QMutexLocker lock(&this->mutex);
|
||||||
|
|
||||||
this->data.clear();
|
this->data.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void insert(const TKey &name, const TValue &value)
|
void insert(const TKey &name, const TValue &value)
|
||||||
{
|
{
|
||||||
QMutexLocker lock(this->mutex.get());
|
QMutexLocker lock(&this->mutex);
|
||||||
|
|
||||||
this->data.insert(name, value);
|
this->data.insert(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void each(std::function<void(const TKey &name, const TValue &value)> &func) const
|
void each(std::function<void(const TKey &name, const TValue &value)> func) const
|
||||||
{
|
{
|
||||||
QMutexLocker lock(this->mutex.get());
|
QMutexLocker lock(&this->mutex);
|
||||||
|
|
||||||
QMapIterator<TKey, TValue> it(this->data);
|
QMapIterator<TKey, TValue> it(this->data);
|
||||||
|
|
||||||
|
@ -94,66 +80,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable std::unique_ptr<QMutex> mutex;
|
mutable QMutex mutex;
|
||||||
QMap<TKey, TValue> data;
|
QMap<TKey, TValue> data;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename TKey, typename TValue>
|
|
||||||
class ConcurrentStdMap
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
bool tryGet(const TKey &name, TValue &value) const
|
|
||||||
{
|
|
||||||
QMutexLocker lock(&_mutex);
|
|
||||||
|
|
||||||
auto a = _map.find(name);
|
|
||||||
if (a == _map.end()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
value = a.value();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
TValue getOrAdd(const TKey &name, std::function<TValue()> addLambda)
|
|
||||||
{
|
|
||||||
QMutexLocker lock(&_mutex);
|
|
||||||
|
|
||||||
auto a = _map.find(name);
|
|
||||||
if (a == _map.end()) {
|
|
||||||
TValue value = addLambda();
|
|
||||||
_map.insert(name, value);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return a.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
TValue &operator[](const TKey &name)
|
|
||||||
{
|
|
||||||
QMutexLocker lock(&_mutex);
|
|
||||||
|
|
||||||
return this->_map[name];
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear()
|
|
||||||
{
|
|
||||||
QMutexLocker lock(&_mutex);
|
|
||||||
|
|
||||||
_map.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void insert(const TKey &name, const TValue &value)
|
|
||||||
{
|
|
||||||
QMutexLocker lock(&_mutex);
|
|
||||||
|
|
||||||
_map.insert(name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
mutable QMutex _mutex;
|
|
||||||
std::map<TKey, TValue> _map;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -39,15 +39,19 @@ void EmoteManager::loadGlobalEmotes()
|
||||||
this->loadFFZEmotes();
|
this->loadFFZEmotes();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmoteManager::reloadBTTVChannelEmotes(const QString &channelName)
|
void EmoteManager::reloadBTTVChannelEmotes(const QString &channelName, std::weak_ptr<EmoteMap> _map)
|
||||||
{
|
{
|
||||||
printf("[EmoteManager] Reload BTTV Channel Emotes for channel %s\n", qPrintable(channelName));
|
printf("[EmoteManager] Reload BTTV Channel Emotes for channel %s\n", qPrintable(channelName));
|
||||||
|
|
||||||
QString url("https://api.betterttv.net/2/channels/" + channelName);
|
QString url("https://api.betterttv.net/2/channels/" + channelName);
|
||||||
util::urlFetchJSON(url, [this, channelName](QJsonObject &rootNode) {
|
util::urlFetchJSON(url, [this, channelName, _map](QJsonObject &rootNode) {
|
||||||
EmoteMap &channelEmoteMap = this->bttvChannels[channelName];
|
auto map = _map.lock();
|
||||||
|
|
||||||
channelEmoteMap.clear();
|
if (_map.expired()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
map->clear();
|
||||||
|
|
||||||
auto emotesNode = rootNode.value("emotes").toArray();
|
auto emotesNode = rootNode.value("emotes").toArray();
|
||||||
|
|
||||||
|
@ -72,7 +76,7 @@ void EmoteManager::reloadBTTVChannelEmotes(const QString &channelName)
|
||||||
});
|
});
|
||||||
|
|
||||||
this->bttvChannelEmotes.insert(code, emote);
|
this->bttvChannelEmotes.insert(code, emote);
|
||||||
channelEmoteMap.insert(code, emote);
|
map->insert(code, emote);
|
||||||
codes.push_back(code.toStdString());
|
codes.push_back(code.toStdString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,16 +84,20 @@ void EmoteManager::reloadBTTVChannelEmotes(const QString &channelName)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmoteManager::reloadFFZChannelEmotes(const QString &channelName)
|
void EmoteManager::reloadFFZChannelEmotes(const QString &channelName, std::weak_ptr<EmoteMap> _map)
|
||||||
{
|
{
|
||||||
printf("[EmoteManager] Reload FFZ Channel Emotes for channel %s\n", qPrintable(channelName));
|
printf("[EmoteManager] Reload FFZ Channel Emotes for channel %s\n", qPrintable(channelName));
|
||||||
|
|
||||||
QString url("http://api.frankerfacez.com/v1/room/" + channelName);
|
QString url("http://api.frankerfacez.com/v1/room/" + channelName);
|
||||||
|
|
||||||
util::urlFetchJSON(url, [this, channelName](QJsonObject &rootNode) {
|
util::urlFetchJSON(url, [this, channelName, _map](QJsonObject &rootNode) {
|
||||||
EmoteMap &channelEmoteMap = this->ffzChannels[channelName];
|
auto map = _map.lock();
|
||||||
|
|
||||||
channelEmoteMap.clear();
|
if (_map.expired()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
map->clear();
|
||||||
|
|
||||||
auto setsNode = rootNode.value("sets").toObject();
|
auto setsNode = rootNode.value("sets").toObject();
|
||||||
|
|
||||||
|
@ -114,7 +122,7 @@ void EmoteManager::reloadFFZChannelEmotes(const QString &channelName)
|
||||||
});
|
});
|
||||||
|
|
||||||
this->ffzChannelEmotes.insert(code, emote);
|
this->ffzChannelEmotes.insert(code, emote);
|
||||||
channelEmoteMap.insert(code, emote);
|
map->insert(code, emote);
|
||||||
codes.push_back(code.toStdString());
|
codes.push_back(code.toStdString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,17 +136,17 @@ ConcurrentMap<QString, twitch::EmoteValue *> &EmoteManager::getTwitchEmotes()
|
||||||
return _twitchEmotes;
|
return _twitchEmotes;
|
||||||
}
|
}
|
||||||
|
|
||||||
EmoteManager::EmoteMap &EmoteManager::getFFZEmotes()
|
EmoteMap &EmoteManager::getFFZEmotes()
|
||||||
{
|
{
|
||||||
return ffzGlobalEmotes;
|
return ffzGlobalEmotes;
|
||||||
}
|
}
|
||||||
|
|
||||||
EmoteManager::EmoteMap &EmoteManager::getChatterinoEmotes()
|
EmoteMap &EmoteManager::getChatterinoEmotes()
|
||||||
{
|
{
|
||||||
return _chatterinoEmotes;
|
return _chatterinoEmotes;
|
||||||
}
|
}
|
||||||
|
|
||||||
EmoteManager::EmoteMap &EmoteManager::getBTTVChannelEmoteFromCaches()
|
EmoteMap &EmoteManager::getBTTVChannelEmoteFromCaches()
|
||||||
{
|
{
|
||||||
return _bttvChannelEmoteFromCaches;
|
return _bttvChannelEmoteFromCaches;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,17 +32,19 @@ struct EmoteData {
|
||||||
messages::LazyLoadedImage *image = nullptr;
|
messages::LazyLoadedImage *image = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef ConcurrentMap<QString, EmoteData> EmoteMap;
|
||||||
|
|
||||||
class EmoteManager
|
class EmoteManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using EmoteMap = ConcurrentMap<QString, EmoteData>;
|
|
||||||
|
|
||||||
explicit EmoteManager(WindowManager &_windowManager);
|
explicit EmoteManager(WindowManager &_windowManager);
|
||||||
|
|
||||||
void loadGlobalEmotes();
|
void loadGlobalEmotes();
|
||||||
|
|
||||||
void reloadBTTVChannelEmotes(const QString &channelName);
|
void reloadBTTVChannelEmotes(const QString &channelName,
|
||||||
void reloadFFZChannelEmotes(const QString &channelName);
|
std::weak_ptr<EmoteMap> channelEmoteMap);
|
||||||
|
void reloadFFZChannelEmotes(const QString &channelName,
|
||||||
|
std::weak_ptr<EmoteMap> channelEmoteMap);
|
||||||
|
|
||||||
ConcurrentMap<QString, twitch::EmoteValue *> &getTwitchEmotes();
|
ConcurrentMap<QString, twitch::EmoteValue *> &getTwitchEmotes();
|
||||||
EmoteMap &getFFZEmotes();
|
EmoteMap &getFFZEmotes();
|
||||||
|
|
|
@ -237,7 +237,7 @@ void IrcManager::partChannel(const QString &channelName)
|
||||||
void IrcManager::privateMessageReceived(Communi::IrcPrivateMessage *message)
|
void IrcManager::privateMessageReceived(Communi::IrcPrivateMessage *message)
|
||||||
{
|
{
|
||||||
this->onPrivateMessage.invoke(message);
|
this->onPrivateMessage.invoke(message);
|
||||||
auto c = this->channelManager.getChannel(message->target().mid(1));
|
auto c = this->channelManager.getTwitchChannel(message->target().mid(1));
|
||||||
|
|
||||||
if (!c) {
|
if (!c) {
|
||||||
return;
|
return;
|
||||||
|
@ -283,7 +283,7 @@ void IrcManager::handleRoomStateMessage(Communi::IrcMessage *message)
|
||||||
std::string roomID = iterator.value().toString().toStdString();
|
std::string roomID = iterator.value().toString().toStdString();
|
||||||
|
|
||||||
auto channel = QString(message->toData()).split("#").at(1);
|
auto channel = QString(message->toData()).split("#").at(1);
|
||||||
channelManager.getChannel(channel)->setRoomID(roomID);
|
channelManager.getTwitchChannel(channel)->setRoomID(roomID);
|
||||||
|
|
||||||
this->resources.loadChannelData(roomID);
|
this->resources.loadChannelData(roomID);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ class Message
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// explicit Message(const QString &text);
|
// explicit Message(const QString &text);
|
||||||
//explicit Message(const QString &text, const std::vector<messages::Word> &words,
|
// explicit Message(const QString &text, const std::vector<messages::Word> &words,
|
||||||
// const bool &highlight);
|
// const bool &highlight);
|
||||||
|
|
||||||
bool getCanHighlightTab() const;
|
bool getCanHighlightTab() const;
|
||||||
|
@ -39,6 +39,7 @@ public:
|
||||||
const QString &getId() const;
|
const QString &getId() const;
|
||||||
|
|
||||||
const QString text;
|
const QString text;
|
||||||
|
bool centered = false;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static LazyLoadedImage *badgeStaff;
|
static LazyLoadedImage *badgeStaff;
|
||||||
|
|
|
@ -12,7 +12,7 @@ MessageBuilder::MessageBuilder()
|
||||||
_parseTime = std::chrono::system_clock::now();
|
_parseTime = std::chrono::system_clock::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedMessage MessageBuilder::build()
|
SharedMessage MessageBuilder::getMessage()
|
||||||
{
|
{
|
||||||
return this->message;
|
return this->message;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ class MessageBuilder
|
||||||
public:
|
public:
|
||||||
MessageBuilder();
|
MessageBuilder();
|
||||||
|
|
||||||
SharedMessage build();
|
SharedMessage getMessage();
|
||||||
|
|
||||||
void appendWord(const Word &&word);
|
void appendWord(const Word &&word);
|
||||||
void appendTimestamp();
|
void appendTimestamp();
|
||||||
|
|
|
@ -129,7 +129,7 @@ bool MessageRef::layout(int width, bool enableEmoteMargins)
|
||||||
|
|
||||||
// word wrapping
|
// word wrapping
|
||||||
if (word.isText() && word.getWidth() + MARGIN_LEFT > right) {
|
if (word.isText() && word.getWidth() + MARGIN_LEFT > right) {
|
||||||
alignWordParts(lineStart, lineHeight);
|
alignWordParts(lineStart, lineHeight, width);
|
||||||
|
|
||||||
y += lineHeight;
|
y += lineHeight;
|
||||||
|
|
||||||
|
@ -183,7 +183,7 @@ bool MessageRef::layout(int width, bool enableEmoteMargins)
|
||||||
first = false;
|
first = false;
|
||||||
} else {
|
} else {
|
||||||
// doesn't fit in the line
|
// doesn't fit in the line
|
||||||
alignWordParts(lineStart, lineHeight);
|
alignWordParts(lineStart, lineHeight, width);
|
||||||
|
|
||||||
y += lineHeight;
|
y += lineHeight;
|
||||||
|
|
||||||
|
@ -201,7 +201,7 @@ bool MessageRef::layout(int width, bool enableEmoteMargins)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
alignWordParts(lineStart, lineHeight);
|
alignWordParts(lineStart, lineHeight, width);
|
||||||
|
|
||||||
if (_height != y + lineHeight) {
|
if (_height != y + lineHeight) {
|
||||||
sizeChanged = true;
|
sizeChanged = true;
|
||||||
|
@ -224,12 +224,18 @@ const std::vector<WordPart> &MessageRef::getWordParts() const
|
||||||
return _wordParts;
|
return _wordParts;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageRef::alignWordParts(int lineStart, int lineHeight)
|
void MessageRef::alignWordParts(int lineStart, int lineHeight, int width)
|
||||||
{
|
{
|
||||||
for (size_t i = lineStart; i < _wordParts.size(); i++) {
|
int xOffset = 0;
|
||||||
WordPart &wordPart2 = _wordParts.at(i);
|
|
||||||
|
|
||||||
wordPart2.setY(wordPart2.getY() + lineHeight);
|
if (this->_message->centered && _wordParts.size() > 0) {
|
||||||
|
xOffset = (width - this->_wordParts.at(_wordParts.size() - 1).getRight()) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = lineStart; i < this->_wordParts.size(); i++) {
|
||||||
|
WordPart &wordPart2 = this->_wordParts.at(i);
|
||||||
|
|
||||||
|
wordPart2.setPosition(wordPart2.getX() + xOffset, wordPart2.getY() + lineHeight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ private:
|
||||||
Word::Type _currentWordTypes = Word::None;
|
Word::Type _currentWordTypes = Word::None;
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
void alignWordParts(int lineStart, int lineHeight);
|
void alignWordParts(int lineStart, int lineHeight, int width);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace messages
|
} // namespace messages
|
||||||
|
|
|
@ -77,9 +77,11 @@ public:
|
||||||
EmojiImage = (1 << 23),
|
EmojiImage = (1 << 23),
|
||||||
EmojiText = (1 << 24),
|
EmojiText = (1 << 24),
|
||||||
|
|
||||||
|
AlwaysShow = (1 << 25),
|
||||||
|
|
||||||
Default = TimestampNoSeconds | Badges | Username | BitsStatic | FfzEmoteImage |
|
Default = TimestampNoSeconds | Badges | Username | BitsStatic | FfzEmoteImage |
|
||||||
BttvEmoteImage | BttvGifEmoteImage | TwitchEmoteImage | BitsAmount | Text |
|
BttvEmoteImage | BttvGifEmoteImage | TwitchEmoteImage | BitsAmount | Text |
|
||||||
ButtonBan | ButtonTimeout
|
ButtonBan | ButtonTimeout | AlwaysShow
|
||||||
};
|
};
|
||||||
|
|
||||||
Word()
|
Word()
|
||||||
|
|
|
@ -146,6 +146,8 @@ void SettingsManager::updateWordTypeMask()
|
||||||
|
|
||||||
newMaskUint |= Word::Username;
|
newMaskUint |= Word::Username;
|
||||||
|
|
||||||
|
newMaskUint |= Word::AlwaysShow;
|
||||||
|
|
||||||
Word::Type newMask = static_cast<Word::Type>(newMaskUint);
|
Word::Type newMask = static_cast<Word::Type>(newMaskUint);
|
||||||
|
|
||||||
if (newMask != _wordTypeMask) {
|
if (newMask != _wordTypeMask) {
|
||||||
|
|
80
src/twitch/twitchchannel.cpp
Normal file
80
src/twitch/twitchchannel.cpp
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
#include "twitchchannel.hpp"
|
||||||
|
#include "emotemanager.hpp"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
namespace twitch {
|
||||||
|
|
||||||
|
TwitchChannel::TwitchChannel(EmoteManager &emoteManager, IrcManager &ircManager,
|
||||||
|
const QString &channelName, bool isSpecial)
|
||||||
|
: emoteManager(emoteManager)
|
||||||
|
, ircManager(ircManager)
|
||||||
|
// , name(channelName)
|
||||||
|
, bttvChannelEmotes(new EmoteMap)
|
||||||
|
, ffzChannelEmotes(new EmoteMap)
|
||||||
|
, subLink("https://www.twitch.tv/" + name + "/subscribe?ref=in_chat_subscriber_link")
|
||||||
|
, channelLink("https://twitch.tv/" + name)
|
||||||
|
, popoutPlayerLink("https://player.twitch.tv/?channel=" + name)
|
||||||
|
, isLive(false)
|
||||||
|
, isSpecial(isSpecial)
|
||||||
|
{
|
||||||
|
this->name = channelName;
|
||||||
|
|
||||||
|
qDebug() << "Open twitch channel:" << this->name;
|
||||||
|
|
||||||
|
if (!isSpecial) {
|
||||||
|
this->reloadChannelEmotes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TwitchChannel::isEmpty() const
|
||||||
|
{
|
||||||
|
return this->name.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &TwitchChannel::getSubLink() const
|
||||||
|
{
|
||||||
|
return this->subLink;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TwitchChannel::canSendMessage() const
|
||||||
|
{
|
||||||
|
return !this->isEmpty() && !this->isSpecial;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &TwitchChannel::getChannelLink() const
|
||||||
|
{
|
||||||
|
return this->channelLink;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &TwitchChannel::getPopoutPlayerLink() const
|
||||||
|
{
|
||||||
|
return this->popoutPlayerLink;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TwitchChannel::setRoomID(std::string id)
|
||||||
|
{
|
||||||
|
this->roomID = id;
|
||||||
|
this->roomIDchanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TwitchChannel::reloadChannelEmotes()
|
||||||
|
{
|
||||||
|
printf("[TwitchChannel:%s] Reloading channel emotes\n", qPrintable(this->name));
|
||||||
|
|
||||||
|
this->emoteManager.reloadBTTVChannelEmotes(this->name, this->bttvChannelEmotes);
|
||||||
|
this->emoteManager.reloadFFZChannelEmotes(this->name, this->ffzChannelEmotes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TwitchChannel::sendMessage(const QString &message)
|
||||||
|
{
|
||||||
|
qDebug() << "TwitchChannel send message: " << message;
|
||||||
|
|
||||||
|
// Do last message processing
|
||||||
|
QString parsedMessage = this->emoteManager.replaceShortCodes(message);
|
||||||
|
|
||||||
|
this->ircManager.sendMessage(this->name, parsedMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
49
src/twitch/twitchchannel.hpp
Normal file
49
src/twitch/twitchchannel.hpp
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "channel.hpp"
|
||||||
|
#include "concurrentmap.hpp"
|
||||||
|
#include "ircmanager.hpp"
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
namespace twitch {
|
||||||
|
|
||||||
|
class TwitchChannel : public Channel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit TwitchChannel(EmoteManager &emoteManager, IrcManager &ircManager,
|
||||||
|
const QString &channelName, bool isSpecial = false);
|
||||||
|
|
||||||
|
void reloadChannelEmotes();
|
||||||
|
|
||||||
|
bool isEmpty() const override;
|
||||||
|
bool canSendMessage() const override;
|
||||||
|
void sendMessage(const QString &message) override;
|
||||||
|
|
||||||
|
const QString &getSubLink() const;
|
||||||
|
const QString &getChannelLink() const;
|
||||||
|
const QString &getPopoutPlayerLink() const;
|
||||||
|
|
||||||
|
void setRoomID(std::string id);
|
||||||
|
boost::signals2::signal<void()> roomIDchanged;
|
||||||
|
|
||||||
|
std::string roomID;
|
||||||
|
bool isLive;
|
||||||
|
QString streamViewerCount;
|
||||||
|
QString streamStatus;
|
||||||
|
QString streamGame;
|
||||||
|
QString streamUptime;
|
||||||
|
|
||||||
|
const std::shared_ptr<EmoteMap> bttvChannelEmotes;
|
||||||
|
const std::shared_ptr<EmoteMap> ffzChannelEmotes;
|
||||||
|
|
||||||
|
private:
|
||||||
|
EmoteManager &emoteManager;
|
||||||
|
IrcManager &ircManager;
|
||||||
|
|
||||||
|
QString subLink;
|
||||||
|
QString channelLink;
|
||||||
|
QString popoutPlayerLink;
|
||||||
|
bool isSpecial;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,12 +15,13 @@ using namespace chatterino::messages;
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
namespace twitch {
|
namespace twitch {
|
||||||
|
|
||||||
TwitchMessageBuilder::TwitchMessageBuilder(Channel *_channel, Resources &_resources,
|
TwitchMessageBuilder::TwitchMessageBuilder(TwitchChannel *_channel, Resources &_resources,
|
||||||
EmoteManager &_emoteManager,
|
EmoteManager &_emoteManager,
|
||||||
WindowManager &_windowManager,
|
WindowManager &_windowManager,
|
||||||
const Communi::IrcPrivateMessage *_ircMessage,
|
const Communi::IrcPrivateMessage *_ircMessage,
|
||||||
const messages::MessageParseArgs &_args)
|
const messages::MessageParseArgs &_args)
|
||||||
: channel(_channel)
|
: channel(_channel)
|
||||||
|
, twitchChannel(_channel)
|
||||||
, resources(_resources)
|
, resources(_resources)
|
||||||
, windowManager(_windowManager)
|
, windowManager(_windowManager)
|
||||||
, colorScheme(this->windowManager.colorScheme)
|
, colorScheme(this->windowManager.colorScheme)
|
||||||
|
@ -249,7 +250,7 @@ SharedMessage TwitchMessageBuilder::parse()
|
||||||
// HighlightTab = false;
|
// HighlightTab = false;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
return this->build();
|
return this->getMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TwitchMessageBuilder::parseMessageID()
|
void TwitchMessageBuilder::parseMessageID()
|
||||||
|
@ -264,11 +265,12 @@ void TwitchMessageBuilder::parseMessageID()
|
||||||
void TwitchMessageBuilder::parseRoomID()
|
void TwitchMessageBuilder::parseRoomID()
|
||||||
{
|
{
|
||||||
auto iterator = this->tags.find("room-id");
|
auto iterator = this->tags.find("room-id");
|
||||||
|
|
||||||
if (iterator != std::end(this->tags)) {
|
if (iterator != std::end(this->tags)) {
|
||||||
this->roomID = iterator.value().toString().toStdString();
|
this->roomID = iterator.value().toString().toStdString();
|
||||||
|
|
||||||
if (this->channel->roomID.empty()) {
|
if (this->twitchChannel->roomID.empty()) {
|
||||||
this->channel->roomID = this->roomID;
|
this->twitchChannel->roomID = this->roomID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -503,13 +505,13 @@ bool TwitchMessageBuilder::tryAppendEmote(QString &emoteString)
|
||||||
if (emoteManager.bttvGlobalEmotes.tryGet(emoteString, emoteData)) {
|
if (emoteManager.bttvGlobalEmotes.tryGet(emoteString, emoteData)) {
|
||||||
// BTTV Global Emote
|
// BTTV Global Emote
|
||||||
return this->appendEmote(emoteData);
|
return this->appendEmote(emoteData);
|
||||||
} else if (this->channel->bttvChannelEmotes.tryGet(emoteString, emoteData)) {
|
} else if (this->twitchChannel->bttvChannelEmotes->tryGet(emoteString, emoteData)) {
|
||||||
// BTTV Channel Emote
|
// BTTV Channel Emote
|
||||||
return this->appendEmote(emoteData);
|
return this->appendEmote(emoteData);
|
||||||
} else if (emoteManager.ffzGlobalEmotes.tryGet(emoteString, emoteData)) {
|
} else if (emoteManager.ffzGlobalEmotes.tryGet(emoteString, emoteData)) {
|
||||||
// FFZ Global Emote
|
// FFZ Global Emote
|
||||||
return this->appendEmote(emoteData);
|
return this->appendEmote(emoteData);
|
||||||
} else if (this->channel->ffzChannelEmotes.tryGet(emoteString, emoteData)) {
|
} else if (this->twitchChannel->ffzChannelEmotes->tryGet(emoteString, emoteData)) {
|
||||||
// FFZ Channel Emote
|
// FFZ Channel Emote
|
||||||
return this->appendEmote(emoteData);
|
return this->appendEmote(emoteData);
|
||||||
} else if (emoteManager.getChatterinoEmotes().tryGet(emoteString, emoteData)) {
|
} else if (emoteManager.getChatterinoEmotes().tryGet(emoteString, emoteData)) {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "emotemanager.hpp"
|
#include "emotemanager.hpp"
|
||||||
#include "messages/messagebuilder.hpp"
|
#include "messages/messagebuilder.hpp"
|
||||||
#include "resources.hpp"
|
#include "resources.hpp"
|
||||||
|
#include "twitch/twitchchannel.hpp"
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
@ -26,12 +27,13 @@ public:
|
||||||
|
|
||||||
TwitchMessageBuilder() = delete;
|
TwitchMessageBuilder() = delete;
|
||||||
|
|
||||||
explicit TwitchMessageBuilder(Channel *_channel, Resources &_resources,
|
explicit TwitchMessageBuilder(TwitchChannel *_channel, Resources &_resources,
|
||||||
EmoteManager &_emoteManager, WindowManager &_windowManager,
|
EmoteManager &_emoteManager, WindowManager &_windowManager,
|
||||||
const Communi::IrcPrivateMessage *_ircMessage,
|
const Communi::IrcPrivateMessage *_ircMessage,
|
||||||
const messages::MessageParseArgs &_args);
|
const messages::MessageParseArgs &_args);
|
||||||
|
|
||||||
Channel *channel;
|
Channel *channel;
|
||||||
|
TwitchChannel *twitchChannel;
|
||||||
Resources &resources;
|
Resources &resources;
|
||||||
WindowManager &windowManager;
|
WindowManager &windowManager;
|
||||||
ColorScheme &colorScheme;
|
ColorScheme &colorScheme;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "widgets/chatwidgetview.hpp"
|
#include "widgets/channelview.hpp"
|
||||||
#include "channelmanager.hpp"
|
#include "channelmanager.hpp"
|
||||||
#include "colorscheme.hpp"
|
#include "colorscheme.hpp"
|
||||||
#include "messages/limitedqueuesnapshot.hpp"
|
#include "messages/limitedqueuesnapshot.hpp"
|
||||||
|
@ -20,14 +20,15 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
using namespace chatterino::messages;
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
namespace widgets {
|
namespace widgets {
|
||||||
|
|
||||||
ChatWidgetView::ChatWidgetView(ChatWidget *_chatWidget)
|
ChannelView::ChannelView(BaseWidget *parent)
|
||||||
: BaseWidget(_chatWidget)
|
: BaseWidget(parent)
|
||||||
, chatWidget(_chatWidget)
|
|
||||||
, scrollBar(this)
|
, scrollBar(this)
|
||||||
, userPopupWidget(_chatWidget->getChannelRef())
|
, userPopupWidget(std::shared_ptr<Channel>())
|
||||||
{
|
{
|
||||||
#ifndef Q_OS_MAC
|
#ifndef Q_OS_MAC
|
||||||
// this->setAttribute(Qt::WA_OpaquePaintEvent);
|
// this->setAttribute(Qt::WA_OpaquePaintEvent);
|
||||||
|
@ -35,7 +36,7 @@ ChatWidgetView::ChatWidgetView(ChatWidget *_chatWidget)
|
||||||
this->setMouseTracking(true);
|
this->setMouseTracking(true);
|
||||||
|
|
||||||
QObject::connect(&SettingsManager::getInstance(), &SettingsManager::wordTypeMaskChanged, this,
|
QObject::connect(&SettingsManager::getInstance(), &SettingsManager::wordTypeMaskChanged, this,
|
||||||
&ChatWidgetView::wordTypeMaskChanged);
|
&ChannelView::wordTypeMaskChanged);
|
||||||
|
|
||||||
this->scrollBar.getCurrentValueChanged().connect([this] {
|
this->scrollBar.getCurrentValueChanged().connect([this] {
|
||||||
// Whenever the scrollbar value has been changed, re-render the ChatWidgetView
|
// Whenever the scrollbar value has been changed, re-render the ChatWidgetView
|
||||||
|
@ -45,15 +46,15 @@ ChatWidgetView::ChatWidgetView(ChatWidget *_chatWidget)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatWidgetView::~ChatWidgetView()
|
ChannelView::~ChannelView()
|
||||||
{
|
{
|
||||||
QObject::disconnect(&SettingsManager::getInstance(), &SettingsManager::wordTypeMaskChanged,
|
QObject::disconnect(&SettingsManager::getInstance(), &SettingsManager::wordTypeMaskChanged,
|
||||||
this, &ChatWidgetView::wordTypeMaskChanged);
|
this, &ChannelView::wordTypeMaskChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChatWidgetView::layoutMessages()
|
bool ChannelView::layoutMessages()
|
||||||
{
|
{
|
||||||
auto messages = this->chatWidget->getMessagesSnapshot();
|
auto messages = this->getMessagesSnapshot();
|
||||||
|
|
||||||
if (messages.getLength() == 0) {
|
if (messages.getLength() == 0) {
|
||||||
this->scrollBar.setVisible(false);
|
this->scrollBar.setVisible(false);
|
||||||
|
@ -130,21 +131,30 @@ bool ChatWidgetView::layoutMessages()
|
||||||
return redraw;
|
return redraw;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatWidgetView::updateGifEmotes()
|
void ChannelView::clearMessages()
|
||||||
|
{
|
||||||
|
// Clear all stored messages in this chat widget
|
||||||
|
this->messages.clear();
|
||||||
|
|
||||||
|
// Layout chat widget messages, and force an update regardless if there are no messages
|
||||||
|
this->layoutMessages();
|
||||||
|
this->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChannelView::updateGifEmotes()
|
||||||
{
|
{
|
||||||
this->onlyUpdateEmotes = true;
|
this->onlyUpdateEmotes = true;
|
||||||
this->update();
|
this->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
ScrollBar &ChatWidgetView::getScrollBar()
|
ScrollBar &ChannelView::getScrollBar()
|
||||||
{
|
{
|
||||||
return this->scrollBar;
|
return this->scrollBar;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ChatWidgetView::getSelectedText() const
|
QString ChannelView::getSelectedText()
|
||||||
{
|
{
|
||||||
messages::LimitedQueueSnapshot<messages::SharedMessageRef> messages =
|
LimitedQueueSnapshot<SharedMessageRef> messages = this->getMessagesSnapshot();
|
||||||
this->chatWidget->getMessagesSnapshot();
|
|
||||||
|
|
||||||
QString text;
|
QString text;
|
||||||
bool isSingleMessage = this->selection.isSingleMessage();
|
bool isSingleMessage = this->selection.isSingleMessage();
|
||||||
|
@ -232,7 +242,72 @@ QString ChatWidgetView::getSelectedText() const
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatWidgetView::resizeEvent(QResizeEvent *)
|
messages::LimitedQueueSnapshot<SharedMessageRef> ChannelView::getMessagesSnapshot()
|
||||||
|
{
|
||||||
|
return this->messages.getSnapshot();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChannelView::setChannel(std::shared_ptr<Channel> channel)
|
||||||
|
{
|
||||||
|
if (this->channel) {
|
||||||
|
this->detachChannel();
|
||||||
|
}
|
||||||
|
this->messages.clear();
|
||||||
|
|
||||||
|
// on new message
|
||||||
|
this->messageAppendedConnection =
|
||||||
|
channel->messageAppended.connect([this](SharedMessage &message) {
|
||||||
|
SharedMessageRef deleted;
|
||||||
|
|
||||||
|
auto messageRef = new MessageRef(message);
|
||||||
|
|
||||||
|
if (this->messages.appendItem(SharedMessageRef(messageRef), deleted)) {
|
||||||
|
qreal value = std::max(0.0, this->getScrollBar().getDesiredValue() - 1);
|
||||||
|
|
||||||
|
this->getScrollBar().setDesiredValue(value, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
layoutMessages();
|
||||||
|
update();
|
||||||
|
});
|
||||||
|
|
||||||
|
// on message removed
|
||||||
|
this->messageRemovedConnection =
|
||||||
|
channel->messageRemovedFromStart.connect([this](SharedMessage &) {
|
||||||
|
this->selection.min.messageIndex--;
|
||||||
|
this->selection.max.messageIndex--;
|
||||||
|
this->selection.start.messageIndex--;
|
||||||
|
this->selection.end.messageIndex--;
|
||||||
|
|
||||||
|
layoutMessages();
|
||||||
|
update();
|
||||||
|
});
|
||||||
|
|
||||||
|
auto snapshot = channel->getMessageSnapshot();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < snapshot.getLength(); i++) {
|
||||||
|
SharedMessageRef deleted;
|
||||||
|
|
||||||
|
auto messageRef = new MessageRef(snapshot[i]);
|
||||||
|
|
||||||
|
this->messages.appendItem(SharedMessageRef(messageRef), deleted);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->channel = channel;
|
||||||
|
|
||||||
|
this->userPopupWidget.setChannel(channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChannelView::detachChannel()
|
||||||
|
{
|
||||||
|
// on message added
|
||||||
|
this->messageAppendedConnection.disconnect();
|
||||||
|
|
||||||
|
// on message removed
|
||||||
|
this->messageRemovedConnection.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChannelView::resizeEvent(QResizeEvent *)
|
||||||
{
|
{
|
||||||
this->scrollBar.resize(this->scrollBar.width(), height());
|
this->scrollBar.resize(this->scrollBar.width(), height());
|
||||||
this->scrollBar.move(width() - this->scrollBar.width(), 0);
|
this->scrollBar.move(width() - this->scrollBar.width(), 0);
|
||||||
|
@ -242,7 +317,7 @@ void ChatWidgetView::resizeEvent(QResizeEvent *)
|
||||||
this->update();
|
this->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatWidgetView::setSelection(const SelectionItem &start, const SelectionItem &end)
|
void ChannelView::setSelection(const SelectionItem &start, const SelectionItem &end)
|
||||||
{
|
{
|
||||||
// selections
|
// selections
|
||||||
this->selection = Selection(start, end);
|
this->selection = Selection(start, end);
|
||||||
|
@ -251,7 +326,7 @@ void ChatWidgetView::setSelection(const SelectionItem &start, const SelectionIte
|
||||||
// << max.charIndex;
|
// << max.charIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatWidgetView::paintEvent(QPaintEvent * /*event*/)
|
void ChannelView::paintEvent(QPaintEvent * /*event*/)
|
||||||
{
|
{
|
||||||
QPainter painter(this);
|
QPainter painter(this);
|
||||||
|
|
||||||
|
@ -288,9 +363,9 @@ void ChatWidgetView::paintEvent(QPaintEvent * /*event*/)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatWidgetView::drawMessages(QPainter &painter)
|
void ChannelView::drawMessages(QPainter &painter)
|
||||||
{
|
{
|
||||||
auto messages = this->chatWidget->getMessagesSnapshot();
|
auto messages = this->getMessagesSnapshot();
|
||||||
|
|
||||||
size_t start = this->scrollBar.getCurrentValue();
|
size_t start = this->scrollBar.getCurrentValue();
|
||||||
|
|
||||||
|
@ -341,7 +416,9 @@ void ChatWidgetView::drawMessages(QPainter &painter)
|
||||||
|
|
||||||
messageRef->buffer = bufferPtr;
|
messageRef->buffer = bufferPtr;
|
||||||
|
|
||||||
|
// if (buffer != nullptr) {
|
||||||
painter.drawPixmap(0, y, *buffer);
|
painter.drawPixmap(0, y, *buffer);
|
||||||
|
// }
|
||||||
|
|
||||||
y += messageRef->getHeight();
|
y += messageRef->getHeight();
|
||||||
|
|
||||||
|
@ -351,7 +428,7 @@ void ChatWidgetView::drawMessages(QPainter &painter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatWidgetView::updateMessageBuffer(messages::MessageRef *messageRef, QPixmap *buffer,
|
void ChannelView::updateMessageBuffer(messages::MessageRef *messageRef, QPixmap *buffer,
|
||||||
int messageIndex)
|
int messageIndex)
|
||||||
{
|
{
|
||||||
QPainter painter(buffer);
|
QPainter painter(buffer);
|
||||||
|
@ -403,7 +480,7 @@ void ChatWidgetView::updateMessageBuffer(messages::MessageRef *messageRef, QPixm
|
||||||
messageRef->updateBuffer = false;
|
messageRef->updateBuffer = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatWidgetView::drawMessageSelection(QPainter &painter, messages::MessageRef *messageRef,
|
void ChannelView::drawMessageSelection(QPainter &painter, messages::MessageRef *messageRef,
|
||||||
int messageIndex, int bufferHeight)
|
int messageIndex, int bufferHeight)
|
||||||
{
|
{
|
||||||
if (this->selection.min.messageIndex > messageIndex ||
|
if (this->selection.min.messageIndex > messageIndex ||
|
||||||
|
@ -552,7 +629,7 @@ void ChatWidgetView::drawMessageSelection(QPainter &painter, messages::MessageRe
|
||||||
painter.fillRect(rect, selectionColor);
|
painter.fillRect(rect, selectionColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatWidgetView::wheelEvent(QWheelEvent *event)
|
void ChannelView::wheelEvent(QWheelEvent *event)
|
||||||
{
|
{
|
||||||
if (this->scrollBar.isVisible()) {
|
if (this->scrollBar.isVisible()) {
|
||||||
auto mouseMultiplier = SettingsManager::getInstance().mouseScrollMultiplier.get();
|
auto mouseMultiplier = SettingsManager::getInstance().mouseScrollMultiplier.get();
|
||||||
|
@ -562,7 +639,7 @@ void ChatWidgetView::wheelEvent(QWheelEvent *event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatWidgetView::mouseMoveEvent(QMouseEvent *event)
|
void ChannelView::mouseMoveEvent(QMouseEvent *event)
|
||||||
{
|
{
|
||||||
std::shared_ptr<messages::MessageRef> message;
|
std::shared_ptr<messages::MessageRef> message;
|
||||||
QPoint relativePos;
|
QPoint relativePos;
|
||||||
|
@ -594,10 +671,8 @@ void ChatWidgetView::mouseMoveEvent(QMouseEvent *event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatWidgetView::mousePressEvent(QMouseEvent *event)
|
void ChannelView::mousePressEvent(QMouseEvent *event)
|
||||||
{
|
{
|
||||||
this->chatWidget->giveFocus(Qt::MouseFocusReason);
|
|
||||||
|
|
||||||
this->isMouseDown = true;
|
this->isMouseDown = true;
|
||||||
|
|
||||||
this->lastPressPosition = event->screenPos();
|
this->lastPressPosition = event->screenPos();
|
||||||
|
@ -621,7 +696,7 @@ void ChatWidgetView::mousePressEvent(QMouseEvent *event)
|
||||||
this->repaint();
|
this->repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatWidgetView::mouseReleaseEvent(QMouseEvent *event)
|
void ChannelView::mouseReleaseEvent(QMouseEvent *event)
|
||||||
{
|
{
|
||||||
if (!this->isMouseDown) {
|
if (!this->isMouseDown) {
|
||||||
// We didn't grab the mouse press, so we shouldn't be handling the mouse
|
// We didn't grab the mouse press, so we shouldn't be handling the mouse
|
||||||
|
@ -682,10 +757,10 @@ void ChatWidgetView::mouseReleaseEvent(QMouseEvent *event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChatWidgetView::tryGetMessageAt(QPoint p, std::shared_ptr<messages::MessageRef> &_message,
|
bool ChannelView::tryGetMessageAt(QPoint p, std::shared_ptr<messages::MessageRef> &_message,
|
||||||
QPoint &relativePos, int &index)
|
QPoint &relativePos, int &index)
|
||||||
{
|
{
|
||||||
auto messages = this->chatWidget->getMessagesSnapshot();
|
auto messages = this->getMessagesSnapshot();
|
||||||
|
|
||||||
size_t start = this->scrollBar.getCurrentValue();
|
size_t start = this->scrollBar.getCurrentValue();
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "channel.hpp"
|
#include "channel.hpp"
|
||||||
#include "messages/lazyloadedimage.hpp"
|
#include "messages/lazyloadedimage.hpp"
|
||||||
|
#include "messages/limitedqueuesnapshot.hpp"
|
||||||
#include "messages/messageref.hpp"
|
#include "messages/messageref.hpp"
|
||||||
#include "messages/word.hpp"
|
#include "messages/word.hpp"
|
||||||
#include "widgets/accountpopup.hpp"
|
#include "widgets/accountpopup.hpp"
|
||||||
|
@ -13,6 +14,8 @@
|
||||||
#include <QWheelEvent>
|
#include <QWheelEvent>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
|
#include <boost/signals2.hpp>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
namespace widgets {
|
namespace widgets {
|
||||||
|
|
||||||
|
@ -75,21 +78,23 @@ struct Selection {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ChatWidget;
|
class ChannelView : public BaseWidget
|
||||||
|
|
||||||
class ChatWidgetView : public BaseWidget
|
|
||||||
{
|
{
|
||||||
friend class ChatWidget;
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ChatWidgetView(ChatWidget *_chatWidget);
|
explicit ChannelView(BaseWidget *parent = 0);
|
||||||
~ChatWidgetView();
|
~ChannelView();
|
||||||
|
|
||||||
bool layoutMessages();
|
|
||||||
|
|
||||||
void updateGifEmotes();
|
void updateGifEmotes();
|
||||||
ScrollBar &getScrollBar();
|
ScrollBar &getScrollBar();
|
||||||
QString getSelectedText() const;
|
QString getSelectedText();
|
||||||
|
|
||||||
|
void setChannel(std::shared_ptr<Channel> channel);
|
||||||
|
messages::LimitedQueueSnapshot<messages::SharedMessageRef> getMessagesSnapshot();
|
||||||
|
bool layoutMessages();
|
||||||
|
|
||||||
|
void clearMessages();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void resizeEvent(QResizeEvent *) override;
|
virtual void resizeEvent(QResizeEvent *) override;
|
||||||
|
@ -110,15 +115,17 @@ private:
|
||||||
QRect rect;
|
QRect rect;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void detachChannel();
|
||||||
|
|
||||||
void drawMessages(QPainter &painter);
|
void drawMessages(QPainter &painter);
|
||||||
void updateMessageBuffer(messages::MessageRef *messageRef, QPixmap *buffer, int messageIndex);
|
void updateMessageBuffer(messages::MessageRef *messageRef, QPixmap *buffer, int messageIndex);
|
||||||
void drawMessageSelection(QPainter &painter, messages::MessageRef *messageRef, int messageIndex,
|
void drawMessageSelection(QPainter &painter, messages::MessageRef *messageRef, int messageIndex,
|
||||||
int bufferHeight);
|
int bufferHeight);
|
||||||
void setSelection(const SelectionItem &start, const SelectionItem &end);
|
void setSelection(const SelectionItem &start, const SelectionItem &end);
|
||||||
|
|
||||||
std::vector<GifEmoteData> gifEmotes;
|
std::shared_ptr<Channel> channel;
|
||||||
|
|
||||||
ChatWidget *const chatWidget;
|
std::vector<GifEmoteData> gifEmotes;
|
||||||
|
|
||||||
ScrollBar scrollBar;
|
ScrollBar scrollBar;
|
||||||
|
|
||||||
|
@ -136,6 +143,11 @@ private:
|
||||||
Selection selection;
|
Selection selection;
|
||||||
bool selecting = false;
|
bool selecting = false;
|
||||||
|
|
||||||
|
messages::LimitedQueue<messages::SharedMessageRef> messages;
|
||||||
|
|
||||||
|
boost::signals2::connection messageAppendedConnection;
|
||||||
|
boost::signals2::connection messageRemovedConnection;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void wordTypeMaskChanged()
|
void wordTypeMaskChanged()
|
||||||
{
|
{
|
|
@ -18,6 +18,7 @@
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QShortcut>
|
#include <QShortcut>
|
||||||
|
#include <QTimer>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <boost/signals2.hpp>
|
#include <boost/signals2.hpp>
|
||||||
|
|
||||||
|
@ -52,7 +53,7 @@ ChatWidget::ChatWidget(ChannelManager &_channelManager, NotebookPage *parent)
|
||||||
, vbox(this)
|
, vbox(this)
|
||||||
, header(this)
|
, header(this)
|
||||||
, view(this)
|
, view(this)
|
||||||
, input(this)
|
, input(this, _channelManager.getEmoteManager())
|
||||||
{
|
{
|
||||||
this->vbox.setSpacing(0);
|
this->vbox.setSpacing(0);
|
||||||
this->vbox.setMargin(1);
|
this->vbox.setMargin(1);
|
||||||
|
@ -80,11 +81,15 @@ ChatWidget::ChatWidget(ChannelManager &_channelManager, NotebookPage *parent)
|
||||||
this->channelNameUpdated(this->channelName.getValue());
|
this->channelNameUpdated(this->channelName.getValue());
|
||||||
|
|
||||||
this->input.textInput.installEventFilter(parent);
|
this->input.textInput.installEventFilter(parent);
|
||||||
|
|
||||||
|
connect(&view, &this->view.mousePressEvent, this, [&](QMouseEvent *) {
|
||||||
|
QTimer::singleShot(10, [this] { this->giveFocus(Qt::MouseFocusReason); });
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatWidget::~ChatWidget()
|
ChatWidget::~ChatWidget()
|
||||||
{
|
{
|
||||||
this->detachChannel();
|
channelNameUpdated("");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Channel> ChatWidget::getChannel() const
|
std::shared_ptr<Channel> ChatWidget::getChannel() const
|
||||||
|
@ -99,82 +104,33 @@ std::shared_ptr<Channel> &ChatWidget::getChannelRef()
|
||||||
|
|
||||||
void ChatWidget::setChannel(std::shared_ptr<Channel> _newChannel)
|
void ChatWidget::setChannel(std::shared_ptr<Channel> _newChannel)
|
||||||
{
|
{
|
||||||
|
this->view.setChannel(_newChannel);
|
||||||
|
|
||||||
this->channel = _newChannel;
|
this->channel = _newChannel;
|
||||||
this->channel->roomIDchanged.connect([this]() { this->header.checkLive(); });
|
|
||||||
|
|
||||||
this->view.userPopupWidget.setChannel(_newChannel);
|
twitch::TwitchChannel *twitchChannel = dynamic_cast<twitch::TwitchChannel *>(_newChannel.get());
|
||||||
|
if (twitchChannel != nullptr) {
|
||||||
// on new message
|
twitchChannel->roomIDchanged.connect([this]() { this->header.checkLive(); });
|
||||||
this->messageAppendedConnection =
|
|
||||||
this->channel->messageAppended.connect([this](SharedMessage &message) {
|
|
||||||
SharedMessageRef deleted;
|
|
||||||
|
|
||||||
auto messageRef = new MessageRef(message);
|
|
||||||
|
|
||||||
if (this->messages.appendItem(SharedMessageRef(messageRef), deleted)) {
|
|
||||||
qreal value = std::max(0.0, this->view.getScrollBar().getDesiredValue() - 1);
|
|
||||||
|
|
||||||
this->view.getScrollBar().setDesiredValue(value, false);
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
// on message removed
|
|
||||||
this->messageRemovedConnection =
|
|
||||||
this->channel->messageRemovedFromStart.connect([this](SharedMessage &) {
|
|
||||||
this->view.selection.min.messageIndex--;
|
|
||||||
this->view.selection.max.messageIndex--;
|
|
||||||
this->view.selection.start.messageIndex--;
|
|
||||||
this->view.selection.end.messageIndex--;
|
|
||||||
});
|
|
||||||
|
|
||||||
auto snapshot = this->channel->getMessageSnapshot();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < snapshot.getLength(); i++) {
|
|
||||||
SharedMessageRef deleted;
|
|
||||||
|
|
||||||
auto messageRef = new MessageRef(snapshot[i]);
|
|
||||||
|
|
||||||
this->messages.appendItem(SharedMessageRef(messageRef), deleted);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatWidget::detachChannel()
|
|
||||||
{
|
|
||||||
// on message added
|
|
||||||
this->messageAppendedConnection.disconnect();
|
|
||||||
|
|
||||||
// on message removed
|
|
||||||
this->messageRemovedConnection.disconnect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatWidget::channelNameUpdated(const std::string &newChannelName)
|
void ChatWidget::channelNameUpdated(const std::string &newChannelName)
|
||||||
{
|
{
|
||||||
// remove current channel
|
// remove current channel
|
||||||
if (!this->channel->isEmpty()) {
|
if (!this->channel->isEmpty()) {
|
||||||
this->channelManager.removeChannel(this->channel->name);
|
this->channelManager.removeTwitchChannel(this->channel->name);
|
||||||
|
|
||||||
this->detachChannel();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// update messages
|
// update messages
|
||||||
this->messages.clear();
|
|
||||||
|
|
||||||
if (newChannelName.empty()) {
|
if (newChannelName.empty()) {
|
||||||
this->channel = this->channelManager.emptyChannel;
|
this->setChannel(this->channelManager.emptyChannel);
|
||||||
} else {
|
} else {
|
||||||
this->setChannel(this->channelManager.addChannel(QString::fromStdString(newChannelName)));
|
this->setChannel(
|
||||||
|
this->channelManager.addTwitchChannel(QString::fromStdString(newChannelName)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// update header
|
// update header
|
||||||
this->header.updateChannelText();
|
this->header.updateChannelText();
|
||||||
|
|
||||||
// update view
|
|
||||||
this->layoutMessages(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
LimitedQueueSnapshot<SharedMessageRef> ChatWidget::getMessagesSnapshot()
|
|
||||||
{
|
|
||||||
return this->messages.getSnapshot();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChatWidget::showChangeChannelPopup(const char *dialogTitle, bool empty)
|
bool ChatWidget::showChangeChannelPopup(const char *dialogTitle, bool empty)
|
||||||
|
@ -202,9 +158,12 @@ bool ChatWidget::showChangeChannelPopup(const char *dialogTitle, bool empty)
|
||||||
|
|
||||||
void ChatWidget::layoutMessages(bool forceUpdate)
|
void ChatWidget::layoutMessages(bool forceUpdate)
|
||||||
{
|
{
|
||||||
if (this->view.layoutMessages() || forceUpdate) {
|
this->view.layoutMessages();
|
||||||
this->view.update();
|
this->view.update();
|
||||||
}
|
|
||||||
|
// if (this->view.layoutMessages() || forceUpdate) {
|
||||||
|
// this->view.update();
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatWidget::updateGifEmotes()
|
void ChatWidget::updateGifEmotes()
|
||||||
|
@ -285,11 +244,7 @@ void ChatWidget::doPopup()
|
||||||
|
|
||||||
void ChatWidget::doClearChat()
|
void ChatWidget::doClearChat()
|
||||||
{
|
{
|
||||||
// Clear all stored messages in this chat widget
|
view.clearMessages();
|
||||||
this->messages.clear();
|
|
||||||
|
|
||||||
// Layout chat widget messages, and force an update regardless if there are no messages
|
|
||||||
this->layoutMessages(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatWidget::doOpenChannel()
|
void ChatWidget::doOpenChannel()
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
#include "messages/word.hpp"
|
#include "messages/word.hpp"
|
||||||
#include "messages/wordpart.hpp"
|
#include "messages/wordpart.hpp"
|
||||||
#include "widgets/basewidget.hpp"
|
#include "widgets/basewidget.hpp"
|
||||||
|
#include "widgets/channelview.hpp"
|
||||||
#include "widgets/chatwidgetheader.hpp"
|
#include "widgets/chatwidgetheader.hpp"
|
||||||
#include "widgets/chatwidgetinput.hpp"
|
#include "widgets/chatwidgetinput.hpp"
|
||||||
#include "widgets/chatwidgetview.hpp"
|
|
||||||
|
|
||||||
#include <QFont>
|
#include <QFont>
|
||||||
#include <QShortcut>
|
#include <QShortcut>
|
||||||
|
@ -49,13 +49,13 @@ public:
|
||||||
std::shared_ptr<Channel> &getChannelRef();
|
std::shared_ptr<Channel> &getChannelRef();
|
||||||
|
|
||||||
bool showChangeChannelPopup(const char *dialogTitle, bool empty = false);
|
bool showChangeChannelPopup(const char *dialogTitle, bool empty = false);
|
||||||
messages::LimitedQueueSnapshot<messages::SharedMessageRef> getMessagesSnapshot();
|
|
||||||
void layoutMessages(bool forceUpdate = false);
|
|
||||||
void updateGifEmotes();
|
|
||||||
|
|
||||||
void giveFocus(Qt::FocusReason reason);
|
void giveFocus(Qt::FocusReason reason);
|
||||||
bool hasFocus() const;
|
bool hasFocus() const;
|
||||||
|
|
||||||
|
void layoutMessages(bool forceUpdate = false);
|
||||||
|
void updateGifEmotes();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void paintEvent(QPaintEvent *) override;
|
virtual void paintEvent(QPaintEvent *) override;
|
||||||
|
|
||||||
|
@ -67,24 +67,20 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setChannel(std::shared_ptr<Channel> newChannel);
|
void setChannel(std::shared_ptr<Channel> newChannel);
|
||||||
void detachChannel();
|
|
||||||
void doOpenAccountPopupWidget(AccountPopupWidget *widget, QString user);
|
void doOpenAccountPopupWidget(AccountPopupWidget *widget, QString user);
|
||||||
|
|
||||||
void channelNameUpdated(const std::string &newChannelName);
|
void channelNameUpdated(const std::string &newChannelName);
|
||||||
|
|
||||||
NotebookPage &parentPage;
|
NotebookPage &parentPage;
|
||||||
|
|
||||||
messages::LimitedQueue<messages::SharedMessageRef> messages;
|
|
||||||
|
|
||||||
std::shared_ptr<Channel> channel;
|
std::shared_ptr<Channel> channel;
|
||||||
|
|
||||||
QVBoxLayout vbox;
|
QVBoxLayout vbox;
|
||||||
ChatWidgetHeader header;
|
ChatWidgetHeader header;
|
||||||
ChatWidgetView view;
|
ChannelView view;
|
||||||
ChatWidgetInput input;
|
ChatWidgetInput input;
|
||||||
|
|
||||||
boost::signals2::connection messageAppendedConnection;
|
boost::signals2::connection channelIDChangedConnection;
|
||||||
boost::signals2::connection messageRemovedConnection;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void load(const boost::property_tree::ptree &tree);
|
void load(const boost::property_tree::ptree &tree);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "widgets/chatwidgetheader.hpp"
|
#include "widgets/chatwidgetheader.hpp"
|
||||||
#include "colorscheme.hpp"
|
#include "colorscheme.hpp"
|
||||||
|
#include "twitch/twitchchannel.hpp"
|
||||||
#include "util/urlfetch.hpp"
|
#include "util/urlfetch.hpp"
|
||||||
#include "widgets/chatwidget.hpp"
|
#include "widgets/chatwidget.hpp"
|
||||||
#include "widgets/notebookpage.hpp"
|
#include "widgets/notebookpage.hpp"
|
||||||
|
@ -81,16 +82,22 @@ void ChatWidgetHeader::updateChannelText()
|
||||||
if (channelName.empty()) {
|
if (channelName.empty()) {
|
||||||
this->channelNameLabel.setText("<no channel>");
|
this->channelNameLabel.setText("<no channel>");
|
||||||
} else {
|
} else {
|
||||||
if (this->chatWidget->getChannelRef()->isLive) {
|
auto channel = this->chatWidget->getChannel();
|
||||||
auto channel = this->chatWidget->getChannelRef();
|
|
||||||
|
twitch::TwitchChannel *twitchChannel = dynamic_cast<twitch::TwitchChannel *>(channel.get());
|
||||||
|
|
||||||
|
if (channel->isEmpty()) {
|
||||||
this->channelNameLabel.setText(QString::fromStdString(channelName) + " (live)");
|
this->channelNameLabel.setText(QString::fromStdString(channelName) + " (live)");
|
||||||
this->setToolTip(
|
if (twitchChannel != nullptr) {
|
||||||
"<style>.center { text-align: center; }</style>"
|
this->setToolTip("<style>.center { text-align: center; }</style>"
|
||||||
"<p class = \"center\">" +
|
"<p class = \"center\">" +
|
||||||
channel->streamStatus + "<br><br>" + channel->streamGame + "<br>"
|
twitchChannel->streamStatus + "<br><br>" +
|
||||||
|
twitchChannel->streamGame + "<br>"
|
||||||
"Live for " +
|
"Live for " +
|
||||||
channel->streamUptime + " with " + channel->streamViewerCount + " viewers"
|
twitchChannel->streamUptime + " with " +
|
||||||
|
twitchChannel->streamViewerCount + " viewers"
|
||||||
"</p>");
|
"</p>");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this->channelNameLabel.setText(QString::fromStdString(channelName));
|
this->channelNameLabel.setText(QString::fromStdString(channelName));
|
||||||
this->setToolTip("");
|
this->setToolTip("");
|
||||||
|
@ -157,7 +164,7 @@ void ChatWidgetHeader::mouseDoubleClickEvent(QMouseEvent *event)
|
||||||
|
|
||||||
void ChatWidgetHeader::leftButtonClicked()
|
void ChatWidgetHeader::leftButtonClicked()
|
||||||
{
|
{
|
||||||
QTimer::singleShot(100, [&] {
|
QTimer::singleShot(80, [&] {
|
||||||
this->leftMenu.move(this->leftLabel.mapToGlobal(QPoint(0, this->leftLabel.height())));
|
this->leftMenu.move(this->leftLabel.mapToGlobal(QPoint(0, this->leftLabel.height())));
|
||||||
this->leftMenu.show();
|
this->leftMenu.show();
|
||||||
});
|
});
|
||||||
|
@ -193,10 +200,18 @@ void ChatWidgetHeader::menuShowChangelog()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: this needs to be moved out of here
|
||||||
void ChatWidgetHeader::checkLive()
|
void ChatWidgetHeader::checkLive()
|
||||||
{
|
{
|
||||||
auto channel = this->chatWidget->getChannelRef();
|
twitch::TwitchChannel *channel =
|
||||||
|
dynamic_cast<twitch::TwitchChannel *>(this->chatWidget->getChannel().get());
|
||||||
|
|
||||||
|
if (channel == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto id = QString::fromStdString(channel->roomID);
|
auto id = QString::fromStdString(channel->roomID);
|
||||||
|
|
||||||
util::twitch::get("https://api.twitch.tv/kraken/streams/" + id, [=](QJsonObject obj) {
|
util::twitch::get("https://api.twitch.tv/kraken/streams/" + id, [=](QJsonObject obj) {
|
||||||
if (obj.value("stream").isNull()) {
|
if (obj.value("stream").isNull()) {
|
||||||
channel->isLive = false;
|
channel->isLive = false;
|
||||||
|
|
|
@ -23,12 +23,12 @@ ChatWidgetHeaderButton::ChatWidgetHeaderButton(BaseWidget *parent, int spacing)
|
||||||
this->setMouseEffectColor(QColor(255, 255, 255, 63));
|
this->setMouseEffectColor(QColor(255, 255, 255, 63));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatWidgetHeaderButton::paintEvent(QPaintEvent *)
|
// void ChatWidgetHeaderButton::paintEvent(QPaintEvent *)
|
||||||
{
|
//{
|
||||||
QPainter painter(this);
|
// QPainter painter(this);
|
||||||
|
|
||||||
this->fancyPaint(painter);
|
// this->fancyPaint(painter);
|
||||||
}
|
//}
|
||||||
|
|
||||||
} // namespace widgets
|
} // namespace widgets
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -28,7 +28,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void paintEvent(QPaintEvent *) override;
|
// virtual void paintEvent(QPaintEvent *) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct {
|
struct {
|
||||||
|
|
|
@ -13,9 +13,10 @@
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
namespace widgets {
|
namespace widgets {
|
||||||
|
|
||||||
ChatWidgetInput::ChatWidgetInput(ChatWidget *_chatWidget)
|
ChatWidgetInput::ChatWidgetInput(ChatWidget *_chatWidget, EmoteManager &emoteManager)
|
||||||
: BaseWidget(_chatWidget)
|
: BaseWidget(_chatWidget)
|
||||||
, chatWidget(_chatWidget)
|
, chatWidget(_chatWidget)
|
||||||
|
, emoteManager(emoteManager)
|
||||||
, emotesLabel(this)
|
, emotesLabel(this)
|
||||||
{
|
{
|
||||||
this->setMaximumHeight(150);
|
this->setMaximumHeight(150);
|
||||||
|
@ -46,10 +47,12 @@ ChatWidgetInput::ChatWidgetInput(ChatWidget *_chatWidget)
|
||||||
|
|
||||||
connect(&this->emotesLabel, &ChatWidgetHeaderButton::clicked, [this] {
|
connect(&this->emotesLabel, &ChatWidgetHeaderButton::clicked, [this] {
|
||||||
if (this->emotePopup == nullptr) {
|
if (this->emotePopup == nullptr) {
|
||||||
this->emotePopup = new EmotePopup();
|
this->emotePopup = new EmotePopup(this->colorScheme, this->emoteManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->emotePopup->show(); //
|
this->emotePopup->resize(300, 500);
|
||||||
|
this->emotePopup->loadChannel(this->chatWidget->getChannel());
|
||||||
|
this->emotePopup->show();
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(&textInput, &ResizingTextEdit::textChanged, this, &ChatWidgetInput::editTextChanged);
|
connect(&textInput, &ResizingTextEdit::textChanged, this, &ChatWidgetInput::editTextChanged);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "emotemanager.hpp"
|
||||||
#include "resizingtextedit.hpp"
|
#include "resizingtextedit.hpp"
|
||||||
#include "widgets/basewidget.hpp"
|
#include "widgets/basewidget.hpp"
|
||||||
#include "widgets/chatwidgetheaderbutton.hpp"
|
#include "widgets/chatwidgetheaderbutton.hpp"
|
||||||
|
@ -25,7 +26,7 @@ class ChatWidgetInput : public BaseWidget
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ChatWidgetInput(ChatWidget *_chatWidget);
|
ChatWidgetInput(ChatWidget *_chatWidget, EmoteManager &);
|
||||||
~ChatWidgetInput();
|
~ChatWidgetInput();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -37,6 +38,7 @@ protected:
|
||||||
private:
|
private:
|
||||||
ChatWidget *const chatWidget;
|
ChatWidget *const chatWidget;
|
||||||
EmotePopup *emotePopup = nullptr;
|
EmotePopup *emotePopup = nullptr;
|
||||||
|
EmoteManager &emoteManager;
|
||||||
|
|
||||||
boost::signals2::connection textLengthVisibleChangedConnection;
|
boost::signals2::connection textLengthVisibleChangedConnection;
|
||||||
QHBoxLayout hbox;
|
QHBoxLayout hbox;
|
||||||
|
|
|
@ -1,18 +1,70 @@
|
||||||
#include "emotepopup.h"
|
#include "emotepopup.h"
|
||||||
|
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
|
||||||
|
#include "messages/messagebuilder.hpp"
|
||||||
|
#include "twitch/twitchchannel.hpp"
|
||||||
|
|
||||||
|
using namespace chatterino::twitch;
|
||||||
|
using namespace chatterino::messages;
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
namespace widgets {
|
namespace widgets {
|
||||||
|
|
||||||
EmotePopup::EmotePopup(QWidget *parent)
|
EmotePopup::EmotePopup(ColorScheme &colorScheme, EmoteManager &emoteManager)
|
||||||
: QWidget(parent)
|
: BaseWidget(colorScheme, 0)
|
||||||
|
, emoteManager(emoteManager)
|
||||||
{
|
{
|
||||||
|
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||||
|
this->setLayout(layout);
|
||||||
|
layout->setMargin(0);
|
||||||
|
|
||||||
|
view = new ChannelView(this);
|
||||||
|
layout->addWidget(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmotePopup::loadChannel(std::shared_ptr<Channel> channel)
|
void EmotePopup::loadChannel(std::shared_ptr<Channel> _channel)
|
||||||
{
|
{
|
||||||
// channel->bttvChannelEmotes.each([](const QString &key, const EmoteData &value) {
|
TwitchChannel *channel = dynamic_cast<TwitchChannel *>(_channel.get());
|
||||||
|
|
||||||
// //
|
if (channel == nullptr) {
|
||||||
// });
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Channel> emoteChannel(new Channel);
|
||||||
|
|
||||||
|
auto addEmotes = [&](EmoteMap &map, const QString &title, const QString &emoteDesc) {
|
||||||
|
// TITLE
|
||||||
|
messages::MessageBuilder builder1;
|
||||||
|
|
||||||
|
builder1.appendWord(
|
||||||
|
Word(title, Word::Type::Text, QColor(255, 255, 255), QString(), QString()));
|
||||||
|
|
||||||
|
builder1.getMessage()->centered = true;
|
||||||
|
emoteChannel->addMessage(builder1.getMessage());
|
||||||
|
|
||||||
|
// EMOTES
|
||||||
|
messages::MessageBuilder builder2;
|
||||||
|
builder2.getMessage()->centered = true;
|
||||||
|
|
||||||
|
map.each([&](const QString &key, const EmoteData &value) {
|
||||||
|
builder2.appendWord(Word(value.image, Word::Type::AlwaysShow, key, emoteDesc,
|
||||||
|
Link(Link::Type::InsertText, key)));
|
||||||
|
});
|
||||||
|
|
||||||
|
emoteChannel->addMessage(builder2.getMessage());
|
||||||
|
};
|
||||||
|
|
||||||
|
addEmotes(this->emoteManager.bttvGlobalEmotes, "BetterTTV Global Emotes",
|
||||||
|
"BetterTTV Global Emote");
|
||||||
|
addEmotes(*channel->bttvChannelEmotes.get(), "BetterTTV Channel Emotes",
|
||||||
|
"BetterTTV Channel Emote");
|
||||||
|
addEmotes(this->emoteManager.ffzGlobalEmotes, "FrankerFaceZ Global Emotes",
|
||||||
|
"FrankerFaceZ Global Emote");
|
||||||
|
addEmotes(*channel->ffzChannelEmotes.get(), "FrankerFaceZ Channel Emotes",
|
||||||
|
"FrankerFaceZ Channel Emote");
|
||||||
|
|
||||||
|
view->setChannel(emoteChannel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,23 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
#include "channel.hpp"
|
#include "channel.hpp"
|
||||||
|
#include "emotemanager.hpp"
|
||||||
|
#include "widgets/basewidget.hpp"
|
||||||
|
#include "widgets/channelview.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
namespace widgets {
|
namespace widgets {
|
||||||
|
|
||||||
class EmotePopup : public QWidget
|
class EmotePopup : public BaseWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit EmotePopup(QWidget *parent = 0);
|
explicit EmotePopup(ColorScheme &, EmoteManager &);
|
||||||
|
|
||||||
void loadChannel(std::shared_ptr<Channel> channel);
|
void loadChannel(std::shared_ptr<Channel> channel);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ChannelView *view;
|
||||||
|
EmoteManager &emoteManager;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ void FancyButton::setMouseEffectColor(QColor color)
|
||||||
|
|
||||||
void FancyButton::paintEvent(QPaintEvent *)
|
void FancyButton::paintEvent(QPaintEvent *)
|
||||||
{
|
{
|
||||||
QPainter painter;
|
QPainter painter(this);
|
||||||
|
|
||||||
this->fancyPaint(painter);
|
this->fancyPaint(painter);
|
||||||
}
|
}
|
||||||
|
|
|
@ -212,7 +212,7 @@ void Notebook::resizeEvent(QResizeEvent *)
|
||||||
|
|
||||||
void Notebook::settingsButtonClicked()
|
void Notebook::settingsButtonClicked()
|
||||||
{
|
{
|
||||||
QTimer::singleShot(100, [this] { SettingsDialog::showDialog(); });
|
QTimer::singleShot(80, [this] { SettingsDialog::showDialog(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void Notebook::usersButtonClicked()
|
void Notebook::usersButtonClicked()
|
||||||
|
@ -221,7 +221,7 @@ void Notebook::usersButtonClicked()
|
||||||
|
|
||||||
void Notebook::addPageButtonClicked()
|
void Notebook::addPageButtonClicked()
|
||||||
{
|
{
|
||||||
QTimer::singleShot(100, [this] { this->addPage(true); });
|
QTimer::singleShot(80, [this] { this->addPage(true); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void Notebook::load(const boost::property_tree::ptree &tree)
|
void Notebook::load(const boost::property_tree::ptree &tree)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "widgets/scrollbar.hpp"
|
#include "widgets/scrollbar.hpp"
|
||||||
#include "colorscheme.hpp"
|
#include "colorscheme.hpp"
|
||||||
#include "widgets/chatwidgetview.hpp"
|
#include "widgets/channelview.hpp"
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
|
@ -11,7 +11,7 @@
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
namespace widgets {
|
namespace widgets {
|
||||||
|
|
||||||
ScrollBar::ScrollBar(ChatWidgetView *parent)
|
ScrollBar::ScrollBar(ChannelView *parent)
|
||||||
: BaseWidget(parent)
|
: BaseWidget(parent)
|
||||||
, _currentValueAnimation(this, "_currentValue")
|
, _currentValueAnimation(this, "_currentValue")
|
||||||
, _highlights(nullptr)
|
, _highlights(nullptr)
|
||||||
|
|
|
@ -14,14 +14,14 @@ class ColorScheme;
|
||||||
|
|
||||||
namespace widgets {
|
namespace widgets {
|
||||||
|
|
||||||
class ChatWidgetView;
|
class ChannelView;
|
||||||
|
|
||||||
class ScrollBar : public BaseWidget
|
class ScrollBar : public BaseWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ScrollBar(ChatWidgetView *parent = 0);
|
ScrollBar(ChannelView *parent = 0);
|
||||||
~ScrollBar();
|
~ScrollBar();
|
||||||
|
|
||||||
void removeHighlightsWhere(std::function<bool(ScrollBarHighlight &)> func);
|
void removeHighlightsWhere(std::function<bool(ScrollBarHighlight &)> func);
|
||||||
|
|
|
@ -46,12 +46,12 @@ void WindowManager::repaintGifEmotes()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::updateAll()
|
// void WindowManager::updateAll()
|
||||||
{
|
//{
|
||||||
if (this->mainWindow != nullptr) {
|
// if (this->mainWindow != nullptr) {
|
||||||
this->mainWindow->update();
|
// this->mainWindow->update();
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
widgets::MainWindow &WindowManager::getMainWindow()
|
widgets::MainWindow &WindowManager::getMainWindow()
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,7 +23,7 @@ public:
|
||||||
void layoutVisibleChatWidgets(Channel *channel = nullptr);
|
void layoutVisibleChatWidgets(Channel *channel = nullptr);
|
||||||
void repaintVisibleChatWidgets(Channel *channel = nullptr);
|
void repaintVisibleChatWidgets(Channel *channel = nullptr);
|
||||||
void repaintGifEmotes();
|
void repaintGifEmotes();
|
||||||
void updateAll();
|
// void updateAll();
|
||||||
|
|
||||||
widgets::MainWindow &getMainWindow();
|
widgets::MainWindow &getMainWindow();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue