From dc578a5f29765a79d4948ba7261dcd9b27026bfd Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 24 Mar 2018 16:55:28 +0100 Subject: [PATCH 01/69] Add "Timeout action" setting --- src/messages/layouts/messagelayout.cpp | 2 +- src/singletons/settingsmanager.hpp | 1 + src/widgets/settingspages/moderationpage.cpp | 7 +++++++ src/widgets/settingspages/moderationpage.hpp | 1 + 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/messages/layouts/messagelayout.cpp b/src/messages/layouts/messagelayout.cpp index f24ce173..baed0381 100644 --- a/src/messages/layouts/messagelayout.cpp +++ b/src/messages/layouts/messagelayout.cpp @@ -164,7 +164,7 @@ void MessageLayout::paint(QPainter &painter, int y, int messageIndex, Selection QColor color = isWindowFocused ? themeManager.tabs.selected.backgrounds.regular.color() : themeManager.tabs.selected.backgrounds.unfocused.color(); - QBrush brush = QBrush(color, Qt::VerPattern); + QBrush brush(color, Qt::VerPattern); painter.fillRect(0, y + this->container.getHeight() - 1, this->container.getWidth(), 1, brush); diff --git a/src/singletons/settingsmanager.hpp b/src/singletons/settingsmanager.hpp index 056cf1f0..b3dce522 100644 --- a/src/singletons/settingsmanager.hpp +++ b/src/singletons/settingsmanager.hpp @@ -82,6 +82,7 @@ public: /// Moderation QStringSetting moderationActions = {"/moderation/actions", "/ban {user}\n/timeout {user} 300"}; + QStringSetting timeoutAction = {"/moderation/timeoutAction", "Disable"}; /// Highlighting BoolSetting enableHighlights = {"/highlighting/enabled", true}; diff --git a/src/widgets/settingspages/moderationpage.cpp b/src/widgets/settingspages/moderationpage.cpp index 62566164..5106d95a 100644 --- a/src/widgets/settingspages/moderationpage.cpp +++ b/src/widgets/settingspages/moderationpage.cpp @@ -13,6 +13,7 @@ namespace chatterino { namespace widgets { namespace settingspages { + ModerationPage::ModerationPage() : SettingsPage("Moderation", "") { @@ -27,6 +28,12 @@ ModerationPage::ModerationPage() label->setStyleSheet("color: #bbb"); // clang-format on + auto form = layout.emplace(); + { + form->addRow("Action on timed out messages (unimplemented):", + this->createComboBox({"Disable", "Hide"}, settings.timeoutAction)); + } + auto modButtons = layout.emplace("Custom moderator buttons").setLayoutType(); { diff --git a/src/widgets/settingspages/moderationpage.hpp b/src/widgets/settingspages/moderationpage.hpp index c6ebdbdc..4e30c717 100644 --- a/src/widgets/settingspages/moderationpage.hpp +++ b/src/widgets/settingspages/moderationpage.hpp @@ -18,6 +18,7 @@ public: private: QTimer itemsChangedTimer; }; + } // namespace settingspages } // namespace widgets } // namespace chatterino From 4790f685571f4bd8be49e0bbd773843d37231e15 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sun, 25 Mar 2018 11:37:57 +0200 Subject: [PATCH 02/69] make helper function for trimming a twitch channel name from irc --- chatterino.pro | 6 ++-- src/providers/twitch/ircmessagehandler.cpp | 37 ++++++++++------------ src/providers/twitch/ircmessagehandler.hpp | 2 ++ src/providers/twitch/twitchhelpers.cpp | 22 +++++++++++++ src/providers/twitch/twitchhelpers.hpp | 13 ++++++++ src/providers/twitch/twitchserver.cpp | 10 +++++- src/providers/twitch/twitchserver.hpp | 2 ++ 7 files changed, 68 insertions(+), 24 deletions(-) create mode 100644 src/providers/twitch/twitchhelpers.cpp create mode 100644 src/providers/twitch/twitchhelpers.hpp diff --git a/chatterino.pro b/chatterino.pro index 9f40c576..c3dc988f 100644 --- a/chatterino.pro +++ b/chatterino.pro @@ -176,7 +176,8 @@ SOURCES += \ src/providers/irc/ircaccount.cpp \ src/providers/irc/ircserver.cpp \ src/providers/irc/ircchannel2.cpp \ - src/util/streamlink.cpp + src/util/streamlink.cpp \ + src/providers/twitch/twitchhelpers.cpp HEADERS += \ src/precompiled_header.hpp \ @@ -289,7 +290,8 @@ HEADERS += \ src/providers/irc/ircaccount.hpp \ src/providers/irc/ircserver.hpp \ src/providers/irc/ircchannel2.hpp \ - src/util/streamlink.hpp + src/util/streamlink.hpp \ + src/providers/twitch/twitchhelpers.hpp RESOURCES += \ resources/resources.qrc diff --git a/src/providers/twitch/ircmessagehandler.cpp b/src/providers/twitch/ircmessagehandler.cpp index 8ee2e312..421e70aa 100644 --- a/src/providers/twitch/ircmessagehandler.cpp +++ b/src/providers/twitch/ircmessagehandler.cpp @@ -6,6 +6,7 @@ #include "messages/limitedqueue.hpp" #include "messages/message.hpp" #include "providers/twitch/twitchchannel.hpp" +#include "providers/twitch/twitchhelpers.hpp" #include "providers/twitch/twitchmessagebuilder.hpp" #include "providers/twitch/twitchserver.hpp" #include "singletons/resourcemanager.hpp" @@ -59,16 +60,14 @@ void IrcMessageHandler::handleRoomStateMessage(Communi::IrcMessage *message) void IrcMessageHandler::handleClearChatMessage(Communi::IrcMessage *message) { // check parameter count - if (message->parameters().length() < 1) + if (message->parameters().length() < 1) { return; + } - QString chanName = message->parameter(0); - - // check channel name length - if (chanName.length() >= 2) + QString chanName; + if (!TrimChannelName(message->parameter(0), chanName)) { return; - - chanName = chanName.mid(1); + } // get channel auto chan = TwitchServer::getInstance().getChannel(chanName); @@ -86,8 +85,6 @@ void IrcMessageHandler::handleClearChatMessage(Communi::IrcMessage *message) return; } - assert(message->parameters().length() >= 2); - // get username, duration and message of the timed out user QString username = message->parameter(1); QString durationInSeconds, reason; @@ -136,10 +133,12 @@ void IrcMessageHandler::handleUserStateMessage(Communi::IrcMessage *message) QVariant _mod = message->tag("mod"); if (_mod.isValid()) { - auto rawChannelName = message->parameters().at(0); - auto trimmedChannelName = rawChannelName.mid(1); + QString channelName; + if (!TrimChannelName(message->parameter(0), channelName)) { + return; + } - auto c = TwitchServer::getInstance().getChannel(trimmedChannelName); + auto c = TwitchServer::getInstance().getChannel(channelName); twitch::TwitchChannel *tc = dynamic_cast(c.get()); if (tc != nullptr) { tc->setMod(_mod == "1"); @@ -192,13 +191,11 @@ void IrcMessageHandler::handleModeMessage(Communi::IrcMessage *message) void IrcMessageHandler::handleNoticeMessage(Communi::IrcNoticeMessage *message) { - auto rawChannelName = message->target(); - - bool broadcast = rawChannelName.length() < 2; MessagePtr msg = Message::createSystemMessage(message->content()); - if (broadcast) { - // fourtf: send to all twitch channels + QString channelName; + if (!TrimChannelName(message->target(), channelName)) { + // Notice wasn't targeted at a single channel, send to all twitch channels TwitchServer::getInstance().forEachChannelAndSpecialChannels([msg](const auto &c) { c->addMessage(msg); // }); @@ -206,13 +203,11 @@ void IrcMessageHandler::handleNoticeMessage(Communi::IrcNoticeMessage *message) return; } - auto trimmedChannelName = rawChannelName.mid(1); - - auto channel = TwitchServer::getInstance().getChannel(trimmedChannelName); + auto channel = TwitchServer::getInstance().getChannel(channelName); if (!channel) { debug::Log("[IrcManager:handleNoticeMessage] Channel {} not found in channel manager", - trimmedChannelName); + channelName); return; } diff --git a/src/providers/twitch/ircmessagehandler.hpp b/src/providers/twitch/ircmessagehandler.hpp index a23ad254..210f1b16 100644 --- a/src/providers/twitch/ircmessagehandler.hpp +++ b/src/providers/twitch/ircmessagehandler.hpp @@ -10,6 +10,7 @@ class ResourceManager; namespace providers { namespace twitch { + class IrcMessageHandler { IrcMessageHandler(singletons::ResourceManager &resourceManager); @@ -28,6 +29,7 @@ public: void handleNoticeMessage(Communi::IrcNoticeMessage *message); void handleWriteConnectionNoticeMessage(Communi::IrcNoticeMessage *message); }; + } // namespace twitch } // namespace providers } // namespace chatterino diff --git a/src/providers/twitch/twitchhelpers.cpp b/src/providers/twitch/twitchhelpers.cpp new file mode 100644 index 00000000..830da86d --- /dev/null +++ b/src/providers/twitch/twitchhelpers.cpp @@ -0,0 +1,22 @@ +#include "providers/twitch/twitchhelpers.hpp" +#include "debug/log.hpp" + +namespace chatterino { +namespace providers { +namespace twitch { + +bool TrimChannelName(const QString &channelName, QString &outChannelName) +{ + if (channelName.length() < 3) { + debug::Log("channel name length below 2"); + return false; + } + + outChannelName = channelName.mid(1); + + return true; +} + +} // namespace twitch +} // namespace providers +} // namespace chatterino diff --git a/src/providers/twitch/twitchhelpers.hpp b/src/providers/twitch/twitchhelpers.hpp new file mode 100644 index 00000000..997821d6 --- /dev/null +++ b/src/providers/twitch/twitchhelpers.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include + +namespace chatterino { +namespace providers { +namespace twitch { + +bool TrimChannelName(const QString &channelName, QString &outChannelName); + +} // namespace twitch +} // namespace providers +} // namespace chatterino diff --git a/src/providers/twitch/twitchserver.cpp b/src/providers/twitch/twitchserver.cpp index c45b5193..5dfbc946 100644 --- a/src/providers/twitch/twitchserver.cpp +++ b/src/providers/twitch/twitchserver.cpp @@ -2,6 +2,7 @@ #include "providers/twitch/ircmessagehandler.hpp" #include "providers/twitch/twitchaccount.hpp" +#include "providers/twitch/twitchhelpers.hpp" #include "providers/twitch/twitchmessagebuilder.hpp" #include "singletons/accountmanager.hpp" #include "util/posttothread.hpp" @@ -14,6 +15,7 @@ using namespace chatterino::singletons; namespace chatterino { namespace providers { namespace twitch { + TwitchServer::TwitchServer() : whispersChannel(new Channel("/mentions")) , mentionsChannel(new Channel("/mentions")) @@ -72,8 +74,13 @@ std::shared_ptr TwitchServer::createChannel(const QString &channelName) void TwitchServer::privateMessageReceived(IrcPrivateMessage *message) { + QString channelName; + if (!TrimChannelName(message->target(), channelName)) { + return; + } + this->onPrivateMessage.invoke(message); - auto chan = TwitchServer::getInstance().getChannel(message->target().mid(1)); + auto chan = TwitchServer::getInstance().getChannel(channelName); if (!chan) { return; @@ -163,6 +170,7 @@ void TwitchServer::forEachChannelAndSpecialChannels(std::functionwhispersChannel); func(this->mentionsChannel); } + } // namespace twitch } // namespace providers } // namespace chatterino diff --git a/src/providers/twitch/twitchserver.hpp b/src/providers/twitch/twitchserver.hpp index e6eadd8c..9932204b 100644 --- a/src/providers/twitch/twitchserver.hpp +++ b/src/providers/twitch/twitchserver.hpp @@ -9,6 +9,7 @@ namespace chatterino { namespace providers { namespace twitch { + class TwitchServer final : public irc::AbstractIrcServer { TwitchServer(); @@ -33,6 +34,7 @@ protected: virtual std::shared_ptr getCustomChannel(const QString &channelname) override; }; + } // namespace twitch } // namespace providers } // namespace chatterino From f567f10d102c86f7de62f350e338339b15261687 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Fri, 30 Mar 2018 12:06:02 +0200 Subject: [PATCH 03/69] CompletionModel tagged strings now have types (i.e. bttv emote, name, twitch emote) Usernames can be overriden (capitalized overrides lowercase, but not the other way around) --- src/util/completionmodel.cpp | 36 +++++++++---- src/util/completionmodel.hpp | 97 ++++++++++++++++++++---------------- 2 files changed, 79 insertions(+), 54 deletions(-) diff --git a/src/util/completionmodel.cpp b/src/util/completionmodel.cpp index e94cd3a4..a13b917f 100644 --- a/src/util/completionmodel.cpp +++ b/src/util/completionmodel.cpp @@ -7,6 +7,8 @@ #include +#include + namespace chatterino { CompletionModel::CompletionModel(const QString &_channelName) @@ -24,40 +26,41 @@ void CompletionModel::refresh() // TODO: Fix this so it properly updates with the proper api. oauth token needs proper scope for (const auto &m : emoteManager.twitchAccountEmotes) { for (const auto &emoteName : m.second.emoteCodes) { - this->addString(emoteName); + // XXX: No way to discern between a twitch global emote and sub emote right now + this->addString(emoteName, TaggedString::Type::TwitchGlobalEmote); } } // Global: BTTV Global Emotes std::vector &bttvGlobalEmoteCodes = emoteManager.bttvGlobalEmoteCodes; for (const auto &m : bttvGlobalEmoteCodes) { - this->addString(m); + this->addString(m, TaggedString::Type::BTTVGlobalEmote); } // Global: FFZ Global Emotes std::vector &ffzGlobalEmoteCodes = emoteManager.ffzGlobalEmoteCodes; for (const auto &m : ffzGlobalEmoteCodes) { - this->addString(m); + this->addString(m, TaggedString::Type::FFZGlobalEmote); } // Channel-specific: BTTV Channel Emotes std::vector &bttvChannelEmoteCodes = emoteManager.bttvChannelEmoteCodes[this->channelName.toStdString()]; for (const auto &m : bttvChannelEmoteCodes) { - this->addString(m); + this->addString(m, TaggedString::Type::BTTVChannelEmote); } // Channel-specific: FFZ Channel Emotes std::vector &ffzChannelEmoteCodes = emoteManager.ffzChannelEmoteCodes[this->channelName.toStdString()]; for (const auto &m : ffzChannelEmoteCodes) { - this->addString(m); + this->addString(m, TaggedString::Type::FFZChannelEmote); } // Global: Emojis const auto &emojiShortCodes = emoteManager.emojiShortCodes; for (const auto &m : emojiShortCodes) { - this->addString(":" + m + ":"); + this->addString(":" + m + ":", TaggedString::Type::Emoji); } // Channel-specific: Usernames @@ -76,22 +79,33 @@ void CompletionModel::refresh() // } } -void CompletionModel::addString(const std::string &str) +void CompletionModel::addString(const std::string &str, TaggedString::Type type) { // Always add a space at the end of completions - this->emotes.insert(this->createEmote(str + " ")); + this->emotes.insert({qS(str + " "), type}); } -void CompletionModel::addString(const QString &str) +void CompletionModel::addString(const QString &str, TaggedString::Type type) { // Always add a space at the end of completions - this->emotes.insert(this->createEmote(str + " ")); + this->emotes.insert({str + " ", type}); } void CompletionModel::addUser(const QString &str) { + auto ts = this->createUser(str + " "); // Always add a space at the end of completions - this->emotes.insert(this->createUser(str + " ")); + std::pair::iterator, bool> p = this->emotes.insert(ts); + if (!p.second) { + // No inseration was made, figure out if we need to replace the username. + + if (p.first->str > ts.str) { + // Replace lowercase version of name with mixed-case version + this->emotes.erase(p.first); + auto result2 = this->emotes.insert(ts); + assert(result2.second); + } + } } } // namespace chatterino diff --git a/src/util/completionmodel.hpp b/src/util/completionmodel.hpp index 0c996a19..b804b524 100644 --- a/src/util/completionmodel.hpp +++ b/src/util/completionmodel.hpp @@ -4,7 +4,6 @@ #include -#include #include #include @@ -12,6 +11,56 @@ namespace chatterino { class CompletionModel : public QAbstractListModel { + struct TaggedString { + QString str; + + // Type will help decide the lifetime of the tagged strings + enum Type { + Username, + + // Emotes + FFZGlobalEmote = 20, + FFZChannelEmote, + BTTVGlobalEmote, + BTTVChannelEmote, + TwitchGlobalEmote, + TwitchSubscriberEmote, + Emoji, + } type; + + bool IsEmote() const + { + return this->type >= 20; + } + + bool operator<(const TaggedString &that) const + { + if (this->IsEmote()) { + if (that.IsEmote()) { + int k = QString::compare(this->str, that.str, Qt::CaseInsensitive); + if (k == 0) { + return this->str > that.str; + } else { + return k < 0; + } + } else { + return true; + } + } else { + if (that.IsEmote()) { + return false; + } else { + int k = QString::compare(this->str, that.str, Qt::CaseInsensitive); + if (k == 0) { + return false; + } else { + return k < 0; + } + } + } + } + }; + public: CompletionModel(const QString &_channelName); @@ -34,55 +83,17 @@ public: } void refresh(); - void addString(const std::string &str); - void addString(const QString &str); + void addString(const std::string &str, TaggedString::Type type); + void addString(const QString &str, TaggedString::Type type); void addUser(const QString &str); private: - struct TaggedString { - QString str; - // emote == true - // username == false - bool isEmote = true; - bool operator<(const TaggedString &that) const - { - if (this->isEmote) { - if (that.isEmote) { - int k = QString::compare(this->str, that.str, Qt::CaseInsensitive); - if (k == 0) { - return this->str > that.str; - } else { - return k < 0; - } - } else - return true; - } else { - if (that.isEmote) - return false; - else { - int k = QString::compare(this->str, that.str, Qt::CaseInsensitive); - if (k == 0) { - return this->str > that.str; - } else { - return k < 0; - } - } - } - } - }; - TaggedString createEmote(const std::string &str) - { - return TaggedString{qS(str), true}; - } - TaggedString createEmote(const QString &str) - { - return TaggedString{str, true}; - } TaggedString createUser(const QString &str) { - return TaggedString{str, false}; + return TaggedString{str, TaggedString::Type::Username}; } + std::set emotes; QString channelName; From 95878dc7db57851c4a5dcbb578c22d54f80b5753 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Fri, 30 Mar 2018 12:16:12 +0200 Subject: [PATCH 04/69] No longer add username to the completion model in privateMessageReceived The username is added to the completion model with the "addRecentChatter" method instead Moved "NameOptions" stuff from base class Channel to TwitchChannel where it belongs Remove unused Channel::getUsernamesForCompletions method --- src/channel.cpp | 21 ++------------------- src/channel.hpp | 17 +---------------- src/providers/twitch/twitchchannel.cpp | 11 +++++++++++ src/providers/twitch/twitchchannel.hpp | 11 +++++++++++ src/providers/twitch/twitchserver.cpp | 3 --- 5 files changed, 25 insertions(+), 38 deletions(-) diff --git a/src/channel.cpp b/src/channel.cpp index 08265f39..3e214bb3 100644 --- a/src/channel.cpp +++ b/src/channel.cpp @@ -79,25 +79,7 @@ void Channel::replaceMessage(messages::MessagePtr message, messages::MessagePtr void Channel::addRecentChatter(const std::shared_ptr &message) { - assert(!message->loginName.isEmpty()); - - std::lock_guard lock(this->recentChattersMutex); - - this->recentChatters[message->loginName] = {message->displayName, message->localizedName}; -} - -std::vector Channel::getUsernamesForCompletions() -{ - std::vector names; - - this->recentChattersMutex.lock(); - for (const auto &p : this->recentChatters) { - names.push_back(p.second); - } - // usernames.insert(this->recentChatters.begin(), this->recentChatters.end()); - this->recentChattersMutex.unlock(); - - return names; + // Do nothing by default } bool Channel::canSendMessage() const @@ -118,4 +100,5 @@ std::shared_ptr Channel::getEmpty() void Channel::onConnected() { } + } // namespace chatterino diff --git a/src/channel.hpp b/src/channel.hpp index bd653aee..940f0d90 100644 --- a/src/channel.hpp +++ b/src/channel.hpp @@ -6,14 +6,10 @@ #include "util/completionmodel.hpp" #include "util/concurrentmap.hpp" -#include -#include #include -#include #include #include -#include namespace chatterino { namespace messages { @@ -40,22 +36,11 @@ public: void addMessage(messages::MessagePtr message); void addMessagesAtStart(std::vector &messages); void replaceMessage(messages::MessagePtr message, messages::MessagePtr replacement); - void addRecentChatter(const std::shared_ptr &message); - - struct NameOptions { - QString displayName; - QString localizedName; - }; - - std::vector getUsernamesForCompletions(); + virtual void addRecentChatter(const std::shared_ptr &message); QString name; QStringList modList; - // Key = login name - std::map recentChatters; - std::mutex recentChattersMutex; - virtual bool canSendMessage() const; virtual void sendMessage(const QString &message); virtual bool isMod() const diff --git a/src/providers/twitch/twitchchannel.cpp b/src/providers/twitch/twitchchannel.cpp index adb7cfe3..049566a3 100644 --- a/src/providers/twitch/twitchchannel.cpp +++ b/src/providers/twitch/twitchchannel.cpp @@ -163,6 +163,17 @@ bool TwitchChannel::hasModRights() return this->isMod() || this->isBroadcaster(); } +void TwitchChannel::addRecentChatter(const std::shared_ptr &message) +{ + assert(!message->loginName.isEmpty()); + + std::lock_guard lock(this->recentChattersMutex); + + this->recentChatters[message->loginName] = {message->displayName, message->localizedName}; + + this->completionModel.addUser(message->displayName); +} + void TwitchChannel::setLive(bool newLiveStatus) { if (this->isLive == newLiveStatus) { diff --git a/src/providers/twitch/twitchchannel.hpp b/src/providers/twitch/twitchchannel.hpp index c0aba110..26763bb9 100644 --- a/src/providers/twitch/twitchchannel.hpp +++ b/src/providers/twitch/twitchchannel.hpp @@ -33,6 +33,8 @@ public: bool isBroadcaster(); bool hasModRights(); + void addRecentChatter(const std::shared_ptr &message) final; + const std::shared_ptr bttvChannelEmotes; const std::shared_ptr ffzChannelEmotes; @@ -54,6 +56,11 @@ public: QString streamGame; QString streamUptime; + struct NameOptions { + QString displayName; + QString localizedName; + }; + private: explicit TwitchChannel(const QString &channelName, Communi::IrcConnection *readConnection); @@ -71,6 +78,10 @@ private: Communi::IrcConnection *readConnecetion; friend class TwitchServer; + + // Key = login name + std::map recentChatters; + std::mutex recentChattersMutex; }; } // namespace twitch diff --git a/src/providers/twitch/twitchserver.cpp b/src/providers/twitch/twitchserver.cpp index 5dfbc946..ddff5b55 100644 --- a/src/providers/twitch/twitchserver.cpp +++ b/src/providers/twitch/twitchserver.cpp @@ -90,9 +90,6 @@ void TwitchServer::privateMessageReceived(IrcPrivateMessage *message) TwitchMessageBuilder builder(chan.get(), message, args); - // XXX: Thread-safety - chan->completionModel.addUser(message->nick()); - if (!builder.isIgnored()) { messages::MessagePtr _message = builder.build(); if (_message->flags & messages::Message::Highlighted) { From ea21aa5dea4f7a005b8abcac43637b6a507766f9 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Fri, 30 Mar 2018 12:37:00 +0200 Subject: [PATCH 05/69] reformat/cleanup --- src/channel.hpp | 2 +- src/providers/twitch/twitchchannel.cpp | 38 ++++++++++++++------------ src/providers/twitch/twitchchannel.hpp | 2 +- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/channel.hpp b/src/channel.hpp index 940f0d90..f7993c7f 100644 --- a/src/channel.hpp +++ b/src/channel.hpp @@ -59,6 +59,6 @@ private: messages::LimitedQueue messages; }; -typedef std::shared_ptr ChannelPtr; +using ChannelPtr = std::shared_ptr; } // namespace chatterino diff --git a/src/providers/twitch/twitchchannel.cpp b/src/providers/twitch/twitchchannel.cpp index 049566a3..61ae939a 100644 --- a/src/providers/twitch/twitchchannel.cpp +++ b/src/providers/twitch/twitchchannel.cpp @@ -265,26 +265,30 @@ void TwitchChannel::fetchRecentMessages() return; } - TwitchChannel *channel = dynamic_cast(shared.get()); + auto channel = dynamic_cast(shared.get()); + assert(channel != nullptr); + static auto readConnection = channel->readConnecetion; - auto msgArray = obj.value("messages").toArray(); - if (msgArray.size() > 0) { - std::vector messages; - - for (int i = 0; i < msgArray.size(); i++) { - QByteArray content = msgArray[i].toString().toUtf8(); - auto msg = Communi::IrcMessage::fromData(content, readConnection); - auto privMsg = static_cast(msg); - - messages::MessageParseArgs args; - twitch::TwitchMessageBuilder builder(channel, privMsg, args); - if (!builder.isIgnored()) { - messages.push_back(builder.build()); - } - } - channel->addMessagesAtStart(messages); + QJsonArray msgArray = obj.value("messages").toArray(); + if (msgArray.empty()) { + return; } + + std::vector messages; + + for (const QJsonValueRef _msg : msgArray) { + QByteArray content = _msg.toString().toUtf8(); + auto msg = Communi::IrcMessage::fromData(content, readConnection); + auto privMsg = static_cast(msg); + + messages::MessageParseArgs args; + twitch::TwitchMessageBuilder builder(channel, privMsg, args); + if (!builder.isIgnored()) { + messages.push_back(builder.build()); + } + } + channel->addMessagesAtStart(messages); }); } diff --git a/src/providers/twitch/twitchchannel.hpp b/src/providers/twitch/twitchchannel.hpp index 26763bb9..5cc5c649 100644 --- a/src/providers/twitch/twitchchannel.hpp +++ b/src/providers/twitch/twitchchannel.hpp @@ -20,7 +20,7 @@ class TwitchChannel final : public Channel QTimer *chattersListTimer; public: - ~TwitchChannel(); + ~TwitchChannel() final; void reloadChannelEmotes(); From ec349f5978e5a8f5a12889d5c4b65155c12a2ac8 Mon Sep 17 00:00:00 2001 From: fourtf Date: Fri, 30 Mar 2018 13:44:01 +0200 Subject: [PATCH 06/69] added experimental new tabs --- src/singletons/thememanager.cpp | 2 + src/widgets/helper/notebooktab.cpp | 60 ++++++++++++++++++++++-------- src/widgets/notebook.cpp | 2 + 3 files changed, 49 insertions(+), 15 deletions(-) diff --git a/src/singletons/thememanager.cpp b/src/singletons/thememanager.cpp index d425cb19..c9e02d5b 100644 --- a/src/singletons/thememanager.cpp +++ b/src/singletons/thememanager.cpp @@ -89,6 +89,7 @@ void ThemeManager::actuallyUpdate(double hue, double multiplier) // tabs // text, {regular, hover, unfocused} + this->windowBg = "#ccc"; this->tabs.regular = {tabFg, {windowBg, blendColors(windowBg, "#999", 0.5), windowBg}}; this->tabs.selected = {"#fff", {themeColor, themeColor, QColor::fromHslF(hue, 0, 0.5)}}; @@ -103,6 +104,7 @@ void ThemeManager::actuallyUpdate(double hue, double multiplier) tabFg, {blendColors(themeColor, windowBg, 0.7), blendColors(themeColor, windowBg, 0.5), blendColors(themeColorNoSat, windowBg, 0.7)}}; + this->windowBg = "#fff"; // Split bool flat = isLight; diff --git a/src/widgets/helper/notebooktab.cpp b/src/widgets/helper/notebooktab.cpp index 0034dc76..432a44b4 100644 --- a/src/widgets/helper/notebooktab.cpp +++ b/src/widgets/helper/notebooktab.cpp @@ -77,13 +77,16 @@ void NotebookTab::themeRefreshEvent() void NotebookTab::updateSize() { float scale = getScale(); - QString qTitle(qS(this->title)); - if (singletons::SettingManager::getInstance().hideTabX) { - this->resize((int)((fontMetrics().width(qTitle) + 16) * scale), (int)(24 * scale)); - } else { - this->resize((int)((fontMetrics().width(qTitle) + 8 + 24) * scale), (int)(24 * scale)); - } + this->resize((int)(150 * scale), (int)(24 * scale)); + + // QString qTitle(qS(this->title)); + // if (singletons::SettingManager::getInstance().hideTabX) { + // this->resize((int)((fontMetrics().width(qTitle) + 16) * scale), (int)(24 * scale)); + // } else { + // this->resize((int)((fontMetrics().width(qTitle) + 8 + 24) * scale), (int)(24 * + // scale)); + // } if (this->parent() != nullptr) { (static_cast(this->parent()))->performLayout(true); @@ -168,6 +171,7 @@ void NotebookTab::paintEvent(QPaintEvent *) { singletons::SettingManager &settingManager = singletons::SettingManager::getInstance(); QPainter painter(this); + float scale = this->getScale(); // select the right tab colors singletons::ThemeManager::TabColors colors; @@ -186,25 +190,51 @@ void NotebookTab::paintEvent(QPaintEvent *) bool windowFocused = this->window() == QApplication::activeWindow(); // || SettingsDialog::getHandle() == QApplication::activeWindow(); - painter.fillRect(rect(), this->mouseOver ? regular.backgrounds.hover - : (windowFocused ? regular.backgrounds.regular - : regular.backgrounds.unfocused)); + if (false) { + painter.fillRect(rect(), this->mouseOver ? regular.backgrounds.hover + : (windowFocused ? regular.backgrounds.regular + : regular.backgrounds.unfocused)); - // fill the tab background - painter.fillRect(rect(), this->mouseOver ? colors.backgrounds.hover - : (windowFocused ? colors.backgrounds.regular - : colors.backgrounds.unfocused)); + // fill the tab background + painter.fillRect(rect(), this->mouseOver ? colors.backgrounds.hover + : (windowFocused ? colors.backgrounds.regular + : colors.backgrounds.unfocused)); + } else { + QPainterPath path(QPointF(0, this->height())); + path.lineTo(8 * scale, 0); + path.lineTo(this->width() - 8 * scale, 0); + path.lineTo(this->width(), this->height()); + painter.fillPath(path, this->mouseOver ? regular.backgrounds.hover + : (windowFocused ? regular.backgrounds.regular + : regular.backgrounds.unfocused)); + + // fill the tab background + painter.fillPath(path, this->mouseOver ? colors.backgrounds.hover + : (windowFocused ? colors.backgrounds.regular + : colors.backgrounds.unfocused)); + painter.setPen(QColor("#FFF")); + painter.setRenderHint(QPainter::Antialiasing); + painter.drawPath(path); + // painter.setBrush(QColor("#000")); + } // set the pen color painter.setPen(colors.text); // set area for text - float scale = this->getScale(); int rectW = (settingManager.hideTabX ? 0 : static_cast(16) * scale); QRect rect(0, 0, this->width() - rectW, this->height()); // draw text - painter.drawText(rect, this->getTitle(), QTextOption(Qt::AlignCenter)); + if (false) { // legacy + painter.drawText(rect, this->getTitle(), QTextOption(Qt::AlignCenter)); + } else { + QTextOption option(Qt::AlignLeft | Qt::AlignVCenter); + option.setWrapMode(QTextOption::NoWrap); + int offset = (int)(scale * 16); + QRect textRect(offset, 0, this->width() - offset - offset, this->height()); + painter.drawText(textRect, this->getTitle(), option); + } // draw close x if (!settingManager.hideTabX && (mouseOver || selected)) { diff --git a/src/widgets/notebook.cpp b/src/widgets/notebook.cpp index b3082f47..f790e62a 100644 --- a/src/widgets/notebook.cpp +++ b/src/widgets/notebook.cpp @@ -250,6 +250,8 @@ void Notebook::performLayout(bool animated) x += i->getTab()->width(); } + x -= (int)(8 * scale); + first = false; } From d4f37f786bb738b8973a984e577c95bb5c9a8a8e Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Fri, 30 Mar 2018 13:45:27 +0200 Subject: [PATCH 07/69] Once again reset completion model first time tab is pressed. This ensures we never tab the wrong username, but it's really expensive. --- src/widgets/helper/resizingtextedit.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/widgets/helper/resizingtextedit.cpp b/src/widgets/helper/resizingtextedit.cpp index 130db785..46038718 100644 --- a/src/widgets/helper/resizingtextedit.cpp +++ b/src/widgets/helper/resizingtextedit.cpp @@ -101,6 +101,7 @@ void ResizingTextEdit::keyPressEvent(QKeyEvent *event) if (!this->completionInProgress) { // First type pressing tab after modifying a message, we refresh our completion model + this->completer->setModel(completionModel); completionModel->refresh(); this->completionInProgress = true; this->completer->setCompletionPrefix(currentCompletionPrefix); From 89d7b7db8748ad49064c324d930c667ee5934b86 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Fri, 30 Mar 2018 13:50:43 +0200 Subject: [PATCH 08/69] expire non-recent chatters --- src/channel.cpp | 8 ++++ src/channel.hpp | 3 ++ src/util/completionmodel.cpp | 23 +++++++++- src/util/completionmodel.hpp | 81 ++++++++++++++++++++++++++---------- 4 files changed, 91 insertions(+), 24 deletions(-) diff --git a/src/channel.cpp b/src/channel.cpp index 3e214bb3..f72a0a01 100644 --- a/src/channel.cpp +++ b/src/channel.cpp @@ -22,11 +22,19 @@ Channel::Channel(const QString &_name) : name(_name) , completionModel(this->name) { + this->clearCompletionModelTimer = new QTimer; + QObject::connect(this->clearCompletionModelTimer, &QTimer::timeout, [this]() { + this->completionModel.ClearExpiredStrings(); // + }); + this->clearCompletionModelTimer->start(60 * 1000); } Channel::~Channel() { this->destroyed.invoke(); + + this->clearCompletionModelTimer->stop(); + this->clearCompletionModelTimer->deleteLater(); } bool Channel::isEmpty() const diff --git a/src/channel.hpp b/src/channel.hpp index f7993c7f..ca51c7c2 100644 --- a/src/channel.hpp +++ b/src/channel.hpp @@ -7,6 +7,7 @@ #include "util/concurrentmap.hpp" #include +#include #include #include @@ -18,6 +19,8 @@ struct Message; class Channel : public std::enable_shared_from_this { + QTimer *clearCompletionModelTimer; + public: explicit Channel(const QString &_name); virtual ~Channel(); diff --git a/src/util/completionmodel.cpp b/src/util/completionmodel.cpp index a13b917f..0bef743b 100644 --- a/src/util/completionmodel.cpp +++ b/src/util/completionmodel.cpp @@ -81,12 +81,13 @@ void CompletionModel::refresh() void CompletionModel::addString(const std::string &str, TaggedString::Type type) { - // Always add a space at the end of completions - this->emotes.insert({qS(str + " "), type}); + this->addString(qS(str), type); } void CompletionModel::addString(const QString &str, TaggedString::Type type) { + std::lock_guard lock(this->emotesMutex); + // Always add a space at the end of completions this->emotes.insert({str + " ", type}); } @@ -108,4 +109,22 @@ void CompletionModel::addUser(const QString &str) } } +void CompletionModel::ClearExpiredStrings() +{ + std::lock_guard lock(this->emotesMutex); + + auto now = std::chrono::steady_clock::now(); + + for (auto it = this->emotes.begin(); it != this->emotes.end();) { + const auto &taggedString = *it; + + if (taggedString.HasExpired(now)) { + // debug::Log("String {} expired", taggedString.str); + it = this->emotes.erase(it); + } else { + ++it; + } + } +} + } // namespace chatterino diff --git a/src/util/completionmodel.hpp b/src/util/completionmodel.hpp index b804b524..629f5dd1 100644 --- a/src/util/completionmodel.hpp +++ b/src/util/completionmodel.hpp @@ -4,6 +4,8 @@ #include +#include +#include #include #include @@ -12,9 +14,6 @@ namespace chatterino { class CompletionModel : public QAbstractListModel { struct TaggedString { - QString str; - - // Type will help decide the lifetime of the tagged strings enum Type { Username, @@ -26,7 +25,38 @@ class CompletionModel : public QAbstractListModel TwitchGlobalEmote, TwitchSubscriberEmote, Emoji, - } type; + }; + + TaggedString(const QString &_str, Type _type) + : str(_str) + , type(_type) + , timeAdded(std::chrono::steady_clock::now()) + { + } + + QString str; + + // Type will help decide the lifetime of the tagged strings + Type type; + + std::chrono::steady_clock::time_point timeAdded; + + bool HasExpired(const std::chrono::steady_clock::time_point &now) const + { + switch (this->type) { + case Type::Username: { + static std::chrono::minutes expirationTimer(10); + + return (this->timeAdded + expirationTimer < now); + } break; + + default: { + return false; + } break; + } + + return false; + } bool IsEmote() const { @@ -40,45 +70,49 @@ class CompletionModel : public QAbstractListModel int k = QString::compare(this->str, that.str, Qt::CaseInsensitive); if (k == 0) { return this->str > that.str; - } else { - return k < 0; - } - } else { - return true; - } - } else { - if (that.IsEmote()) { - return false; - } else { - int k = QString::compare(this->str, that.str, Qt::CaseInsensitive); - if (k == 0) { - return false; - } else { - return k < 0; } + + return k < 0; } + + return true; } + + if (that.IsEmote()) { + return false; + } + + int k = QString::compare(this->str, that.str, Qt::CaseInsensitive); + if (k == 0) { + return false; + } + + return k < 0; } }; public: CompletionModel(const QString &_channelName); - virtual int columnCount(const QModelIndex &) const override + int columnCount(const QModelIndex &) const override { return 1; } - virtual QVariant data(const QModelIndex &index, int) const override + QVariant data(const QModelIndex &index, int) const override { + std::lock_guard lock(this->emotesMutex); + // TODO: Implement more safely auto it = this->emotes.begin(); std::advance(it, index.row()); return QVariant(it->str); } - virtual int rowCount(const QModelIndex &) const override + int rowCount(const QModelIndex &) const override { + std::lock_guard lock(this->emotesMutex); + return this->emotes.size(); } @@ -88,12 +122,15 @@ public: void addUser(const QString &str); + void ClearExpiredStrings(); + private: TaggedString createUser(const QString &str) { return TaggedString{str, TaggedString::Type::Username}; } + mutable std::mutex emotesMutex; std::set emotes; QString channelName; From 1c7f397f1bcc8dfb94fe5f1f7304960cfaa2a903 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Fri, 30 Mar 2018 14:39:33 +0200 Subject: [PATCH 09/69] Move signallabel code out from its header --- chatterino.pro | 3 ++- src/widgets/helper/signallabel.cpp | 34 ++++++++++++++++++++++++++ src/widgets/helper/signallabel.hpp | 38 +++++------------------------- 3 files changed, 42 insertions(+), 33 deletions(-) create mode 100644 src/widgets/helper/signallabel.cpp diff --git a/chatterino.pro b/chatterino.pro index c3dc988f..b7c10c64 100644 --- a/chatterino.pro +++ b/chatterino.pro @@ -177,7 +177,8 @@ SOURCES += \ src/providers/irc/ircserver.cpp \ src/providers/irc/ircchannel2.cpp \ src/util/streamlink.cpp \ - src/providers/twitch/twitchhelpers.cpp + src/providers/twitch/twitchhelpers.cpp \ + src/widgets/helper/signallabel.cpp HEADERS += \ src/precompiled_header.hpp \ diff --git a/src/widgets/helper/signallabel.cpp b/src/widgets/helper/signallabel.cpp new file mode 100644 index 00000000..c7bb8794 --- /dev/null +++ b/src/widgets/helper/signallabel.cpp @@ -0,0 +1,34 @@ +#include "widgets/helper/signallabel.hpp" + +SignalLabel::SignalLabel(QWidget *parent, Qt::WindowFlags f) + : QLabel(parent, f) +{ +} + +void SignalLabel::mouseDoubleClickEvent(QMouseEvent *ev) +{ + emit this->mouseDoubleClick(ev); +} + +void SignalLabel::mousePressEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) { + emit mouseDown(); + } + + event->ignore(); +} + +void SignalLabel::mouseReleaseEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) { + emit mouseUp(); + } + + event->ignore(); +} + +void SignalLabel::mouseMoveEvent(QMouseEvent *event) +{ + event->ignore(); +} diff --git a/src/widgets/helper/signallabel.hpp b/src/widgets/helper/signallabel.hpp index e479b569..513fdbab 100644 --- a/src/widgets/helper/signallabel.hpp +++ b/src/widgets/helper/signallabel.hpp @@ -10,11 +10,8 @@ class SignalLabel : public QLabel Q_OBJECT public: - explicit SignalLabel(QWidget *parent = 0, Qt::WindowFlags f = 0) - : QLabel(parent, f) - { - } - virtual ~SignalLabel() = default; + explicit SignalLabel(QWidget *parent = nullptr, Qt::WindowFlags f = 0); + ~SignalLabel() override = default; signals: void mouseDoubleClick(QMouseEvent *ev); @@ -23,31 +20,8 @@ signals: void mouseUp(); protected: - virtual void mouseDoubleClickEvent(QMouseEvent *ev) override - { - emit this->mouseDoubleClick(ev); - } - - virtual void mousePressEvent(QMouseEvent *event) override - { - if (event->button() == Qt::LeftButton) { - emit mouseDown(); - } - - event->ignore(); - } - - void mouseReleaseEvent(QMouseEvent *event) override - { - if (event->button() == Qt::LeftButton) { - emit mouseUp(); - } - - event->ignore(); - } - - virtual void mouseMoveEvent(QMouseEvent *event) override - { - event->ignore(); - } + void mouseDoubleClickEvent(QMouseEvent *ev) override; + void mousePressEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; }; From 1b9fa36e06569820106dcd2c70643b2688185e14 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Fri, 30 Mar 2018 14:46:29 +0200 Subject: [PATCH 10/69] add mouseMove signal to SignalLabel Make use of the mouseMove signal in SplitHeader for the stream uptime tooltip --- src/widgets/helper/signallabel.cpp | 1 + src/widgets/helper/signallabel.hpp | 1 + src/widgets/helper/splitheader.cpp | 1 + 3 files changed, 3 insertions(+) diff --git a/src/widgets/helper/signallabel.cpp b/src/widgets/helper/signallabel.cpp index c7bb8794..bc1eb6aa 100644 --- a/src/widgets/helper/signallabel.cpp +++ b/src/widgets/helper/signallabel.cpp @@ -30,5 +30,6 @@ void SignalLabel::mouseReleaseEvent(QMouseEvent *event) void SignalLabel::mouseMoveEvent(QMouseEvent *event) { + emit this->mouseMove(event); event->ignore(); } diff --git a/src/widgets/helper/signallabel.hpp b/src/widgets/helper/signallabel.hpp index 513fdbab..658e3ccf 100644 --- a/src/widgets/helper/signallabel.hpp +++ b/src/widgets/helper/signallabel.hpp @@ -18,6 +18,7 @@ signals: void mouseDown(); void mouseUp(); + void mouseMove(QMouseEvent *event); protected: void mouseDoubleClickEvent(QMouseEvent *ev) override; diff --git a/src/widgets/helper/splitheader.cpp b/src/widgets/helper/splitheader.cpp index 45b7f70e..ca43da27 100644 --- a/src/widgets/helper/splitheader.cpp +++ b/src/widgets/helper/splitheader.cpp @@ -57,6 +57,7 @@ SplitHeader::SplitHeader(Split *_split) title->setMouseTracking(true); QObject::connect(this->titleLabel, &SignalLabel::mouseDoubleClick, this, &SplitHeader::mouseDoubleClickEvent); + QObject::connect(this->titleLabel, &SignalLabel::mouseMove, this, &SplitHeader::mouseMoveEvent); layout->addStretch(1); From 1cac80c8baf44448ba4ce3fa1b0b393326ec9277 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Fri, 30 Mar 2018 15:05:33 +0200 Subject: [PATCH 11/69] Changed how the channel live status is stored --- src/providers/twitch/twitchchannel.cpp | 30 ++++++++++++++++---------- src/providers/twitch/twitchchannel.hpp | 30 +++++++++++++++++++++----- src/singletons/commandmanager.cpp | 4 +++- src/widgets/helper/splitheader.cpp | 29 +++++++++++++++---------- 4 files changed, 65 insertions(+), 28 deletions(-) diff --git a/src/providers/twitch/twitchchannel.cpp b/src/providers/twitch/twitchchannel.cpp index 61ae939a..e6562c3a 100644 --- a/src/providers/twitch/twitchchannel.cpp +++ b/src/providers/twitch/twitchchannel.cpp @@ -24,7 +24,6 @@ TwitchChannel::TwitchChannel(const QString &channelName, Communi::IrcConnection , subscriptionURL("https://www.twitch.tv/subs/" + name) , channelURL("https://twitch.tv/" + name) , popoutPlayerURL("https://player.twitch.tv/?channel=" + name) - , isLive(false) , mod(false) , readConnecetion(_readConnection) { @@ -176,11 +175,16 @@ void TwitchChannel::addRecentChatter(const std::shared_ptr &m void TwitchChannel::setLive(bool newLiveStatus) { - if (this->isLive == newLiveStatus) { - return; + { + std::lock_guard lock(this->streamStatusMutex); + if (this->streamStatus.live == newLiveStatus) { + // Nothing changed + return; + } + + this->streamStatus.live = newLiveStatus; } - this->isLive = newLiveStatus; this->onlineStatusChanged(); } @@ -239,13 +243,17 @@ void TwitchChannel::refreshLiveStatus() } // Stream is live - channel->streamViewerCount = QString::number(stream["viewers"].GetInt()); - channel->streamGame = stream["game"].GetString(); - channel->streamStatus = streamChannel["status"].GetString(); - QDateTime since = QDateTime::fromString(stream["created_at"].GetString(), Qt::ISODate); - auto diff = since.secsTo(QDateTime::currentDateTime()); - channel->streamUptime = - QString::number(diff / 3600) + "h " + QString::number(diff % 3600 / 60) + "m"; + + { + std::lock_guard lock(channel->streamStatusMutex); + channel->streamStatus.viewerCount = stream["viewers"].GetUint(); + channel->streamStatus.game = stream["game"].GetString(); + channel->streamStatus.title = streamChannel["status"].GetString(); + QDateTime since = QDateTime::fromString(stream["created_at"].GetString(), Qt::ISODate); + auto diff = since.secsTo(QDateTime::currentDateTime()); + channel->streamStatus.uptime = + QString::number(diff / 3600) + "h " + QString::number(diff % 3600 / 60) + "m"; + } channel->setLive(true); }); diff --git a/src/providers/twitch/twitchchannel.hpp b/src/providers/twitch/twitchchannel.hpp index 5cc5c649..3389dea1 100644 --- a/src/providers/twitch/twitchchannel.hpp +++ b/src/providers/twitch/twitchchannel.hpp @@ -8,6 +8,8 @@ #include "singletons/ircmanager.hpp" #include "util/concurrentmap.hpp" +#include + namespace chatterino { namespace providers { namespace twitch { @@ -20,6 +22,14 @@ class TwitchChannel final : public Channel QTimer *chattersListTimer; public: + struct StreamStatus { + bool live = false; + unsigned viewerCount = 0; + QString title; + QString game; + QString uptime; + }; + ~TwitchChannel() final; void reloadChannelEmotes(); @@ -50,23 +60,33 @@ public: boost::signals2::signal userStateChanged; QString roomID; - bool isLive; - QString streamViewerCount; - QString streamStatus; - QString streamGame; - QString streamUptime; + + StreamStatus GetStreamStatus() const + { + std::lock_guard lock(this->streamStatusMutex); + return this->streamStatus; + } struct NameOptions { QString displayName; QString localizedName; }; + bool IsLive() const + { + std::lock_guard lock(this->streamStatusMutex); + return this->streamStatus.live; + } + private: explicit TwitchChannel(const QString &channelName, Communi::IrcConnection *readConnection); void setLive(bool newLiveStatus); void refreshLiveStatus(); + mutable std::mutex streamStatusMutex; + StreamStatus streamStatus; + void fetchRecentMessages(); boost::signals2::connection connectedConnection; diff --git a/src/singletons/commandmanager.cpp b/src/singletons/commandmanager.cpp index 60deb66a..3c561ec3 100644 --- a/src/singletons/commandmanager.cpp +++ b/src/singletons/commandmanager.cpp @@ -112,8 +112,10 @@ QString CommandManager::execCommand(const QString &text, ChannelPtr channel, boo if (!dryRun && twitchChannel != nullptr) { if (commandName == "/uptime") { + const auto &streamStatus = twitchChannel->GetStreamStatus(); + QString messageText = - twitchChannel->isLive ? twitchChannel->streamUptime : "Channel is not live."; + streamStatus.live ? streamStatus.uptime : "Channel is not live."; channel->addMessage(messages::Message::createSystemMessage(messageText)); diff --git a/src/widgets/helper/splitheader.cpp b/src/widgets/helper/splitheader.cpp index ca43da27..2942f137 100644 --- a/src/widgets/helper/splitheader.cpp +++ b/src/widgets/helper/splitheader.cpp @@ -157,29 +157,36 @@ void SplitHeader::updateChannelText() const QString channelName = this->split->channelName; if (channelName.isEmpty()) { this->titleLabel->setText(""); - } else { - auto channel = this->split->getChannel(); + return; + } - TwitchChannel *twitchChannel = dynamic_cast(channel.get()); + auto channel = this->split->getChannel(); - if (twitchChannel != nullptr && twitchChannel->isLive) { + TwitchChannel *twitchChannel = dynamic_cast(channel.get()); + + if (twitchChannel != nullptr) { + const auto &streamStatus = twitchChannel->GetStreamStatus(); + + if (streamStatus.live) { this->isLive = true; this->tooltip = "" "

" + - twitchChannel->streamStatus + "

" + twitchChannel->streamGame + + streamStatus.title + "

" + streamStatus.game + "
" "Live for " + - twitchChannel->streamUptime + " with " + - twitchChannel->streamViewerCount + + streamStatus.uptime + " with " + + QString::number(streamStatus.viewerCount) + " viewers" "

"; this->titleLabel->setText(channelName + " (live)"); - } else { - this->isLive = false; - this->titleLabel->setText(channelName); - this->tooltip = ""; + + return; } } + + this->isLive = false; + this->titleLabel->setText(channelName); + this->tooltip = ""; } void SplitHeader::updateModerationModeIcon() From 5a88f084a35dc376031dccda77de989a3a41e760 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Fri, 30 Mar 2018 15:42:59 +0200 Subject: [PATCH 12/69] Add setting to not fetch chatters for bigger streamers Work on #57 --- src/providers/twitch/twitchchannel.cpp | 9 +++++++++ src/singletons/settingsmanager.hpp | 7 +++++++ src/widgets/settingspages/behaviourpage.cpp | 17 +++++++++++++++-- src/widgets/settingspages/settingspage.cpp | 14 ++++++++++++++ src/widgets/settingspages/settingspage.hpp | 2 ++ 5 files changed, 47 insertions(+), 2 deletions(-) diff --git a/src/providers/twitch/twitchchannel.cpp b/src/providers/twitch/twitchchannel.cpp index e6562c3a..45b22e69 100644 --- a/src/providers/twitch/twitchchannel.cpp +++ b/src/providers/twitch/twitchchannel.cpp @@ -59,6 +59,15 @@ TwitchChannel::TwitchChannel(const QString &channelName, Communi::IrcConnection }; auto doRefreshChatters = [=]() { + const auto streamStatus = this->GetStreamStatus(); + + auto &settingManager = singletons::SettingManager::getInstance(); + if (settingManager.onlyFetchChattersForSmallerStreamers) { + if (streamStatus.live && streamStatus.viewerCount > settingManager.smallStreamerLimit) { + return; + } + } + util::twitch::get("https://tmi.twitch.tv/group/user/" + this->name + "/chatters", QThread::currentThread(), refreshChatters); }; diff --git a/src/singletons/settingsmanager.hpp b/src/singletons/settingsmanager.hpp index b3dce522..0e397992 100644 --- a/src/singletons/settingsmanager.hpp +++ b/src/singletons/settingsmanager.hpp @@ -50,6 +50,13 @@ public: BoolSetting allowDuplicateMessages = {"/behaviour/allowDuplicateMessages", true}; BoolSetting mentionUsersWithAt = {"/behaviour/mentionUsersWithAt", false}; FloatSetting mouseScrollMultiplier = {"/behaviour/mouseScrollMultiplier", 1.0}; + + // Auto-completion + BoolSetting onlyFetchChattersForSmallerStreamers = { + "/behaviour/autocompletion/onlyFetchChattersForSmallerStreamers", true}; + IntSetting smallStreamerLimit = {"/behaviour/autocompletion/smallStreamerLimit", 1000}; + + // Streamlink QStringSetting streamlinkPath = {"/behaviour/streamlink/path", ""}; QStringSetting preferredQuality = {"/behaviour/streamlink/quality", "Choose"}; QStringSetting streamlinkOpts = {"/behaviour/streamlink/options", ""}; diff --git a/src/widgets/settingspages/behaviourpage.cpp b/src/widgets/settingspages/behaviourpage.cpp index 82419e10..c596d210 100644 --- a/src/widgets/settingspages/behaviourpage.cpp +++ b/src/widgets/settingspages/behaviourpage.cpp @@ -12,6 +12,8 @@ #define LAST_MSG "Show last read message indicator (marks the spot where you left the window)" #define PAUSE_HOVERING "When hovering" +#define LIMIT_CHATTERS_FOR_SMALLER_STREAMERS "Only fetch chatters list for viewers under X viewers" + #define STREAMLINK_QUALITY "Choose", "Source", "High", "Medium", "Low", "Audio only" namespace chatterino { @@ -39,8 +41,19 @@ BehaviourPage::BehaviourPage() layout->addSpacing(16); - auto group = layout.emplace("Streamlink"); { + auto group = layout.emplace("Auto-completion"); + auto groupLayout = group.setLayoutType(); + groupLayout->addRow( + LIMIT_CHATTERS_FOR_SMALLER_STREAMERS, + this->createCheckBox("", settings.onlyFetchChattersForSmallerStreamers)); + + groupLayout->addRow("What viewer count counts as a \"smaller streamer\"", + this->createSpinBox(settings.smallStreamerLimit, 10, 50000)); + } + + { + auto group = layout.emplace("Streamlink"); auto groupLayout = group.setLayoutType(); groupLayout->addRow("Streamlink path:", this->createLineEdit(settings.streamlinkPath)); groupLayout->addRow("Prefered quality:", @@ -53,7 +66,7 @@ BehaviourPage::BehaviourPage() QSlider *BehaviourPage::createMouseScrollSlider() { - QSlider *slider = new QSlider(Qt::Horizontal); + auto slider = new QSlider(Qt::Horizontal); float currentValue = singletons::SettingManager::getInstance().mouseScrollMultiplier; int sliderValue = ((currentValue - 0.1f) / 2.f) * 99.f; diff --git a/src/widgets/settingspages/settingspage.cpp b/src/widgets/settingspages/settingspage.cpp index ca9153ba..1d6bb9d2 100644 --- a/src/widgets/settingspages/settingspage.cpp +++ b/src/widgets/settingspages/settingspage.cpp @@ -79,6 +79,20 @@ QLineEdit *SettingsPage::createLineEdit(pajlada::Settings::Setting &set return edit; } +QSpinBox *SettingsPage::createSpinBox(pajlada::Settings::Setting &setting, int min, int max) +{ + QSpinBox *w = new QSpinBox; + + w->setMinimum(min); + w->setMaximum(max); + + setting.connect([w](const int &value, auto) { w->setValue(value); }); + QObject::connect(w, QOverload::of(&QSpinBox::valueChanged), + [&setting](int value) { setting.setValue(value); }); + + return w; +} + } // namespace settingspages } // namespace widgets } // namespace chatterino diff --git a/src/widgets/settingspages/settingspage.hpp b/src/widgets/settingspages/settingspage.hpp index e669f37f..1e800878 100644 --- a/src/widgets/settingspages/settingspage.hpp +++ b/src/widgets/settingspages/settingspage.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include "singletons/settingsmanager.hpp" @@ -25,6 +26,7 @@ public: QComboBox *createComboBox(const QStringList &items, pajlada::Settings::Setting &setting); QLineEdit *createLineEdit(pajlada::Settings::Setting &setting); + QSpinBox *createSpinBox(pajlada::Settings::Setting &setting, int min = 0, int max = 2500); protected: QString name; From 57e0e85d777d18374b168b39d6df85417878067f Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Fri, 30 Mar 2018 15:58:05 +0200 Subject: [PATCH 13/69] Update a usernames "timeAdded" every time it tries to be added This keeps "recent chatters" from expiring Progress on #57 --- src/util/completionmodel.cpp | 2 ++ src/util/completionmodel.hpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/util/completionmodel.cpp b/src/util/completionmodel.cpp index 0bef743b..a183c04a 100644 --- a/src/util/completionmodel.cpp +++ b/src/util/completionmodel.cpp @@ -105,6 +105,8 @@ void CompletionModel::addUser(const QString &str) this->emotes.erase(p.first); auto result2 = this->emotes.insert(ts); assert(result2.second); + } else { + p.first->timeAdded = std::chrono::steady_clock::now(); } } } diff --git a/src/util/completionmodel.hpp b/src/util/completionmodel.hpp index 629f5dd1..016e2398 100644 --- a/src/util/completionmodel.hpp +++ b/src/util/completionmodel.hpp @@ -39,7 +39,7 @@ class CompletionModel : public QAbstractListModel // Type will help decide the lifetime of the tagged strings Type type; - std::chrono::steady_clock::time_point timeAdded; + mutable std::chrono::steady_clock::time_point timeAdded; bool HasExpired(const std::chrono::steady_clock::time_point &now) const { From 700b15c483dbbbcf429d3d35f6c3820234fe4b18 Mon Sep 17 00:00:00 2001 From: fourtf Date: Fri, 30 Mar 2018 16:25:49 +0200 Subject: [PATCH 14/69] improved new tabs --- src/singletons/thememanager.cpp | 3 ++ src/singletons/thememanager.hpp | 1 + src/widgets/helper/notebookbutton.cpp | 2 +- src/widgets/helper/notebooktab.cpp | 48 +++++++++++++++++---------- src/widgets/notebook.cpp | 13 +++++++- 5 files changed, 47 insertions(+), 20 deletions(-) diff --git a/src/singletons/thememanager.cpp b/src/singletons/thememanager.cpp index c9e02d5b..5c228a26 100644 --- a/src/singletons/thememanager.cpp +++ b/src/singletons/thememanager.cpp @@ -90,6 +90,8 @@ void ThemeManager::actuallyUpdate(double hue, double multiplier) // tabs // text, {regular, hover, unfocused} this->windowBg = "#ccc"; + + this->tabs.border = "#999"; this->tabs.regular = {tabFg, {windowBg, blendColors(windowBg, "#999", 0.5), windowBg}}; this->tabs.selected = {"#fff", {themeColor, themeColor, QColor::fromHslF(hue, 0, 0.5)}}; @@ -104,6 +106,7 @@ void ThemeManager::actuallyUpdate(double hue, double multiplier) tabFg, {blendColors(themeColor, windowBg, 0.7), blendColors(themeColor, windowBg, 0.5), blendColors(themeColorNoSat, windowBg, 0.7)}}; + this->windowBg = "#fff"; // Split diff --git a/src/singletons/thememanager.hpp b/src/singletons/thememanager.hpp index 98f82575..26ccfdea 100644 --- a/src/singletons/thememanager.hpp +++ b/src/singletons/thememanager.hpp @@ -37,6 +37,7 @@ public: TabColors selected; TabColors highlighted; TabColors newMessage; + QColor border; } tabs; struct { diff --git a/src/widgets/helper/notebookbutton.cpp b/src/widgets/helper/notebookbutton.cpp index 6aa06dc1..6570c304 100644 --- a/src/widgets/helper/notebookbutton.cpp +++ b/src/widgets/helper/notebookbutton.cpp @@ -38,7 +38,7 @@ void NotebookButton::paintEvent(QPaintEvent *) } painter.setPen(Qt::NoPen); - painter.fillRect(this->rect(), background); + // painter.fillRect(this->rect(), background); float h = height(), w = width(); diff --git a/src/widgets/helper/notebooktab.cpp b/src/widgets/helper/notebooktab.cpp index 432a44b4..9f3d8e9e 100644 --- a/src/widgets/helper/notebooktab.cpp +++ b/src/widgets/helper/notebooktab.cpp @@ -10,6 +10,7 @@ #include #include +#include #include namespace chatterino { @@ -78,15 +79,16 @@ void NotebookTab::updateSize() { float scale = getScale(); - this->resize((int)(150 * scale), (int)(24 * scale)); + int width; - // QString qTitle(qS(this->title)); - // if (singletons::SettingManager::getInstance().hideTabX) { - // this->resize((int)((fontMetrics().width(qTitle) + 16) * scale), (int)(24 * scale)); - // } else { - // this->resize((int)((fontMetrics().width(qTitle) + 8 + 24) * scale), (int)(24 * - // scale)); - // } + QString qTitle(qS(this->title)); + if (singletons::SettingManager::getInstance().hideTabX) { + width = (int)((fontMetrics().width(qTitle) + 16 + 16) * scale); + } else { + width = (int)((fontMetrics().width(qTitle) + 8 + 24 + 16) * scale); + } + + this->resize(std::min((int)(150 * scale), width), (int)(48 * scale)); if (this->parent() != nullptr) { (static_cast(this->parent()))->performLayout(true); @@ -173,6 +175,9 @@ void NotebookTab::paintEvent(QPaintEvent *) QPainter painter(this); float scale = this->getScale(); + int height = (int)(scale * 24); + int fullHeight = (int)(scale * 48); + // select the right tab colors singletons::ThemeManager::TabColors colors; singletons::ThemeManager::TabColors regular = this->themeManager.tabs.regular; @@ -190,32 +195,39 @@ void NotebookTab::paintEvent(QPaintEvent *) bool windowFocused = this->window() == QApplication::activeWindow(); // || SettingsDialog::getHandle() == QApplication::activeWindow(); + QBrush tabBackground = this->mouseOver ? colors.backgrounds.hover + : (windowFocused ? colors.backgrounds.regular + : colors.backgrounds.unfocused); + if (false) { painter.fillRect(rect(), this->mouseOver ? regular.backgrounds.hover : (windowFocused ? regular.backgrounds.regular : regular.backgrounds.unfocused)); // fill the tab background - painter.fillRect(rect(), this->mouseOver ? colors.backgrounds.hover - : (windowFocused ? colors.backgrounds.regular - : colors.backgrounds.unfocused)); + painter.fillRect(rect(), tabBackground); } else { - QPainterPath path(QPointF(0, this->height())); + QPainterPath path(QPointF(0, height)); path.lineTo(8 * scale, 0); path.lineTo(this->width() - 8 * scale, 0); - path.lineTo(this->width(), this->height()); + path.lineTo(this->width(), height); painter.fillPath(path, this->mouseOver ? regular.backgrounds.hover : (windowFocused ? regular.backgrounds.regular : regular.backgrounds.unfocused)); // fill the tab background - painter.fillPath(path, this->mouseOver ? colors.backgrounds.hover - : (windowFocused ? colors.backgrounds.regular - : colors.backgrounds.unfocused)); + painter.fillPath(path, tabBackground); painter.setPen(QColor("#FFF")); painter.setRenderHint(QPainter::Antialiasing); painter.drawPath(path); // painter.setBrush(QColor("#000")); + + QLinearGradient gradient(0, height, 0, fullHeight); + gradient.setColorAt(0, tabBackground.color()); + gradient.setColorAt(1, "#fff"); + + QBrush brush(gradient); + painter.fillRect(0, height, this->width(), fullHeight - height, brush); } // set the pen color @@ -223,7 +235,7 @@ void NotebookTab::paintEvent(QPaintEvent *) // set area for text int rectW = (settingManager.hideTabX ? 0 : static_cast(16) * scale); - QRect rect(0, 0, this->width() - rectW, this->height()); + QRect rect(0, 0, this->width() - rectW, height); // draw text if (false) { // legacy @@ -232,7 +244,7 @@ void NotebookTab::paintEvent(QPaintEvent *) QTextOption option(Qt::AlignLeft | Qt::AlignVCenter); option.setWrapMode(QTextOption::NoWrap); int offset = (int)(scale * 16); - QRect textRect(offset, 0, this->width() - offset - offset, this->height()); + QRect textRect(offset, 0, this->width() - offset - offset, height); painter.drawText(textRect, this->getTitle(), option); } diff --git a/src/widgets/notebook.cpp b/src/widgets/notebook.cpp index f790e62a..ae19ad9a 100644 --- a/src/widgets/notebook.cpp +++ b/src/widgets/notebook.cpp @@ -162,6 +162,8 @@ SplitContainer *Notebook::tabAt(QPoint point, int &index, int maxWidth) for (auto *page : this->pages) { QRect rect = page->getTab()->getDesiredRect(); + rect.setHeight((int)(this->getScale() * 22)); + rect.setWidth(std::min(maxWidth, rect.width())); if (rect.contains(point)) { @@ -242,7 +244,8 @@ void Notebook::performLayout(bool animated) for (auto &i : this->pages) { if (!first && (i == this->pages.last() ? tabHeight : 0) + x + i->getTab()->width() > width()) { - y += i->getTab()->height(); + // y += i->getTab()->height(); + y += 20; i->getTab()->moveAnimated(QPoint(0, y), animated); x = i->getTab()->width(); } else { @@ -255,8 +258,16 @@ void Notebook::performLayout(bool animated) first = false; } + x += (int)(8 * scale); + this->addButton.move(x, y); + for (auto &i : this->pages) { + i->getTab()->raise(); + } + + this->addButton.raise(); + if (this->selectedPage != nullptr) { this->selectedPage->move(0, y + tabHeight); this->selectedPage->resize(width(), height() - y - tabHeight); From 2d15716b5f6aa2aab6c0dcf7b6ac99ecfeda3f72 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 31 Mar 2018 11:23:07 +0200 Subject: [PATCH 15/69] Add helper methods to FlagsEnum where I can make sure that it actually works forsenT --- src/util/flagsenum.hpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/util/flagsenum.hpp b/src/util/flagsenum.hpp index 08a7ea55..9e5daed2 100644 --- a/src/util/flagsenum.hpp +++ b/src/util/flagsenum.hpp @@ -12,7 +12,7 @@ class FlagsEnum { public: FlagsEnum() - : value((T)0) + : value(static_cast(0)) { } @@ -50,7 +50,18 @@ public: return (T &)((Q &)this->value ^= (Q)a); } + void EnableFlag(T flag) + { + reinterpret_cast(this->value) |= static_cast(flag); + } + + bool HasFlag(Q flag) const + { + return (this->value & flag) == flag; + } + T value; }; + } // namespace util } // namespace chatterino From d3212b0a59c7a407d6c196be243d9cde211574cd Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 31 Mar 2018 11:32:29 +0200 Subject: [PATCH 16/69] Fixes the previous "Disabled message" behaviour Fixes #295 --- src/messages/layouts/messagelayout.cpp | 2 +- src/messages/message.hpp | 4 +++- src/providers/twitch/ircmessagehandler.cpp | 5 +++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/messages/layouts/messagelayout.cpp b/src/messages/layouts/messagelayout.cpp index baed0381..dd348fd9 100644 --- a/src/messages/layouts/messagelayout.cpp +++ b/src/messages/layouts/messagelayout.cpp @@ -152,7 +152,7 @@ void MessageLayout::paint(QPainter &painter, int y, int messageIndex, Selection // painter.drawPixmap(0, y, this->container.width, this->container.getHeight(), *pixmap); // draw disabled - if (this->message->flags & Message::Disabled) { + if (this->message->flags.HasFlag(Message::Disabled)) { painter.fillRect(0, y, pixmap->width(), pixmap->height(), themeManager.messages.disabled); } diff --git a/src/messages/message.hpp b/src/messages/message.hpp index 3a6b1bce..341d6a4a 100644 --- a/src/messages/message.hpp +++ b/src/messages/message.hpp @@ -12,6 +12,7 @@ namespace chatterino { namespace messages { + struct Message { enum MessageFlags : uint16_t { None = 0, @@ -53,6 +54,7 @@ public: const QString &reason, bool multipleTimes); }; -typedef std::shared_ptr MessagePtr; +using MessagePtr = std::shared_ptr; + } // namespace messages } // namespace chatterino diff --git a/src/providers/twitch/ircmessagehandler.cpp b/src/providers/twitch/ircmessagehandler.cpp index 421e70aa..d1ab09f2 100644 --- a/src/providers/twitch/ircmessagehandler.cpp +++ b/src/providers/twitch/ircmessagehandler.cpp @@ -119,8 +119,9 @@ void IrcMessageHandler::handleClearChatMessage(Communi::IrcMessage *message) // disable the messages from the user for (int i = 0; i < snapshotLength; i++) { - if (!(snapshot[i]->flags & Message::Timeout) && snapshot[i]->loginName == username) { - snapshot[i]->flags &= Message::Disabled; + auto &s = snapshot[i]; + if (!(s->flags & Message::Timeout) && s->loginName == username) { + s->flags.EnableFlag(Message::Disabled); } } From 3cdaeb071aadde9389d7e416b1f8e89c4511c434 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 31 Mar 2018 13:14:43 +0200 Subject: [PATCH 17/69] Fixes some emojis that wouldn't display properly Fix #198 --- src/singletons/emotemanager.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/singletons/emotemanager.cpp b/src/singletons/emotemanager.cpp index 470af5cb..94576188 100644 --- a/src/singletons/emotemanager.cpp +++ b/src/singletons/emotemanager.cpp @@ -295,9 +295,12 @@ void EmoteManager::loadEmojis() this->emojis.insert(code, util::EmoteData(new Image(url, 0.35, ":" + shortCode + ":", ":" + shortCode + ":
Emoji"))); + } - // TODO(pajlada): The vectors in emojiFirstByte need to be sorted by - // emojiData.code.length() + for (auto &p : this->emojiFirstByte) { + std::stable_sort(p.begin(), p.end(), [](const auto &lhs, const auto &rhs) { + return lhs.value.length() > rhs.value.length(); + }); } } @@ -306,7 +309,7 @@ void EmoteManager::parseEmojis(std::vector> { int lastParsedEmojiEndIndex = 0; - for (auto i = 0; i < text.length() - 1; i++) { + for (auto i = 0; i < text.length(); ++i) { const QChar character = text.at(i); if (character.isLowSurrogate()) { @@ -321,14 +324,15 @@ void EmoteManager::parseEmojis(std::vector> const QVector possibleEmojis = it.value(); - int remainingCharacters = text.length() - i; + int remainingCharacters = text.length() - i - 1; EmojiData matchedEmoji; int matchedEmojiLength = 0; for (const EmojiData &emoji : possibleEmojis) { - if (remainingCharacters < emoji.value.length()) { + int emojiExtraCharacters = emoji.value.length() - 1; + if (emojiExtraCharacters > remainingCharacters) { // It cannot be this emoji, there's not enough space for it continue; } From be66338fe21f16837e6a4f894cd56844711edacb Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 31 Mar 2018 13:44:15 +0200 Subject: [PATCH 18/69] General cleanups/reformats - Clean up imports - Comment EmojiData - Reorder TwitchAccount constructor - Fix typo in TwitchChannel - Add emoji parsing test code at the bottom of EmoteManager --- src/const.hpp | 7 ++- src/emojis.hpp | 7 +-- src/providers/twitch/twitchaccount.cpp | 7 ++- src/providers/twitch/twitchaccount.hpp | 2 + src/providers/twitch/twitchchannel.cpp | 4 +- src/providers/twitch/twitchchannel.hpp | 2 +- src/singletons/emotemanager.cpp | 79 ++++++++++++++++++++++---- src/util/concurrentmap.hpp | 7 +-- src/util/distancebetweenpoints.hpp | 4 +- src/util/emotemap.hpp | 6 +- src/util/irchelpers.hpp | 10 ++-- src/util/networkmanager.hpp | 16 +++--- src/widgets/basewidget.cpp | 6 +- src/widgets/helper/titlebarbutton.cpp | 2 + src/widgets/helper/titlebarbutton.hpp | 4 +- src/widgets/split.cpp | 6 +- src/widgets/split.hpp | 13 ++--- 17 files changed, 118 insertions(+), 64 deletions(-) diff --git a/src/const.hpp b/src/const.hpp index 925e0b5a..bfb15547 100644 --- a/src/const.hpp +++ b/src/const.hpp @@ -4,13 +4,14 @@ namespace chatterino { -static const QString ANONYMOUS_USERNAME_LABEL(" - anonymous - "); +static const char *ANONYMOUS_USERNAME_LABEL = " - anonymous - "; namespace providers { namespace twitch { -static const QString ANONYMOUS_USERNAME("justinfan64537"); -} +static const char *ANONYMOUS_USERNAME = "justinfan64537"; + +} // namespace twitch } // namespace providers } // namespace chatterino diff --git a/src/emojis.hpp b/src/emojis.hpp index e74fc443..b845003d 100644 --- a/src/emojis.hpp +++ b/src/emojis.hpp @@ -1,16 +1,11 @@ #pragma once -#include "messages/image.hpp" -#include "util/concurrentmap.hpp" - -#include #include -#include - namespace chatterino { struct EmojiData { + // actual byte-representation of the emoji (i.e. \154075\156150 which is :male:) QString value; // what's used in the emoji-one url diff --git a/src/providers/twitch/twitchaccount.cpp b/src/providers/twitch/twitchaccount.cpp index 5e11adbb..fc7ea45c 100644 --- a/src/providers/twitch/twitchaccount.cpp +++ b/src/providers/twitch/twitchaccount.cpp @@ -1,15 +1,15 @@ #include "providers/twitch/twitchaccount.hpp" #include "const.hpp" -#include "util/urlfetch.hpp" namespace chatterino { namespace providers { namespace twitch { + TwitchAccount::TwitchAccount(const QString &_username, const QString &_oauthToken, const QString &_oauthClient) - : userName(_username) - , oauthClient(_oauthClient) + : oauthClient(_oauthClient) , oauthToken(_oauthToken) + , userName(_username) , _isAnon(_username == ANONYMOUS_USERNAME) { } @@ -65,6 +65,7 @@ bool TwitchAccount::isAnon() const { return this->_isAnon; } + } // namespace twitch } // namespace providers } // namespace chatterino diff --git a/src/providers/twitch/twitchaccount.hpp b/src/providers/twitch/twitchaccount.hpp index f33d713a..6e3fdb8a 100644 --- a/src/providers/twitch/twitchaccount.hpp +++ b/src/providers/twitch/twitchaccount.hpp @@ -6,6 +6,7 @@ namespace chatterino { namespace providers { namespace twitch { + class TwitchAccount { public: @@ -37,6 +38,7 @@ private: QString userName; const bool _isAnon; }; + } // namespace twitch } // namespace providers } // namespace chatterino diff --git a/src/providers/twitch/twitchchannel.cpp b/src/providers/twitch/twitchchannel.cpp index 45b22e69..82537aed 100644 --- a/src/providers/twitch/twitchchannel.cpp +++ b/src/providers/twitch/twitchchannel.cpp @@ -25,7 +25,7 @@ TwitchChannel::TwitchChannel(const QString &channelName, Communi::IrcConnection , channelURL("https://twitch.tv/" + name) , popoutPlayerURL("https://player.twitch.tv/?channel=" + name) , mod(false) - , readConnecetion(_readConnection) + , readConnection(_readConnection) { debug::Log("[TwitchChannel:{}] Opened", this->name); @@ -285,7 +285,7 @@ void TwitchChannel::fetchRecentMessages() auto channel = dynamic_cast(shared.get()); assert(channel != nullptr); - static auto readConnection = channel->readConnecetion; + static auto readConnection = channel->readConnection; QJsonArray msgArray = obj.value("messages").toArray(); if (msgArray.empty()) { diff --git a/src/providers/twitch/twitchchannel.hpp b/src/providers/twitch/twitchchannel.hpp index 3389dea1..949c5a55 100644 --- a/src/providers/twitch/twitchchannel.hpp +++ b/src/providers/twitch/twitchchannel.hpp @@ -95,7 +95,7 @@ private: QByteArray messageSuffix; QString lastSentMessage; - Communi::IrcConnection *readConnecetion; + Communi::IrcConnection *readConnection; friend class TwitchServer; diff --git a/src/singletons/emotemanager.cpp b/src/singletons/emotemanager.cpp index 94576188..48269770 100644 --- a/src/singletons/emotemanager.cpp +++ b/src/singletons/emotemanager.cpp @@ -26,7 +26,7 @@ namespace singletons { namespace { -static QString GetTwitchEmoteLink(long id, const QString &emoteScale) +QString GetTwitchEmoteLink(long id, const QString &emoteScale) { QString value = TWITCH_EMOTE_TEMPLATE; @@ -35,14 +35,14 @@ static QString GetTwitchEmoteLink(long id, const QString &emoteScale) return value.replace("{id}", QString::number(id)).replace("{scale}", emoteScale); } -static QString GetBTTVEmoteLink(QString urlTemplate, const QString &id, const QString &emoteScale) +QString GetBTTVEmoteLink(QString urlTemplate, const QString &id, const QString &emoteScale) { urlTemplate.detach(); return urlTemplate.replace("{{id}}", id).replace("{{image}}", emoteScale); } -static QString GetFFZEmoteLink(const QJsonObject &urls, const QString &emoteScale) +QString GetFFZEmoteLink(const QJsonObject &urls, const QString &emoteScale) { auto emote = urls.value(emoteScale); if (emote.isUndefined()) { @@ -54,8 +54,7 @@ static QString GetFFZEmoteLink(const QJsonObject &urls, const QString &emoteScal return "http:" + emote.toString(); } -static void FillInFFZEmoteData(const QJsonObject &urls, const QString &code, - util::EmoteData &emoteData) +void FillInFFZEmoteData(const QJsonObject &urls, const QString &code, util::EmoteData &emoteData) { QString url1x = GetFFZEmoteLink(urls, "1"); QString url2x = GetFFZEmoteLink(urls, "2"); @@ -366,9 +365,8 @@ void EmoteManager::parseEmojis(std::vector> if (charactersFromLastParsedEmoji > 0) { // Add characters inbetween emojis - parsedWords.push_back(std::tuple( - util::EmoteData(), - text.mid(lastParsedEmojiEndIndex, charactersFromLastParsedEmoji))); + parsedWords.emplace_back(util::EmoteData(), text.mid(lastParsedEmojiEndIndex, + charactersFromLastParsedEmoji)); } QString url = "https://cdnjs.cloudflare.com/ajax/libs/" @@ -376,7 +374,7 @@ void EmoteManager::parseEmojis(std::vector> matchedEmoji.code + ".png"; // Create or fetch cached emoji image - auto emojiImage = this->emojis.getOrAdd(matchedEmoji.code, [this, &url] { + auto emojiImage = this->emojis.getOrAdd(matchedEmoji.code, [&url] { return util::EmoteData(new Image(url, 0.35, "?????????", "???????????????")); // }); @@ -390,8 +388,7 @@ void EmoteManager::parseEmojis(std::vector> if (lastParsedEmojiEndIndex < text.length()) { // Add remaining characters - parsedWords.push_back(std::tuple( - util::EmoteData(), text.mid(lastParsedEmojiEndIndex))); + parsedWords.emplace_back(util::EmoteData(), text.mid(lastParsedEmojiEndIndex)); } } @@ -546,7 +543,7 @@ util::EmoteData EmoteManager::getTwitchEmoteById(long id, const QString &emoteNa QString _emoteName = emoteName; _emoteName.replace("<", "<"); - return _twitchEmoteFromCache.getOrAdd(id, [this, &emoteName, &_emoteName, &id] { + return _twitchEmoteFromCache.getOrAdd(id, [&emoteName, &_emoteName, &id] { util::EmoteData newEmoteData; newEmoteData.image1x = new Image(GetTwitchEmoteLink(id, "1.0"), 1, emoteName, _emoteName + "
Twitch Emote 1x"); @@ -593,3 +590,61 @@ boost::signals2::signal &EmoteManager::getGifUpdateSignal() } // namespace singletons } // namespace chatterino + +#if 0 +namespace chatterino { + +void EmojiTest() +{ + auto &emoteManager = singletons::EmoteManager::getInstance(); + + emoteManager.loadEmojis(); + + { + std::vector> dummy; + + // couple_mm 1f468-2764-1f468 + // "\154075\156150❤\154075\156150" + // [0] 55357 0xd83d QChar + // [1] 56424 0xdc68 QChar + // [2] '❤' 10084 0x2764 QChar + // [3] 55357 0xd83d QChar + // [4] 56424 0xdc68 QChar + QString text = "👨❤👨"; + + emoteManager.parseEmojis(dummy, text); + + assert(dummy.size() == 1); + } + + { + std::vector> dummy; + + // "✍\154074\157777" + // [0] '✍' 9997 0x270d QChar + // [1] 55356 0xd83c QChar + // [2] 57343 0xdfff QChar + QString text = "✍🏿"; + + emoteManager.parseEmojis(dummy, text); + + assert(dummy.size() == 1); + + assert(std::get<0>(dummy[0]).isValid()); + } + + { + std::vector> dummy; + + QString text = "✍"; + + emoteManager.parseEmojis(dummy, text); + + assert(dummy.size() == 1); + + assert(std::get<0>(dummy[0]).isValid()); + } +} + +} // namespace chatterino +#endif diff --git a/src/util/concurrentmap.hpp b/src/util/concurrentmap.hpp index 183d726d..41b0ece3 100644 --- a/src/util/concurrentmap.hpp +++ b/src/util/concurrentmap.hpp @@ -15,9 +15,7 @@ template class ConcurrentMap { public: - ConcurrentMap() - { - } + ConcurrentMap() = default; bool tryGet(const TKey &name, TValue &value) const { @@ -84,5 +82,6 @@ private: mutable QMutex mutex; QMap data; }; + +} // namespace util } // namespace chatterino -} diff --git a/src/util/distancebetweenpoints.hpp b/src/util/distancebetweenpoints.hpp index 2c7fd49f..098aab1a 100644 --- a/src/util/distancebetweenpoints.hpp +++ b/src/util/distancebetweenpoints.hpp @@ -1,6 +1,8 @@ #pragma once -#include +#include + +#include namespace chatterino { namespace util { diff --git a/src/util/emotemap.hpp b/src/util/emotemap.hpp index 56c5823d..d787a745 100644 --- a/src/util/emotemap.hpp +++ b/src/util/emotemap.hpp @@ -9,9 +9,7 @@ namespace chatterino { namespace util { struct EmoteData { - EmoteData() - { - } + EmoteData() = default; EmoteData(messages::Image *_image) : image1x(_image) @@ -29,7 +27,7 @@ struct EmoteData { messages::Image *image3x = nullptr; }; -typedef ConcurrentMap EmoteMap; +using EmoteMap = ConcurrentMap; } // namespace util } // namespace chatterino diff --git a/src/util/irchelpers.hpp b/src/util/irchelpers.hpp index 9462680b..9bf21502 100644 --- a/src/util/irchelpers.hpp +++ b/src/util/irchelpers.hpp @@ -4,7 +4,8 @@ namespace chatterino { namespace util { -QString ParseTagString(const QString &input) + +inline QString ParseTagString(const QString &input) { QString output = input; output.detach(); @@ -49,9 +50,10 @@ QString ParseTagString(const QString &input) if (changed) { return output.replace("\0", ""); - } else { - return output; } + + return output; } -} + +} // namespace util } // namespace chatterino diff --git a/src/util/networkmanager.hpp b/src/util/networkmanager.hpp index 309c0ec6..7cf9dcfe 100644 --- a/src/util/networkmanager.hpp +++ b/src/util/networkmanager.hpp @@ -51,11 +51,11 @@ public: worker->moveToThread(&NetworkManager::workerThread); QObject::connect( &requester, &NetworkRequester::requestUrl, worker, - [ worker, onFinished = std::move(onFinished), request = std::move(request) ]() { + [worker, onFinished = std::move(onFinished), request = std::move(request)]() { QNetworkReply *reply = NetworkManager::NaM.get(request); QObject::connect(reply, &QNetworkReply::finished, - [ worker, reply, onFinished = std::move(onFinished) ]() { + [worker, reply, onFinished = std::move(onFinished)]() { onFinished(reply); delete worker; }); @@ -111,11 +111,11 @@ public: worker->moveToThread(&NetworkManager::workerThread); QObject::connect( &requester, &NetworkRequester::requestUrl, worker, - [ worker, data, onFinished = std::move(onFinished), request = std::move(request) ]() { + [worker, data, onFinished = std::move(onFinished), request = std::move(request)]() { QNetworkReply *reply = NetworkManager::NaM.put(request, *data); QObject::connect(reply, &QNetworkReply::finished, - [ worker, reply, onFinished = std::move(onFinished) ]() { + [worker, reply, onFinished = std::move(onFinished)]() { onFinished(reply); delete worker; }); @@ -133,11 +133,11 @@ public: worker->moveToThread(&NetworkManager::workerThread); QObject::connect( &requester, &NetworkRequester::requestUrl, worker, - [ onFinished = std::move(onFinished), request = std::move(request), worker ]() { + [onFinished = std::move(onFinished), request = std::move(request), worker]() { QNetworkReply *reply = NetworkManager::NaM.put(request, ""); QObject::connect(reply, &QNetworkReply::finished, - [ onFinished = std::move(onFinished), reply, worker ]() { + [onFinished = std::move(onFinished), reply, worker]() { onFinished(reply); delete worker; }); @@ -155,11 +155,11 @@ public: worker->moveToThread(&NetworkManager::workerThread); QObject::connect( &requester, &NetworkRequester::requestUrl, worker, - [ onFinished = std::move(onFinished), request = std::move(request), worker ]() { + [onFinished = std::move(onFinished), request = std::move(request), worker]() { QNetworkReply *reply = NetworkManager::NaM.deleteResource(request); QObject::connect(reply, &QNetworkReply::finished, - [ onFinished = std::move(onFinished), reply, worker ]() { + [onFinished = std::move(onFinished), reply, worker]() { onFinished(reply); delete worker; }); diff --git a/src/widgets/basewidget.cpp b/src/widgets/basewidget.cpp index b915abbc..6680134e 100644 --- a/src/widgets/basewidget.cpp +++ b/src/widgets/basewidget.cpp @@ -33,9 +33,9 @@ float BaseWidget::getScale() const if (baseWidget == nullptr) { return 1.f; - } else { - return baseWidget->scale; } + + return baseWidget->scale; } QSize BaseWidget::getScaleIndependantSize() const @@ -98,7 +98,7 @@ void BaseWidget::childEvent(QChildEvent *event) if (event->added()) { BaseWidget *widget = dynamic_cast(event->child()); - if (widget) { + if (widget != nullptr) { this->widgets.push_back(widget); } } else if (event->removed()) { diff --git a/src/widgets/helper/titlebarbutton.cpp b/src/widgets/helper/titlebarbutton.cpp index 1d3f45aa..d3b2cd34 100644 --- a/src/widgets/helper/titlebarbutton.cpp +++ b/src/widgets/helper/titlebarbutton.cpp @@ -2,6 +2,7 @@ namespace chatterino { namespace widgets { + TitleBarButton::TitleBarButton() : RippleEffectButton(nullptr) { @@ -114,5 +115,6 @@ void TitleBarButton::paintEvent(QPaintEvent *) this->fancyPaint(painter); } + } // namespace widgets } // namespace chatterino diff --git a/src/widgets/helper/titlebarbutton.hpp b/src/widgets/helper/titlebarbutton.hpp index cdc13026..418e9143 100644 --- a/src/widgets/helper/titlebarbutton.hpp +++ b/src/widgets/helper/titlebarbutton.hpp @@ -4,6 +4,7 @@ namespace chatterino { namespace widgets { + class TitleBarButton : public RippleEffectButton { public: @@ -15,10 +16,11 @@ public: void setButtonStyle(Style style); protected: - virtual void paintEvent(QPaintEvent *) override; + void paintEvent(QPaintEvent *) override; private: Style style; }; + } // namespace widgets } // namespace chatterino diff --git a/src/widgets/split.cpp b/src/widgets/split.cpp index 19550d75..f738f0ea 100644 --- a/src/widgets/split.cpp +++ b/src/widgets/split.cpp @@ -18,17 +18,12 @@ #include #include -#include #include #include #include -#include -#include #include #include #include -#include -#include #include #include @@ -540,5 +535,6 @@ void Split::drag() SplitContainer::isDraggingSplit = false; } } + } // namespace widgets } // namespace chatterino diff --git a/src/widgets/split.hpp b/src/widgets/split.hpp index 5f38a196..ce5f193e 100644 --- a/src/widgets/split.hpp +++ b/src/widgets/split.hpp @@ -19,7 +19,6 @@ #include namespace chatterino { - namespace widgets { class SplitContainer; @@ -45,7 +44,7 @@ class Split : public BaseWidget public: Split(SplitContainer *parent, const std::string &_uuid); - virtual ~Split(); + ~Split() override; pajlada::Settings::Setting channelName; boost::signals2::signal channelChanged; @@ -75,11 +74,11 @@ public: void drag(); protected: - virtual void paintEvent(QPaintEvent *) override; - virtual void mouseMoveEvent(QMouseEvent *) override; - virtual void mousePressEvent(QMouseEvent *event) override; - virtual void keyPressEvent(QKeyEvent *) override; - virtual void keyReleaseEvent(QKeyEvent *) override; + void paintEvent(QPaintEvent *) override; + void mouseMoveEvent(QMouseEvent *) override; + void mousePressEvent(QMouseEvent *event) override; + void keyPressEvent(QKeyEvent *) override; + void keyReleaseEvent(QKeyEvent *) override; private: SplitContainer &parentPage; From fdea4f32f03324e88e821d4a7425979bc2982968 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 31 Mar 2018 13:59:17 +0200 Subject: [PATCH 19/69] Re-fix timeout message merging Fix #298 --- src/messages/message.cpp | 5 +++-- src/providers/twitch/ircmessagehandler.cpp | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/messages/message.cpp b/src/messages/message.cpp index f3ebd5b4..d2fca598 100644 --- a/src/messages/message.cpp +++ b/src/messages/message.cpp @@ -31,7 +31,7 @@ MessagePtr Message::createSystemMessage(const QString &text) message->addElement(new TimestampElement(QTime::currentTime())); message->addElement(new TextElement(text, MessageElement::Text, MessageColor::System)); - message->flags |= MessageFlags::System; + message->flags.EnableFlag(MessageFlags::System); message->searchText = text; return message; @@ -72,7 +72,8 @@ MessagePtr Message::createTimeoutMessage(const QString &username, const QString } MessagePtr message = Message::createSystemMessage(text); - message->flags |= MessageFlags::System; + message->flags.EnableFlag(MessageFlags::System); + message->flags.EnableFlag(MessageFlags::Timeout); message->timeoutUser = username; return message; } diff --git a/src/providers/twitch/ircmessagehandler.cpp b/src/providers/twitch/ircmessagehandler.cpp index d1ab09f2..ea493e3d 100644 --- a/src/providers/twitch/ircmessagehandler.cpp +++ b/src/providers/twitch/ircmessagehandler.cpp @@ -104,10 +104,11 @@ void IrcMessageHandler::handleClearChatMessage(Communi::IrcMessage *message) int snapshotLength = snapshot.getLength(); for (int i = std::max(0, snapshotLength - 20); i < snapshotLength; i++) { - if (snapshot[i]->flags & Message::Timeout && snapshot[i]->loginName == username) { + auto &s = snapshot[i]; + if (s->flags.HasFlag(Message::Timeout) && s->timeoutUser == username) { MessagePtr replacement( Message::createTimeoutMessage(username, durationInSeconds, reason, true)); - chan->replaceMessage(snapshot[i], replacement); + chan->replaceMessage(s, replacement); addMessage = false; break; } From 87cf79440b4a54b8312c6170a2c4d6c76da3fe4e Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sun, 1 Apr 2018 11:43:26 +0200 Subject: [PATCH 20/69] Fixed an issue where Badges and emotes were not rendered transparently in disabled messages I'm a master programmator Fixes #300 --- src/messages/layouts/messagelayout.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/messages/layouts/messagelayout.cpp b/src/messages/layouts/messagelayout.cpp index dd348fd9..ee38aef1 100644 --- a/src/messages/layouts/messagelayout.cpp +++ b/src/messages/layouts/messagelayout.cpp @@ -151,14 +151,14 @@ void MessageLayout::paint(QPainter &painter, int y, int messageIndex, Selection painter.drawPixmap(0, y, *pixmap); // painter.drawPixmap(0, y, this->container.width, this->container.getHeight(), *pixmap); + // draw gif emotes + this->container.paintAnimatedElements(painter, y); + // draw disabled if (this->message->flags.HasFlag(Message::Disabled)) { painter.fillRect(0, y, pixmap->width(), pixmap->height(), themeManager.messages.disabled); } - // draw gif emotes - this->container.paintAnimatedElements(painter, y); - // draw last read message line if (isLastReadMessage) { QColor color = isWindowFocused ? themeManager.tabs.selected.backgrounds.regular.color() From 58fe1f6dcc422b69e550d92b5ce2f9bb1a677f29 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sun, 1 Apr 2018 14:56:05 +0200 Subject: [PATCH 21/69] Fix typo --- src/providers/twitch/twitchserver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/twitch/twitchserver.cpp b/src/providers/twitch/twitchserver.cpp index ddff5b55..1ea95691 100644 --- a/src/providers/twitch/twitchserver.cpp +++ b/src/providers/twitch/twitchserver.cpp @@ -17,7 +17,7 @@ namespace providers { namespace twitch { TwitchServer::TwitchServer() - : whispersChannel(new Channel("/mentions")) + : whispersChannel(new Channel("/whispers")) , mentionsChannel(new Channel("/mentions")) { AccountManager::getInstance().Twitch.userChanged.connect([this]() { // From d075231081ade44e3debd94b9537d7ec5cb93d86 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sun, 1 Apr 2018 15:10:15 +0200 Subject: [PATCH 22/69] Added a "CleanChannelName" virtual method to AbstractIrcServer the TwitchServer implementation makes the channelName full lowercase Fixes #293 --- src/providers/irc/abstractircserver.cpp | 13 +++++++++++-- src/providers/irc/abstractircserver.hpp | 6 ++++-- src/providers/twitch/twitchserver.cpp | 5 +++++ src/providers/twitch/twitchserver.hpp | 2 ++ 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/providers/irc/abstractircserver.cpp b/src/providers/irc/abstractircserver.cpp index 83450b65..4bd95a0d 100644 --- a/src/providers/irc/abstractircserver.cpp +++ b/src/providers/irc/abstractircserver.cpp @@ -95,8 +95,10 @@ void AbstractIrcServer::writeConnectionMessageReceived(Communi::IrcMessage *mess { } -std::shared_ptr AbstractIrcServer::addChannel(const QString &channelName) +std::shared_ptr AbstractIrcServer::addChannel(const QString &dirtyChannelName) { + auto channelName = this->CleanChannelName(dirtyChannelName); + // try get channel ChannelPtr chan = this->getChannel(channelName); if (chan != Channel::getEmpty()) { @@ -137,8 +139,10 @@ std::shared_ptr AbstractIrcServer::addChannel(const QString &channelNam return chan; } -std::shared_ptr AbstractIrcServer::getChannel(const QString &channelName) +std::shared_ptr AbstractIrcServer::getChannel(const QString &dirtyChannelName) { + auto channelName = this->CleanChannelName(dirtyChannelName); + std::lock_guard lock(this->channelMutex); // try get special channel @@ -210,6 +214,11 @@ std::shared_ptr AbstractIrcServer::getCustomChannel(const QString &chan return nullptr; } +QString AbstractIrcServer::CleanChannelName(const QString &dirtyChannelName) +{ + return dirtyChannelName; +} + void AbstractIrcServer::addFakeMessage(const QString &data) { auto fakeMessage = Communi::IrcMessage::fromData(data.toUtf8(), this->readConnection.get()); diff --git a/src/providers/irc/abstractircserver.hpp b/src/providers/irc/abstractircserver.hpp index 823071f8..266c2226 100644 --- a/src/providers/irc/abstractircserver.hpp +++ b/src/providers/irc/abstractircserver.hpp @@ -22,8 +22,8 @@ public: void sendMessage(const QString &channelName, const QString &message); // channels - std::shared_ptr addChannel(const QString &channelName); - std::shared_ptr getChannel(const QString &channelName); + std::shared_ptr addChannel(const QString &dirtyChannelName); + std::shared_ptr getChannel(const QString &dirtyChannelName); // signals pajlada::Signals::NoArgSignal connected; @@ -51,6 +51,8 @@ protected: virtual std::shared_ptr getCustomChannel(const QString &channelName); + virtual QString CleanChannelName(const QString &dirtyChannelName); + QMap> channels; std::mutex channelMutex; diff --git a/src/providers/twitch/twitchserver.cpp b/src/providers/twitch/twitchserver.cpp index 1ea95691..aec19a32 100644 --- a/src/providers/twitch/twitchserver.cpp +++ b/src/providers/twitch/twitchserver.cpp @@ -168,6 +168,11 @@ void TwitchServer::forEachChannelAndSpecialChannels(std::functionmentionsChannel); } +QString TwitchServer::CleanChannelName(const QString &dirtyChannelName) +{ + return dirtyChannelName.toLower(); +} + } // namespace twitch } // namespace providers } // namespace chatterino diff --git a/src/providers/twitch/twitchserver.hpp b/src/providers/twitch/twitchserver.hpp index 9932204b..891868ae 100644 --- a/src/providers/twitch/twitchserver.hpp +++ b/src/providers/twitch/twitchserver.hpp @@ -33,6 +33,8 @@ protected: virtual void writeConnectionMessageReceived(Communi::IrcMessage *message) override; virtual std::shared_ptr getCustomChannel(const QString &channelname) override; + + QString CleanChannelName(const QString &dirtyChannelName) override; }; } // namespace twitch From 56f0e5e76ade61cf1f56121c7154d42c01bbf37b Mon Sep 17 00:00:00 2001 From: fourtf Date: Sun, 1 Apr 2018 16:41:32 +0200 Subject: [PATCH 23/69] removed the chrome style tabs --- src/messages/layouts/messagelayout.cpp | 2 +- .../layouts/messagelayoutcontainer.cpp | 4 +- .../layouts/messagelayoutcontainer.hpp | 2 +- src/singletons/thememanager.cpp | 4 +- src/widgets/helper/notebooktab.cpp | 76 ++++++++++++------- src/widgets/notebook.cpp | 14 ++-- 6 files changed, 62 insertions(+), 40 deletions(-) diff --git a/src/messages/layouts/messagelayout.cpp b/src/messages/layouts/messagelayout.cpp index ee38aef1..4ac17008 100644 --- a/src/messages/layouts/messagelayout.cpp +++ b/src/messages/layouts/messagelayout.cpp @@ -117,7 +117,7 @@ void MessageLayout::actuallyLayout(int width, MessageElement::Flags flags) this->deleteBuffer(); } - this->container.finish(); + this->container.end(); this->height = this->container.getHeight(); } diff --git a/src/messages/layouts/messagelayoutcontainer.cpp b/src/messages/layouts/messagelayoutcontainer.cpp index 7a236615..1913e7b7 100644 --- a/src/messages/layouts/messagelayoutcontainer.cpp +++ b/src/messages/layouts/messagelayoutcontainer.cpp @@ -142,7 +142,7 @@ void MessageLayoutContainer::breakLine() } this->lineStart = this->elements.size(); - this->currentX = 0; + this->currentX = (int)(this->scale * 8); this->currentY += this->lineHeight; this->height = this->currentY + (this->margin.bottom * this->scale); this->lineHeight = 0; @@ -158,7 +158,7 @@ bool MessageLayoutContainer::fitsInLine(int _width) return this->currentX + _width <= this->width - this->margin.left - this->margin.right; } -void MessageLayoutContainer::finish() +void MessageLayoutContainer::end() { if (!this->atStartOfLine()) { this->breakLine(); diff --git a/src/messages/layouts/messagelayoutcontainer.hpp b/src/messages/layouts/messagelayoutcontainer.hpp index 9656b9b4..d8469ad7 100644 --- a/src/messages/layouts/messagelayoutcontainer.hpp +++ b/src/messages/layouts/messagelayoutcontainer.hpp @@ -56,7 +56,7 @@ public: // methods void begin(int width, float scale, Message::MessageFlags flags); - void finish(); + void end(); void clear(); void addElement(MessageLayoutElement *element); diff --git a/src/singletons/thememanager.cpp b/src/singletons/thememanager.cpp index 5c228a26..a088a0b8 100644 --- a/src/singletons/thememanager.cpp +++ b/src/singletons/thememanager.cpp @@ -89,7 +89,7 @@ void ThemeManager::actuallyUpdate(double hue, double multiplier) // tabs // text, {regular, hover, unfocused} - this->windowBg = "#ccc"; + // this->windowBg = "#ccc"; this->tabs.border = "#999"; this->tabs.regular = {tabFg, {windowBg, blendColors(windowBg, "#999", 0.5), windowBg}}; @@ -107,7 +107,7 @@ void ThemeManager::actuallyUpdate(double hue, double multiplier) {blendColors(themeColor, windowBg, 0.7), blendColors(themeColor, windowBg, 0.5), blendColors(themeColorNoSat, windowBg, 0.7)}}; - this->windowBg = "#fff"; + // this->windowBg = "#fff"; // Split bool flat = isLight; diff --git a/src/widgets/helper/notebooktab.cpp b/src/widgets/helper/notebooktab.cpp index 9f3d8e9e..ad2f481d 100644 --- a/src/widgets/helper/notebooktab.cpp +++ b/src/widgets/helper/notebooktab.cpp @@ -83,12 +83,12 @@ void NotebookTab::updateSize() QString qTitle(qS(this->title)); if (singletons::SettingManager::getInstance().hideTabX) { - width = (int)((fontMetrics().width(qTitle) + 16 + 16) * scale); + width = (int)((fontMetrics().width(qTitle) + 16 /*+ 16*/) * scale); } else { - width = (int)((fontMetrics().width(qTitle) + 8 + 24 + 16) * scale); + width = (int)((fontMetrics().width(qTitle) + 8 + 24 /*+ 16*/) * scale); } - this->resize(std::min((int)(150 * scale), width), (int)(48 * scale)); + this->resize(std::min((int)(150 * scale), width), (int)(24 * scale)); if (this->parent() != nullptr) { (static_cast(this->parent()))->performLayout(true); @@ -176,7 +176,7 @@ void NotebookTab::paintEvent(QPaintEvent *) float scale = this->getScale(); int height = (int)(scale * 24); - int fullHeight = (int)(scale * 48); + // int fullHeight = (int)(scale * 48); // select the right tab colors singletons::ThemeManager::TabColors colors; @@ -199,35 +199,47 @@ void NotebookTab::paintEvent(QPaintEvent *) : (windowFocused ? colors.backgrounds.regular : colors.backgrounds.unfocused); - if (false) { + if (true) { painter.fillRect(rect(), this->mouseOver ? regular.backgrounds.hover : (windowFocused ? regular.backgrounds.regular : regular.backgrounds.unfocused)); // fill the tab background painter.fillRect(rect(), tabBackground); - } else { + + // draw border + painter.setPen(QPen("#ccc")); QPainterPath path(QPointF(0, height)); - path.lineTo(8 * scale, 0); - path.lineTo(this->width() - 8 * scale, 0); - path.lineTo(this->width(), height); - painter.fillPath(path, this->mouseOver ? regular.backgrounds.hover - : (windowFocused ? regular.backgrounds.regular - : regular.backgrounds.unfocused)); - - // fill the tab background - painter.fillPath(path, tabBackground); - painter.setPen(QColor("#FFF")); - painter.setRenderHint(QPainter::Antialiasing); + path.lineTo(0, 0); + path.lineTo(this->width() - 1, 0); + path.lineTo(this->width() - 1, this->height() - 1); + path.lineTo(0, this->height() - 1); painter.drawPath(path); - // painter.setBrush(QColor("#000")); + } else { + // QPainterPath path(QPointF(0, height)); + // path.lineTo(8 * scale, 0); + // path.lineTo(this->width() - 8 * scale, 0); + // path.lineTo(this->width(), height); + // painter.fillPath(path, this->mouseOver ? regular.backgrounds.hover + // : (windowFocused ? + // regular.backgrounds.regular + // : + // regular.backgrounds.unfocused)); - QLinearGradient gradient(0, height, 0, fullHeight); - gradient.setColorAt(0, tabBackground.color()); - gradient.setColorAt(1, "#fff"); + // // fill the tab background + // painter.fillPath(path, tabBackground); + // painter.setPen(QColor("#FFF")); + // painter.setRenderHint(QPainter::Antialiasing); + // painter.drawPath(path); + // // painter.setBrush(QColor("#000")); - QBrush brush(gradient); - painter.fillRect(0, height, this->width(), fullHeight - height, brush); + // QLinearGradient gradient(0, height, 0, fullHeight); + // gradient.setColorAt(0, tabBackground.color()); + // gradient.setColorAt(1, "#fff"); + + // QBrush brush(gradient); + // painter.fillRect(0, height, this->width(), fullHeight - height, + // brush); } // set the pen color @@ -238,14 +250,20 @@ void NotebookTab::paintEvent(QPaintEvent *) QRect rect(0, 0, this->width() - rectW, height); // draw text - if (false) { // legacy - painter.drawText(rect, this->getTitle(), QTextOption(Qt::AlignCenter)); - } else { + if (true) { // legacy + // painter.drawText(rect, this->getTitle(), QTextOption(Qt::AlignCenter)); + int offset = (int)(scale * 8); + QRect textRect(offset, 0, this->width() - offset - offset, height); + QTextOption option(Qt::AlignLeft | Qt::AlignVCenter); option.setWrapMode(QTextOption::NoWrap); - int offset = (int)(scale * 16); - QRect textRect(offset, 0, this->width() - offset - offset, height); painter.drawText(textRect, this->getTitle(), option); + } else { + // QTextOption option(Qt::AlignLeft | Qt::AlignVCenter); + // option.setWrapMode(QTextOption::NoWrap); + // int offset = (int)(scale * 16); + // QRect textRect(offset, 0, this->width() - offset - offset, height); + // painter.drawText(textRect, this->getTitle(), option); } // draw close x @@ -264,7 +282,7 @@ void NotebookTab::paintEvent(QPaintEvent *) painter.drawLine(xRect.topLeft() + QPoint(a, a), xRect.bottomRight() + QPoint(-a, -a)); painter.drawLine(xRect.topRight() + QPoint(-a, a), xRect.bottomLeft() + QPoint(a, -a)); } -} +} // namespace widgets void NotebookTab::mousePressEvent(QMouseEvent *event) { diff --git a/src/widgets/notebook.cpp b/src/widgets/notebook.cpp index ae19ad9a..fd73921a 100644 --- a/src/widgets/notebook.cpp +++ b/src/widgets/notebook.cpp @@ -162,7 +162,7 @@ SplitContainer *Notebook::tabAt(QPoint point, int &index, int maxWidth) for (auto *page : this->pages) { QRect rect = page->getTab()->getDesiredRect(); - rect.setHeight((int)(this->getScale() * 22)); + rect.setHeight((int)(this->getScale() * 24)); rect.setWidth(std::min(maxWidth, rect.width())); @@ -244,8 +244,8 @@ void Notebook::performLayout(bool animated) for (auto &i : this->pages) { if (!first && (i == this->pages.last() ? tabHeight : 0) + x + i->getTab()->width() > width()) { - // y += i->getTab()->height(); - y += 20; + y += i->getTab()->height() - 1; + // y += 20; i->getTab()->moveAnimated(QPoint(0, y), animated); x = i->getTab()->width(); } else { @@ -253,15 +253,19 @@ void Notebook::performLayout(bool animated) x += i->getTab()->width(); } - x -= (int)(8 * scale); + // x -= (int)(8 * scale); + x += 1; first = false; } - x += (int)(8 * scale); + // x += (int)(8 * scale); + // x += 1; this->addButton.move(x, y); + y -= 1; + for (auto &i : this->pages) { i->getTab()->raise(); } From 3dae83e749ade62d4a4c8716283365e02d43c6a7 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sun, 1 Apr 2018 16:16:54 +0200 Subject: [PATCH 24/69] Add an EmojiMap which is like an EmoteMap except it contains data for Emojis Fix emote popup not inserting the correct emoji value on click. It no inserts the shortcode (i.e. :ok_hand:) Fix #299 --- src/emojis.hpp | 10 ++++++++++ src/singletons/emotemanager.cpp | 26 +++++++++----------------- src/singletons/emotemanager.hpp | 5 ++--- src/widgets/emotepopup.cpp | 8 ++++---- 4 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/emojis.hpp b/src/emojis.hpp index b845003d..39f2be24 100644 --- a/src/emojis.hpp +++ b/src/emojis.hpp @@ -1,5 +1,7 @@ #pragma once +#include "util/emotemap.hpp" + #include namespace chatterino { @@ -13,6 +15,14 @@ struct EmojiData { // i.e. thinking QString shortCode; + + util::EmoteData emoteData; }; +namespace util { + +using EmojiMap = ConcurrentMap; + +} // namespace util + } // namespace chatterino diff --git a/src/singletons/emotemanager.cpp b/src/singletons/emotemanager.cpp index 48269770..1c25d233 100644 --- a/src/singletons/emotemanager.cpp +++ b/src/singletons/emotemanager.cpp @@ -226,7 +226,7 @@ util::EmoteMap &EmoteManager::getBTTVChannelEmoteFromCaches() return _bttvChannelEmoteFromCaches; } -util::EmoteMap &EmoteManager::getEmojis() +util::EmojiMap &EmoteManager::getEmojis() { return this->emojis; } @@ -277,10 +277,15 @@ void EmoteManager::loadEmojis() unicodeBytes[numUnicodeBytes++] = QString(unicodeCharacter).toUInt(nullptr, 16); } + QString url = "https://cdnjs.cloudflare.com/ajax/libs/" + "emojione/2.2.6/assets/png/" + + code + ".png"; + EmojiData emojiData{ QString::fromUcs4(unicodeBytes, numUnicodeBytes), // code, // shortCode, // + {new Image(url, 0.35, ":" + shortCode + ":", ":" + shortCode + ":
Emoji")}, }; this->emojiShortCodeToEmoji.insert(shortCode, emojiData); @@ -288,12 +293,7 @@ void EmoteManager::loadEmojis() this->emojiFirstByte[emojiData.value.at(0)].append(emojiData); - QString url = "https://cdnjs.cloudflare.com/ajax/libs/" - "emojione/2.2.6/assets/png/" + - code + ".png"; - - this->emojis.insert(code, util::EmoteData(new Image(url, 0.35, ":" + shortCode + ":", - ":" + shortCode + ":
Emoji"))); + this->emojis.insert(code, emojiData); } for (auto &p : this->emojiFirstByte) { @@ -369,17 +369,9 @@ void EmoteManager::parseEmojis(std::vector> charactersFromLastParsedEmoji)); } - QString url = "https://cdnjs.cloudflare.com/ajax/libs/" - "emojione/2.2.6/assets/png/" + - matchedEmoji.code + ".png"; - - // Create or fetch cached emoji image - auto emojiImage = this->emojis.getOrAdd(matchedEmoji.code, [&url] { - return util::EmoteData(new Image(url, 0.35, "?????????", "???????????????")); // - }); - // Push the emoji as a word to parsedWords - parsedWords.push_back(std::tuple(emojiImage, QString())); + parsedWords.push_back( + std::tuple(matchedEmoji.emoteData, QString())); lastParsedEmojiEndIndex = currentParsedEmojiEndIndex; diff --git a/src/singletons/emotemanager.hpp b/src/singletons/emotemanager.hpp index 75ef6744..2a9365f3 100644 --- a/src/singletons/emotemanager.hpp +++ b/src/singletons/emotemanager.hpp @@ -42,7 +42,7 @@ public: util::EmoteMap &getFFZEmotes(); util::EmoteMap &getChatterinoEmotes(); util::EmoteMap &getBTTVChannelEmoteFromCaches(); - util::EmoteMap &getEmojis(); + util::EmojiMap &getEmojis(); util::ConcurrentMap &getFFZChannelEmoteFromCaches(); util::ConcurrentMap &getTwitchEmoteFromCache(); @@ -78,8 +78,7 @@ private: // Maps the first character of the emoji unicode string to a vector of possible emojis QMap> emojiFirstByte; - // url Emoji-one image - util::EmoteMap emojis; + util::EmojiMap emojis; void loadEmojis(); diff --git a/src/widgets/emotepopup.cpp b/src/widgets/emotepopup.cpp index 5cd092d5..c4b5537a 100644 --- a/src/widgets/emotepopup.cpp +++ b/src/widgets/emotepopup.cpp @@ -89,7 +89,7 @@ void EmotePopup::loadChannel(ChannelPtr _channel) void EmotePopup::loadEmojis() { - util::EmoteMap &emojis = singletons::EmoteManager::getInstance().getEmojis(); + auto &emojis = singletons::EmoteManager::getInstance().getEmojis(); ChannelPtr emojiChannel(new Channel("")); @@ -105,9 +105,9 @@ void EmotePopup::loadEmojis() builder.getMessage()->flags &= Message::Centered; builder.getMessage()->flags &= Message::DisableCompactEmotes; - emojis.each([this, &builder](const QString &key, const util::EmoteData &value) { - builder.append((new EmoteElement(value, MessageElement::Flags::AlwaysShow)) - ->setLink(Link(Link::Type::InsertText, key))); + emojis.each([this, &builder](const QString &key, const auto &value) { + builder.append((new EmoteElement(value.emoteData, MessageElement::Flags::AlwaysShow)) + ->setLink(Link(Link::Type::InsertText, ":" + value.shortCode + ":"))); }); emojiChannel->addMessage(builder.getMessage()); From f820024fd5908029b94499c5a5661a77cc34c42d Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sun, 1 Apr 2018 16:43:30 +0200 Subject: [PATCH 25/69] Reformat --- src/messages/layouts/messagelayout.cpp | 1 + src/messages/layouts/messagelayout.hpp | 4 +- .../layouts/messagelayoutcontainer.cpp | 14 ++----- .../layouts/messagelayoutcontainer.hpp | 25 +++++++------ src/messages/layouts/messagelayoutelement.cpp | 1 + src/messages/layouts/messagelayoutelement.hpp | 37 ++++++++++--------- src/providers/irc/abstractircserver.cpp | 1 + src/providers/irc/abstractircserver.hpp | 6 ++- src/providers/twitch/twitchserver.hpp | 14 +++---- src/singletons/emotemanager.cpp | 15 ++++---- src/singletons/emotemanager.hpp | 9 +---- src/util/emotemap.hpp | 2 - 12 files changed, 62 insertions(+), 67 deletions(-) diff --git a/src/messages/layouts/messagelayout.cpp b/src/messages/layouts/messagelayout.cpp index 4ac17008..7da65450 100644 --- a/src/messages/layouts/messagelayout.cpp +++ b/src/messages/layouts/messagelayout.cpp @@ -244,6 +244,7 @@ void MessageLayout::addSelectionText(QString &str, int from, int to) { this->container.addSelectionText(str, from, to); } + } // namespace layouts } // namespace messages } // namespace chatterino diff --git a/src/messages/layouts/messagelayout.hpp b/src/messages/layouts/messagelayout.hpp index a4e3079c..09dd2e61 100644 --- a/src/messages/layouts/messagelayout.hpp +++ b/src/messages/layouts/messagelayout.hpp @@ -15,6 +15,7 @@ namespace chatterino { namespace messages { namespace layouts { + class MessageLayout : boost::noncopyable { public: @@ -73,7 +74,8 @@ private: void updateBuffer(QPixmap *pixmap, int messageIndex, Selection &selection); }; -typedef std::shared_ptr MessageLayoutPtr; +using MessageLayoutPtr = std::shared_ptr; + } // namespace layouts } // namespace messages } // namespace chatterino diff --git a/src/messages/layouts/messagelayoutcontainer.cpp b/src/messages/layouts/messagelayoutcontainer.cpp index 1913e7b7..8ea48b45 100644 --- a/src/messages/layouts/messagelayoutcontainer.cpp +++ b/src/messages/layouts/messagelayoutcontainer.cpp @@ -12,13 +12,6 @@ namespace chatterino { namespace messages { namespace layouts { -MessageLayoutContainer::MessageLayoutContainer() - : scale(1) - , flags(Message::None) - , margin(4, 8, 4, 8) -{ - this->clear(); -} int MessageLayoutContainer::getHeight() const { @@ -36,11 +29,11 @@ float MessageLayoutContainer::getScale() const } // methods -void MessageLayoutContainer::begin(int width, float _scale, Message::MessageFlags _flags) +void MessageLayoutContainer::begin(int _width, float _scale, Message::MessageFlags _flags) { this->clear(); - this->width = width; - this->scale = this->scale; + this->width = _width; + this->scale = _scale; this->flags = _flags; } @@ -434,6 +427,7 @@ void MessageLayoutContainer::addSelectionText(QString &str, int from, int to) index += c; } } + } // namespace layouts } // namespace messages } // namespace chatterino diff --git a/src/messages/layouts/messagelayoutcontainer.hpp b/src/messages/layouts/messagelayoutcontainer.hpp index d8469ad7..6c95082c 100644 --- a/src/messages/layouts/messagelayoutcontainer.hpp +++ b/src/messages/layouts/messagelayoutcontainer.hpp @@ -43,12 +43,11 @@ struct Margin { }; struct MessageLayoutContainer { -public: - MessageLayoutContainer(); + MessageLayoutContainer() = default; - Margin margin; - bool centered; - bool enableCompactEmotes; + Margin margin = {4, 8, 4, 8}; + bool centered = false; + bool enableCompactEmotes = false; int getHeight() const; int getWidth() const; @@ -89,20 +88,22 @@ private: void _addElement(MessageLayoutElement *element); // variables - float scale; - int width; - Message::MessageFlags flags; - int line; - int height; - int currentX, currentY; + float scale = 1.f; + int width = 0; + Message::MessageFlags flags = Message::MessageFlags::None; + int line = 0; + int height = 0; + int currentX = 0; + int currentY = 0; int charIndex = 0; size_t lineStart = 0; int lineHeight = 0; int spaceWidth = 4; - std::vector> elements; + std::vector> elements; std::vector lines; }; + } // namespace layouts } // namespace messages } // namespace chatterino diff --git a/src/messages/layouts/messagelayoutelement.cpp b/src/messages/layouts/messagelayoutelement.cpp index 994016b5..6d0213ac 100644 --- a/src/messages/layouts/messagelayoutelement.cpp +++ b/src/messages/layouts/messagelayoutelement.cpp @@ -272,6 +272,7 @@ int TextIconLayoutElement::getXFromIndex(int index) return this->getRect().right(); } } + } // namespace layouts } // namespace messages } // namespace chatterino diff --git a/src/messages/layouts/messagelayoutelement.hpp b/src/messages/layouts/messagelayoutelement.hpp index 16b8db0e..1df72ebb 100644 --- a/src/messages/layouts/messagelayoutelement.hpp +++ b/src/messages/layouts/messagelayoutelement.hpp @@ -56,12 +56,12 @@ public: ImageLayoutElement(MessageElement &creator, Image *image, const QSize &size); protected: - virtual void addCopyTextToString(QString &str, int from = 0, int to = INT_MAX) const override; - virtual int getSelectionIndexCount() override; - virtual void paint(QPainter &painter) override; - virtual void paintAnimated(QPainter &painter, int yOffset) override; - virtual int getMouseOverIndex(const QPoint &abs) override; - virtual int getXFromIndex(int index) override; + void addCopyTextToString(QString &str, int from = 0, int to = INT_MAX) const override; + int getSelectionIndexCount() override; + void paint(QPainter &painter) override; + void paintAnimated(QPainter &painter, int yOffset) override; + int getMouseOverIndex(const QPoint &abs) override; + int getXFromIndex(int index) override; private: Image *image; @@ -75,12 +75,12 @@ public: FontStyle style, float scale); protected: - virtual void addCopyTextToString(QString &str, int from = 0, int to = INT_MAX) const override; - virtual int getSelectionIndexCount() override; - virtual void paint(QPainter &painter) override; - virtual void paintAnimated(QPainter &painter, int yOffset) override; - virtual int getMouseOverIndex(const QPoint &abs) override; - virtual int getXFromIndex(int index) override; + void addCopyTextToString(QString &str, int from = 0, int to = INT_MAX) const override; + int getSelectionIndexCount() override; + void paint(QPainter &painter) override; + void paintAnimated(QPainter &painter, int yOffset) override; + int getMouseOverIndex(const QPoint &abs) override; + int getXFromIndex(int index) override; private: QString text; @@ -98,18 +98,19 @@ public: float scale, const QSize &size); protected: - virtual void addCopyTextToString(QString &str, int from = 0, int to = INT_MAX) const override; - virtual int getSelectionIndexCount() override; - virtual void paint(QPainter &painter) override; - virtual void paintAnimated(QPainter &painter, int yOffset) override; - virtual int getMouseOverIndex(const QPoint &abs) override; - virtual int getXFromIndex(int index) override; + void addCopyTextToString(QString &str, int from = 0, int to = INT_MAX) const override; + int getSelectionIndexCount() override; + void paint(QPainter &painter) override; + void paintAnimated(QPainter &painter, int yOffset) override; + int getMouseOverIndex(const QPoint &abs) override; + int getXFromIndex(int index) override; private: QString line1; QString line2; float scale; }; + } // namespace layouts } // namespace messages } // namespace chatterino diff --git a/src/providers/irc/abstractircserver.cpp b/src/providers/irc/abstractircserver.cpp index 4bd95a0d..c2150f5b 100644 --- a/src/providers/irc/abstractircserver.cpp +++ b/src/providers/irc/abstractircserver.cpp @@ -247,6 +247,7 @@ void AbstractIrcServer::forEachChannel(std::function func) func(chan); } } + } // namespace irc } // namespace providers } // namespace chatterino diff --git a/src/providers/irc/abstractircserver.hpp b/src/providers/irc/abstractircserver.hpp index 266c2226..e62368a3 100644 --- a/src/providers/irc/abstractircserver.hpp +++ b/src/providers/irc/abstractircserver.hpp @@ -1,15 +1,16 @@ #pragma once +#include "channel.hpp" + #include #include #include #include -#include "channel.hpp" - namespace chatterino { namespace providers { namespace irc { + class AbstractIrcServer { public: @@ -64,6 +65,7 @@ private: std::mutex connectionMutex; }; + } // namespace irc } // namespace providers } // namespace chatterino diff --git a/src/providers/twitch/twitchserver.hpp b/src/providers/twitch/twitchserver.hpp index 891868ae..94a8e900 100644 --- a/src/providers/twitch/twitchserver.hpp +++ b/src/providers/twitch/twitchserver.hpp @@ -24,15 +24,15 @@ public: const ChannelPtr mentionsChannel; protected: - virtual void initializeConnection(Communi::IrcConnection *connection, bool isRead, - bool isWrite) override; - virtual std::shared_ptr createChannel(const QString &channelName) override; + void initializeConnection(Communi::IrcConnection *connection, bool isRead, + bool isWrite) override; + std::shared_ptr createChannel(const QString &channelName) override; - virtual void privateMessageReceived(Communi::IrcPrivateMessage *message) override; - virtual void messageReceived(Communi::IrcMessage *message) override; - virtual void writeConnectionMessageReceived(Communi::IrcMessage *message) override; + void privateMessageReceived(Communi::IrcPrivateMessage *message) override; + void messageReceived(Communi::IrcMessage *message) override; + void writeConnectionMessageReceived(Communi::IrcMessage *message) override; - virtual std::shared_ptr getCustomChannel(const QString &channelname) override; + std::shared_ptr getCustomChannel(const QString &channelname) override; QString CleanChannelName(const QString &dirtyChannelName) override; }; diff --git a/src/singletons/emotemanager.cpp b/src/singletons/emotemanager.cpp index 1c25d233..8a24d81e 100644 --- a/src/singletons/emotemanager.cpp +++ b/src/singletons/emotemanager.cpp @@ -75,10 +75,8 @@ void FillInFFZEmoteData(const QJsonObject &urls, const QString &code, util::Emot } // namespace -EmoteManager::EmoteManager(SettingManager &_settingsManager, WindowManager &_windowManager) - : settingsManager(_settingsManager) - , windowManager(_windowManager) - , findShortCodesRegex(":([-+\\w]+):") +EmoteManager::EmoteManager() + : findShortCodesRegex(":([-+\\w]+):") { auto &accountManager = AccountManager::getInstance(); @@ -91,7 +89,7 @@ EmoteManager::EmoteManager(SettingManager &_settingsManager, WindowManager &_win EmoteManager &EmoteManager::getInstance() { - static EmoteManager instance(SettingManager::getInstance(), WindowManager::getInstance()); + static EmoteManager instance; return instance; } @@ -562,7 +560,9 @@ boost::signals2::signal &EmoteManager::getGifUpdateSignal() this->gifUpdateTimer.setInterval(30); this->gifUpdateTimer.start(); - this->settingsManager.enableGifAnimations.connect([this](bool enabled, auto) { + auto &settingManager = singletons::SettingManager::getInstance(); + + settingManager.enableGifAnimations.connect([this](bool enabled, auto) { if (enabled) { this->gifUpdateTimer.start(); } else { @@ -573,7 +573,8 @@ boost::signals2::signal &EmoteManager::getGifUpdateSignal() QObject::connect(&this->gifUpdateTimer, &QTimer::timeout, [this] { this->gifUpdateTimerSignal(); // fourtf: - this->windowManager.repaintGifEmotes(); + auto &windowManager = singletons::WindowManager::getInstance(); + windowManager.repaintGifEmotes(); }); } diff --git a/src/singletons/emotemanager.hpp b/src/singletons/emotemanager.hpp index 2a9365f3..c9005aaa 100644 --- a/src/singletons/emotemanager.hpp +++ b/src/singletons/emotemanager.hpp @@ -20,13 +20,9 @@ namespace chatterino { namespace singletons { -class SettingManager; -class WindowManager; - class EmoteManager { - explicit EmoteManager(singletons::SettingManager &manager, - singletons::WindowManager &windowManager); + EmoteManager(); public: static EmoteManager &getInstance(); @@ -66,9 +62,6 @@ public: util::ConcurrentMap miscImageCache; private: - SettingManager &settingsManager; - WindowManager &windowManager; - /// Emojis QRegularExpression findShortCodesRegex; diff --git a/src/util/emotemap.hpp b/src/util/emotemap.hpp index d787a745..47816909 100644 --- a/src/util/emotemap.hpp +++ b/src/util/emotemap.hpp @@ -3,8 +3,6 @@ #include "messages/image.hpp" #include "util/concurrentmap.hpp" -#include - namespace chatterino { namespace util { From e5c852ecba781247d7c441ab8f7f1b5ff64edd57 Mon Sep 17 00:00:00 2001 From: Cranken Date: Mon, 2 Apr 2018 11:46:56 +0200 Subject: [PATCH 26/69] Fixed crash upon starting Fixes issue #304 --- src/widgets/basewindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/basewindow.cpp b/src/widgets/basewindow.cpp index c85bec6f..bb7eda86 100644 --- a/src/widgets/basewindow.cpp +++ b/src/widgets/basewindow.cpp @@ -148,7 +148,7 @@ QWidget *BaseWindow::getLayoutContainer() bool BaseWindow::hasCustomWindowFrame() { -#ifdef Q_OS_WIN +#ifdef USEWINSDK return this->enableCustomFrame; #else return false; From 5bcb561eb29698089af0c6f7e0ead5d3c008b895 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Tue, 3 Apr 2018 02:35:02 +0200 Subject: [PATCH 27/69] Simplify debug::Log. No need for a second function --- src/debug/log.hpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/debug/log.hpp b/src/debug/log.hpp index e2a3fbea..2eb6e126 100644 --- a/src/debug/log.hpp +++ b/src/debug/log.hpp @@ -8,19 +8,11 @@ namespace chatterino { namespace debug { -namespace detail { - -static void _log(const std::string &message) -{ - qDebug().noquote() << QTime::currentTime().toString("hh:mm:ss.zzz") << message.c_str(); -} - -} // namespace detail - template inline void Log(const std::string &formatString, Args &&... args) { - detail::_log(fS(formatString, std::forward(args)...)); + qDebug().noquote() << QTime::currentTime().toString("hh:mm:ss.zzz") + << fS(formatString, std::forward(args)...).c_str(); } } // namespace debug From adf3ff307526fd7f91ab80f19d21516c67c0554e Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Tue, 3 Apr 2018 02:55:32 +0200 Subject: [PATCH 28/69] Switch some c-style includes to c++-style includes (i.e. stdint.h to cstdint) Make MessageElement to a class to fit better with the derived classes. Make MessageLayoutElement to a class to fit better with the derived classes. Remove virtual from override functions Replace all instances of boost::signals2 with pajlada::Signals. This lets us properly use clang code model to check for issues. Add missing virtual destructor to AbstractIrcServer Add missing virtual destructor to MessageLayoutElement Remove unused "connectedConnection" connection in TwitchChannel Fix typo in TrimChannelName function Fix typo in MessageParseArgs Replace some raw pointers with unique pointers where it made more sense. This allowed us to remove some manually written destructors whose only purpose was to delete that raw pointer. Reformat: Add namespace comments Reformat: Add empty empty lines between main namespace beginning and end Reformat: Re-order includes Reformat: Fix some includes that used quotes where they should use angle brackets Reformat: Replace some typedef's with using's Filter out more useless warnings --- chatterino.pro | 4 ++ src/channel.cpp | 8 ++-- src/channel.hpp | 12 ++--- src/common.hpp | 5 ++- src/credentials.hpp | 2 + src/messages/image.hpp | 1 - .../layouts/messagelayoutcontainer.hpp | 2 +- src/messages/layouts/messagelayoutelement.cpp | 10 ++--- src/messages/layouts/messagelayoutelement.hpp | 6 ++- src/messages/limitedqueue.hpp | 4 +- src/messages/limitedqueuesnapshot.hpp | 11 ++--- src/messages/link.cpp | 2 + src/messages/link.hpp | 2 + src/messages/message.cpp | 2 +- src/messages/message.hpp | 4 +- src/messages/messagecolor.cpp | 2 + src/messages/messagecolor.hpp | 6 ++- src/messages/messageelement.cpp | 29 +++--------- src/messages/messageelement.hpp | 45 +++++++++---------- src/messages/messageparseargs.hpp | 3 +- src/messages/selection.hpp | 8 ++-- src/precompiled_header.hpp | 5 +-- src/providers/irc/abstractircserver.hpp | 6 ++- src/providers/twitch/emotevalue.hpp | 2 +- src/providers/twitch/ircmessagehandler.cpp | 5 ++- src/providers/twitch/twitchaccountmanager.hpp | 6 ++- src/providers/twitch/twitchchannel.cpp | 8 ++-- src/providers/twitch/twitchchannel.hpp | 8 ++-- src/providers/twitch/twitchhelpers.cpp | 2 +- src/singletons/emotemanager.cpp | 4 +- src/singletons/emotemanager.hpp | 6 +-- src/singletons/fontmanager.cpp | 1 + src/singletons/fontmanager.hpp | 4 +- src/singletons/helper/chatterinosetting.hpp | 6 ++- src/singletons/helper/moderationaction.cpp | 1 + src/singletons/helper/moderationaction.hpp | 5 ++- src/singletons/thememanager.cpp | 4 +- src/singletons/thememanager.hpp | 6 +-- src/singletons/windowmanager.cpp | 4 +- src/singletons/windowmanager.hpp | 4 +- src/util/layoutcreator.hpp | 1 + src/util/nativeeventhelper.hpp | 1 + src/util/networkrequest.hpp | 32 ++++++------- src/util/networkworker.hpp | 2 + src/util/posttothread.hpp | 4 +- src/util/property.hpp | 6 ++- src/util/streamlink.hpp | 1 + src/util/urlfetch.hpp | 1 + src/widgets/accountpopup.hpp | 8 ++-- src/widgets/accountswitchpopupwidget.cpp | 1 + src/widgets/accountswitchpopupwidget.hpp | 4 +- src/widgets/basewidget.cpp | 6 +-- src/widgets/basewidget.hpp | 5 ++- src/widgets/basewindow.cpp | 5 ++- src/widgets/basewindow.hpp | 4 ++ src/widgets/helper/channelview.cpp | 6 +-- src/widgets/helper/channelview.hpp | 40 ++++++++--------- src/widgets/helper/droppreview.hpp | 4 +- src/widgets/helper/label.cpp | 2 + src/widgets/helper/label.hpp | 1 + src/widgets/helper/notebookbutton.cpp | 1 + src/widgets/helper/notebooktab.cpp | 1 + src/widgets/helper/notebooktab.hpp | 1 - src/widgets/helper/resizingtextedit.cpp | 2 +- src/widgets/helper/resizingtextedit.hpp | 8 ++-- src/widgets/helper/scrollbarhighlight.hpp | 3 +- src/widgets/helper/searchpopup.hpp | 9 +++- src/widgets/helper/settingsdialogtab.hpp | 6 +-- src/widgets/helper/splitcolumn.cpp | 8 ++-- src/widgets/helper/splitcolumn.hpp | 12 ++--- src/widgets/helper/splitheader.cpp | 3 +- src/widgets/helper/splitheader.hpp | 4 +- src/widgets/scrollbar.cpp | 4 +- src/widgets/scrollbar.hpp | 6 +-- src/widgets/settingsdialog.hpp | 4 +- src/widgets/settingspages/aboutpage.cpp | 1 + src/widgets/settingspages/aboutpage.hpp | 1 + src/widgets/settingspages/accountspage.cpp | 2 + src/widgets/settingspages/accountspage.hpp | 5 ++- src/widgets/settingspages/appearancepage.cpp | 5 ++- src/widgets/settingspages/appearancepage.hpp | 2 - src/widgets/settingspages/behaviourpage.cpp | 2 + src/widgets/settingspages/emotespage.hpp | 1 + .../settingspages/highlightingpage.cpp | 2 + .../settingspages/highlightingpage.hpp | 4 +- .../settingspages/ignoremessagespage.cpp | 2 + .../settingspages/ignoremessagespage.hpp | 4 +- src/widgets/settingspages/ignoreuserspage.cpp | 2 + src/widgets/settingspages/ignoreuserspage.hpp | 2 + .../settingspages/keyboardsettingspage.cpp | 2 + .../settingspages/keyboardsettingspage.hpp | 2 + src/widgets/settingspages/logspage.hpp | 1 + .../settingspages/specialchannelspage.cpp | 2 + .../settingspages/specialchannelspage.hpp | 2 + src/widgets/split.cpp | 3 +- src/widgets/split.hpp | 7 ++- src/widgets/streamview.cpp | 2 + src/widgets/streamview.hpp | 4 ++ src/widgets/textinputdialog.cpp | 2 - src/widgets/tooltipwidget.cpp | 1 + src/widgets/tooltipwidget.hpp | 8 ++-- src/widgets/window.cpp | 12 ++--- src/widgets/window.hpp | 9 ++-- 103 files changed, 305 insertions(+), 248 deletions(-) diff --git a/chatterino.pro b/chatterino.pro index b7c10c64..1665eef0 100644 --- a/chatterino.pro +++ b/chatterino.pro @@ -313,12 +313,16 @@ win32-msvc* { # 4127 - conditional expression is constant # 4503 - decorated name length exceeded, name was truncated # 4100 - unreferences formal parameter + # 4305 - possible truncation of data + # 4267 - possible loss of data in return QMAKE_CXXFLAGS_WARN_ON += /wd4714 QMAKE_CXXFLAGS_WARN_ON += /wd4996 QMAKE_CXXFLAGS_WARN_ON += /wd4505 QMAKE_CXXFLAGS_WARN_ON += /wd4127 QMAKE_CXXFLAGS_WARN_ON += /wd4503 QMAKE_CXXFLAGS_WARN_ON += /wd4100 + QMAKE_CXXFLAGS_WARN_ON += /wd4305 + QMAKE_CXXFLAGS_WARN_ON += /wd4267 } else { QMAKE_CXXFLAGS_WARN_ON = -Wall diff --git a/src/channel.cpp b/src/channel.cpp index f72a0a01..1834979f 100644 --- a/src/channel.cpp +++ b/src/channel.cpp @@ -61,10 +61,10 @@ void Channel::addMessage(MessagePtr message) singletons::LoggingManager::getInstance().addMessage(this->name, message); if (this->messages.pushBack(message, deleted)) { - this->messageRemovedFromStart(deleted); + this->messageRemovedFromStart.invoke(deleted); } - this->messageAppended(message); + this->messageAppended.invoke(message); } void Channel::addMessagesAtStart(std::vector &_messages) @@ -72,7 +72,7 @@ void Channel::addMessagesAtStart(std::vector &_messages) std::vector addedMessages = this->messages.pushFront(_messages); if (addedMessages.size() != 0) { - this->messagesAddedAtStart(addedMessages); + this->messagesAddedAtStart.invoke(addedMessages); } } @@ -81,7 +81,7 @@ void Channel::replaceMessage(messages::MessagePtr message, messages::MessagePtr int index = this->messages.replaceItem(message, replacement); if (index >= 0) { - this->messageReplaced((size_t)index, replacement); + this->messageReplaced.invoke((size_t)index, replacement); } } diff --git a/src/channel.hpp b/src/channel.hpp index ca51c7c2..e42b5b7c 100644 --- a/src/channel.hpp +++ b/src/channel.hpp @@ -8,14 +8,14 @@ #include #include -#include +#include #include namespace chatterino { namespace messages { struct Message; -} +} // namespace messages class Channel : public std::enable_shared_from_this { @@ -27,10 +27,10 @@ public: pajlada::Signals::Signal sendMessageSignal; - boost::signals2::signal messageRemovedFromStart; - boost::signals2::signal messageAppended; - boost::signals2::signal &)> messagesAddedAtStart; - boost::signals2::signal messageReplaced; + pajlada::Signals::Signal messageRemovedFromStart; + pajlada::Signals::Signal messageAppended; + pajlada::Signals::Signal &> messagesAddedAtStart; + pajlada::Signals::Signal messageReplaced; pajlada::Signals::NoArgSignal destroyed; virtual bool isEmpty() const; diff --git a/src/common.hpp b/src/common.hpp index 80ca6608..bba4fa46 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -1,10 +1,11 @@ #pragma once +#include "debug/log.hpp" + #include #include -#include -#include "debug/log.hpp" +#include namespace chatterino { diff --git a/src/credentials.hpp b/src/credentials.hpp index e66cd2d3..c0e97d25 100644 --- a/src/credentials.hpp +++ b/src/credentials.hpp @@ -1,5 +1,7 @@ #pragma once +#include + namespace chatterino { inline QByteArray getDefaultClientID() diff --git a/src/messages/image.hpp b/src/messages/image.hpp index a32446d8..f107ed76 100644 --- a/src/messages/image.hpp +++ b/src/messages/image.hpp @@ -5,7 +5,6 @@ #include #include -#include namespace chatterino { namespace messages { diff --git a/src/messages/layouts/messagelayoutcontainer.hpp b/src/messages/layouts/messagelayoutcontainer.hpp index 6c95082c..85537811 100644 --- a/src/messages/layouts/messagelayoutcontainer.hpp +++ b/src/messages/layouts/messagelayoutcontainer.hpp @@ -15,7 +15,7 @@ namespace chatterino { namespace messages { namespace layouts { -struct MessageLayoutElement; +class MessageLayoutElement; struct Margin { int top; diff --git a/src/messages/layouts/messagelayoutelement.cpp b/src/messages/layouts/messagelayoutelement.cpp index 6d0213ac..cf43237c 100644 --- a/src/messages/layouts/messagelayoutelement.cpp +++ b/src/messages/layouts/messagelayoutelement.cpp @@ -102,9 +102,9 @@ void ImageLayoutElement::paintAnimated(QPainter &painter, int yOffset) if (pixmap != nullptr) { // fourtf: make it use qreal values - QRect rect = this->getRect(); - rect.moveTop(rect.y() + yOffset); - painter.drawPixmap(QRectF(rect), *pixmap, QRectF()); + QRect _rect = this->getRect(); + _rect.moveTop(_rect.y() + yOffset); + painter.drawPixmap(QRectF(_rect), *pixmap, QRectF()); } } } @@ -240,8 +240,8 @@ void TextIconLayoutElement::paint(QPainter &painter) option.setAlignment(Qt::AlignHCenter); if (this->line2.isEmpty()) { - QRect rect(this->getRect()); - painter.drawText(rect, this->line1, option); + QRect _rect(this->getRect()); + painter.drawText(_rect, this->line1, option); } else { painter.drawText( QPoint(this->getRect().x(), this->getRect().y() + this->getRect().height() / 2), diff --git a/src/messages/layouts/messagelayoutelement.hpp b/src/messages/layouts/messagelayoutelement.hpp index 1df72ebb..646c44c7 100644 --- a/src/messages/layouts/messagelayoutelement.hpp +++ b/src/messages/layouts/messagelayoutelement.hpp @@ -15,14 +15,16 @@ class QPainter; namespace chatterino { namespace messages { -struct MessageElement; +class MessageElement; class Image; namespace layouts { -struct MessageLayoutElement : boost::noncopyable { +class MessageLayoutElement : boost::noncopyable +{ public: MessageLayoutElement(MessageElement &creator, const QSize &size); + virtual ~MessageLayoutElement() = default; const QRect &getRect() const; MessageElement &getCreator() const; diff --git a/src/messages/limitedqueue.hpp b/src/messages/limitedqueue.hpp index 23618fe0..78d76180 100644 --- a/src/messages/limitedqueue.hpp +++ b/src/messages/limitedqueue.hpp @@ -1,9 +1,9 @@ #pragma once -#include "QDebug" - #include "messages/limitedqueuesnapshot.hpp" +#include + #include #include #include diff --git a/src/messages/limitedqueuesnapshot.hpp b/src/messages/limitedqueuesnapshot.hpp index 84dc83b3..87918816 100644 --- a/src/messages/limitedqueuesnapshot.hpp +++ b/src/messages/limitedqueuesnapshot.hpp @@ -11,10 +11,7 @@ template class LimitedQueueSnapshot { public: - LimitedQueueSnapshot() - : length(0) - { - } + LimitedQueueSnapshot() = default; LimitedQueueSnapshot(std::shared_ptr>>> _chunks, size_t _length, size_t _firstChunkOffset, size_t _lastChunkEnd) @@ -53,9 +50,9 @@ public: private: std::shared_ptr>>> chunks; - size_t length; - size_t firstChunkOffset; - size_t lastChunkEnd; + size_t length = 0; + size_t firstChunkOffset = 0; + size_t lastChunkEnd = 0; }; } // namespace messages diff --git a/src/messages/link.cpp b/src/messages/link.cpp index 419bfaf7..510d248e 100644 --- a/src/messages/link.cpp +++ b/src/messages/link.cpp @@ -2,6 +2,7 @@ namespace chatterino { namespace messages { + Link::Link() : type(None) , value(QString()) @@ -18,5 +19,6 @@ bool Link::isValid() const { return this->type != None; } + } // namespace messages } // namespace chatterino diff --git a/src/messages/link.hpp b/src/messages/link.hpp index 071a175f..945f414f 100644 --- a/src/messages/link.hpp +++ b/src/messages/link.hpp @@ -4,6 +4,7 @@ namespace chatterino { namespace messages { + struct Link { public: enum Type { @@ -26,5 +27,6 @@ public: bool isValid() const; }; + } // namespace messages } // namespace chatterino diff --git a/src/messages/message.cpp b/src/messages/message.cpp index d2fca598..93d564fa 100644 --- a/src/messages/message.cpp +++ b/src/messages/message.cpp @@ -2,7 +2,7 @@ #include "messageelement.hpp" #include "util/irchelpers.hpp" -typedef chatterino::widgets::ScrollbarHighlight SBHighlight; +using SBHighlight = chatterino::widgets::ScrollbarHighlight; namespace chatterino { namespace messages { diff --git a/src/messages/message.hpp b/src/messages/message.hpp index 341d6a4a..56afc2b5 100644 --- a/src/messages/message.hpp +++ b/src/messages/message.hpp @@ -4,12 +4,12 @@ #include "util/flagsenum.hpp" #include "widgets/helper/scrollbarhighlight.hpp" +#include + #include #include #include -#include - namespace chatterino { namespace messages { diff --git a/src/messages/messagecolor.cpp b/src/messages/messagecolor.cpp index 8a070834..6e0f877e 100644 --- a/src/messages/messagecolor.cpp +++ b/src/messages/messagecolor.cpp @@ -2,6 +2,7 @@ namespace chatterino { namespace messages { + MessageColor::MessageColor(const QColor &_color) : type(Type::Custom) , customColor(_color) @@ -29,5 +30,6 @@ const QColor &MessageColor::getColor(singletons::ThemeManager &themeManager) con static QColor _default; return _default; } + } // namespace messages } // namespace chatterino diff --git a/src/messages/messagecolor.hpp b/src/messages/messagecolor.hpp index 00e59a02..04387bfb 100644 --- a/src/messages/messagecolor.hpp +++ b/src/messages/messagecolor.hpp @@ -1,11 +1,12 @@ #pragma once -#include - #include "singletons/thememanager.hpp" +#include + namespace chatterino { namespace messages { + struct MessageColor { enum Type { Custom, Text, Link, System }; @@ -18,5 +19,6 @@ private: Type type; QColor customColor; }; + } // namespace messages } // namespace chatterino diff --git a/src/messages/messageelement.cpp b/src/messages/messageelement.cpp index e5d34b91..85b0e4e9 100644 --- a/src/messages/messageelement.cpp +++ b/src/messages/messageelement.cpp @@ -74,18 +74,10 @@ void ImageElement::addToContainer(MessageLayoutContainer &container, MessageElem EmoteElement::EmoteElement(const util::EmoteData &_data, MessageElement::Flags flags) : MessageElement(flags) , data(_data) - , textElement(nullptr) { if (_data.isValid()) { this->setTooltip(data.image1x->getTooltip()); - this->textElement = new TextElement(_data.image1x->getName(), MessageElement::Misc); - } -} - -EmoteElement::~EmoteElement() -{ - if (this->textElement != nullptr) { - delete this->textElement; + this->textElement.reset(new TextElement(_data.image1x->getName(), MessageElement::Misc)); } } @@ -114,7 +106,7 @@ void EmoteElement::addToContainer(MessageLayoutContainer &container, MessageElem container.addElement( (new ImageLayoutElement(*this, _image, size))->setLink(this->getLink())); } else { - if (this->textElement != nullptr) { + if (this->textElement) { this->textElement->addToContainer(container, MessageElement::Misc); } } @@ -130,7 +122,7 @@ TextElement::TextElement(const QString &text, MessageElement::Flags flags, { for (QString word : text.split(' ')) { this->words.push_back({word, -1}); - // fourtf: add logic to store mutliple spaces after message + // fourtf: add logic to store multiple spaces after message } } @@ -213,32 +205,21 @@ void TextElement::addToContainer(MessageLayoutContainer &container, MessageEleme } // TIMESTAMP -TimestampElement::TimestampElement() - : TimestampElement(QTime::currentTime()) -{ -} - TimestampElement::TimestampElement(QTime _time) : MessageElement(MessageElement::Timestamp) , time(_time) - , element(formatTime(_time)) + , element(this->formatTime(_time)) { assert(this->element != nullptr); } -TimestampElement::~TimestampElement() -{ - delete this->element; -} - void TimestampElement::addToContainer(MessageLayoutContainer &container, MessageElement::Flags _flags) { if (_flags & this->getFlags()) { if (singletons::SettingManager::getInstance().timestampFormat != this->format) { this->format = singletons::SettingManager::getInstance().timestampFormat.getValue(); - delete this->element; - this->element = TimestampElement::formatTime(this->time); + this->element.reset(this->formatTime(this->time)); } this->element->addToContainer(container, _flags); diff --git a/src/messages/messageelement.hpp b/src/messages/messageelement.hpp index bdae0129..e943b0e7 100644 --- a/src/messages/messageelement.hpp +++ b/src/messages/messageelement.hpp @@ -4,28 +4,29 @@ #include "messages/link.hpp" #include "messages/messagecolor.hpp" #include "singletons/fontmanager.hpp" +#include "util/emotemap.hpp" -#include #include #include #include - #include -#include "util/emotemap.hpp" + +#include +#include namespace chatterino { class Channel; namespace util { struct EmoteData; -} +} // namespace util namespace messages { namespace layouts { struct MessageLayoutContainer; -} +} // namespace layouts using namespace chatterino::messages::layouts; -struct MessageElement : boost::noncopyable +class MessageElement : boost::noncopyable { public: enum Flags : uint32_t { @@ -109,9 +110,7 @@ public: Update_All = Update_Text | Update_Emotes | Update_Images }; - virtual ~MessageElement() - { - } + virtual ~MessageElement() = default; MessageElement *setLink(const Link &link); MessageElement *setTooltip(const QString &tooltip); @@ -141,8 +140,7 @@ class ImageElement : public MessageElement public: ImageElement(Image *image, MessageElement::Flags flags); - virtual void addToContainer(MessageLayoutContainer &container, - MessageElement::Flags flags) override; + void addToContainer(MessageLayoutContainer &container, MessageElement::Flags flags) override; }; // contains a text, it will split it into words @@ -161,9 +159,9 @@ public: TextElement(const QString &text, MessageElement::Flags flags, const MessageColor &color = MessageColor::Text, FontStyle style = FontStyle::Medium); + ~TextElement() override = default; - virtual void addToContainer(MessageLayoutContainer &container, - MessageElement::Flags flags) override; + void addToContainer(MessageLayoutContainer &container, MessageElement::Flags flags) override; }; // contains emote data and will pick the emote based on : @@ -172,30 +170,27 @@ public: class EmoteElement : public MessageElement { const util::EmoteData data; - TextElement *textElement; + std::unique_ptr textElement; public: EmoteElement(const util::EmoteData &data, MessageElement::Flags flags); - ~EmoteElement(); + ~EmoteElement() override = default; - virtual void addToContainer(MessageLayoutContainer &container, - MessageElement::Flags flags) override; + void addToContainer(MessageLayoutContainer &container, MessageElement::Flags flags) override; }; // contains a text, formated depending on the preferences class TimestampElement : public MessageElement { QTime time; - TextElement *element; + std::unique_ptr element; QString format; public: - TimestampElement(); - TimestampElement(QTime time); - virtual ~TimestampElement(); + TimestampElement(QTime time = QTime::currentTime()); + ~TimestampElement() override = default; - virtual void addToContainer(MessageLayoutContainer &container, - MessageElement::Flags flags) override; + void addToContainer(MessageLayoutContainer &container, MessageElement::Flags flags) override; TextElement *formatTime(const QTime &time); }; @@ -207,8 +202,8 @@ class TwitchModerationElement : public MessageElement public: TwitchModerationElement(); - virtual void addToContainer(MessageLayoutContainer &container, - MessageElement::Flags flags) override; + void addToContainer(MessageLayoutContainer &container, MessageElement::Flags flags) override; }; + } // namespace messages } // namespace chatterino diff --git a/src/messages/messageparseargs.hpp b/src/messages/messageparseargs.hpp index d0d355d7..e9b0b4db 100644 --- a/src/messages/messageparseargs.hpp +++ b/src/messages/messageparseargs.hpp @@ -4,8 +4,7 @@ namespace chatterino { namespace messages { struct MessageParseArgs { -public: - bool disablePingSoungs = false; + bool disablePingSounds = false; bool isReceivedWhisper = false; bool isSentWhisper = false; }; diff --git a/src/messages/selection.hpp b/src/messages/selection.hpp index 1ae5d715..ad5b05e0 100644 --- a/src/messages/selection.hpp +++ b/src/messages/selection.hpp @@ -1,7 +1,10 @@ #pragma once +#include + namespace chatterino { namespace messages { + struct SelectionItem { int messageIndex; int charIndex; @@ -47,9 +50,7 @@ struct Selection { SelectionItem min; SelectionItem max; - Selection() - { - } + Selection() = default; Selection(const SelectionItem &start, const SelectionItem &end) : start(start) @@ -72,5 +73,6 @@ struct Selection { return this->min.messageIndex == this->max.messageIndex; } }; + } // namespace messages } // namespace chatterino diff --git a/src/precompiled_header.hpp b/src/precompiled_header.hpp index fc981efd..89f032be 100644 --- a/src/precompiled_header.hpp +++ b/src/precompiled_header.hpp @@ -2,11 +2,9 @@ #include #include #include -#include #include #include #include -#include #include #include #include @@ -127,13 +125,12 @@ #include #include #include -#include -#include #include #include #include #include #include +#include #include #include #include diff --git a/src/providers/irc/abstractircserver.hpp b/src/providers/irc/abstractircserver.hpp index e62368a3..277e9b56 100644 --- a/src/providers/irc/abstractircserver.hpp +++ b/src/providers/irc/abstractircserver.hpp @@ -2,10 +2,12 @@ #include "channel.hpp" +#include #include +#include + #include #include -#include namespace chatterino { namespace providers { @@ -14,6 +16,8 @@ namespace irc { class AbstractIrcServer { public: + virtual ~AbstractIrcServer() = default; + // connection Communi::IrcConnection *getReadConnection() const; diff --git a/src/providers/twitch/emotevalue.hpp b/src/providers/twitch/emotevalue.hpp index 18f4e542..4518690e 100644 --- a/src/providers/twitch/emotevalue.hpp +++ b/src/providers/twitch/emotevalue.hpp @@ -1,6 +1,6 @@ #pragma once -#include "QString" +#include namespace chatterino { namespace providers { diff --git a/src/providers/twitch/ircmessagehandler.cpp b/src/providers/twitch/ircmessagehandler.cpp index ea493e3d..796f048d 100644 --- a/src/providers/twitch/ircmessagehandler.cpp +++ b/src/providers/twitch/ircmessagehandler.cpp @@ -1,7 +1,5 @@ #include "ircmessagehandler.hpp" -#include - #include "debug/log.hpp" #include "messages/limitedqueue.hpp" #include "messages/message.hpp" @@ -12,6 +10,8 @@ #include "singletons/resourcemanager.hpp" #include "singletons/windowmanager.hpp" +#include + using namespace chatterino::singletons; using namespace chatterino::messages; @@ -233,6 +233,7 @@ void IrcMessageHandler::handleWriteConnectionNoticeMessage(Communi::IrcNoticeMes this->handleNoticeMessage(message); } + } // namespace twitch } // namespace providers } // namespace chatterino diff --git a/src/providers/twitch/twitchaccountmanager.hpp b/src/providers/twitch/twitchaccountmanager.hpp index 4ca070f6..b9793113 100644 --- a/src/providers/twitch/twitchaccountmanager.hpp +++ b/src/providers/twitch/twitchaccountmanager.hpp @@ -13,11 +13,14 @@ // namespace chatterino { + namespace singletons { class AccountManager; -} +} // namespace singletons + namespace providers { namespace twitch { + class TwitchAccountManager { TwitchAccountManager(); @@ -62,6 +65,7 @@ private: friend class chatterino::singletons::AccountManager; }; + } // namespace twitch } // namespace providers } // namespace chatterino diff --git a/src/providers/twitch/twitchchannel.cpp b/src/providers/twitch/twitchchannel.cpp index 82537aed..729612d4 100644 --- a/src/providers/twitch/twitchchannel.cpp +++ b/src/providers/twitch/twitchchannel.cpp @@ -81,8 +81,6 @@ TwitchChannel::TwitchChannel(const QString &channelName, Communi::IrcConnection TwitchChannel::~TwitchChannel() { - this->connectedConnection.disconnect(); - this->liveStatusTimer->stop(); this->liveStatusTimer->deleteLater(); @@ -103,7 +101,7 @@ bool TwitchChannel::canSendMessage() const void TwitchChannel::setRoomID(const QString &_roomID) { this->roomID = _roomID; - this->roomIDchanged(); + this->roomIDchanged.invoke(); this->fetchMessages.invoke(); } @@ -155,7 +153,7 @@ void TwitchChannel::setMod(bool value) if (this->mod != value) { this->mod = value; - this->userStateChanged(); + this->userStateChanged.invoke(); } } @@ -194,7 +192,7 @@ void TwitchChannel::setLive(bool newLiveStatus) this->streamStatus.live = newLiveStatus; } - this->onlineStatusChanged(); + this->onlineStatusChanged.invoke(); } void TwitchChannel::refreshLiveStatus() diff --git a/src/providers/twitch/twitchchannel.hpp b/src/providers/twitch/twitchchannel.hpp index 949c5a55..718b7b3c 100644 --- a/src/providers/twitch/twitchchannel.hpp +++ b/src/providers/twitch/twitchchannel.hpp @@ -53,11 +53,11 @@ public: const QString popoutPlayerURL; void setRoomID(const QString &_roomID); - boost::signals2::signal roomIDchanged; - boost::signals2::signal onlineStatusChanged; + pajlada::Signals::NoArgSignal roomIDchanged; + pajlada::Signals::NoArgSignal onlineStatusChanged; pajlada::Signals::NoArgBoltSignal fetchMessages; - boost::signals2::signal userStateChanged; + pajlada::Signals::NoArgSignal userStateChanged; QString roomID; @@ -89,8 +89,6 @@ private: void fetchRecentMessages(); - boost::signals2::connection connectedConnection; - bool mod; QByteArray messageSuffix; QString lastSentMessage; diff --git a/src/providers/twitch/twitchhelpers.cpp b/src/providers/twitch/twitchhelpers.cpp index 830da86d..4f6f663a 100644 --- a/src/providers/twitch/twitchhelpers.cpp +++ b/src/providers/twitch/twitchhelpers.cpp @@ -8,7 +8,7 @@ namespace twitch { bool TrimChannelName(const QString &channelName, QString &outChannelName) { if (channelName.length() < 3) { - debug::Log("channel name length below 2"); + debug::Log("channel name length below 3"); return false; } diff --git a/src/singletons/emotemanager.cpp b/src/singletons/emotemanager.cpp index 8a24d81e..c7a7a932 100644 --- a/src/singletons/emotemanager.cpp +++ b/src/singletons/emotemanager.cpp @@ -552,7 +552,7 @@ util::EmoteData EmoteManager::getCheerImage(long long amount, bool animated) return util::EmoteData(); } -boost::signals2::signal &EmoteManager::getGifUpdateSignal() +pajlada::Signals::NoArgSignal &EmoteManager::getGifUpdateSignal() { if (!this->gifUpdateTimerInitiated) { this->gifUpdateTimerInitiated = true; @@ -571,7 +571,7 @@ boost::signals2::signal &EmoteManager::getGifUpdateSignal() }); QObject::connect(&this->gifUpdateTimer, &QTimer::timeout, [this] { - this->gifUpdateTimerSignal(); + this->gifUpdateTimerSignal.invoke(); // fourtf: auto &windowManager = singletons::WindowManager::getInstance(); windowManager.repaintGifEmotes(); diff --git a/src/singletons/emotemanager.hpp b/src/singletons/emotemanager.hpp index c9005aaa..97376f1a 100644 --- a/src/singletons/emotemanager.hpp +++ b/src/singletons/emotemanager.hpp @@ -15,7 +15,7 @@ #include #include #include -#include +#include namespace chatterino { namespace singletons { @@ -56,7 +56,7 @@ public: _generation++; } - boost::signals2::signal &getGifUpdateSignal(); + pajlada::Signals::NoArgSignal &getGifUpdateSignal(); // Bit badge/emotes? util::ConcurrentMap miscImageCache; @@ -140,7 +140,7 @@ private: /// Chatterino emotes util::EmoteMap _chatterinoEmotes; - boost::signals2::signal gifUpdateTimerSignal; + pajlada::Signals::NoArgSignal gifUpdateTimerSignal; QTimer gifUpdateTimer; bool gifUpdateTimerInitiated = false; diff --git a/src/singletons/fontmanager.cpp b/src/singletons/fontmanager.cpp index a0c0d828..45214917 100644 --- a/src/singletons/fontmanager.cpp +++ b/src/singletons/fontmanager.cpp @@ -105,5 +105,6 @@ FontManager::Font &FontManager::getCurrentFont(float scale) return this->currentFontByScale.back().second; } + } // namespace singletons } // namespace chatterino diff --git a/src/singletons/fontmanager.hpp b/src/singletons/fontmanager.hpp index 0f29116f..454bafbb 100644 --- a/src/singletons/fontmanager.hpp +++ b/src/singletons/fontmanager.hpp @@ -137,7 +137,9 @@ private: int generation = 0; }; + } // namespace singletons -typedef singletons::FontManager::Type FontStyle; +using FontStyle = singletons::FontManager::Type; + } // namespace chatterino diff --git a/src/singletons/helper/chatterinosetting.hpp b/src/singletons/helper/chatterinosetting.hpp index 54f86433..ffa8f987 100644 --- a/src/singletons/helper/chatterinosetting.hpp +++ b/src/singletons/helper/chatterinosetting.hpp @@ -2,6 +2,7 @@ namespace chatterino { namespace singletons { + static void _registerSetting(std::weak_ptr setting); template @@ -71,5 +72,6 @@ public: return this->getValue(); } }; -} -} + +} // namespace singletons +} // namespace chatterino diff --git a/src/singletons/helper/moderationaction.cpp b/src/singletons/helper/moderationaction.cpp index 47433fe0..c8b322a1 100644 --- a/src/singletons/helper/moderationaction.cpp +++ b/src/singletons/helper/moderationaction.cpp @@ -46,5 +46,6 @@ const QString &ModerationAction::getAction() const { return this->action; } + } // namespace singletons } // namespace chatterino diff --git a/src/singletons/helper/moderationaction.hpp b/src/singletons/helper/moderationaction.hpp index 1170df80..0f081c9f 100644 --- a/src/singletons/helper/moderationaction.hpp +++ b/src/singletons/helper/moderationaction.hpp @@ -3,9 +3,11 @@ #include namespace chatterino { + namespace messages { class Image; -} +} // namespace messages + namespace singletons { class ModerationAction @@ -27,5 +29,6 @@ private: QString line2; QString action; }; + } // namespace singletons } // namespace chatterino diff --git a/src/singletons/thememanager.cpp b/src/singletons/thememanager.cpp index a088a0b8..6f522b88 100644 --- a/src/singletons/thememanager.cpp +++ b/src/singletons/thememanager.cpp @@ -4,7 +4,7 @@ #include -#include +#include namespace chatterino { namespace singletons { @@ -156,7 +156,7 @@ void ThemeManager::actuallyUpdate(double hue, double multiplier) // Selection this->messages.selection = isLightTheme() ? QColor(0, 0, 0, 64) : QColor(255, 255, 255, 64); - this->updated(); + this->updated.invoke(); } QColor ThemeManager::blendColors(const QColor &color1, const QColor &color2, qreal ratio) diff --git a/src/singletons/thememanager.hpp b/src/singletons/thememanager.hpp index 26ccfdea..e0b67e0c 100644 --- a/src/singletons/thememanager.hpp +++ b/src/singletons/thememanager.hpp @@ -1,10 +1,10 @@ #pragma once +#include "util/serialize-custom.hpp" + #include #include -#include #include -#include "util/serialize-custom.hpp" namespace chatterino { namespace singletons { @@ -105,7 +105,7 @@ public: void update(); - boost::signals2::signal updated; + pajlada::Signals::NoArgSignal updated; pajlada::Settings::Setting themeName; pajlada::Settings::Setting themeHue; diff --git a/src/singletons/windowmanager.cpp b/src/singletons/windowmanager.cpp index 578879f0..bc601bec 100644 --- a/src/singletons/windowmanager.cpp +++ b/src/singletons/windowmanager.cpp @@ -58,7 +58,7 @@ void WindowManager::initMainWindow() void WindowManager::layoutVisibleChatWidgets(Channel *channel) { - this->layout(channel); + this->layout.invoke(channel); } void WindowManager::repaintVisibleChatWidgets(Channel *channel) @@ -70,7 +70,7 @@ void WindowManager::repaintVisibleChatWidgets(Channel *channel) void WindowManager::repaintGifEmotes() { - this->repaintGifs(); + this->repaintGifs.invoke(); } // void WindowManager::updateAll() diff --git a/src/singletons/windowmanager.hpp b/src/singletons/windowmanager.hpp index 8ff0a460..c95984d2 100644 --- a/src/singletons/windowmanager.hpp +++ b/src/singletons/windowmanager.hpp @@ -32,8 +32,8 @@ public: void save(); - boost::signals2::signal repaintGifs; - boost::signals2::signal layout; + pajlada::Signals::NoArgSignal repaintGifs; + pajlada::Signals::Signal layout; private: ThemeManager &themeManager; diff --git a/src/util/layoutcreator.hpp b/src/util/layoutcreator.hpp index f28e569e..48f5c435 100644 --- a/src/util/layoutcreator.hpp +++ b/src/util/layoutcreator.hpp @@ -126,5 +126,6 @@ private: return this->item->layout(); } }; + } // namespace util } // namespace chatterino diff --git a/src/util/nativeeventhelper.hpp b/src/util/nativeeventhelper.hpp index 2995b1ff..982e6bf1 100644 --- a/src/util/nativeeventhelper.hpp +++ b/src/util/nativeeventhelper.hpp @@ -9,6 +9,7 @@ namespace chatterino { namespace util { + static boost::optional getWindowDpi(quintptr ptr) { typedef UINT(WINAPI * GetDpiForWindow)(HWND); diff --git a/src/util/networkrequest.hpp b/src/util/networkrequest.hpp index 8a3466ec..9973906d 100644 --- a/src/util/networkrequest.hpp +++ b/src/util/networkrequest.hpp @@ -5,6 +5,8 @@ #include "util/networkrequester.hpp" #include "util/networkworker.hpp" +#include +#include #include #include @@ -152,7 +154,7 @@ public: if (this->data.caller != nullptr) { QObject::connect(worker, &NetworkWorker::doneUrl, this->data.caller, - [ onFinished, data = this->data ](auto reply) mutable { + [onFinished, data = this->data](auto reply) mutable { if (reply->error() != QNetworkReply::NetworkError::NoError) { // TODO: We might want to call an onError callback here return; @@ -172,7 +174,7 @@ public: QObject::connect( &requester, &NetworkRequester::requestUrl, worker, - [ timer, data = std::move(this->data), worker, onFinished{std::move(onFinished)} ]() { + [timer, data = std::move(this->data), worker, onFinished{std::move(onFinished)}]() { QNetworkReply *reply = NetworkManager::NaM.get(data.request); if (timer != nullptr) { @@ -187,21 +189,21 @@ public: data.onReplyCreated(reply); } - QObject::connect(reply, &QNetworkReply::finished, worker, [ - data = std::move(data), worker, reply, onFinished = std::move(onFinished) - ]() mutable { - if (data.caller == nullptr) { - QByteArray bytes = reply->readAll(); - data.writeToCache(bytes); - onFinished(bytes); + QObject::connect(reply, &QNetworkReply::finished, worker, + [data = std::move(data), worker, reply, + onFinished = std::move(onFinished)]() mutable { + if (data.caller == nullptr) { + QByteArray bytes = reply->readAll(); + data.writeToCache(bytes); + onFinished(bytes); - reply->deleteLater(); - } else { - emit worker->doneUrl(reply); - } + reply->deleteLater(); + } else { + emit worker->doneUrl(reply); + } - delete worker; - }); + delete worker; + }); }); emit requester.requestUrl(); diff --git a/src/util/networkworker.hpp b/src/util/networkworker.hpp index 7da13fe1..21efeead 100644 --- a/src/util/networkworker.hpp +++ b/src/util/networkworker.hpp @@ -2,6 +2,8 @@ #include +class QNetworkReply; + namespace chatterino { namespace util { diff --git a/src/util/posttothread.hpp b/src/util/posttothread.hpp index 9868a3d3..12bdb9a3 100644 --- a/src/util/posttothread.hpp +++ b/src/util/posttothread.hpp @@ -11,6 +11,7 @@ namespace chatterino { namespace util { + class LambdaRunnable : public QRunnable { public: @@ -47,12 +48,13 @@ static void postToThread(F &&fun, QObject *obj = qApp) , fun(fun) { } - ~Event() + ~Event() override { fun(); } }; QCoreApplication::postEvent(obj, new Event(std::forward(fun))); } + } // namespace util } // namespace chatterino diff --git a/src/util/property.hpp b/src/util/property.hpp index aee1a037..23e6563d 100644 --- a/src/util/property.hpp +++ b/src/util/property.hpp @@ -4,6 +4,7 @@ namespace chatterino { namespace util { + template class Property final : boost::noncopyable { @@ -30,5 +31,6 @@ public: protected: T value; }; -} -} + +} // namespace util +} // namespace chatterino diff --git a/src/util/streamlink.hpp b/src/util/streamlink.hpp index 396c09af..b38da260 100644 --- a/src/util/streamlink.hpp +++ b/src/util/streamlink.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include diff --git a/src/util/urlfetch.hpp b/src/util/urlfetch.hpp index cd83e7c2..5b730c08 100644 --- a/src/util/urlfetch.hpp +++ b/src/util/urlfetch.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include diff --git a/src/widgets/accountpopup.hpp b/src/widgets/accountpopup.hpp index 14d81965..f8fed98b 100644 --- a/src/widgets/accountpopup.hpp +++ b/src/widgets/accountpopup.hpp @@ -11,7 +11,7 @@ namespace Ui { class AccountPopup; -} +} // namespace Ui namespace chatterino { @@ -35,7 +35,7 @@ signals: void refreshButtons(); protected: - virtual void scaleChangedEvent(float newDpi) override; + void scaleChangedEvent(float newDpi) override; private: Ui::AccountPopup *ui; @@ -76,8 +76,8 @@ private: } relationship; protected: - virtual void focusOutEvent(QFocusEvent *event) override; - virtual void showEvent(QShowEvent *event) override; + void focusOutEvent(QFocusEvent *event) override; + void showEvent(QShowEvent *event) override; }; } // namespace widgets diff --git a/src/widgets/accountswitchpopupwidget.cpp b/src/widgets/accountswitchpopupwidget.cpp index 0b69066c..922834d2 100644 --- a/src/widgets/accountswitchpopupwidget.cpp +++ b/src/widgets/accountswitchpopupwidget.cpp @@ -54,5 +54,6 @@ void AccountSwitchPopupWidget::paintEvent(QPaintEvent *event) painter.fillRect(this->rect(), QColor(255, 255, 255)); } + } // namespace widgets } // namespace chatterino diff --git a/src/widgets/accountswitchpopupwidget.hpp b/src/widgets/accountswitchpopupwidget.hpp index f2a45a98..27c22ecc 100644 --- a/src/widgets/accountswitchpopupwidget.hpp +++ b/src/widgets/accountswitchpopupwidget.hpp @@ -17,8 +17,8 @@ public: void refresh(); protected: - virtual void focusOutEvent(QFocusEvent *event) override final; - virtual void paintEvent(QPaintEvent *event) override; + void focusOutEvent(QFocusEvent *event) final; + void paintEvent(QPaintEvent *event) override; private: struct { diff --git a/src/widgets/basewidget.cpp b/src/widgets/basewidget.cpp index 6680134e..0d01964b 100644 --- a/src/widgets/basewidget.cpp +++ b/src/widgets/basewidget.cpp @@ -1,4 +1,5 @@ #include "widgets/basewidget.hpp" +#include "debug/log.hpp" #include "singletons/settingsmanager.hpp" #include "singletons/thememanager.hpp" @@ -7,7 +8,6 @@ #include #include #include -#include namespace chatterino { namespace widgets { @@ -82,13 +82,13 @@ void BaseWidget::setScaleIndependantHeight(int value) void BaseWidget::init() { - auto connection = this->themeManager.updated.connect([this]() { + pajlada::Signals::Connection connection = this->themeManager.updated.connect([this]() { this->themeRefreshEvent(); this->update(); }); - QObject::connect(this, &QObject::destroyed, [connection] { + QObject::connect(this, &QObject::destroyed, [connection]() mutable { connection.disconnect(); // }); } diff --git a/src/widgets/basewidget.hpp b/src/widgets/basewidget.hpp index 376d1f21..2e2a9c0b 100644 --- a/src/widgets/basewidget.hpp +++ b/src/widgets/basewidget.hpp @@ -6,9 +6,10 @@ namespace chatterino { namespace singletons { class ThemeManager; -} +} // namespace singletons namespace widgets { + class BaseWindow; class BaseWidget : public QWidget @@ -34,7 +35,7 @@ public: void setScaleIndependantHeight(int value); protected: - virtual void childEvent(QChildEvent *) override; + void childEvent(QChildEvent *) override; virtual void scaleChangedEvent(float newScale); virtual void themeRefreshEvent(); diff --git a/src/widgets/basewindow.cpp b/src/widgets/basewindow.cpp index bb7eda86..cb92ddc1 100644 --- a/src/widgets/basewindow.cpp +++ b/src/widgets/basewindow.cpp @@ -1,5 +1,6 @@ #include "basewindow.hpp" +#include "debug/log.hpp" #include "singletons/settingsmanager.hpp" #include "util/nativeeventhelper.hpp" #include "widgets/helper/rippleeffectlabel.hpp" @@ -11,10 +12,10 @@ #include #ifdef USEWINSDK +#include +#include #include #include -#include -#include #include #pragma comment(lib, "Dwmapi.lib") diff --git a/src/widgets/basewindow.hpp b/src/widgets/basewindow.hpp index 3f4c3c0f..2c382eb4 100644 --- a/src/widgets/basewindow.hpp +++ b/src/widgets/basewindow.hpp @@ -9,12 +9,15 @@ class QHBoxLayout; namespace chatterino { namespace widgets { + class RippleEffectButton; class RippleEffectLabel; class TitleBarButton; class BaseWindow : public BaseWidget { + Q_OBJECT + public: explicit BaseWindow(singletons::ThemeManager &_themeManager, QWidget *parent, bool enableCustomFrame = false); @@ -60,5 +63,6 @@ private: QWidget *layoutBase; std::vector buttons; }; + } // namespace widgets } // namespace chatterino diff --git a/src/widgets/helper/channelview.cpp b/src/widgets/helper/channelview.cpp index 663b7882..2d12bf4d 100644 --- a/src/widgets/helper/channelview.cpp +++ b/src/widgets/helper/channelview.cpp @@ -20,9 +20,9 @@ #include #include -#include #include #include +#include #include #include @@ -461,7 +461,7 @@ void ChannelView::setSelection(const SelectionItem &start, const SelectionItem & // selections this->selection = Selection(start, end); - this->selectionChanged(); + this->selectionChanged.invoke(); } messages::MessageElement::Flags ChannelView::getFlags() const @@ -729,7 +729,7 @@ void ChannelView::mousePressEvent(QMouseEvent *event) QPoint relativePos; int messageIndex; - this->mouseDown(event); + this->mouseDown.invoke(event); if (!tryGetMessageAt(event->pos(), layout, relativePos, messageIndex)) { setCursor(Qt::ArrowCursor); diff --git a/src/widgets/helper/channelview.hpp b/src/widgets/helper/channelview.hpp index 8c794263..bc62fb87 100644 --- a/src/widgets/helper/channelview.hpp +++ b/src/widgets/helper/channelview.hpp @@ -16,8 +16,8 @@ #include #include #include -#include #include + #include namespace chatterino { @@ -28,7 +28,7 @@ class ChannelView : public BaseWidget Q_OBJECT public: - explicit ChannelView(BaseWidget *parent = 0); + explicit ChannelView(BaseWidget *parent = nullptr); virtual ~ChannelView(); void queueUpdate(); @@ -49,26 +49,26 @@ public: void clearMessages(); - boost::signals2::signal mouseDown; - boost::signals2::signal selectionChanged; + pajlada::Signals::Signal mouseDown; + pajlada::Signals::NoArgSignal selectionChanged; pajlada::Signals::NoArgSignal highlightedMessageReceived; pajlada::Signals::Signal linkClicked; protected: - virtual void themeRefreshEvent() override; + void themeRefreshEvent() override; - virtual void resizeEvent(QResizeEvent *) override; + void resizeEvent(QResizeEvent *) override; - virtual void paintEvent(QPaintEvent *) override; - virtual void wheelEvent(QWheelEvent *event) override; + void paintEvent(QPaintEvent *) override; + void wheelEvent(QWheelEvent *event) override; - virtual void enterEvent(QEvent *) override; - virtual void leaveEvent(QEvent *) override; + void enterEvent(QEvent *) override; + void leaveEvent(QEvent *) override; - virtual void mouseMoveEvent(QMouseEvent *event) override; - virtual void mousePressEvent(QMouseEvent *event) override; - virtual void mouseReleaseEvent(QMouseEvent *event) override; - virtual void mouseDoubleClickEvent(QMouseEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; + void mousePressEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + void mouseDoubleClickEvent(QMouseEvent *event) override; void handleLinkClick(QMouseEvent *event, const messages::Link &link, messages::MessageLayout *layout); @@ -116,12 +116,12 @@ private: messages::LimitedQueue messages; - boost::signals2::connection messageAppendedConnection; - boost::signals2::connection messageAddedAtStartConnection; - boost::signals2::connection messageRemovedConnection; - boost::signals2::connection messageReplacedConnection; - boost::signals2::connection repaintGifsConnection; - boost::signals2::connection layoutConnection; + pajlada::Signals::Connection messageAppendedConnection; + pajlada::Signals::Connection messageAddedAtStartConnection; + pajlada::Signals::Connection messageRemovedConnection; + pajlada::Signals::Connection messageReplacedConnection; + pajlada::Signals::Connection repaintGifsConnection; + pajlada::Signals::Connection layoutConnection; std::vector managedConnections; diff --git a/src/widgets/helper/droppreview.hpp b/src/widgets/helper/droppreview.hpp index ae5a51be..990ece25 100644 --- a/src/widgets/helper/droppreview.hpp +++ b/src/widgets/helper/droppreview.hpp @@ -16,8 +16,8 @@ public: void setBounds(const QRect &rect); protected: - virtual void paintEvent(QPaintEvent *) override; - virtual void hideEvent(QHideEvent *) override; + void paintEvent(QPaintEvent *) override; + void hideEvent(QHideEvent *) override; QPropertyAnimation positionAnimation; QRect desiredGeometry; diff --git a/src/widgets/helper/label.cpp b/src/widgets/helper/label.cpp index a8332d9e..26bc7160 100644 --- a/src/widgets/helper/label.cpp +++ b/src/widgets/helper/label.cpp @@ -5,6 +5,7 @@ namespace chatterino { namespace widgets { + Label::Label(BaseWidget *parent) : BaseWidget(parent) { @@ -74,5 +75,6 @@ void Label::paintEvent(QPaintEvent *) painter.drawText(this->rect(), flags, this->text); } + } // namespace widgets } // namespace chatterino diff --git a/src/widgets/helper/label.hpp b/src/widgets/helper/label.hpp index ea3b3b60..5afa0e00 100644 --- a/src/widgets/helper/label.hpp +++ b/src/widgets/helper/label.hpp @@ -29,5 +29,6 @@ private: QString text; FontStyle fontStyle = FontStyle::Medium; }; + } // namespace widgets } // namespace chatterino diff --git a/src/widgets/helper/notebookbutton.cpp b/src/widgets/helper/notebookbutton.cpp index 6570c304..be07b2f8 100644 --- a/src/widgets/helper/notebookbutton.cpp +++ b/src/widgets/helper/notebookbutton.cpp @@ -144,5 +144,6 @@ void NotebookButton::dropEvent(QDropEvent *event) } } } + } // namespace widgets } // namespace chatterino diff --git a/src/widgets/helper/notebooktab.cpp b/src/widgets/helper/notebooktab.cpp index ad2f481d..21961c0a 100644 --- a/src/widgets/helper/notebooktab.cpp +++ b/src/widgets/helper/notebooktab.cpp @@ -12,6 +12,7 @@ #include #include #include +#include namespace chatterino { namespace widgets { diff --git a/src/widgets/helper/notebooktab.hpp b/src/widgets/helper/notebooktab.hpp index 8cdb9656..c474e705 100644 --- a/src/widgets/helper/notebooktab.hpp +++ b/src/widgets/helper/notebooktab.hpp @@ -9,7 +9,6 @@ #include namespace chatterino { - namespace widgets { class Notebook; diff --git a/src/widgets/helper/resizingtextedit.cpp b/src/widgets/helper/resizingtextedit.cpp index 46038718..609dafc5 100644 --- a/src/widgets/helper/resizingtextedit.cpp +++ b/src/widgets/helper/resizingtextedit.cpp @@ -73,7 +73,7 @@ void ResizingTextEdit::keyPressEvent(QKeyEvent *event) { event->ignore(); - this->keyPressed(event); + this->keyPressed.invoke(event); if (event->key() == Qt::Key_Backtab) { // Ignore for now. We want to use it for autocomplete later diff --git a/src/widgets/helper/resizingtextedit.hpp b/src/widgets/helper/resizingtextedit.hpp index 727e44bd..d68ea0eb 100644 --- a/src/widgets/helper/resizingtextedit.hpp +++ b/src/widgets/helper/resizingtextedit.hpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include class ResizingTextEdit : public QTextEdit { @@ -14,14 +14,14 @@ public: bool hasHeightForWidth() const override; - boost::signals2::signal keyPressed; + pajlada::Signals::Signal keyPressed; void setCompleter(QCompleter *c); QCompleter *getCompleter() const; protected: - virtual int heightForWidth(int) const override; - virtual void keyPressEvent(QKeyEvent *event) override; + int heightForWidth(int) const override; + void keyPressEvent(QKeyEvent *event) override; private: QCompleter *completer = nullptr; diff --git a/src/widgets/helper/scrollbarhighlight.hpp b/src/widgets/helper/scrollbarhighlight.hpp index a387617f..7dbccee1 100644 --- a/src/widgets/helper/scrollbarhighlight.hpp +++ b/src/widgets/helper/scrollbarhighlight.hpp @@ -1,9 +1,10 @@ #pragma once -#include "QString" +#include namespace chatterino { namespace widgets { + class ScrollbarHighlight { public: diff --git a/src/widgets/helper/searchpopup.hpp b/src/widgets/helper/searchpopup.hpp index 28e06f01..909626ff 100644 --- a/src/widgets/helper/searchpopup.hpp +++ b/src/widgets/helper/searchpopup.hpp @@ -1,15 +1,19 @@ #pragma once -#include - #include "messages/limitedqueuesnapshot.hpp" #include "messages/message.hpp" #include "widgets/basewindow.hpp" +#include + class QLineEdit; + namespace chatterino { + class Channel; + namespace widgets { + class ChannelView; class SearchPopup : public BaseWindow @@ -27,5 +31,6 @@ private: void initLayout(); void performSearch(); }; + } // namespace widgets } // namespace chatterino diff --git a/src/widgets/helper/settingsdialogtab.hpp b/src/widgets/helper/settingsdialogtab.hpp index 8242e820..45aa27be 100644 --- a/src/widgets/helper/settingsdialogtab.hpp +++ b/src/widgets/helper/settingsdialogtab.hpp @@ -1,16 +1,16 @@ #pragma once +#include "widgets/basewidget.hpp" + #include #include #include -#include "widgets/basewidget.hpp" - namespace chatterino { namespace widgets { namespace settingspages { class SettingsPage; -} +} // namespace settingspages class SettingsDialog; diff --git a/src/widgets/helper/splitcolumn.cpp b/src/widgets/helper/splitcolumn.cpp index b6f346fb..b3e7e3c7 100644 --- a/src/widgets/helper/splitcolumn.cpp +++ b/src/widgets/helper/splitcolumn.cpp @@ -2,8 +2,6 @@ namespace chatterino { namespace helper { -SplitColumn::SplitColumn() -{ -} -} -} + +} // namespace helper +} // namespace chatterino diff --git a/src/widgets/helper/splitcolumn.hpp b/src/widgets/helper/splitcolumn.hpp index 98418d8c..de63fffe 100644 --- a/src/widgets/helper/splitcolumn.hpp +++ b/src/widgets/helper/splitcolumn.hpp @@ -1,15 +1,16 @@ #pragma once -#include - #include "widgets/split.hpp" +#include + namespace chatterino { namespace helper { + class SplitColumn { public: - SplitColumn(); + SplitColumn() = default; void insert(widgets::Split *split, int index = -1); void remove(int index); @@ -19,5 +20,6 @@ public: private: std::vector items; }; -} -} + +} // namespace helper +} // namespace chatterino diff --git a/src/widgets/helper/splitheader.cpp b/src/widgets/helper/splitheader.cpp index 2942f137..3228e2f0 100644 --- a/src/widgets/helper/splitheader.cpp +++ b/src/widgets/helper/splitheader.cpp @@ -57,7 +57,8 @@ SplitHeader::SplitHeader(Split *_split) title->setMouseTracking(true); QObject::connect(this->titleLabel, &SignalLabel::mouseDoubleClick, this, &SplitHeader::mouseDoubleClickEvent); - QObject::connect(this->titleLabel, &SignalLabel::mouseMove, this, &SplitHeader::mouseMoveEvent); + QObject::connect(this->titleLabel, &SignalLabel::mouseMove, this, + &SplitHeader::mouseMoveEvent); layout->addStretch(1); diff --git a/src/widgets/helper/splitheader.hpp b/src/widgets/helper/splitheader.hpp index 329f65ac..80d81ab5 100644 --- a/src/widgets/helper/splitheader.hpp +++ b/src/widgets/helper/splitheader.hpp @@ -13,11 +13,9 @@ #include #include #include -#include #include namespace chatterino { - namespace widgets { class Split; @@ -50,7 +48,7 @@ private: QPoint dragStart; bool dragging = false; - boost::signals2::connection onlineStatusChangedConnection; + pajlada::Signals::Connection onlineStatusChangedConnection; RippleEffectButton *dropdownButton; // Label *titleLabel; diff --git a/src/widgets/scrollbar.cpp b/src/widgets/scrollbar.cpp index 720c2e88..2525ddf8 100644 --- a/src/widgets/scrollbar.cpp +++ b/src/widgets/scrollbar.cpp @@ -162,7 +162,7 @@ void Scrollbar::offset(qreal value) } } -boost::signals2::signal &Scrollbar::getCurrentValueChanged() +pajlada::Signals::NoArgSignal &Scrollbar::getCurrentValueChanged() { return this->currentValueChanged; } @@ -176,7 +176,7 @@ void Scrollbar::setCurrentValue(qreal value) this->currentValue = value; this->updateScroll(); - this->currentValueChanged(); + this->currentValueChanged.invoke(); this->update(); } diff --git a/src/widgets/scrollbar.hpp b/src/widgets/scrollbar.hpp index 478b40a3..9ce64659 100644 --- a/src/widgets/scrollbar.hpp +++ b/src/widgets/scrollbar.hpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include namespace chatterino { @@ -43,7 +43,7 @@ public: qreal getCurrentValue() const; // offset the desired value without breaking smooth scolling void offset(qreal value); - boost::signals2::signal &getCurrentValueChanged(); + pajlada::Signals::NoArgSignal &getCurrentValueChanged(); void setCurrentValue(qreal value); void printCurrentState(const QString &prefix = QString()) const; @@ -86,7 +86,7 @@ private: qreal currentValue = 0; qreal smoothScrollingOffset = 0; - boost::signals2::signal currentValueChanged; + pajlada::Signals::NoArgSignal currentValueChanged; pajlada::Settings::Setting &smoothScrollingSetting; diff --git a/src/widgets/settingsdialog.hpp b/src/widgets/settingsdialog.hpp index 2feecfc9..362809cf 100644 --- a/src/widgets/settingsdialog.hpp +++ b/src/widgets/settingsdialog.hpp @@ -13,7 +13,7 @@ namespace widgets { namespace settingspages { class SettingsPage; -} +} // namespace settingspages class SettingsDialogTab; @@ -32,7 +32,7 @@ public: static void showDialog(PreferredTab preferredTab = PreferredTab::NoPreference); protected: - virtual void scaleChangedEvent(float newDpi) override; + void scaleChangedEvent(float newDpi) override; private: void refresh(); diff --git a/src/widgets/settingspages/aboutpage.cpp b/src/widgets/settingspages/aboutpage.cpp index cba3ae55..a9398dd7 100644 --- a/src/widgets/settingspages/aboutpage.cpp +++ b/src/widgets/settingspages/aboutpage.cpp @@ -53,6 +53,7 @@ AboutPage::AboutPage() } layout->addStretch(1); } + } // namespace settingspages } // namespace widgets } // namespace chatterino diff --git a/src/widgets/settingspages/aboutpage.hpp b/src/widgets/settingspages/aboutpage.hpp index 3f27f552..f482244b 100644 --- a/src/widgets/settingspages/aboutpage.hpp +++ b/src/widgets/settingspages/aboutpage.hpp @@ -16,6 +16,7 @@ public: private: QLabel *logo; }; + } // namespace settingspages } // namespace widgets } // namespace chatterino diff --git a/src/widgets/settingspages/accountspage.cpp b/src/widgets/settingspages/accountspage.cpp index 0ad7cdc6..e3ef8da4 100644 --- a/src/widgets/settingspages/accountspage.cpp +++ b/src/widgets/settingspages/accountspage.cpp @@ -11,6 +11,7 @@ namespace chatterino { namespace widgets { namespace settingspages { + AccountsPage::AccountsPage() : SettingsPage("Accounts", ":/images/accounts.svg") { @@ -41,6 +42,7 @@ AccountsPage::AccountsPage() singletons::AccountManager::getInstance().Twitch.removeUser(selectedUser); }); } + } // namespace settingspages } // namespace widgets } // namespace chatterino diff --git a/src/widgets/settingspages/accountspage.hpp b/src/widgets/settingspages/accountspage.hpp index fb553495..0e5c1c5b 100644 --- a/src/widgets/settingspages/accountspage.hpp +++ b/src/widgets/settingspages/accountspage.hpp @@ -1,10 +1,10 @@ #pragma once -#include - #include "widgets/accountswitchwidget.hpp" #include "widgets/settingspages/settingspage.hpp" +#include + namespace chatterino { namespace widgets { namespace settingspages { @@ -19,6 +19,7 @@ private: QPushButton *removeButton; AccountSwitchWidget *accSwitchWidget; }; + } // namespace settingspages } // namespace widgets } // namespace chatterino diff --git a/src/widgets/settingspages/appearancepage.cpp b/src/widgets/settingspages/appearancepage.cpp index d591164a..997167dd 100644 --- a/src/widgets/settingspages/appearancepage.cpp +++ b/src/widgets/settingspages/appearancepage.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include "util/layoutcreator.hpp" @@ -65,7 +66,8 @@ AppearancePage::AppearancePage() } messages.append(this->createCheckBox("Show badges", settings.showBadges)); messages.append(this->createCheckBox("Seperate messages", settings.seperateMessages)); - messages.append(this->createCheckBox("Show message length while typing", settings.showMessageLength)); + messages.append( + this->createCheckBox("Show message length while typing", settings.showMessageLength)); } layout->addStretch(1); @@ -148,6 +150,7 @@ QLayout *AppearancePage::createFontChanger() return layout; } + } // namespace settingspages } // namespace widgets } // namespace chatterino diff --git a/src/widgets/settingspages/appearancepage.hpp b/src/widgets/settingspages/appearancepage.hpp index 40a5f5cb..b1ac61b2 100644 --- a/src/widgets/settingspages/appearancepage.hpp +++ b/src/widgets/settingspages/appearancepage.hpp @@ -2,8 +2,6 @@ #include "widgets/settingspages/settingspage.hpp" -#include - namespace chatterino { namespace widgets { namespace settingspages { diff --git a/src/widgets/settingspages/behaviourpage.cpp b/src/widgets/settingspages/behaviourpage.cpp index c596d210..3c89b2a0 100644 --- a/src/widgets/settingspages/behaviourpage.cpp +++ b/src/widgets/settingspages/behaviourpage.cpp @@ -19,6 +19,7 @@ namespace chatterino { namespace widgets { namespace settingspages { + BehaviourPage::BehaviourPage() : SettingsPage("Behaviour", ":/images/behave.svg") { @@ -80,6 +81,7 @@ QSlider *BehaviourPage::createMouseScrollSlider() return slider; } + } // namespace settingspages } // namespace widgets } // namespace chatterino diff --git a/src/widgets/settingspages/emotespage.hpp b/src/widgets/settingspages/emotespage.hpp index c09ff45f..75cfec6a 100644 --- a/src/widgets/settingspages/emotespage.hpp +++ b/src/widgets/settingspages/emotespage.hpp @@ -11,6 +11,7 @@ class EmotesPage : public SettingsPage public: EmotesPage(); }; + } // namespace settingspages } // namespace widgets } // namespace chatterino diff --git a/src/widgets/settingspages/highlightingpage.cpp b/src/widgets/settingspages/highlightingpage.cpp index 796f7da8..bbcd1d34 100644 --- a/src/widgets/settingspages/highlightingpage.cpp +++ b/src/widgets/settingspages/highlightingpage.cpp @@ -19,6 +19,7 @@ namespace chatterino { namespace widgets { namespace settingspages { + HighlightingPage::HighlightingPage() : SettingsPage("Highlights", ":/images/notifications.svg") { @@ -239,6 +240,7 @@ void HighlightingPage::addHighlightTabSignals() delete selectedHighlight; }); } + } // namespace settingspages } // namespace widgets } // namespace chatterino diff --git a/src/widgets/settingspages/highlightingpage.hpp b/src/widgets/settingspages/highlightingpage.hpp index 12cd20ec..6bf447ec 100644 --- a/src/widgets/settingspages/highlightingpage.hpp +++ b/src/widgets/settingspages/highlightingpage.hpp @@ -1,9 +1,9 @@ #pragma once -#include - #include "widgets/settingspages/settingspage.hpp" +#include + class QPushButton; class QListWidget; diff --git a/src/widgets/settingspages/ignoremessagespage.cpp b/src/widgets/settingspages/ignoremessagespage.cpp index 19f8b551..c4bba2c7 100644 --- a/src/widgets/settingspages/ignoremessagespage.cpp +++ b/src/widgets/settingspages/ignoremessagespage.cpp @@ -8,6 +8,7 @@ namespace chatterino { namespace widgets { namespace settingspages { + IgnoreMessagesPage::IgnoreMessagesPage() : SettingsPage("Ignore Messages", "") { @@ -32,6 +33,7 @@ IgnoreMessagesPage::IgnoreMessagesPage() // ---- misc this->keywordsUpdated.setSingleShot(true); } + } // namespace settingspages } // namespace widgets } // namespace chatterino diff --git a/src/widgets/settingspages/ignoremessagespage.hpp b/src/widgets/settingspages/ignoremessagespage.hpp index f6cb3f77..571b9152 100644 --- a/src/widgets/settingspages/ignoremessagespage.hpp +++ b/src/widgets/settingspages/ignoremessagespage.hpp @@ -1,8 +1,9 @@ #pragma once -#include #include "widgets/settingspages/settingspage.hpp" +#include + namespace chatterino { namespace widgets { namespace settingspages { @@ -14,6 +15,7 @@ public: QTimer keywordsUpdated; }; + } // namespace settingspages } // namespace widgets } // namespace chatterino diff --git a/src/widgets/settingspages/ignoreuserspage.cpp b/src/widgets/settingspages/ignoreuserspage.cpp index bccef00c..62cd7284 100644 --- a/src/widgets/settingspages/ignoreuserspage.cpp +++ b/src/widgets/settingspages/ignoreuserspage.cpp @@ -17,6 +17,7 @@ namespace chatterino { namespace widgets { namespace settingspages { + IgnoreUsersPage::IgnoreUsersPage() : SettingsPage("Ignore Users", "") { @@ -50,6 +51,7 @@ IgnoreUsersPage::IgnoreUsersPage() auto userList = group.emplace(); } } + } // namespace settingspages } // namespace widgets } // namespace chatterino diff --git a/src/widgets/settingspages/ignoreuserspage.hpp b/src/widgets/settingspages/ignoreuserspage.hpp index ab231eea..74773089 100644 --- a/src/widgets/settingspages/ignoreuserspage.hpp +++ b/src/widgets/settingspages/ignoreuserspage.hpp @@ -5,11 +5,13 @@ namespace chatterino { namespace widgets { namespace settingspages { + class IgnoreUsersPage : public SettingsPage { public: IgnoreUsersPage(); }; + } // namespace settingspages } // namespace widgets } // namespace chatterino diff --git a/src/widgets/settingspages/keyboardsettingspage.cpp b/src/widgets/settingspages/keyboardsettingspage.cpp index 57565fe8..bc9b0081 100644 --- a/src/widgets/settingspages/keyboardsettingspage.cpp +++ b/src/widgets/settingspages/keyboardsettingspage.cpp @@ -3,10 +3,12 @@ namespace chatterino { namespace widgets { namespace settingspages { + KeyboardSettingsPage::KeyboardSettingsPage() : SettingsPage("Keybindings", "") { } + } // namespace settingspages } // namespace widgets } // namespace chatterino diff --git a/src/widgets/settingspages/keyboardsettingspage.hpp b/src/widgets/settingspages/keyboardsettingspage.hpp index 3cf4a614..7064e6e3 100644 --- a/src/widgets/settingspages/keyboardsettingspage.hpp +++ b/src/widgets/settingspages/keyboardsettingspage.hpp @@ -5,11 +5,13 @@ namespace chatterino { namespace widgets { namespace settingspages { + class KeyboardSettingsPage : public SettingsPage { public: KeyboardSettingsPage(); }; + } // namespace settingspages } // namespace widgets } // namespace chatterino diff --git a/src/widgets/settingspages/logspage.hpp b/src/widgets/settingspages/logspage.hpp index f43c13af..01af3537 100644 --- a/src/widgets/settingspages/logspage.hpp +++ b/src/widgets/settingspages/logspage.hpp @@ -11,6 +11,7 @@ class LogsPage : public SettingsPage public: LogsPage(); }; + } // namespace settingspages } // namespace widgets } // namespace chatterino diff --git a/src/widgets/settingspages/specialchannelspage.cpp b/src/widgets/settingspages/specialchannelspage.cpp index f6df3373..0c5550a1 100644 --- a/src/widgets/settingspages/specialchannelspage.cpp +++ b/src/widgets/settingspages/specialchannelspage.cpp @@ -10,6 +10,7 @@ namespace chatterino { namespace widgets { namespace settingspages { + SpecialChannelsPage::SpecialChannelsPage() : SettingsPage("Special channels", "") { @@ -30,6 +31,7 @@ SpecialChannelsPage::SpecialChannelsPage() layout->addStretch(1); } + } // namespace settingspages } // namespace widgets } // namespace chatterino diff --git a/src/widgets/settingspages/specialchannelspage.hpp b/src/widgets/settingspages/specialchannelspage.hpp index 5c964559..fbf18f31 100644 --- a/src/widgets/settingspages/specialchannelspage.hpp +++ b/src/widgets/settingspages/specialchannelspage.hpp @@ -5,11 +5,13 @@ namespace chatterino { namespace widgets { namespace settingspages { + class SpecialChannelsPage : public SettingsPage { public: SpecialChannelsPage(); }; + } // namespace settingspages } // namespace widgets } // namespace chatterino diff --git a/src/widgets/split.cpp b/src/widgets/split.cpp index f738f0ea..7d669200 100644 --- a/src/widgets/split.cpp +++ b/src/widgets/split.cpp @@ -25,7 +25,6 @@ #include #include #include -#include #include #include @@ -150,7 +149,7 @@ void Split::setChannel(ChannelPtr _newChannel) this->header.updateModerationModeIcon(); - this->channelChanged(); + this->channelChanged.invoke(); } void Split::setFlexSizeX(double x) diff --git a/src/widgets/split.hpp b/src/widgets/split.hpp index ce5f193e..054513b2 100644 --- a/src/widgets/split.hpp +++ b/src/widgets/split.hpp @@ -16,7 +16,6 @@ #include #include #include -#include namespace chatterino { namespace widgets { @@ -47,7 +46,7 @@ public: ~Split() override; pajlada::Settings::Setting channelName; - boost::signals2::signal channelChanged; + pajlada::Signals::NoArgSignal channelChanged; ChannelView &getChannelView() { @@ -93,8 +92,8 @@ private: bool moderationMode; - boost::signals2::connection channelIDChangedConnection; - boost::signals2::connection usermodeChangedConnection; + pajlada::Signals::Connection channelIDChangedConnection; + pajlada::Signals::Connection usermodeChangedConnection; void setChannel(ChannelPtr newChannel); void doOpenAccountPopupWidget(AccountPopupWidget *widget, QString user); diff --git a/src/widgets/streamview.cpp b/src/widgets/streamview.cpp index 7ad017d6..a3e2a001 100644 --- a/src/widgets/streamview.cpp +++ b/src/widgets/streamview.cpp @@ -11,6 +11,7 @@ namespace chatterino { namespace widgets { + StreamView::StreamView(ChannelPtr channel, QUrl url) { util::LayoutCreator layoutCreator(this); @@ -30,5 +31,6 @@ StreamView::StreamView(ChannelPtr channel, QUrl url) this->layout()->setSpacing(0); this->layout()->setMargin(0); } + } // namespace widgets } // namespace chatterino diff --git a/src/widgets/streamview.hpp b/src/widgets/streamview.hpp index 7c80abec..deb9f4d2 100644 --- a/src/widgets/streamview.hpp +++ b/src/widgets/streamview.hpp @@ -2,14 +2,17 @@ #include #include + #include class QWebEngineView; namespace chatterino { + class Channel; namespace widgets { + class StreamView : public QWidget { public: @@ -18,5 +21,6 @@ public: private: QWebEngineView *stream; }; + } // namespace widgets } // namespace chatterino diff --git a/src/widgets/textinputdialog.cpp b/src/widgets/textinputdialog.cpp index 87cafa78..deb97e7a 100644 --- a/src/widgets/textinputdialog.cpp +++ b/src/widgets/textinputdialog.cpp @@ -7,8 +7,6 @@ namespace widgets { TextInputDialog::TextInputDialog(QWidget *parent) : QDialog(parent) , _vbox(this) - , _lineEdit() - , _buttonBox() , _okButton("OK") , _cancelButton("Cancel") { diff --git a/src/widgets/tooltipwidget.cpp b/src/widgets/tooltipwidget.cpp index 3d4ed9e6..22c3f0be 100644 --- a/src/widgets/tooltipwidget.cpp +++ b/src/widgets/tooltipwidget.cpp @@ -65,5 +65,6 @@ void TooltipWidget::leaveEvent(QEvent *) { // clear parents event } + } // namespace widgets } // namespace chatterino diff --git a/src/widgets/tooltipwidget.hpp b/src/widgets/tooltipwidget.hpp index 96f3af2c..ff3a7bf0 100644 --- a/src/widgets/tooltipwidget.hpp +++ b/src/widgets/tooltipwidget.hpp @@ -1,4 +1,5 @@ #pragma once + #include "widgets/basewindow.hpp" #include @@ -11,6 +12,7 @@ namespace widgets { class TooltipWidget : public BaseWindow { Q_OBJECT + public: TooltipWidget(BaseWidget *parent = nullptr); ~TooltipWidget(); @@ -27,9 +29,9 @@ public: } protected: - virtual void changeEvent(QEvent *) override; - virtual void leaveEvent(QEvent *) override; - virtual void scaleChangedEvent(float) override; + void changeEvent(QEvent *) override; + void leaveEvent(QEvent *) override; + void scaleChangedEvent(float) override; private: QLabel *displayText; diff --git a/src/widgets/window.cpp b/src/widgets/window.cpp index 29f7d4a5..3326a33f 100644 --- a/src/widgets/window.cpp +++ b/src/widgets/window.cpp @@ -110,13 +110,9 @@ void Window::repaintVisibleChatWidgets(Channel *channel) return; } - const std::vector &widgets = page->getSplits(); - - for (auto it = widgets.begin(); it != widgets.end(); ++it) { - Split *widget = *it; - - if (channel == nullptr || channel == widget->getChannel().get()) { - widget->layoutMessages(); + for (const auto &split : page->getSplits()) { + if (channel == nullptr || channel == split->getChannel().get()) { + split->layoutMessages(); } } } @@ -140,7 +136,7 @@ void Window::closeEvent(QCloseEvent *) this->windowGeometry.width = geom.width(); this->windowGeometry.height = geom.height(); - this->closed(); + this->closed.invoke(); } bool Window::event(QEvent *e) diff --git a/src/widgets/window.hpp b/src/widgets/window.hpp index 79ce2420..a82a9b29 100644 --- a/src/widgets/window.hpp +++ b/src/widgets/window.hpp @@ -8,14 +8,13 @@ //#include //#endif -#include #include #include namespace chatterino { namespace singletons { class ThemeManager; -} +} // namespace singletons namespace widgets { @@ -52,11 +51,11 @@ public: void refreshWindowTitle(const QString &username); - boost::signals2::signal closed; + pajlada::Signals::NoArgSignal closed; protected: - virtual void closeEvent(QCloseEvent *event) override; - virtual bool event(QEvent *event) override; + void closeEvent(QCloseEvent *event) override; + bool event(QEvent *event) override; private: float dpi; From 5c23be21227325070d7d1cc95f283c0db6893c26 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Tue, 3 Apr 2018 02:59:24 +0200 Subject: [PATCH 29/69] Update settings library. make use of new define --- dependencies/settings.pri | 2 ++ lib/settings | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/dependencies/settings.pri b/dependencies/settings.pri index 7c6b080a..9b30da6a 100644 --- a/dependencies/settings.pri +++ b/dependencies/settings.pri @@ -1,4 +1,6 @@ # settings +DEFINES += PAJLADA_SETTINGS_NO_BOOST + SOURCES += \ $$PWD/../lib/settings/src/settings/settingdata.cpp \ $$PWD/../lib/settings/src/settings/settingmanager.cpp diff --git a/lib/settings b/lib/settings index 2fa3adf4..ad31b388 160000 --- a/lib/settings +++ b/lib/settings @@ -1 +1 @@ -Subproject commit 2fa3adf42da988dc2a34b9b625654aa08e906d4f +Subproject commit ad31b38866d80a17ced902476ed06da69edce3a0 From 06c3201a1a4c2eaffd37a605af2a5169c3b7cf1e Mon Sep 17 00:00:00 2001 From: fourtf Date: Thu, 5 Apr 2018 23:44:46 +0200 Subject: [PATCH 30/69] added dark window to dark theme --- src/singletons/thememanager.cpp | 73 ++++++++++++--------------- src/singletons/thememanager.hpp | 16 ++++-- src/widgets/basewindow.cpp | 29 +++++++---- src/widgets/helper/notebookbutton.cpp | 12 +++-- src/widgets/helper/notebookbutton.hpp | 1 + src/widgets/helper/notebooktab.cpp | 14 ++--- src/widgets/helper/titlebarbutton.cpp | 12 +++-- src/widgets/splitcontainer.cpp | 2 +- 8 files changed, 88 insertions(+), 71 deletions(-) diff --git a/src/singletons/thememanager.cpp b/src/singletons/thememanager.cpp index 6f522b88..55d61212 100644 --- a/src/singletons/thememanager.cpp +++ b/src/singletons/thememanager.cpp @@ -54,9 +54,10 @@ void ThemeManager::update() void ThemeManager::actuallyUpdate(double hue, double multiplier) { isLight = multiplier > 0; - bool isLightTabs; + bool lightWin = isLight; - QColor themeColor = QColor::fromHslF(hue, 0.5, 0.5); + QColor none(0, 0, 0, 0); + QColor themeColor = QColor::fromHslF(hue, 0.43, 0.5); QColor themeColorNoSat = QColor::fromHslF(hue, 0, 0.5); qreal sat = 0; @@ -66,48 +67,40 @@ void ThemeManager::actuallyUpdate(double hue, double multiplier) return QColor::fromHslF(h, s, ((l - 0.5) * multiplier) + 0.5, a); }; - //#ifdef USEWINSDK - // isLightTabs = isLight; - // QColor tabFg = isLight ? "#000" : "#fff"; - // this->windowBg = isLight ? "#fff" : getColor(0, sat, 0.9); - //#else - isLightTabs = true; - QColor tabFg = isLightTabs ? "#000" : "#fff"; - this->windowBg = "#fff"; - //#endif + /// WINDOW + { + QColor bg = this->window.background = lightWin ? "#fff" : "#444"; + QColor fg = this->window.text = lightWin ? "#000" : "#eee"; + this->window.borderFocused = lightWin ? "#ccc" : themeColor; + this->window.borderUnfocused = lightWin ? "#ccc" : themeColorNoSat; - // Ubuntu style - // TODO: add setting for this - // TabText = QColor(210, 210, 210); - // TabBackground = QColor(61, 60, 56); - // TabHoverText = QColor(210, 210, 210); - // TabHoverBackground = QColor(73, 72, 68); + // Ubuntu style + // TODO: add setting for this + // TabText = QColor(210, 210, 210); + // TabBackground = QColor(61, 60, 56); + // TabHoverText = QColor(210, 210, 210); + // TabHoverBackground = QColor(73, 72, 68); - // message (referenced later) - this->messages.textColors.caret = // - this->messages.textColors.regular = isLight ? "#000" : "#fff"; + // message (referenced later) + this->messages.textColors.caret = // + this->messages.textColors.regular = isLight ? "#000" : "#fff"; - // tabs - // text, {regular, hover, unfocused} - // this->windowBg = "#ccc"; + /// TABS + // text, {regular, hover, unfocused} - this->tabs.border = "#999"; - this->tabs.regular = {tabFg, {windowBg, blendColors(windowBg, "#999", 0.5), windowBg}}; - - this->tabs.selected = {"#fff", {themeColor, themeColor, QColor::fromHslF(hue, 0, 0.5)}}; - - this->tabs.newMessage = { - tabFg, - {QBrush(blendColors(themeColor, windowBg, 0.7), Qt::FDiagPattern), - QBrush(blendColors(themeColor, windowBg, 0.5), Qt::FDiagPattern), - QBrush(blendColors(themeColorNoSat, windowBg, 0.7), Qt::FDiagPattern)}}; - - this->tabs.highlighted = { - tabFg, - {blendColors(themeColor, windowBg, 0.7), blendColors(themeColor, windowBg, 0.5), - blendColors(themeColorNoSat, windowBg, 0.7)}}; - - // this->windowBg = "#fff"; + if (lightWin) { + this->tabs.regular = {fg, {bg, "#ccc", bg}}; + this->tabs.newMessage = {fg, {bg, "#ccc", bg}}; + this->tabs.highlighted = {fg, {bg, "#ccc", bg}}; + this->tabs.selected = {"#fff", {"#333", "#333", "#666"}}; + } else { + this->tabs.regular = {fg, {bg, "#555", bg}}; + this->tabs.newMessage = {fg, {bg, "#555", bg}}; + this->tabs.highlighted = {fg, {bg, "#555", bg}}; + // this->tabs.selected = {"#000", {themeColor, themeColor, themeColorNoSat}}; + this->tabs.selected = {"#000", {"#999", "#999", "#888"}}; + } + } // Split bool flat = isLight; diff --git a/src/singletons/thememanager.hpp b/src/singletons/thememanager.hpp index e0b67e0c..664f9713 100644 --- a/src/singletons/thememanager.hpp +++ b/src/singletons/thememanager.hpp @@ -32,6 +32,15 @@ public: } backgrounds; }; + /// WINDOW + struct { + QColor background; + QColor text; + QColor borderUnfocused; + QColor borderFocused; + } window; + + /// TABS struct { TabColors regular; TabColors selected; @@ -40,6 +49,7 @@ public: QColor border; } tabs; + /// SPLITS struct { QColor messageSeperator; QColor background; @@ -64,6 +74,7 @@ public: } input; } splits; + /// MESSAGES struct { struct { QColor regular; @@ -85,6 +96,7 @@ public: QColor selection; } messages; + /// SCROLLBAR struct { QColor background; QColor thumb; @@ -93,14 +105,12 @@ public: // QColor highlights[3]; } scrollbars; + /// TOOLTIP struct { QColor text; QColor background; } tooltip; - QColor windowBg; - QColor windowText; - void normalizeColor(QColor &color); void update(); diff --git a/src/widgets/basewindow.cpp b/src/widgets/basewindow.cpp index cb92ddc1..950fd679 100644 --- a/src/widgets/basewindow.cpp +++ b/src/widgets/basewindow.cpp @@ -160,12 +160,12 @@ void BaseWindow::themeRefreshEvent() { if (this->enableCustomFrame) { QPalette palette; - palette.setColor(QPalette::Background, this->themeManager.windowBg); - palette.setColor(QPalette::Foreground, this->themeManager.windowText); + palette.setColor(QPalette::Background, this->themeManager.window.background); + palette.setColor(QPalette::Foreground, this->themeManager.window.text); this->setPalette(palette); for (RippleEffectButton *button : this->buttons) { - button->setMouseEffectColor(this->themeManager.windowText); + button->setMouseEffectColor(this->themeManager.window.text); } } } @@ -408,15 +408,22 @@ void BaseWindow::paintEvent(QPaintEvent *event) bool windowFocused = this->window() == QApplication::activeWindow(); - QLinearGradient gradient(0, 0, 10, 250); - gradient.setColorAt(1, this->themeManager.tabs.selected.backgrounds.unfocused.color()); + // QLinearGradient gradient(0, 0, 10, 250); + // gradient.setColorAt(1, + // this->themeManager.tabs.selected.backgrounds.unfocused.color()); - if (windowFocused) { - gradient.setColorAt(.4, this->themeManager.tabs.selected.backgrounds.regular.color()); - } else { - gradient.setColorAt(.4, this->themeManager.tabs.selected.backgrounds.unfocused.color()); - } - painter.setPen(QPen(QBrush(gradient), 1)); + // if (windowFocused) { + // gradient.setColorAt(.4, + // this->themeManager.tabs.selected.backgrounds.regular.color()); + // } else { + // gradient.setColorAt(.4, + // this->themeManager.tabs.selected.backgrounds.unfocused.color()); + // } + // painter.setPen(QPen(QBrush(gradient), 1)); + + QColor &border = windowFocused ? this->themeManager.window.borderFocused + : this->themeManager.window.borderUnfocused; + painter.setPen(QPen(QBrush(border), 1)); painter.drawRect(0, 0, this->width() - 1, this->height() - 1); } diff --git a/src/widgets/helper/notebookbutton.cpp b/src/widgets/helper/notebookbutton.cpp index be07b2f8..eb7bf687 100644 --- a/src/widgets/helper/notebookbutton.cpp +++ b/src/widgets/helper/notebookbutton.cpp @@ -17,11 +17,14 @@ namespace widgets { NotebookButton::NotebookButton(BaseWidget *parent) : RippleEffectButton(parent) { - setMouseEffectColor(QColor(0, 0, 0)); - this->setAcceptDrops(true); } +void NotebookButton::themeRefreshEvent() +{ + this->setMouseEffectColor(this->themeManager.tabs.regular.text); +} + void NotebookButton::paintEvent(QPaintEvent *) { QPainter painter(this); @@ -30,15 +33,14 @@ void NotebookButton::paintEvent(QPaintEvent *) QColor foreground; if (mouseDown || mouseOver) { - background = this->themeManager.tabs.regular.backgrounds.regular.color(); + background = this->themeManager.tabs.regular.backgrounds.hover.color(); foreground = this->themeManager.tabs.regular.text; } else { background = this->themeManager.tabs.regular.backgrounds.regular.color(); - foreground = QColor(70, 80, 80); + foreground = this->themeManager.tabs.regular.text; } painter.setPen(Qt::NoPen); - // painter.fillRect(this->rect(), background); float h = height(), w = width(); diff --git a/src/widgets/helper/notebookbutton.hpp b/src/widgets/helper/notebookbutton.hpp index a62b8002..3a53af51 100644 --- a/src/widgets/helper/notebookbutton.hpp +++ b/src/widgets/helper/notebookbutton.hpp @@ -21,6 +21,7 @@ public: NotebookButton(BaseWidget *parent); protected: + virtual void themeRefreshEvent() override; virtual void paintEvent(QPaintEvent *) override; virtual void mouseReleaseEvent(QMouseEvent *) override; virtual void dragEnterEvent(QDragEnterEvent *) override; diff --git a/src/widgets/helper/notebooktab.cpp b/src/widgets/helper/notebooktab.cpp index 21961c0a..f03c2ea9 100644 --- a/src/widgets/helper/notebooktab.cpp +++ b/src/widgets/helper/notebooktab.cpp @@ -209,13 +209,13 @@ void NotebookTab::paintEvent(QPaintEvent *) painter.fillRect(rect(), tabBackground); // draw border - painter.setPen(QPen("#ccc")); - QPainterPath path(QPointF(0, height)); - path.lineTo(0, 0); - path.lineTo(this->width() - 1, 0); - path.lineTo(this->width() - 1, this->height() - 1); - path.lineTo(0, this->height() - 1); - painter.drawPath(path); + // painter.setPen(QPen("#ccc")); + // QPainterPath path(QPointF(0, height)); + // path.lineTo(0, 0); + // path.lineTo(this->width() - 1, 0); + // path.lineTo(this->width() - 1, this->height() - 1); + // path.lineTo(0, this->height() - 1); + // painter.drawPath(path); } else { // QPainterPath path(QPointF(0, height)); // path.lineTo(8 * scale, 0); diff --git a/src/widgets/helper/titlebarbutton.cpp b/src/widgets/helper/titlebarbutton.cpp index d3b2cd34..987cc8b3 100644 --- a/src/widgets/helper/titlebarbutton.cpp +++ b/src/widgets/helper/titlebarbutton.cpp @@ -1,5 +1,7 @@ #include "titlebarbutton.hpp" +#include "singletons/thememanager.hpp" + namespace chatterino { namespace widgets { @@ -23,8 +25,8 @@ void TitleBarButton::paintEvent(QPaintEvent *) { QPainter painter(this); - QColor color = "#000"; - QColor background = "#fff"; + QColor color = this->themeManager.window.text; + QColor background = this->themeManager.window.background; int xD = this->height() / 3; int centerX = this->width() / 2; @@ -59,7 +61,8 @@ void TitleBarButton::paintEvent(QPaintEvent *) break; } case User: { - color = QColor("#333"); + // color = QColor("#333"); + color = "#999"; painter.setRenderHint(QPainter::Antialiasing); painter.setRenderHint(QPainter::HighQualityAntialiasing); @@ -85,7 +88,8 @@ void TitleBarButton::paintEvent(QPaintEvent *) break; } case Settings: { - color = QColor("#333"); + // color = QColor("#333"); + color = "#999"; painter.setRenderHint(QPainter::Antialiasing); painter.setRenderHint(QPainter::HighQualityAntialiasing); diff --git a/src/widgets/splitcontainer.cpp b/src/widgets/splitcontainer.cpp index be45f987..7689a3d7 100644 --- a/src/widgets/splitcontainer.cpp +++ b/src/widgets/splitcontainer.cpp @@ -414,7 +414,7 @@ void SplitContainer::paintEvent(QPaintEvent *) ? this->themeManager.tabs.selected.backgrounds.regular : this->themeManager.tabs.selected.backgrounds.unfocused); - painter.fillRect(0, 0, width(), 2, accentColor); + painter.fillRect(0, 0, width(), 1, accentColor); } void SplitContainer::showEvent(QShowEvent *event) From c2d1d8bbec6c0e98e564ac56936383121ef3f193 Mon Sep 17 00:00:00 2001 From: pajlada Date: Fri, 6 Apr 2018 01:44:49 +0200 Subject: [PATCH 31/69] Add Ubuntu 18.04 installation instructions --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index c19ec2c1..d281b1fc 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,12 @@ Be sure to add "-j " as a make argument so it will use all y 3. copy `include/rapidjson` from [rapidjson](https://github.com/miloyip/rapidjson/releases/latest) into the chatterino directory so that the file `/rapidjson/document.h` exists 4. open `chatterino.pro` with QT Creator and build +#### Ubuntu 18.04.2 +*most likely works the same for other Debian-like distros* +1. Install dependencies (and the C++ IDE Qt Creator) `sudo apt install qtcreator qtmultimedia5-dev libqt5svg5-dev libboost-dev` +2. Install rapidjson to `/usr/local/` like this: From the Chatterino2 root folder: `sudo cp -r lib/rapidjson/include/rapidjson /usr/local/include`. If you want to install it to another place, you have to make sure it's in the chatterino.pro include path +3. open `chatterino.pro` with QT Creator and build + #### Arch Linux install [chatterino2-git](https://aur.archlinux.org/packages/chatterino2-git/) from the aur or build manually as follows: 1. `sudo pacman -S qt5-base qt5-multimedia gst-plugins-ugly gst-plugins-good boost rapidjson` From 3adec1ae894a2cfba1d0565d27a70c5d63d0515d Mon Sep 17 00:00:00 2001 From: pajlada Date: Fri, 6 Apr 2018 01:46:04 +0200 Subject: [PATCH 32/69] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d281b1fc..2160a620 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ Be sure to add "-j " as a make argument so it will use all y 3. copy `include/rapidjson` from [rapidjson](https://github.com/miloyip/rapidjson/releases/latest) into the chatterino directory so that the file `/rapidjson/document.h` exists 4. open `chatterino.pro` with QT Creator and build -#### Ubuntu 18.04.2 +#### Ubuntu 18.04 *most likely works the same for other Debian-like distros* 1. Install dependencies (and the C++ IDE Qt Creator) `sudo apt install qtcreator qtmultimedia5-dev libqt5svg5-dev libboost-dev` 2. Install rapidjson to `/usr/local/` like this: From the Chatterino2 root folder: `sudo cp -r lib/rapidjson/include/rapidjson /usr/local/include`. If you want to install it to another place, you have to make sure it's in the chatterino.pro include path From 68227fa576f461dda99e7ed0013021dc28a93f15 Mon Sep 17 00:00:00 2001 From: fourtf Date: Fri, 6 Apr 2018 01:57:32 +0200 Subject: [PATCH 33/69] repaint tabs when text changes --- src/widgets/helper/notebooktab.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/widgets/helper/notebooktab.cpp b/src/widgets/helper/notebooktab.cpp index f03c2ea9..de26c24c 100644 --- a/src/widgets/helper/notebooktab.cpp +++ b/src/widgets/helper/notebooktab.cpp @@ -103,9 +103,13 @@ QString NotebookTab::getTitle() const void NotebookTab::setTitle(const QString &newTitle) { - this->title = newTitle.toStdString(); + auto stdTitle = newTitle.toStdString(); - this->updateSize(); + if (this->title != stdTitle) { + this->title = stdTitle; + this->updateSize(); + this->update(); + } } bool NotebookTab::isSelected() const From 86c844c791517ba67ff87b1fc1f11cea19eda44c Mon Sep 17 00:00:00 2001 From: fourtf Date: Fri, 6 Apr 2018 16:37:30 +0200 Subject: [PATCH 34/69] added debug information on F10 --- chatterino.pro | 8 ++- lib/settings | 2 +- src/messages/image.cpp | 18 ++++++ src/messages/image.hpp | 3 +- src/messages/layouts/messagelayout.cpp | 6 ++ src/messages/layouts/messagelayout.hpp | 1 + src/messages/layouts/messagelayoutelement.cpp | 7 +++ src/messages/layouts/messagelayoutelement.hpp | 2 +- src/messages/message.hpp | 12 ++++ src/messages/messageelement.cpp | 6 ++ src/messages/messageelement.hpp | 2 +- src/util/debugcount.cpp | 10 ++++ src/util/debugcount.hpp | 59 +++++++++++++++++++ src/widgets/helper/channelview.cpp | 8 ++- src/widgets/helper/debugpopup.cpp | 30 ++++++++++ src/widgets/helper/debugpopup.hpp | 15 +++++ src/widgets/split.cpp | 8 +++ src/widgets/split.hpp | 4 ++ src/widgets/splitcontainer.cpp | 2 +- 19 files changed, 192 insertions(+), 11 deletions(-) create mode 100644 src/util/debugcount.cpp create mode 100644 src/util/debugcount.hpp create mode 100644 src/widgets/helper/debugpopup.cpp create mode 100644 src/widgets/helper/debugpopup.hpp diff --git a/chatterino.pro b/chatterino.pro index 1665eef0..62a5b2c2 100644 --- a/chatterino.pro +++ b/chatterino.pro @@ -178,7 +178,9 @@ SOURCES += \ src/providers/irc/ircchannel2.cpp \ src/util/streamlink.cpp \ src/providers/twitch/twitchhelpers.cpp \ - src/widgets/helper/signallabel.cpp + src/widgets/helper/signallabel.cpp \ + src/widgets/helper/debugpopup.cpp \ + src/util/debugcount.cpp HEADERS += \ src/precompiled_header.hpp \ @@ -292,7 +294,9 @@ HEADERS += \ src/providers/irc/ircserver.hpp \ src/providers/irc/ircchannel2.hpp \ src/util/streamlink.hpp \ - src/providers/twitch/twitchhelpers.hpp + src/providers/twitch/twitchhelpers.hpp \ + src/util/debugcount.hpp \ + src/widgets/helper/debugpopup.hpp RESOURCES += \ resources/resources.qrc diff --git a/lib/settings b/lib/settings index ad31b388..2fa3adf4 160000 --- a/lib/settings +++ b/lib/settings @@ -1 +1 @@ -Subproject commit ad31b38866d80a17ced902476ed06da69edce3a0 +Subproject commit 2fa3adf42da988dc2a34b9b625654aa08e906d4f diff --git a/src/messages/image.cpp b/src/messages/image.cpp index 0792d8c3..57c09062 100644 --- a/src/messages/image.cpp +++ b/src/messages/image.cpp @@ -30,6 +30,7 @@ Image::Image(const QString &url, qreal scale, const QString &name, const QString , scale(scale) , isLoading(false) { + util::DebugCount::increase("images"); } Image::Image(QPixmap *image, qreal scale, const QString &name, const QString &tooltip, @@ -43,6 +44,20 @@ Image::Image(QPixmap *image, qreal scale, const QString &name, const QString &to , isLoading(true) , isLoaded(true) { + util::DebugCount::increase("images"); +} + +Image::~Image() +{ + util::DebugCount::decrease("images"); + + if (this->isAnimated()) { + util::DebugCount::decrease("animated images"); + } + + if (this->isLoaded) { + util::DebugCount::decrease("loaded images"); + } } void Image::loadImage() @@ -79,11 +94,14 @@ void Image::loadImage() if (lli->allFrames.size() > 1) { lli->animated = true; + + util::DebugCount::increase("animated images"); } lli->currentPixmap = lli->loadedPixmap; lli->isLoaded = true; + util::DebugCount::increase("loaded images"); singletons::EmoteManager::getInstance().incGeneration(); diff --git a/src/messages/image.hpp b/src/messages/image.hpp index f107ed76..f5b340e7 100644 --- a/src/messages/image.hpp +++ b/src/messages/image.hpp @@ -12,8 +12,6 @@ namespace messages { class Image : public QObject, boost::noncopyable { public: - Image() = delete; - explicit Image(const QString &_url, qreal _scale = 1, const QString &_name = "", const QString &_tooltip = "", const QMargins &_margin = QMargins(), bool isHat = false); @@ -21,6 +19,7 @@ public: explicit Image(QPixmap *_currentPixmap, qreal _scale = 1, const QString &_name = "", const QString &_tooltip = "", const QMargins &_margin = QMargins(), bool isHat = false); + ~Image(); const QPixmap *getPixmap(); qreal getScale() const; diff --git a/src/messages/layouts/messagelayout.cpp b/src/messages/layouts/messagelayout.cpp index 7da65450..eca39b64 100644 --- a/src/messages/layouts/messagelayout.cpp +++ b/src/messages/layouts/messagelayout.cpp @@ -25,6 +25,12 @@ MessageLayout::MessageLayout(MessagePtr _message) if (_message->flags & Message::Collapsed) { this->flags &= MessageLayout::Collapsed; } + util::DebugCount::increase("message layout"); +} + +MessageLayout::~MessageLayout() +{ + util::DebugCount::decrease("message layout"); } Message *MessageLayout::getMessage() diff --git a/src/messages/layouts/messagelayout.hpp b/src/messages/layouts/messagelayout.hpp index 09dd2e61..82bfaea5 100644 --- a/src/messages/layouts/messagelayout.hpp +++ b/src/messages/layouts/messagelayout.hpp @@ -22,6 +22,7 @@ public: enum Flags : uint8_t { Collapsed, RequiresBufferUpdate, RequiresLayout }; MessageLayout(MessagePtr message); + ~MessageLayout(); Message *getMessage(); diff --git a/src/messages/layouts/messagelayoutelement.cpp b/src/messages/layouts/messagelayoutelement.cpp index cf43237c..0d4d6b1a 100644 --- a/src/messages/layouts/messagelayoutelement.cpp +++ b/src/messages/layouts/messagelayoutelement.cpp @@ -1,5 +1,6 @@ #include "messages/layouts/messagelayoutelement.hpp" #include "messages/messageelement.hpp" +#include "util/debugcount.hpp" #include #include @@ -17,6 +18,12 @@ MessageLayoutElement::MessageLayoutElement(MessageElement &_creator, const QSize : creator(_creator) { this->rect.setSize(size); + util::DebugCount::increase("message layout elements"); +} + +MessageLayoutElement::~MessageLayoutElement() +{ + util::DebugCount::decrease("message layout elements"); } MessageElement &MessageLayoutElement::getCreator() const diff --git a/src/messages/layouts/messagelayoutelement.hpp b/src/messages/layouts/messagelayoutelement.hpp index 646c44c7..1f98b6cd 100644 --- a/src/messages/layouts/messagelayoutelement.hpp +++ b/src/messages/layouts/messagelayoutelement.hpp @@ -24,7 +24,7 @@ class MessageLayoutElement : boost::noncopyable { public: MessageLayoutElement(MessageElement &creator, const QSize &size); - virtual ~MessageLayoutElement() = default; + virtual ~MessageLayoutElement(); const QRect &getRect() const; MessageElement &getCreator() const; diff --git a/src/messages/message.hpp b/src/messages/message.hpp index 56afc2b5..2d3ee697 100644 --- a/src/messages/message.hpp +++ b/src/messages/message.hpp @@ -10,10 +10,22 @@ #include #include +#include "util/debugcount.hpp" + namespace chatterino { namespace messages { struct Message { + Message() + { + util::DebugCount::increase("messages"); + } + + ~Message() + { + util::DebugCount::decrease("messages"); + } + enum MessageFlags : uint16_t { None = 0, System = (1 << 0), diff --git a/src/messages/messageelement.cpp b/src/messages/messageelement.cpp index 85b0e4e9..faf3c00b 100644 --- a/src/messages/messageelement.cpp +++ b/src/messages/messageelement.cpp @@ -11,6 +11,12 @@ namespace messages { MessageElement::MessageElement(Flags _flags) : flags(_flags) { + util::DebugCount::increase("message elements"); +} + +MessageElement::~MessageElement() +{ + util::DebugCount::decrease("message elements"); } MessageElement *MessageElement::setLink(const Link &_link) diff --git a/src/messages/messageelement.hpp b/src/messages/messageelement.hpp index e943b0e7..2f281c12 100644 --- a/src/messages/messageelement.hpp +++ b/src/messages/messageelement.hpp @@ -110,7 +110,7 @@ public: Update_All = Update_Text | Update_Emotes | Update_Images }; - virtual ~MessageElement() = default; + virtual ~MessageElement(); MessageElement *setLink(const Link &link); MessageElement *setTooltip(const QString &tooltip); diff --git a/src/util/debugcount.cpp b/src/util/debugcount.cpp new file mode 100644 index 00000000..a8a45435 --- /dev/null +++ b/src/util/debugcount.cpp @@ -0,0 +1,10 @@ +#include "debugcount.hpp" + +namespace chatterino { +namespace util { + +QMap DebugCount::counts; +std::mutex DebugCount::mut; + +} // namespace util +} // namespace chatterino diff --git a/src/util/debugcount.hpp b/src/util/debugcount.hpp new file mode 100644 index 00000000..7aae6ebc --- /dev/null +++ b/src/util/debugcount.hpp @@ -0,0 +1,59 @@ +#pragma once + +#include +#include + +#include +#include + +namespace chatterino { +namespace util { + +class DebugCount +{ + static QMap counts; + static std::mutex mut; + +public: + static void increase(const QString &name) + { + std::lock_guard lock(mut); + + auto it = counts.find(name); + if (it == counts.end()) { + counts.insert(name, 1); + } else { + reinterpret_cast(it.value())++; + } + } + + static void decrease(const QString &name) + { + std::lock_guard lock(mut); + + auto it = counts.find(name); + if (it == counts.end()) { + counts.insert(name, -1); + } else { + reinterpret_cast(it.value())--; + } + } + + static QString getDebugText() + { + std::lock_guard lock(mut); + + QString text; + for (auto it = counts.begin(); it != counts.end(); it++) { + text += it.key() + ": " + QString::number(it.value()) + "\n"; + } + return text; + } + + QString toString() + { + } +}; + +} // namespace util +} // namespace chatterino diff --git a/src/widgets/helper/channelview.cpp b/src/widgets/helper/channelview.cpp index 2d12bf4d..a732bc1f 100644 --- a/src/widgets/helper/channelview.cpp +++ b/src/widgets/helper/channelview.cpp @@ -95,9 +95,11 @@ ChannelView::ChannelView(BaseWidget *parent) this->pauseTimeout.setSingleShot(true); - auto e = new QResizeEvent(this->size(), this->size()); - this->resizeEvent(e); - delete e; + // auto e = new QResizeEvent(this->size(), this->size()); + // this->resizeEvent(e); + // delete e; + + this->scrollBar.resize(this->scrollBar.width(), height()); singletons::SettingManager::getInstance().showLastMessageIndicator.connect( [this](auto, auto) { this->update(); }, this->managedConnections); diff --git a/src/widgets/helper/debugpopup.cpp b/src/widgets/helper/debugpopup.cpp new file mode 100644 index 00000000..d4ecc346 --- /dev/null +++ b/src/widgets/helper/debugpopup.cpp @@ -0,0 +1,30 @@ +#include "debugpopup.hpp" + +#include "util/debugcount.hpp" + +#include +#include +#include +#include + +namespace chatterino { +namespace widgets { + +DebugPopup::DebugPopup() +{ + auto *layout = new QHBoxLayout(this); + auto *text = new QLabel(this); + auto *timer = new QTimer(this); + + timer->setInterval(1000); + QObject::connect(timer, &QTimer::timeout, + [text] { text->setText(util::DebugCount::getDebugText()); }); + timer->start(); + + text->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); + + layout->addWidget(text); +} + +} // namespace widgets +} // namespace chatterino diff --git a/src/widgets/helper/debugpopup.hpp b/src/widgets/helper/debugpopup.hpp new file mode 100644 index 00000000..c9a4c743 --- /dev/null +++ b/src/widgets/helper/debugpopup.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include + +namespace chatterino { +namespace widgets { + +class DebugPopup : public QWidget +{ +public: + DebugPopup(); +}; + +} // namespace widgets +} // namespace chatterino diff --git a/src/widgets/split.cpp b/src/widgets/split.cpp index 7d669200..7cfad2b6 100644 --- a/src/widgets/split.cpp +++ b/src/widgets/split.cpp @@ -9,6 +9,7 @@ #include "singletons/windowmanager.hpp" #include "util/streamlink.hpp" #include "util/urlfetch.hpp" +#include "widgets/helper/debugpopup.hpp" #include "widgets/helper/searchpopup.hpp" #include "widgets/helper/shortcut.hpp" #include "widgets/qualitypopup.hpp" @@ -72,6 +73,13 @@ Split::Split(SplitContainer *parent, const std::string &_uuid) // CTRL+F: Search CreateShortcut(this, "CTRL+F", &Split::doSearch); + // F12 + CreateShortcut(this, "F10", [] { + auto *popup = new DebugPopup; + popup->setAttribute(Qt::WA_DeleteOnClose); + popup->show(); + }); + // xd // CreateShortcut(this, "ALT+SHIFT+RIGHT", &Split::doIncFlexX); // CreateShortcut(this, "ALT+SHIFT+LEFT", &Split::doDecFlexX); diff --git a/src/widgets/split.hpp b/src/widgets/split.hpp index 054513b2..38e2168b 100644 --- a/src/widgets/split.hpp +++ b/src/widgets/split.hpp @@ -22,6 +22,10 @@ namespace widgets { class SplitContainer; +class xD +{ +}; + // Each ChatWidget consists of three sub-elements that handle their own part of the chat widget: // ChatWidgetHeader // - Responsible for rendering which channel the ChatWidget is in, and the menu in the top-left of diff --git a/src/widgets/splitcontainer.cpp b/src/widgets/splitcontainer.cpp index 7689a3d7..b736397a 100644 --- a/src/widgets/splitcontainer.cpp +++ b/src/widgets/splitcontainer.cpp @@ -41,7 +41,7 @@ SplitContainer::SplitContainer(Notebook *parent, NotebookTab *_tab, const std::s this->setHidden(true); this->setAcceptDrops(true); - this->ui.parentLayout.addSpacing(2); + this->ui.parentLayout.addSpacing(1); this->ui.parentLayout.addLayout(&this->ui.hbox); this->ui.parentLayout.setMargin(0); From cc1e3c2f6fa7707d880f3c34c91191c86794ef49 Mon Sep 17 00:00:00 2001 From: fourtf Date: Fri, 6 Apr 2018 17:46:12 +0200 Subject: [PATCH 35/69] fixed an issue where normal emotes would be redrawn like gif emotes --- src/messages/image.cpp | 9 +++++++++ src/messages/layouts/messagelayout.cpp | 7 ++++++- src/messages/layouts/messagelayoutelement.cpp | 1 + 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/messages/image.cpp b/src/messages/image.cpp index 57c09062..c07ef71b 100644 --- a/src/messages/image.cpp +++ b/src/messages/image.cpp @@ -75,6 +75,15 @@ void Image::loadImage() bool first = true; + // clear stuff before loading the image again + lli->allFrames.clear(); + if (lli->isAnimated()) { + util::DebugCount::decrease("animated images"); + } + if (lli->isLoaded) { + util::DebugCount::decrease("loaded images"); + } + for (int index = 0; index < reader.imageCount(); ++index) { if (reader.read(&image)) { auto pixmap = new QPixmap(QPixmap::fromImage(image)); diff --git a/src/messages/layouts/messagelayout.cpp b/src/messages/layouts/messagelayout.cpp index eca39b64..48bac932 100644 --- a/src/messages/layouts/messagelayout.cpp +++ b/src/messages/layouts/messagelayout.cpp @@ -147,6 +147,7 @@ void MessageLayout::paint(QPainter &painter, int y, int messageIndex, Selection this->buffer = std::shared_ptr(pixmap); this->bufferValid = false; + util::DebugCount::increase("message drawing buffers"); } if (!this->bufferValid || !selection.isEmpty()) { @@ -221,7 +222,11 @@ void MessageLayout::invalidateBuffer() void MessageLayout::deleteBuffer() { - this->buffer = nullptr; + if (this->buffer != nullptr) { + util::DebugCount::decrease("message drawing buffers"); + + this->buffer = nullptr; + } } // Elements diff --git a/src/messages/layouts/messagelayoutelement.cpp b/src/messages/layouts/messagelayoutelement.cpp index 0d4d6b1a..61147a09 100644 --- a/src/messages/layouts/messagelayoutelement.cpp +++ b/src/messages/layouts/messagelayoutelement.cpp @@ -105,6 +105,7 @@ void ImageLayoutElement::paintAnimated(QPainter &painter, int yOffset) } if (this->image->isAnimated()) { + // qDebug() << this->image->getUrl(); auto pixmap = this->image->getPixmap(); if (pixmap != nullptr) { From d85dba3e0ea3d599ae682a81ccaa7e607b3526d2 Mon Sep 17 00:00:00 2001 From: fourtf Date: Fri, 6 Apr 2018 18:05:30 +0200 Subject: [PATCH 36/69] fixes #307 --- src/messages/layouts/messagelayoutcontainer.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/messages/layouts/messagelayoutcontainer.cpp b/src/messages/layouts/messagelayoutcontainer.cpp index 8ea48b45..c592b238 100644 --- a/src/messages/layouts/messagelayoutcontainer.cpp +++ b/src/messages/layouts/messagelayoutcontainer.cpp @@ -110,9 +110,8 @@ void MessageLayoutContainer::breakLine() for (size_t i = lineStart; i < this->elements.size(); i++) { MessageLayoutElement *element = this->elements.at(i).get(); - bool isCompactEmote = - !(this->flags & Message::DisableCompactEmotes) && - (this->flags & element->getCreator().getFlags()) & MessageElement::EmoteImages; + bool isCompactEmote = !(this->flags & Message::DisableCompactEmotes) && + element->getCreator().getFlags() & MessageElement::EmoteImages; int yExtra = 0; if (isCompactEmote) { From 4ec2c0d8b3d091be0d3c27d47402f674fb85d712 Mon Sep 17 00:00:00 2001 From: fourtf Date: Fri, 6 Apr 2018 18:27:49 +0200 Subject: [PATCH 37/69] added cooldown to layouting to reduce lag when opening the emojis tab --- src/widgets/helper/channelview.cpp | 38 +++++++++++++++++++++--------- src/widgets/helper/channelview.hpp | 3 +++ 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/widgets/helper/channelview.cpp b/src/widgets/helper/channelview.cpp index a732bc1f..177ecc88 100644 --- a/src/widgets/helper/channelview.cpp +++ b/src/widgets/helper/channelview.cpp @@ -83,15 +83,15 @@ ChannelView::ChannelView(BaseWidget *parent) }); }); - this->updateTimer.setInterval(1000 / 60); - this->updateTimer.setSingleShot(true); - connect(&this->updateTimer, &QTimer::timeout, this, [this] { - if (this->updateQueued) { - this->updateQueued = false; - this->repaint(); - this->updateTimer.start(); - } - }); + // this->updateTimer.setInterval(1000 / 60); + // this->updateTimer.setSingleShot(true); + // connect(&this->updateTimer, &QTimer::timeout, this, [this] { + // if (this->updateQueued) { + // this->updateQueued = false; + // this->repaint(); + // this->updateTimer.start(); + // } + // }); this->pauseTimeout.setSingleShot(true); @@ -99,10 +99,20 @@ ChannelView::ChannelView(BaseWidget *parent) // this->resizeEvent(e); // delete e; - this->scrollBar.resize(this->scrollBar.width(), height()); + this->scrollBar.resize(this->scrollBar.width(), height() + 1); singletons::SettingManager::getInstance().showLastMessageIndicator.connect( [this](auto, auto) { this->update(); }, this->managedConnections); + + this->layoutCooldown = new QTimer(this); + this->layoutCooldown->setSingleShot(true); + this->layoutCooldown->setInterval(66); + + QObject::connect(this->layoutCooldown, &QTimer::timeout, [this] { + if (this->layoutQueued) { + this->layoutMessages(); + } + }); } ChannelView::~ChannelView() @@ -140,7 +150,13 @@ void ChannelView::queueUpdate() void ChannelView::layoutMessages() { - this->actuallyLayoutMessages(); + if (!this->layoutCooldown->isActive()) { + this->actuallyLayoutMessages(); + + this->layoutCooldown->start(); + } else { + this->layoutQueued = true; + } } void ChannelView::actuallyLayoutMessages() diff --git a/src/widgets/helper/channelview.hpp b/src/widgets/helper/channelview.hpp index bc62fb87..0db184ac 100644 --- a/src/widgets/helper/channelview.hpp +++ b/src/widgets/helper/channelview.hpp @@ -77,6 +77,9 @@ protected: QPoint &relativePos, int &index); private: + QTimer *layoutCooldown; + bool layoutQueued; + QTimer updateTimer; bool updateQueued = false; bool messageWasAdded = false; From cb06579c29d0a767e6fafad3a899976a2cb15c05 Mon Sep 17 00:00:00 2001 From: fourtf Date: Fri, 6 Apr 2018 23:31:34 +0200 Subject: [PATCH 38/69] rewrote window saveing/serialization system fixes #212 --- src/application.cpp | 4 +- src/singletons/settingsmanager.cpp | 2 +- src/singletons/settingsmanager.hpp | 2 +- src/singletons/thememanager.cpp | 4 +- src/singletons/windowmanager.cpp | 180 +++++++++++++++++++++++++++-- src/singletons/windowmanager.hpp | 7 +- src/widgets/basewindow.cpp | 7 +- src/widgets/helper/channelview.cpp | 11 +- src/widgets/helper/notebooktab.cpp | 27 ++--- src/widgets/helper/notebooktab.hpp | 11 +- src/widgets/helper/splitheader.cpp | 2 +- src/widgets/notebook.cpp | 52 ++------- src/widgets/notebook.hpp | 21 ++-- src/widgets/split.cpp | 44 ++----- src/widgets/split.hpp | 11 +- src/widgets/splitcontainer.cpp | 109 ++++------------- src/widgets/splitcontainer.hpp | 13 +-- src/widgets/window.cpp | 72 ++++-------- src/widgets/window.hpp | 28 +---- 19 files changed, 291 insertions(+), 316 deletions(-) diff --git a/src/application.cpp b/src/application.cpp index 5f5f33c6..fbd8dacb 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -21,10 +21,10 @@ Application::Application() singletons::LoggingManager::getInstance(); - singletons::SettingManager::getInstance().init(); + singletons::SettingManager::getInstance().initialize(); singletons::CommandManager::getInstance().loadCommands(); - singletons::WindowManager::getInstance().initMainWindow(); + singletons::WindowManager::getInstance().initialize(); // Initialize everything we need singletons::EmoteManager::getInstance().loadGlobalEmotes(); diff --git a/src/singletons/settingsmanager.cpp b/src/singletons/settingsmanager.cpp index 9c697b6e..1c87499d 100644 --- a/src/singletons/settingsmanager.cpp +++ b/src/singletons/settingsmanager.cpp @@ -47,7 +47,7 @@ bool SettingManager::isIgnoredEmote(const QString &) return false; } -void SettingManager::init() +void SettingManager::initialize() { QString settingsPath = PathManager::getInstance().settingsFolderPath + "/settings.json"; diff --git a/src/singletons/settingsmanager.hpp b/src/singletons/settingsmanager.hpp index 0e397992..23b13b06 100644 --- a/src/singletons/settingsmanager.hpp +++ b/src/singletons/settingsmanager.hpp @@ -27,7 +27,7 @@ public: messages::MessageElement::Flags getWordFlags(); bool isIgnoredEmote(const QString &emote); - void init(); + void initialize(); /// Appearance BoolSetting showTimestamps = {"/appearance/messages/showTimestamps", true}; diff --git a/src/singletons/thememanager.cpp b/src/singletons/thememanager.cpp index 55d61212..1ef36383 100644 --- a/src/singletons/thememanager.cpp +++ b/src/singletons/thememanager.cpp @@ -129,8 +129,8 @@ void ThemeManager::actuallyUpdate(double hue, double multiplier) this->messages.textColors.system = QColor(140, 127, 127); this->messages.backgrounds.regular = splits.background; - this->messages.backgrounds.highlighted = blendColors( - this->tabs.selected.backgrounds.regular.color(), this->messages.backgrounds.regular, 0.8); + this->messages.backgrounds.highlighted = + blendColors(themeColor, this->messages.backgrounds.regular, 0.8); // this->messages.backgrounds.resub // this->messages.backgrounds.whisper this->messages.disabled = getColor(0, sat, 1, 0.6); diff --git a/src/singletons/windowmanager.cpp b/src/singletons/windowmanager.cpp index bc601bec..8f8ce007 100644 --- a/src/singletons/windowmanager.cpp +++ b/src/singletons/windowmanager.cpp @@ -1,12 +1,19 @@ #include "windowmanager.hpp" #include "debug/log.hpp" +#include "providers/twitch/twitchserver.hpp" #include "singletons/fontmanager.hpp" +#include "singletons/pathmanager.hpp" #include "singletons/thememanager.hpp" #include "widgets/accountswitchpopupwidget.hpp" #include "widgets/settingsdialog.hpp" +#include +#include + #include +#define SETTINGS_FILENAME "/layout.json" + namespace chatterino { namespace singletons { @@ -51,11 +58,6 @@ WindowManager::WindowManager(ThemeManager &_themeManager) _themeManager.repaintVisibleChatWidgets.connect([this] { this->repaintVisibleChatWidgets(); }); } -void WindowManager::initMainWindow() -{ - this->selectedWindow = this->mainWindow = new widgets::Window("main", this->themeManager, true); -} - void WindowManager::layoutVisibleChatWidgets(Channel *channel) { this->layout.invoke(channel); @@ -90,12 +92,12 @@ widgets::Window &WindowManager::getSelectedWindow() return *this->selectedWindow; } -widgets::Window &WindowManager::createWindow() +widgets::Window &WindowManager::createWindow(widgets::Window::WindowType type) { - auto *window = new widgets::Window("external", this->themeManager, false); - window->getNotebook().addNewPage(); + auto *window = new widgets::Window(this->themeManager, type); this->windows.push_back(window); + window->show(); return *window; } @@ -115,14 +117,168 @@ widgets::Window *WindowManager::windowAt(int index) return this->windows.at(index); } +void WindowManager::initialize() +{ + assert(!this->initialized); + + // load file + QString settingsPath = PathManager::getInstance().settingsFolderPath + SETTINGS_FILENAME; + QFile file(settingsPath); + file.open(QIODevice::ReadOnly); + QByteArray data = file.readAll(); + QJsonDocument document = QJsonDocument::fromJson(data); + QJsonArray windows_arr = document.object().value("windows").toArray(); + + // "deserialize" + for (QJsonValue window_val : windows_arr) { + QJsonObject window_obj = window_val.toObject(); + + // get type + QString type_val = window_obj.value("type").toString(); + widgets::Window::WindowType type = + type_val == "main" ? widgets::Window::Main : widgets::Window::Popup; + + if (type == widgets::Window::Main && mainWindow != nullptr) { + type = widgets::Window::Popup; + } + + widgets::Window &window = createWindow(type); + + if (type == widgets::Window::Main) { + mainWindow = &window; + } + + // get geometry + { + int x = window_obj.value("x").toInt(-1); + int y = window_obj.value("y").toInt(-1); + int width = window_obj.value("width").toInt(-1); + int height = window_obj.value("height").toInt(-1); + + if (x != -1 && y != -1 && width != -1 && height != -1) { + window.setGeometry(x, y, width, height); + } + } + + // load tabs + QJsonArray tabs = window_obj.value("tabs").toArray(); + for (QJsonValue tab_val : tabs) { + widgets::SplitContainer *tab = window.getNotebook().addNewPage(); + + QJsonObject tab_obj = tab_val.toObject(); + + // set custom title + QJsonValue title_val = tab_obj.value("title"); + if (title_val.isString()) { + tab->getTab()->setTitle(title_val.toString()); + tab->getTab()->useDefaultTitle = false; + } + + // load splits + int colNr = 0; + for (QJsonValue column_val : tab_obj.value("splits").toArray()) { + for (QJsonValue split_val : column_val.toArray()) { + widgets::Split *split = new widgets::Split(tab); + + QJsonObject split_obj = split_val.toObject(); + QJsonValue channelName_val = split_obj.value("channelName"); + if (channelName_val.isString()) { + split->setChannel(providers::twitch::TwitchServer::getInstance().addChannel( + channelName_val.toString())); + } + + tab->addToLayout(split, std::make_pair(colNr, -1)); + } + colNr++; + } + } + } + + if (mainWindow == nullptr) { + mainWindow = &createWindow(widgets::Window::Main); + mainWindow->getNotebook().addNewPage(true); + } + + this->initialized = true; +} + void WindowManager::save() { - assert(this->mainWindow); - - this->mainWindow->save(); + QJsonDocument document; + // "serialize" + QJsonArray window_arr; for (widgets::Window *window : this->windows) { - window->save(); + QJsonObject window_obj; + + // window type + switch (window->getType()) { + case widgets::Window::Main: + window_obj.insert("type", "main"); + break; + case widgets::Window::Popup: + window_obj.insert("type", "popup"); + break; + } + + // window geometry + window_obj.insert("x", window->x()); + window_obj.insert("y", window->y()); + window_obj.insert("width", window->width()); + window_obj.insert("height", window->height()); + + // window tabs + QJsonArray tabs_arr; + + for (int tab_i = 0; tab_i < window->getNotebook().tabCount(); tab_i++) { + QJsonObject tab_obj; + widgets::SplitContainer *tab = window->getNotebook().tabAt(tab_i); + + // custom tab title + if (!tab->getTab()->useDefaultTitle) { + tab_obj.insert("title", tab->getTab()->getTitle()); + } + + // splits + QJsonArray columns_arr; + std::vector> columns = tab->getColumns(); + + for (std::vector &cells : columns) { + QJsonArray cells_arr; + + for (widgets::Split *cell : cells) { + QJsonObject cell_obj; + cell_obj.insert("channelName", cell->getChannel()->name); + + cells_arr.append(cell_obj); + } + columns_arr.append(cells_arr); + } + + tab_obj.insert("splits", columns_arr); + tabs_arr.append(tab_obj); + } + + window_obj.insert("tabs", tabs_arr); + window_arr.append(window_obj); + } + + QJsonObject obj; + obj.insert("windows", window_arr); + document.setObject(obj); + + // save file + QString settingsPath = PathManager::getInstance().settingsFolderPath + SETTINGS_FILENAME; + QFile file(settingsPath); + file.open(QIODevice::WriteOnly | QIODevice::Truncate); + file.write(document.toJson()); + file.flush(); +} + +void WindowManager::closeAll() +{ + for (widgets::Window *window : windows) { + window->close(); } } diff --git a/src/singletons/windowmanager.hpp b/src/singletons/windowmanager.hpp index c95984d2..349de4cc 100644 --- a/src/singletons/windowmanager.hpp +++ b/src/singletons/windowmanager.hpp @@ -17,7 +17,6 @@ public: void showSettingsDialog(); void showAccountSelectPopup(QPoint point); - void initMainWindow(); void layoutVisibleChatWidgets(Channel *channel = nullptr); void repaintVisibleChatWidgets(Channel *channel = nullptr); void repaintGifEmotes(); @@ -25,12 +24,14 @@ public: widgets::Window &getMainWindow(); widgets::Window &getSelectedWindow(); - widgets::Window &createWindow(); + widgets::Window &createWindow(widgets::Window::WindowType type); int windowCount(); widgets::Window *windowAt(int index); void save(); + void initialize(); + void closeAll(); pajlada::Signals::NoArgSignal repaintGifs; pajlada::Signals::Signal layout; @@ -38,6 +39,8 @@ public: private: ThemeManager &themeManager; + bool initialized = false; + std::vector windows; widgets::Window *mainWindow = nullptr; diff --git a/src/widgets/basewindow.cpp b/src/widgets/basewindow.cpp index 950fd679..97e6483f 100644 --- a/src/widgets/basewindow.cpp +++ b/src/widgets/basewindow.cpp @@ -69,7 +69,12 @@ void BaseWindow::init() layout->addLayout(buttonLayout); // title - QLabel *title = new QLabel(" Chatterino"); + // QLabel *title = new QLabel(" Chatterino"); + QLabel *title = new QLabel(""); + QSizePolicy policy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); + policy.setHorizontalStretch(1); + title->setBaseSize(0, 0); + title->setSizePolicy(policy); buttonLayout->addWidget(title); this->titleLabel = title; diff --git a/src/widgets/helper/channelview.cpp b/src/widgets/helper/channelview.cpp index 177ecc88..a0733740 100644 --- a/src/widgets/helper/channelview.cpp +++ b/src/widgets/helper/channelview.cpp @@ -111,6 +111,7 @@ ChannelView::ChannelView(BaseWidget *parent) QObject::connect(this->layoutCooldown, &QTimer::timeout, [this] { if (this->layoutQueued) { this->layoutMessages(); + this->layoutQueued = false; } }); } @@ -137,15 +138,15 @@ void ChannelView::themeRefreshEvent() void ChannelView::queueUpdate() { - if (this->updateTimer.isActive()) { - this->updateQueued = true; - return; - } + // if (this->updateTimer.isActive()) { + // this->updateQueued = true; + // return; + // } // this->repaint(); this->update(); - this->updateTimer.start(); + // this->updateTimer.start(); } void ChannelView::layoutMessages() diff --git a/src/widgets/helper/notebooktab.cpp b/src/widgets/helper/notebooktab.cpp index de26c24c..36870bc5 100644 --- a/src/widgets/helper/notebooktab.cpp +++ b/src/widgets/helper/notebooktab.cpp @@ -17,14 +17,10 @@ namespace chatterino { namespace widgets { -NotebookTab::NotebookTab(Notebook *_notebook, const std::string &_uuid) +NotebookTab::NotebookTab(Notebook *_notebook) : BaseWidget(_notebook) - , uuid(_uuid) - , settingRoot(fS("/containers/{}/tab", this->uuid)) , positionChangedAnimation(this, "pos") , notebook(_notebook) - , title(fS("{}/title", this->settingRoot), "") - , useDefaultBehaviour(fS("{}/useDefaultBehaviour", this->settingRoot), true) , menu(this) { this->setAcceptDrops(true); @@ -40,7 +36,7 @@ NotebookTab::NotebookTab(Notebook *_notebook, const std::string &_uuid) TextInputDialog d(this); d.setWindowTitle("Change tab title (Leave empty for default behaviour)"); - if (this->useDefaultBehaviour) { + if (this->useDefaultTitle) { d.setText(""); } else { d.setText(this->getTitle()); @@ -49,10 +45,10 @@ NotebookTab::NotebookTab(Notebook *_notebook, const std::string &_uuid) if (d.exec() == QDialog::Accepted) { QString newTitle = d.getText(); if (newTitle.isEmpty()) { - this->useDefaultBehaviour = true; + this->useDefaultTitle = true; this->page->refreshTitle(); } else { - this->useDefaultBehaviour = false; + this->useDefaultTitle = false; this->setTitle(newTitle); } } @@ -82,11 +78,10 @@ void NotebookTab::updateSize() int width; - QString qTitle(qS(this->title)); if (singletons::SettingManager::getInstance().hideTabX) { - width = (int)((fontMetrics().width(qTitle) + 16 /*+ 16*/) * scale); + width = (int)((fontMetrics().width(this->title) + 16 /*+ 16*/) * scale); } else { - width = (int)((fontMetrics().width(qTitle) + 8 + 24 /*+ 16*/) * scale); + width = (int)((fontMetrics().width(this->title) + 8 + 24 /*+ 16*/) * scale); } this->resize(std::min((int)(150 * scale), width), (int)(24 * scale)); @@ -96,17 +91,15 @@ void NotebookTab::updateSize() } } -QString NotebookTab::getTitle() const +const QString &NotebookTab::getTitle() const { - return qS(this->title); + return this->title; } void NotebookTab::setTitle(const QString &newTitle) { - auto stdTitle = newTitle.toStdString(); - - if (this->title != stdTitle) { - this->title = stdTitle; + if (this->title != newTitle) { + this->title = newTitle; this->updateSize(); this->update(); } diff --git a/src/widgets/helper/notebooktab.hpp b/src/widgets/helper/notebooktab.hpp index c474e705..2f871dd2 100644 --- a/src/widgets/helper/notebooktab.hpp +++ b/src/widgets/helper/notebooktab.hpp @@ -18,17 +18,14 @@ class NotebookTab : public BaseWidget { Q_OBJECT - const std::string uuid; - const std::string settingRoot; - public: - explicit NotebookTab(Notebook *_notebook, const std::string &_uuid); + explicit NotebookTab(Notebook *_notebook); void updateSize(); SplitContainer *page; - QString getTitle() const; + const QString &getTitle() const; void setTitle(const QString &newTitle); bool isSelected() const; void setSelected(bool value); @@ -63,10 +60,10 @@ private: Notebook *notebook; - pajlada::Settings::Setting title; + QString title; public: - pajlada::Settings::Setting useDefaultBehaviour; + bool useDefaultTitle = true; private: bool selected = false; diff --git a/src/widgets/helper/splitheader.cpp b/src/widgets/helper/splitheader.cpp index 3228e2f0..b6c198ab 100644 --- a/src/widgets/helper/splitheader.cpp +++ b/src/widgets/helper/splitheader.cpp @@ -155,7 +155,7 @@ void SplitHeader::scaleChangedEvent(float scale) void SplitHeader::updateChannelText() { - const QString channelName = this->split->channelName; + const QString channelName = this->split->getChannel()->name; if (channelName.isEmpty()) { this->titleLabel->setText(""); return; diff --git a/src/widgets/notebook.cpp b/src/widgets/notebook.cpp index fd73921a..e8f491f9 100644 --- a/src/widgets/notebook.cpp +++ b/src/widgets/notebook.cpp @@ -22,15 +22,13 @@ namespace chatterino { namespace widgets { -Notebook::Notebook(Window *parent, bool _showButtons, const std::string &settingPrefix) +Notebook::Notebook(Window *parent, bool _showButtons) : BaseWidget(parent) - , settingRoot(fS("{}/notebook", settingPrefix)) , parentWindow(parent) , addButton(this) , settingsButton(this) , userButton(this) , showButtons(_showButtons) - , tabs(fS("{}/tabs", this->settingRoot)) , closeConfirmDialog(this) { this->connect(&this->settingsButton, SIGNAL(clicked()), this, SLOT(settingsButtonClicked())); @@ -47,8 +45,6 @@ Notebook::Notebook(Window *parent, bool _showButtons, const std::string &setting settingsManager.hidePreferencesButton.connectSimple([this](auto) { this->performLayout(); }); settingsManager.hideUserButton.connectSimple([this](auto) { this->performLayout(); }); - this->loadTabs(); - closeConfirmDialog.setText("Are you sure you want to close this tab?"); closeConfirmDialog.setIcon(QMessageBox::Icon::Question); closeConfirmDialog.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel); @@ -57,15 +53,10 @@ Notebook::Notebook(Window *parent, bool _showButtons, const std::string &setting this->scaleChangedEvent(this->getScale()); } -SplitContainer *Notebook::addNewPage() +SplitContainer *Notebook::addNewPage(bool select) { - return this->addPage(CreateUUID().toStdString(), true); -} - -SplitContainer *Notebook::addPage(const std::string &uuid, bool select) -{ - auto tab = new NotebookTab(this, uuid); - auto page = new SplitContainer(this, tab, uuid); + auto tab = new NotebookTab(this); + auto page = new SplitContainer(this, tab); tab->show(); @@ -178,6 +169,11 @@ SplitContainer *Notebook::tabAt(QPoint point, int &index, int maxWidth) return nullptr; } +SplitContainer *Notebook::tabAt(int index) +{ + return this->pages[index]; +} + void Notebook::rearrangePage(SplitContainer *page, int index) { this->pages.move(this->pages.indexOf(page), index); @@ -244,7 +240,7 @@ void Notebook::performLayout(bool animated) for (auto &i : this->pages) { if (!first && (i == this->pages.last() ? tabHeight : 0) + x + i->getTab()->width() > width()) { - y += i->getTab()->height() - 1; + y += i->getTab()->height(); // y += 20; i->getTab()->moveAnimated(QPoint(0, y), animated); x = i->getTab()->width(); @@ -310,33 +306,7 @@ void Notebook::usersButtonClicked() void Notebook::addPageButtonClicked() { - QTimer::singleShot(80, [this] { this->addNewPage(); }); -} - -void Notebook::loadTabs() -{ - const std::vector tabArray = this->tabs.getValue(); - - if (tabArray.size() == 0) { - this->addNewPage(); - return; - } - - for (const std::string &tabUUID : tabArray) { - this->addPage(tabUUID); - } -} - -void Notebook::save() -{ - std::vector tabArray; - - for (const auto &page : this->pages) { - tabArray.push_back(page->getUUID()); - page->save(); - } - - this->tabs = tabArray; + QTimer::singleShot(80, [this] { this->addNewPage(true); }); } } // namespace widgets diff --git a/src/widgets/notebook.hpp b/src/widgets/notebook.hpp index 082768af..9f0bd4f1 100644 --- a/src/widgets/notebook.hpp +++ b/src/widgets/notebook.hpp @@ -18,23 +18,24 @@ class Notebook : public BaseWidget { Q_OBJECT - std::string settingRoot; - public: enum HighlightType { none, highlighted, newMessage }; - explicit Notebook(Window *parent, bool _showButtons, const std::string &settingPrefix); + explicit Notebook(Window *parent, bool _showButtons); - SplitContainer *addNewPage(); - SplitContainer *addPage(const std::string &uuid, bool select = false); + SplitContainer *addNewPage(bool select = false); void removePage(SplitContainer *page); void removeCurrentPage(); void select(SplitContainer *page); void selectIndex(int index); - SplitContainer *getSelectedPage() const + SplitContainer *getOrAddSelectedPage() { + if (selectedPage == nullptr) { + this->addNewPage(true); + } + return selectedPage; } @@ -42,6 +43,7 @@ public: int tabCount(); SplitContainer *tabAt(QPoint point, int &index, int maxWidth = 2000000000); + SplitContainer *tabAt(int index); void rearrangePage(SplitContainer *page, int index); void nextTab(); @@ -71,14 +73,7 @@ private: bool showButtons; - pajlada::Settings::Setting> tabs; - - void loadTabs(); - QMessageBox closeConfirmDialog; - -public: - void save(); }; } // namespace widgets diff --git a/src/widgets/split.cpp b/src/widgets/split.cpp index 7cfad2b6..21d952aa 100644 --- a/src/widgets/split.cpp +++ b/src/widgets/split.cpp @@ -36,11 +36,8 @@ using namespace chatterino::messages; namespace chatterino { namespace widgets { -Split::Split(SplitContainer *parent, const std::string &_uuid) +Split::Split(SplitContainer *parent) : BaseWidget(parent) - , uuid(_uuid) - , settingRoot(fS("/splits/{}", this->uuid)) - , channelName(fS("{}/channelName", this->settingRoot)) , parentPage(*parent) , channel(Channel::getEmpty()) , vbox(this) @@ -86,11 +83,6 @@ Split::Split(SplitContainer *parent, const std::string &_uuid) // CreateShortcut(this, "ALT+SHIFT+UP", &Split::doIncFlexY); // CreateShortcut(this, "ALT+SHIFT+DOWN", &Split::doDecFlexY); - this->channelName.getValueChangedSignal().connect( - std::bind(&Split::channelNameUpdated, this, std::placeholders::_1)); - - this->channelNameUpdated(this->channelName.getValue()); - this->input.ui.textEdit->installEventFilter(parent); this->view.mouseDown.connect([this](QMouseEvent *) { this->giveFocus(Qt::MouseFocusReason); }); @@ -130,11 +122,6 @@ Split::~Split() this->channelIDChangedConnection.disconnect(); } -const std::string &Split::getUUID() const -{ - return this->uuid; -} - ChannelPtr Split::getChannel() const { return this->channel; @@ -156,6 +143,7 @@ void Split::setChannel(ChannelPtr _newChannel) } this->header.updateModerationModeIcon(); + this->header.updateChannelText(); this->channelChanged.invoke(); } @@ -196,19 +184,6 @@ bool Split::getModerationMode() const return this->moderationMode; } -void Split::channelNameUpdated(const QString &newChannelName) -{ - // update messages - if (newChannelName.isEmpty()) { - this->setChannel(Channel::getEmpty()); - } else { - this->setChannel(TwitchServer::getInstance().addChannel(newChannelName)); - } - - // update header - this->header.updateChannelText(); -} - bool Split::showChangeChannelPopup(const char *dialogTitle, bool empty) { // create new input dialog and execute it @@ -217,13 +192,13 @@ bool Split::showChangeChannelPopup(const char *dialogTitle, bool empty) dialog.setWindowTitle(dialogTitle); if (!empty) { - dialog.setText(this->channelName); + dialog.setText(this->channel->name); } if (dialog.exec() == QDialog::Accepted) { QString newChannelName = dialog.getText().trimmed(); - this->channelName = newChannelName; + this->setChannel(providers::twitch::TwitchServer::getInstance().addChannel(newChannelName)); this->parentPage.refreshTitle(); return true; @@ -328,12 +303,13 @@ void Split::doChangeChannel() void Split::doPopup() { - Window &window = singletons::WindowManager::getInstance().createWindow(); + Window &window = singletons::WindowManager::getInstance().createWindow(Window::Popup); - Split *split = new Split(static_cast(window.getNotebook().getSelectedPage()), - this->uuid); + Split *split = + new Split(static_cast(window.getNotebook().getOrAddSelectedPage())); - window.getNotebook().getSelectedPage()->addToLayout(split); + split->setChannel(this->getChannel()); + window.getNotebook().getOrAddSelectedPage()->addToLayout(split); window.show(); } @@ -366,7 +342,7 @@ void Split::doOpenPopupPlayer() void Split::doOpenStreamlink() { try { - streamlink::Start(this->channelName.getValue()); + streamlink::Start(this->channel->name); } catch (const streamlink::Exception &ex) { debug::Log("Error in doOpenStreamlink: {}", ex.what()); } diff --git a/src/widgets/split.hpp b/src/widgets/split.hpp index 38e2168b..ddd71416 100644 --- a/src/widgets/split.hpp +++ b/src/widgets/split.hpp @@ -42,14 +42,10 @@ class Split : public BaseWidget Q_OBJECT - const std::string uuid; - const std::string settingRoot; - public: - Split(SplitContainer *parent, const std::string &_uuid); + Split(SplitContainer *parent); ~Split() override; - pajlada::Settings::Setting channelName; pajlada::Signals::NoArgSignal channelChanged; ChannelView &getChannelView() @@ -57,8 +53,9 @@ public: return this->view; } - const std::string &getUUID() const; ChannelPtr getChannel() const; + void setChannel(ChannelPtr newChannel); + void setFlexSizeX(double x); double getFlexSizeX(); void setFlexSizeY(double y); @@ -98,8 +95,6 @@ private: pajlada::Signals::Connection channelIDChangedConnection; pajlada::Signals::Connection usermodeChangedConnection; - - void setChannel(ChannelPtr newChannel); void doOpenAccountPopupWidget(AccountPopupWidget *widget, QString user); void channelNameUpdated(const QString &newChannelName); void handleModifiers(QEvent *event, Qt::KeyboardModifiers modifiers); diff --git a/src/widgets/splitcontainer.cpp b/src/widgets/splitcontainer.cpp index b736397a..f7d6f689 100644 --- a/src/widgets/splitcontainer.cpp +++ b/src/widgets/splitcontainer.cpp @@ -26,12 +26,9 @@ bool SplitContainer::isDraggingSplit = false; Split *SplitContainer::draggingSplit = nullptr; std::pair SplitContainer::dropPosition = std::pair(-1, -1); -SplitContainer::SplitContainer(Notebook *parent, NotebookTab *_tab, const std::string &_uuid) +SplitContainer::SplitContainer(Notebook *parent, NotebookTab *_tab) : BaseWidget(parent->themeManager, parent) - , uuid(_uuid) - , settingRoot(fS("/containers/{}", this->uuid)) , tab(_tab) - , chats(fS("{}/chats", this->settingRoot)) , dropPreview(this) { this->tab->page = this; @@ -48,8 +45,6 @@ SplitContainer::SplitContainer(Notebook *parent, NotebookTab *_tab, const std::s this->ui.hbox.setSpacing(1); this->ui.hbox.setMargin(0); - this->loadSplits(); - this->refreshTitle(); } @@ -147,6 +142,24 @@ const std::vector &SplitContainer::getSplits() const return this->splits; } +std::vector> SplitContainer::getColumns() const +{ + std::vector> columns; + + for (int i = 0; i < this->ui.hbox.count(); i++) { + std::vector cells; + + QLayout *vbox = this->ui.hbox.itemAt(i)->layout(); + for (int j = 0; j < vbox->count(); j++) { + cells.push_back(dynamic_cast(vbox->itemAt(j)->widget())); + } + + columns.push_back(cells); + } + + return columns; +} + NotebookTab *SplitContainer::getTab() const { return this->tab; @@ -447,7 +460,7 @@ std::pair SplitContainer::getChatPosition(const Split *chatWidget) Split *SplitContainer::createChatWidget(const std::string &uuid) { - auto split = new Split(this, uuid); + auto split = new Split(this); split->getChannelView().highlightedMessageReceived.connect([this] { // fourtf: error potentionally here @@ -459,7 +472,7 @@ Split *SplitContainer::createChatWidget(const std::string &uuid) void SplitContainer::refreshTitle() { - if (!this->tab->useDefaultBehaviour) { + if (!this->tab->useDefaultTitle) { return; } @@ -467,7 +480,7 @@ void SplitContainer::refreshTitle() bool first = true; for (const auto &chatWidget : this->splits) { - auto channelName = chatWidget->channelName.getValue(); + auto channelName = chatWidget->getChannel()->name; if (channelName.isEmpty()) { continue; } @@ -487,83 +500,5 @@ void SplitContainer::refreshTitle() this->tab->setTitle(newTitle); } -void SplitContainer::loadSplits() -{ - const auto hboxes = this->chats.getValue(); - int column = 0; - for (const std::vector &hbox : hboxes) { - int row = 0; - for (const std::string &chatUUID : hbox) { - Split *split = this->createChatWidget(chatUUID); - - this->addToLayout(split, std::pair(column, row)); - - ++row; - } - ++column; - } -} - -template -static void saveFromLayout(QLayout *layout, Container &container) -{ - for (int i = 0; i < layout->count(); ++i) { - auto item = layout->itemAt(i); - - auto innerLayout = item->layout(); - if (innerLayout != nullptr) { - std::vector vbox; - - for (int j = 0; j < innerLayout->count(); ++j) { - auto innerItem = innerLayout->itemAt(j); - auto innerWidget = innerItem->widget(); - if (innerWidget == nullptr) { - assert(false); - continue; - } - Split *innerSplit = qobject_cast(innerWidget); - vbox.push_back(innerSplit->getUUID()); - } - - container.push_back(vbox); - - continue; - } - } -} - -void SplitContainer::save() -{ - auto layout = this->ui.hbox.layout(); - - std::vector> _chats; - - for (int i = 0; i < layout->count(); ++i) { - auto item = layout->itemAt(i); - - auto innerLayout = item->layout(); - if (innerLayout != nullptr) { - std::vector vbox; - - for (int j = 0; j < innerLayout->count(); ++j) { - auto innerItem = innerLayout->itemAt(j); - auto innerWidget = innerItem->widget(); - if (innerWidget == nullptr) { - assert(false); - continue; - } - Split *innerSplit = qobject_cast(innerWidget); - vbox.push_back(innerSplit->getUUID()); - } - - _chats.push_back(vbox); - - continue; - } - } - - this->chats = _chats; -} - } // namespace widgets } // namespace chatterino diff --git a/src/widgets/splitcontainer.hpp b/src/widgets/splitcontainer.hpp index bf07022f..44093c8a 100644 --- a/src/widgets/splitcontainer.hpp +++ b/src/widgets/splitcontainer.hpp @@ -19,21 +19,14 @@ class SplitContainer : public BaseWidget { Q_OBJECT - const std::string uuid; - const std::string settingRoot; - public: - SplitContainer(Notebook *parent, NotebookTab *_tab, const std::string &_uuid); - - const std::string &getUUID() const - { - return this->uuid; - } + SplitContainer(Notebook *parent, NotebookTab *_tab); std::pair removeFromLayout(Split *widget); void addToLayout(Split *widget, std::pair position = std::pair(-1, -1)); const std::vector &getSplits() const; + std::vector> getColumns() const; NotebookTab *getTab() const; void addChat(bool openChannelNameDialog = false, std::string chatUUID = std::string()); @@ -90,8 +83,6 @@ private: std::vector splits; std::vector dropRegions; - pajlada::Settings::Setting>> chats; - NotebookPageDropPreview dropPreview; void setPreviewRect(QPoint mousePos); diff --git a/src/widgets/window.cpp b/src/widgets/window.cpp index 3326a33f..b0163014 100644 --- a/src/widgets/window.cpp +++ b/src/widgets/window.cpp @@ -18,13 +18,11 @@ namespace chatterino { namespace widgets { -Window::Window(const QString &windowName, singletons::ThemeManager &_themeManager, - bool _isMainWindow) +Window::Window(singletons::ThemeManager &_themeManager, WindowType _type) : BaseWindow(_themeManager, nullptr, true) - , settingRoot(fS("/windows/{}", windowName)) - , windowGeometry(this->settingRoot) + , type(_type) , dpi(this->getScale()) - , notebook(this, _isMainWindow, this->settingRoot) + , notebook(this, !this->hasCustomWindowFrame()) { singletons::AccountManager::getInstance().Twitch.currentUsername.connect( [this](const std::string &newUsername, auto) { @@ -35,7 +33,7 @@ Window::Window(const QString &windowName, singletons::ThemeManager &_themeManage } }); - if (this->hasCustomWindowFrame()) { + if (this->hasCustomWindowFrame() && _type == Window::Main) { this->addTitleBarButton(TitleBarButton::Settings, [] { singletons::WindowManager::getInstance().showSettingsDialog(); }); @@ -49,6 +47,12 @@ Window::Window(const QString &windowName, singletons::ThemeManager &_themeManage }); } + if (_type == Window::Main) { + this->resize((int)(600 * this->getScale()), (int)(500 * this->getScale())); + } else { + this->resize((int)(300 * this->getScale()), (int)(500 * this->getScale())); + } + QVBoxLayout *layout = new QVBoxLayout(this); layout->addWidget(&this->notebook); @@ -59,8 +63,6 @@ Window::Window(const QString &windowName, singletons::ThemeManager &_themeManage this->themeRefreshEvent(); - this->loadGeometry(); - /// Initialize program-wide hotkeys // CTRL+P: Open Settings Dialog CreateWindowShortcut(this, "CTRL+P", [] { SettingsDialog::showDialog(); }); @@ -77,7 +79,7 @@ Window::Window(const QString &windowName, singletons::ThemeManager &_themeManage CreateWindowShortcut(this, "CTRL+9", [this] { this->notebook.selectIndex(8); }); // CTRL+SHIFT+T: New tab - CreateWindowShortcut(this, "CTRL+SHIFT+T", [this] { this->notebook.addNewPage(); }); + CreateWindowShortcut(this, "CTRL+SHIFT+T", [this] { this->notebook.addNewPage(true); }); // CTRL+SHIFT+W: Close current tab CreateWindowShortcut(this, "CTRL+SHIFT+W", [this] { this->notebook.removeCurrentPage(); }); @@ -102,9 +104,14 @@ Window::Window(const QString &windowName, singletons::ThemeManager &_themeManage // }); } +Window::WindowType Window::getType() +{ + return this->type; +} + void Window::repaintVisibleChatWidgets(Channel *channel) { - auto *page = this->notebook.getSelectedPage(); + auto *page = this->notebook.getOrAddSelectedPage(); if (page == nullptr) { return; @@ -127,18 +134,6 @@ void Window::refreshWindowTitle(const QString &username) this->setWindowTitle(username + " - Chatterino for Twitch"); } -void Window::closeEvent(QCloseEvent *) -{ - const QRect &geom = this->geometry(); - - this->windowGeometry.x = geom.x(); - this->windowGeometry.y = geom.y(); - this->windowGeometry.width = geom.width(); - this->windowGeometry.height = geom.height(); - - this->closed.invoke(); -} - bool Window::event(QEvent *e) { switch (e->type()) { @@ -146,7 +141,7 @@ bool Window::event(QEvent *e) break; case QEvent::WindowDeactivate: { - auto page = this->notebook.getSelectedPage(); + auto page = this->notebook.getOrAddSelectedPage(); if (page != nullptr) { std::vector splits = page->getSplits(); @@ -160,35 +155,14 @@ bool Window::event(QEvent *e) return BaseWindow::event(e); } -void Window::loadGeometry() +void Window::closeEvent(QCloseEvent *event) { - bool doSetGeometry = false; - QRect loadedGeometry; - if (!this->windowGeometry.x.isDefaultValue() && !this->windowGeometry.y.isDefaultValue()) { - loadedGeometry.setX(this->windowGeometry.x); - loadedGeometry.setY(this->windowGeometry.y); - doSetGeometry = true; + if (this->type == Window::Main) { + singletons::WindowManager::getInstance().save(); + singletons::WindowManager::getInstance().closeAll(); } - if (!this->windowGeometry.width.isDefaultValue() && - !this->windowGeometry.height.isDefaultValue()) { - loadedGeometry.setWidth(this->windowGeometry.width); - loadedGeometry.setHeight(this->windowGeometry.height); - } else { - loadedGeometry.setWidth(1280); - loadedGeometry.setHeight(720); - } - - if (doSetGeometry) { - this->setGeometry(loadedGeometry); - } else { - this->resize(loadedGeometry.width(), loadedGeometry.height()); - } -} - -void Window::save() -{ - this->notebook.save(); + this->closed.invoke(); } } // namespace widgets diff --git a/src/widgets/window.hpp b/src/widgets/window.hpp index a82a9b29..b3b7a098 100644 --- a/src/widgets/window.hpp +++ b/src/widgets/window.hpp @@ -18,32 +18,14 @@ class ThemeManager; namespace widgets { -struct WindowGeometry { - WindowGeometry(const std::string &settingPrefix) - : x(fS("{}/geometry/x", settingPrefix)) - , y(fS("{}/geometry/y", settingPrefix)) - , width(fS("{}/geometry/width", settingPrefix)) - , height(fS("{}/geometry/height", settingPrefix)) - { - } - - pajlada::Settings::Setting x; - pajlada::Settings::Setting y; - pajlada::Settings::Setting width; - pajlada::Settings::Setting height; -}; - class Window : public BaseWindow { Q_OBJECT - std::string settingRoot; - - WindowGeometry windowGeometry; - public: - explicit Window(const QString &windowName, singletons::ThemeManager &_themeManager, - bool isMainWindow); + enum WindowType { Main, Popup }; + + explicit Window(singletons::ThemeManager &_themeManager, WindowType type); void repaintVisibleChatWidgets(Channel *channel = nullptr); @@ -53,17 +35,19 @@ public: pajlada::Signals::NoArgSignal closed; + WindowType getType(); + protected: void closeEvent(QCloseEvent *event) override; bool event(QEvent *event) override; private: + WindowType type; float dpi; void loadGeometry(); Notebook notebook; - // TitleBar titleBar; friend class Notebook; From 84c577c0dc03d5d3957f693dc759e1a1295974a7 Mon Sep 17 00:00:00 2001 From: Vilgot Fredenberg Date: Fri, 6 Apr 2018 23:58:08 +0200 Subject: [PATCH 39/69] fixed gcc compile bug --- src/singletons/thememanager.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/singletons/thememanager.cpp b/src/singletons/thememanager.cpp index 1ef36383..d133ee88 100644 --- a/src/singletons/thememanager.cpp +++ b/src/singletons/thememanager.cpp @@ -89,16 +89,16 @@ void ThemeManager::actuallyUpdate(double hue, double multiplier) // text, {regular, hover, unfocused} if (lightWin) { - this->tabs.regular = {fg, {bg, "#ccc", bg}}; - this->tabs.newMessage = {fg, {bg, "#ccc", bg}}; - this->tabs.highlighted = {fg, {bg, "#ccc", bg}}; - this->tabs.selected = {"#fff", {"#333", "#333", "#666"}}; + this->tabs.regular = {fg, {bg, QColor("#ccc"), bg}}; + this->tabs.newMessage = {fg, {bg, QColor("#ccc"), bg}}; + this->tabs.highlighted = {fg, {bg, QColor("#ccc"), bg}}; + this->tabs.selected = {QColor("#fff"), {QColor("#333"), QColor("#333"), QColor("#666")}}; } else { - this->tabs.regular = {fg, {bg, "#555", bg}}; - this->tabs.newMessage = {fg, {bg, "#555", bg}}; - this->tabs.highlighted = {fg, {bg, "#555", bg}}; + this->tabs.regular = {fg, {bg, QColor("#555"), bg}}; + this->tabs.newMessage = {fg, {bg, QColor("#555"), bg}}; + this->tabs.highlighted = {fg, {bg, QColor("#555"), bg}}; // this->tabs.selected = {"#000", {themeColor, themeColor, themeColorNoSat}}; - this->tabs.selected = {"#000", {"#999", "#999", "#888"}}; + this->tabs.selected = {QColor("#000"), {QColor("#999"), QColor("#999"), QColor("#888")}}; } } From 179cd5552df57f570c8baa2ca041e0bb7eea8929 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 7 Apr 2018 12:27:08 +0200 Subject: [PATCH 40/69] Move CTRL+T hotkey handling to Notebook CTRL+T Can now be called anywhere in the window --- src/widgets/notebook.cpp | 11 +++++++++++ src/widgets/split.cpp | 3 --- src/widgets/split.hpp | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/widgets/notebook.cpp b/src/widgets/notebook.cpp index e8f491f9..b1d7d350 100644 --- a/src/widgets/notebook.cpp +++ b/src/widgets/notebook.cpp @@ -4,6 +4,7 @@ #include "singletons/windowmanager.hpp" #include "widgets/helper/notebookbutton.hpp" #include "widgets/helper/notebooktab.hpp" +#include "widgets/helper/shortcut.hpp" #include "widgets/settingsdialog.hpp" #include "widgets/splitcontainer.hpp" #include "widgets/window.hpp" @@ -51,6 +52,16 @@ Notebook::Notebook(Window *parent, bool _showButtons) closeConfirmDialog.setDefaultButton(QMessageBox::Yes); this->scaleChangedEvent(this->getScale()); + + // Window-wide hotkeys + // CTRL+T: Create new split in selected notebook page + CreateWindowShortcut(this, "CTRL+T", [this]() { + if (this->selectedPage == nullptr) { + return; + } + + this->selectedPage->addChat(true); + }); } SplitContainer *Notebook::addNewPage(bool select) diff --git a/src/widgets/split.cpp b/src/widgets/split.cpp index 21d952aa..89cbea39 100644 --- a/src/widgets/split.cpp +++ b/src/widgets/split.cpp @@ -58,9 +58,6 @@ Split::Split(SplitContainer *parent) this->vbox.addWidget(&this->input); // Initialize chat widget-wide hotkeys - // CTRL+T: Create new split (Add page) - CreateShortcut(this, "CTRL+T", &Split::doAddSplit); - // CTRL+W: Close Split CreateShortcut(this, "CTRL+W", &Split::doCloseSplit); diff --git a/src/widgets/split.hpp b/src/widgets/split.hpp index ddd71416..f5195a54 100644 --- a/src/widgets/split.hpp +++ b/src/widgets/split.hpp @@ -101,7 +101,7 @@ private: public slots: // Add new split to the notebook page that this chat widget is in - // Maybe we should use this chat widget as a hint to where the new split should be created + // This is only activated from the menu now. Hotkey is handled in Notebook void doAddSplit(); // Close current split (chat widget) From 945d500701496e67081e7c1d4ecf3e94e9f53ad3 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 7 Apr 2018 12:43:28 +0200 Subject: [PATCH 41/69] Closing splits now tries to focus a neighbouring split Fixes #176 --- src/widgets/splitcontainer.cpp | 67 +++++++++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 10 deletions(-) diff --git a/src/widgets/splitcontainer.cpp b/src/widgets/splitcontainer.cpp index f7d6f689..265625c9 100644 --- a/src/widgets/splitcontainer.cpp +++ b/src/widgets/splitcontainer.cpp @@ -74,30 +74,77 @@ std::pair SplitContainer::removeFromLayout(Split *widget) this->refreshTitle(); } - // remove from box and return location + Split *neighbouringSplit = nullptr; + + // Position the split was found at + int positionX = -1, positionY = -1; + + bool removed = false; + + QVBoxLayout *layoutToRemove = nullptr; + + // Find widget in box, remove it, return its position for (int i = 0; i < this->ui.hbox.count(); ++i) { auto vbox = static_cast(this->ui.hbox.itemAt(i)); - for (int j = 0; j < vbox->count(); ++j) { + auto vboxCount = vbox->count(); + + for (int j = 0; j < vboxCount; ++j) { if (vbox->itemAt(j)->widget() != widget) { + neighbouringSplit = dynamic_cast(vbox->itemAt(j)->widget()); + + if (removed && neighbouringSplit != nullptr) { + // The widget we searched for has been found, and we have a split to switch + // focus to + break; + } + continue; } + removed = true; + positionX = i; + + // Remove split from box widget->setParent(nullptr); - bool isLastItem = vbox->count() == 0; - - if (isLastItem) { - this->ui.hbox.removeItem(vbox); - - delete vbox; + if (vbox->count() == 0) { + // The split was the last item remaining in the vbox + // Remove the vbox once all iteration is done + layoutToRemove = vbox; + positionY = -1; + break; } - return std::pair(i, isLastItem ? -1 : j); + // Don't break here yet, we want to keep iterating this vbox if possible to find the + // closest still-alive neighbour that we can switch focus to + positionY = j; + + --j; + --vboxCount; + } + + if (removed && neighbouringSplit != nullptr) { + // The widget we searched for has been found, and we have a split to switch focus to + break; } } - return std::pair(-1, -1); + if (removed) { + if (layoutToRemove != nullptr) { + // The split we removed was the last split in its box. Remove the box + // We delay the removing of the box so we can keep iterating over hbox safely + this->ui.hbox.removeItem(layoutToRemove); + delete layoutToRemove; + } + + if (neighbouringSplit != nullptr) { + // We found a neighbour split we can switch focus to + neighbouringSplit->giveFocus(Qt::MouseFocusReason); + } + } + + return std::make_pair(positionX, positionY); } void SplitContainer::addToLayout(Split *widget, std::pair position) From c82254aa9e75114d53e3b90870e624c305220c8e Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 7 Apr 2018 12:53:10 +0200 Subject: [PATCH 42/69] Reformat Remove some UUID remnants --- src/widgets/notebook.cpp | 2 +- src/widgets/split.hpp | 8 ++++---- src/widgets/splitcontainer.cpp | 9 +++------ src/widgets/splitcontainer.hpp | 24 ++++++++++++------------ src/widgets/streamview.cpp | 4 +--- src/widgets/streamview.hpp | 2 +- 6 files changed, 22 insertions(+), 27 deletions(-) diff --git a/src/widgets/notebook.cpp b/src/widgets/notebook.cpp index b1d7d350..3faa0409 100644 --- a/src/widgets/notebook.cpp +++ b/src/widgets/notebook.cpp @@ -103,7 +103,7 @@ void Notebook::removePage(SplitContainer *page) this->pages.removeOne(page); - if (this->pages.size() == 0) { + if (this->pages.empty()) { this->addNewPage(); } diff --git a/src/widgets/split.hpp b/src/widgets/split.hpp index f5195a54..e4a51be0 100644 --- a/src/widgets/split.hpp +++ b/src/widgets/split.hpp @@ -74,11 +74,11 @@ public: void drag(); protected: - void paintEvent(QPaintEvent *) override; - void mouseMoveEvent(QMouseEvent *) override; + void paintEvent(QPaintEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; void mousePressEvent(QMouseEvent *event) override; - void keyPressEvent(QKeyEvent *) override; - void keyReleaseEvent(QKeyEvent *) override; + void keyPressEvent(QKeyEvent *event) override; + void keyReleaseEvent(QKeyEvent *event) override; private: SplitContainer &parentPage; diff --git a/src/widgets/splitcontainer.cpp b/src/widgets/splitcontainer.cpp index 265625c9..de37c605 100644 --- a/src/widgets/splitcontainer.cpp +++ b/src/widgets/splitcontainer.cpp @@ -212,12 +212,9 @@ NotebookTab *SplitContainer::getTab() const return this->tab; } -void SplitContainer::addChat(bool openChannelNameDialog, std::string chatUUID) +void SplitContainer::addChat(bool openChannelNameDialog) { - if (chatUUID.empty()) { - chatUUID = CreateUUID().toStdString(); - } - Split *w = this->createChatWidget(chatUUID); + Split *w = this->createChatWidget(); if (openChannelNameDialog) { bool ret = w->showChangeChannelPopup("Open channel name", true); @@ -505,7 +502,7 @@ std::pair SplitContainer::getChatPosition(const Split *chatWidget) return getWidgetPositionInLayout(layout, chatWidget); } -Split *SplitContainer::createChatWidget(const std::string &uuid) +Split *SplitContainer::createChatWidget() { auto split = new Split(this); diff --git a/src/widgets/splitcontainer.hpp b/src/widgets/splitcontainer.hpp index 44093c8a..e2cef4d8 100644 --- a/src/widgets/splitcontainer.hpp +++ b/src/widgets/splitcontainer.hpp @@ -29,7 +29,7 @@ public: std::vector> getColumns() const; NotebookTab *getTab() const; - void addChat(bool openChannelNameDialog = false, std::string chatUUID = std::string()); + void addChat(bool openChannelNameDialog = false); static bool isDraggingSplit; static Split *draggingSplit; @@ -46,19 +46,19 @@ public: int splitCount() const; protected: - virtual bool eventFilter(QObject *object, QEvent *event) override; - virtual void paintEvent(QPaintEvent *) override; + bool eventFilter(QObject *object, QEvent *event) override; + void paintEvent(QPaintEvent *event) override; - virtual void showEvent(QShowEvent *) override; + void showEvent(QShowEvent *event) override; - virtual void enterEvent(QEvent *) override; - virtual void leaveEvent(QEvent *) override; - virtual void mouseReleaseEvent(QMouseEvent *event) override; + void enterEvent(QEvent *event) override; + void leaveEvent(QEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; - virtual void dragEnterEvent(QDragEnterEvent *event) override; - virtual void dragMoveEvent(QDragMoveEvent *event) override; - virtual void dragLeaveEvent(QDragLeaveEvent *event) override; - virtual void dropEvent(QDropEvent *event) override; + void dragEnterEvent(QDragEnterEvent *event) override; + void dragMoveEvent(QDragMoveEvent *event) override; + void dragLeaveEvent(QDragLeaveEvent *event) override; + void dropEvent(QDropEvent *event) override; private: struct DropRegion { @@ -89,7 +89,7 @@ private: std::pair getChatPosition(const Split *chatWidget); - Split *createChatWidget(const std::string &uuid); + Split *createChatWidget(); public: void refreshTitle(); diff --git a/src/widgets/streamview.cpp b/src/widgets/streamview.cpp index a3e2a001..3961fdbb 100644 --- a/src/widgets/streamview.cpp +++ b/src/widgets/streamview.cpp @@ -12,7 +12,7 @@ namespace chatterino { namespace widgets { -StreamView::StreamView(ChannelPtr channel, QUrl url) +StreamView::StreamView(ChannelPtr channel, const QUrl &url) { util::LayoutCreator layoutCreator(this); @@ -22,8 +22,6 @@ StreamView::StreamView(ChannelPtr channel, QUrl url) web->settings()->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true); #endif - // QString uuid = CreateUUID(); - auto chat = layoutCreator.emplace(); chat->setFixedWidth(300); chat->setChannel(channel); diff --git a/src/widgets/streamview.hpp b/src/widgets/streamview.hpp index deb9f4d2..6013fd7f 100644 --- a/src/widgets/streamview.hpp +++ b/src/widgets/streamview.hpp @@ -16,7 +16,7 @@ namespace widgets { class StreamView : public QWidget { public: - StreamView(std::shared_ptr channel, QUrl url); + StreamView(std::shared_ptr channel, const QUrl &url); private: QWebEngineView *stream; From 1fc04d82cacebd74e63f3c68a4f2b2244d8b49d9 Mon Sep 17 00:00:00 2001 From: Cranken Date: Sat, 7 Apr 2018 21:21:56 +0200 Subject: [PATCH 43/69] Now highlights the text in the channel change dialogue. --- src/widgets/split.cpp | 1 + src/widgets/textinputdialog.cpp | 5 +++++ src/widgets/textinputdialog.hpp | 2 ++ 3 files changed, 8 insertions(+) diff --git a/src/widgets/split.cpp b/src/widgets/split.cpp index 89cbea39..0e906181 100644 --- a/src/widgets/split.cpp +++ b/src/widgets/split.cpp @@ -190,6 +190,7 @@ bool Split::showChangeChannelPopup(const char *dialogTitle, bool empty) if (!empty) { dialog.setText(this->channel->name); + dialog.highlightText(); } if (dialog.exec() == QDialog::Accepted) { diff --git a/src/widgets/textinputdialog.cpp b/src/widgets/textinputdialog.cpp index deb97e7a..2cf37209 100644 --- a/src/widgets/textinputdialog.cpp +++ b/src/widgets/textinputdialog.cpp @@ -37,5 +37,10 @@ void TextInputDialog::cancelButtonClicked() close(); } +void TextInputDialog::highlightText() +{ + this->_lineEdit.selectAll(); +} + } // namespace widgets } // namespace chatterino diff --git a/src/widgets/textinputdialog.hpp b/src/widgets/textinputdialog.hpp index 4cf33c59..feb7b047 100644 --- a/src/widgets/textinputdialog.hpp +++ b/src/widgets/textinputdialog.hpp @@ -27,6 +27,8 @@ public: _lineEdit.setText(text); } + void highlightText(); + private: QVBoxLayout _vbox; QLineEdit _lineEdit; From 942e8cefccc9ab4ff9d678fb7013464f7ec17abe Mon Sep 17 00:00:00 2001 From: Cranken Date: Sat, 7 Apr 2018 21:42:06 +0200 Subject: [PATCH 44/69] Also now highlights in tab rename. --- src/widgets/helper/notebooktab.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/widgets/helper/notebooktab.cpp b/src/widgets/helper/notebooktab.cpp index 36870bc5..332fe9c2 100644 --- a/src/widgets/helper/notebooktab.cpp +++ b/src/widgets/helper/notebooktab.cpp @@ -40,6 +40,7 @@ NotebookTab::NotebookTab(Notebook *_notebook) d.setText(""); } else { d.setText(this->getTitle()); + d.highlightText(); } if (d.exec() == QDialog::Accepted) { From 3484abd4af85a159abcf62b1d469d61341b3812e Mon Sep 17 00:00:00 2001 From: fourtf Date: Sun, 8 Apr 2018 14:13:48 +0200 Subject: [PATCH 45/69] fixed popups not getting deleted on close --- src/singletons/windowmanager.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/singletons/windowmanager.cpp b/src/singletons/windowmanager.cpp index 8f8ce007..1530062b 100644 --- a/src/singletons/windowmanager.cpp +++ b/src/singletons/windowmanager.cpp @@ -95,10 +95,22 @@ widgets::Window &WindowManager::getSelectedWindow() widgets::Window &WindowManager::createWindow(widgets::Window::WindowType type) { auto *window = new widgets::Window(this->themeManager, type); - this->windows.push_back(window); window->show(); + if (type != widgets::Window::Main) { + window->setAttribute(Qt::WA_DeleteOnClose); + + QObject::connect(window, &QWidget::destroyed, [this, window] { + for (auto it = this->windows.begin(); it != this->windows.end(); it++) { + if (*it == window) { + this->windows.erase(it); + break; + } + } + }); + } + return *window; } From a1cd315ac88a2ffbb40c96427d07f424cc05a4db Mon Sep 17 00:00:00 2001 From: fourtf Date: Sun, 8 Apr 2018 14:33:45 +0200 Subject: [PATCH 46/69] Fixes #288 arrow up behaviour --- src/widgets/helper/splitinput.cpp | 15 ++++++++++++++- src/widgets/helper/splitinput.hpp | 1 + 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/widgets/helper/splitinput.cpp b/src/widgets/helper/splitinput.cpp index 3a8a2182..69a94e18 100644 --- a/src/widgets/helper/splitinput.cpp +++ b/src/widgets/helper/splitinput.cpp @@ -150,6 +150,7 @@ void SplitInput::installKeyPressedEvent() event->accept(); if (!(event->modifiers() == Qt::ControlModifier)) { + this->currMsg = QString(); this->ui.textEdit->setText(QString()); this->prevIndex = 0; } else if (this->ui.textEdit->toPlainText() == @@ -170,8 +171,16 @@ void SplitInput::installKeyPressedEvent() page->requestFocus(reqX, reqY); } else { if (this->prevMsg.size() && this->prevIndex) { + if (this->prevIndex == (this->prevMsg.size())) { + this->currMsg = ui.textEdit->toPlainText(); + } + this->prevIndex--; this->ui.textEdit->setText(this->prevMsg.at(this->prevIndex)); + + QTextCursor cursor = this->ui.textEdit->textCursor(); + cursor.movePosition(QTextCursor::End); + this->ui.textEdit->setTextCursor(cursor); } } } else if (event->key() == Qt::Key_Down) { @@ -192,8 +201,12 @@ void SplitInput::installKeyPressedEvent() this->ui.textEdit->setText(this->prevMsg.at(this->prevIndex)); } else { this->prevIndex = this->prevMsg.size(); - this->ui.textEdit->setText(QString()); + this->ui.textEdit->setText(this->currMsg); } + + QTextCursor cursor = this->ui.textEdit->textCursor(); + cursor.movePosition(QTextCursor::End); + this->ui.textEdit->setTextCursor(cursor); } } else if (event->key() == Qt::Key_Left) { if (event->modifiers() == Qt::AltModifier) { diff --git a/src/widgets/helper/splitinput.hpp b/src/widgets/helper/splitinput.hpp index 9718b984..a4c9e45c 100644 --- a/src/widgets/helper/splitinput.hpp +++ b/src/widgets/helper/splitinput.hpp @@ -59,6 +59,7 @@ private: // QLabel textLengthLabel; // RippleEffectLabel emotesLabel; QStringList prevMsg; + QString currMsg; int prevIndex = 0; void initLayout(); From abff7bdbca1d05d5a91ca15ea1cdc15255ec172a Mon Sep 17 00:00:00 2001 From: Vilgot Fredenberg Date: Sun, 8 Apr 2018 14:34:58 +0200 Subject: [PATCH 47/69] correct -j flag (#315) source (minigw is basically mini GCC so it applies) https://wiki.gentoo.org/wiki/MAKEOPTS --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2160a620..8aaaaaa7 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ download the [boost library](https://sourceforge.net/projects/boost/files/boost/ #### Using MSYS2 Building using MSYS2 can be quite easier process. Check out MSYS2 at [msys2.org](http://www.msys2.org/). -Be sure to add "-j " as a make argument so it will use all your cpu cores to build. [example setup](https://i.imgur.com/qlESlS1.png) +Be sure to add "-j " as a make argument so it will use all your cpu cores to build. [example setup](https://i.imgur.com/qlESlS1.png) 1. open appropriate MSYS2 terminal and do `pacman -S mingw-w64--boost mingw-w64--qt5 mingw-w64--rapidjson` where `` is x86_64 or i686 2. go into the project directory 3. create build folder `mkdir build && cd build` From c116df96e017c8213e20eb01f381ef7925471a4b Mon Sep 17 00:00:00 2001 From: Vilgot Fredenberg Date: Sun, 8 Apr 2018 14:36:05 +0200 Subject: [PATCH 48/69] Aditional compile flags (#316) * aditional compile flags I have been using these flags while compiling wihtout any problems so I thought I'd share them. [Here is a really long source on GCC optimization](https://wiki.gentoo.org/wiki/GCC_optimization) -O3 might work with chatterino however there might be no speed gains (even negative in some cases (and also it increases compilation time)) so that's why I use -O2 * Now it doesn't error Apparenly qt-creator doesn't like the gentoo standard syntax, also spelling --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 8aaaaaa7..5b90c116 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ download the [boost library](https://sourceforge.net/projects/boost/files/boost/ #### Using MSYS2 Building using MSYS2 can be quite easier process. Check out MSYS2 at [msys2.org](http://www.msys2.org/). Be sure to add "-j " as a make argument so it will use all your cpu cores to build. [example setup](https://i.imgur.com/qlESlS1.png) +You can also add "-o2" to optimize the final binary size but increase compilation time, and add "-pipe" to use more ram in compilation but increase compilation speed 1. open appropriate MSYS2 terminal and do `pacman -S mingw-w64--boost mingw-w64--qt5 mingw-w64--rapidjson` where `` is x86_64 or i686 2. go into the project directory 3. create build folder `mkdir build && cd build` From 2b3fa06539e281219e3d3ce50a620e47cf5e6cfb Mon Sep 17 00:00:00 2001 From: Cranken Date: Sun, 8 Apr 2018 14:45:47 +0200 Subject: [PATCH 49/69] Fixed live status not updating when channel is online. (#319) * Fixed live status not updating when channel is online. --- src/providers/twitch/twitchchannel.cpp | 11 +++++------ src/providers/twitch/twitchchannel.hpp | 2 +- src/widgets/helper/splitheader.cpp | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/providers/twitch/twitchchannel.cpp b/src/providers/twitch/twitchchannel.cpp index 729612d4..d47b7f66 100644 --- a/src/providers/twitch/twitchchannel.cpp +++ b/src/providers/twitch/twitchchannel.cpp @@ -184,15 +184,14 @@ void TwitchChannel::setLive(bool newLiveStatus) { { std::lock_guard lock(this->streamStatusMutex); - if (this->streamStatus.live == newLiveStatus) { - // Nothing changed - return; + if (this->streamStatus.live != newLiveStatus) { + this->streamStatus.live = newLiveStatus; } - - this->streamStatus.live = newLiveStatus; } - this->onlineStatusChanged.invoke(); + if (newLiveStatus) { + this->updateLiveInfo.invoke(); + } } void TwitchChannel::refreshLiveStatus() diff --git a/src/providers/twitch/twitchchannel.hpp b/src/providers/twitch/twitchchannel.hpp index 718b7b3c..9ba0ae0f 100644 --- a/src/providers/twitch/twitchchannel.hpp +++ b/src/providers/twitch/twitchchannel.hpp @@ -54,7 +54,7 @@ public: void setRoomID(const QString &_roomID); pajlada::Signals::NoArgSignal roomIDchanged; - pajlada::Signals::NoArgSignal onlineStatusChanged; + pajlada::Signals::NoArgSignal updateLiveInfo; pajlada::Signals::NoArgBoltSignal fetchMessages; pajlada::Signals::NoArgSignal userStateChanged; diff --git a/src/widgets/helper/splitheader.cpp b/src/widgets/helper/splitheader.cpp index b6c198ab..77ccd8d7 100644 --- a/src/widgets/helper/splitheader.cpp +++ b/src/widgets/helper/splitheader.cpp @@ -136,7 +136,7 @@ void SplitHeader::initializeChannelSignals() TwitchChannel *twitchChannel = dynamic_cast(channel.get()); if (twitchChannel) { - twitchChannel->onlineStatusChanged.connect([this]() { + twitchChannel->updateLiveInfo.connect([this]() { this->updateChannelText(); // }); } From 990ac651ae79bba88ffb0a5efc008a3eba76b539 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sun, 8 Apr 2018 15:14:14 +0200 Subject: [PATCH 50/69] Differentiate live streams and vodcasts Fixes #320 --- src/providers/twitch/twitchchannel.cpp | 13 +++++++++++++ src/providers/twitch/twitchchannel.hpp | 1 + src/widgets/helper/splitheader.cpp | 11 +++++++---- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/providers/twitch/twitchchannel.cpp b/src/providers/twitch/twitchchannel.cpp index d47b7f66..8daa92d7 100644 --- a/src/providers/twitch/twitchchannel.cpp +++ b/src/providers/twitch/twitchchannel.cpp @@ -259,6 +259,19 @@ void TwitchChannel::refreshLiveStatus() auto diff = since.secsTo(QDateTime::currentDateTime()); channel->streamStatus.uptime = QString::number(diff / 3600) + "h " + QString::number(diff % 3600 / 60) + "m"; + + channel->streamStatus.rerun = false; + + if (stream.HasMember("broadcast_platform")) { + const auto &broadcastPlatformValue = stream["broadcast_platform"]; + + if (broadcastPlatformValue.IsString()) { + const char *broadcastPlatform = stream["broadcast_platform"].GetString(); + if (strcmp(broadcastPlatform, "rerun") == 0) { + channel->streamStatus.rerun = true; + } + } + } } channel->setLive(true); diff --git a/src/providers/twitch/twitchchannel.hpp b/src/providers/twitch/twitchchannel.hpp index 9ba0ae0f..948c8650 100644 --- a/src/providers/twitch/twitchchannel.hpp +++ b/src/providers/twitch/twitchchannel.hpp @@ -24,6 +24,7 @@ class TwitchChannel final : public Channel public: struct StreamStatus { bool live = false; + bool rerun = false; unsigned viewerCount = 0; QString title; QString game; diff --git a/src/widgets/helper/splitheader.cpp b/src/widgets/helper/splitheader.cpp index 77ccd8d7..e4f9dc0e 100644 --- a/src/widgets/helper/splitheader.cpp +++ b/src/widgets/helper/splitheader.cpp @@ -172,14 +172,17 @@ void SplitHeader::updateChannelText() this->isLive = true; this->tooltip = "" "

" + - streamStatus.title + "

" + streamStatus.game + - "
" - "Live for " + + streamStatus.title + "

" + streamStatus.game + "
" + + (streamStatus.rerun ? "Vod-casting" : "Live") + " for " + streamStatus.uptime + " with " + QString::number(streamStatus.viewerCount) + " viewers" "

"; - this->titleLabel->setText(channelName + " (live)"); + if (streamStatus.rerun) { + this->titleLabel->setText(channelName + " (rerun)"); + } else { + this->titleLabel->setText(channelName + " (live)"); + } return; } From ce6b1805227a7bc5a32a9885b2cc53ddd8dae31b Mon Sep 17 00:00:00 2001 From: fourtf Date: Sun, 8 Apr 2018 17:07:40 +0200 Subject: [PATCH 51/69] improved custom window handling --- src/widgets/basewindow.cpp | 67 +++++++++++++++----------------------- 1 file changed, 27 insertions(+), 40 deletions(-) diff --git a/src/widgets/basewindow.cpp b/src/widgets/basewindow.cpp index 97e6483f..92bdc153 100644 --- a/src/widgets/basewindow.cpp +++ b/src/widgets/basewindow.cpp @@ -13,6 +13,7 @@ #ifdef USEWINSDK #include +#include #include #include #include @@ -60,7 +61,7 @@ void BaseWindow::init() if (this->hasCustomWindowFrame()) { // CUSTOM WINDOW FRAME QVBoxLayout *layout = new QVBoxLayout(); - layout->setMargin(1); + layout->setContentsMargins(0, 1, 0, 0); layout->setSpacing(0); this->setLayout(layout); { @@ -155,7 +156,9 @@ QWidget *BaseWindow::getLayoutContainer() bool BaseWindow::hasCustomWindowFrame() { #ifdef USEWINSDK - return this->enableCustomFrame; + static bool isWin8 = IsWindows8OrGreater(); + + return isWin8 && this->enableCustomFrame; #else return false; #endif @@ -165,7 +168,8 @@ void BaseWindow::themeRefreshEvent() { if (this->enableCustomFrame) { QPalette palette; - palette.setColor(QPalette::Background, this->themeManager.window.background); + // palette.setColor(QPalette::Background, this->themeManager.window.background); + palette.setColor(QPalette::Background, QColor(0, 0, 0, 0)); palette.setColor(QPalette::Foreground, this->themeManager.window.text); this->setPalette(palette); @@ -283,8 +287,19 @@ bool BaseWindow::nativeEvent(const QByteArray &eventType, void *message, long *r } case WM_NCCALCSIZE: { if (this->hasCustomWindowFrame()) { - // this kills the window frame and title bar we added with - // WS_THICKFRAME and WS_CAPTION + int cx = GetSystemMetrics(SM_CXSIZEFRAME); + int cy = GetSystemMetrics(SM_CYSIZEFRAME); + + if (msg->wParam == TRUE) { + NCCALCSIZE_PARAMS *ncp = (reinterpret_cast(msg->lParam)); + ncp->lppos->flags |= SWP_NOREDRAW; + RECT *clientRect = &ncp->rgrc[0]; + clientRect->left += cx; + clientRect->top += 0; + clientRect->right -= cx; + clientRect->bottom -= cy; + } + *result = 0; return true; } else { @@ -307,21 +322,21 @@ bool BaseWindow::nativeEvent(const QByteArray &eventType, void *message, long *r if (resizeWidth) { // left border - if (x >= winrect.left && x < winrect.left + border_width) { + if (x < winrect.left + border_width) { *result = HTLEFT; } // right border - if (x < winrect.right && x >= winrect.right - border_width) { + if (x >= winrect.right - border_width) { *result = HTRIGHT; } } if (resizeHeight) { // bottom border - if (y < winrect.bottom && y >= winrect.bottom - border_width) { + if (y >= winrect.bottom - border_width) { *result = HTBOTTOM; } // top border - if (y >= winrect.top && y < winrect.top + border_width) { + if (y < winrect.top + border_width) { *result = HTTOP; } } @@ -374,13 +389,6 @@ bool BaseWindow::nativeEvent(const QByteArray &eventType, void *message, long *r return QWidget::nativeEvent(eventType, message, result); } break; - } // end case WM_NCHITTEST - case WM_CLOSE: { - // if (this->enableCustomFrame) { - // this->close(); - // } - return QWidget::nativeEvent(eventType, message, result); - break; } default: return QWidget::nativeEvent(eventType, message, result); @@ -396,9 +404,6 @@ void BaseWindow::showEvent(QShowEvent *event) const MARGINS shadow = {1, 1, 1, 1}; DwmExtendFrameIntoClientArea((HWND)this->winId(), &shadow); - - SetWindowPos((HWND)this->winId(), 0, 0, 0, 0, 0, - SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE); } BaseWidget::showEvent(event); @@ -407,30 +412,12 @@ void BaseWindow::showEvent(QShowEvent *event) void BaseWindow::paintEvent(QPaintEvent *event) { if (this->hasCustomWindowFrame()) { - BaseWidget::paintEvent(event); - QPainter painter(this); - bool windowFocused = this->window() == QApplication::activeWindow(); + // bool windowFocused = this->window() == QApplication::activeWindow(); - // QLinearGradient gradient(0, 0, 10, 250); - // gradient.setColorAt(1, - // this->themeManager.tabs.selected.backgrounds.unfocused.color()); - - // if (windowFocused) { - // gradient.setColorAt(.4, - // this->themeManager.tabs.selected.backgrounds.regular.color()); - // } else { - // gradient.setColorAt(.4, - // this->themeManager.tabs.selected.backgrounds.unfocused.color()); - // } - // painter.setPen(QPen(QBrush(gradient), 1)); - - QColor &border = windowFocused ? this->themeManager.window.borderFocused - : this->themeManager.window.borderUnfocused; - painter.setPen(QPen(QBrush(border), 1)); - - painter.drawRect(0, 0, this->width() - 1, this->height() - 1); + painter.fillRect(QRect(0, 1, this->width(), this->height()), + this->themeManager.window.background); } } #endif From 8f4b58ae0888b0d352a07d038a6b527dd85b67f7 Mon Sep 17 00:00:00 2001 From: fourtf Date: Sun, 8 Apr 2018 17:37:48 +0200 Subject: [PATCH 52/69] slight changes --- src/widgets/basewindow.cpp | 4 ++-- src/widgets/helper/titlebarbutton.cpp | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/widgets/basewindow.cpp b/src/widgets/basewindow.cpp index 92bdc153..49fdd2f3 100644 --- a/src/widgets/basewindow.cpp +++ b/src/widgets/basewindow.cpp @@ -402,7 +402,7 @@ void BaseWindow::showEvent(QShowEvent *event) SetWindowLongPtr((HWND)this->winId(), GWL_STYLE, WS_POPUP | WS_CAPTION | WS_THICKFRAME | WS_MAXIMIZEBOX | WS_MINIMIZEBOX); - const MARGINS shadow = {1, 1, 1, 1}; + const MARGINS shadow = {8, 8, 8, 8}; DwmExtendFrameIntoClientArea((HWND)this->winId(), &shadow); } @@ -416,7 +416,7 @@ void BaseWindow::paintEvent(QPaintEvent *event) // bool windowFocused = this->window() == QApplication::activeWindow(); - painter.fillRect(QRect(0, 1, this->width(), this->height()), + painter.fillRect(QRect(0, 1, this->width() - 0, this->height() - 0), this->themeManager.window.background); } } diff --git a/src/widgets/helper/titlebarbutton.cpp b/src/widgets/helper/titlebarbutton.cpp index 987cc8b3..1ff5f56a 100644 --- a/src/widgets/helper/titlebarbutton.cpp +++ b/src/widgets/helper/titlebarbutton.cpp @@ -48,7 +48,8 @@ void TitleBarButton::paintEvent(QPaintEvent *) int xD3 = xD * 4 / 5; painter.drawRect(centerX - xD / 2 + xD2, xD, xD3, xD3); - painter.fillRect(centerX - xD / 2, xD + xD2, xD3, xD3, QColor("#fff")); + painter.fillRect(centerX - xD / 2, xD + xD2, xD3, xD3, + this->themeManager.window.background); painter.drawRect(centerX - xD / 2, xD + xD2, xD3, xD3); break; } @@ -61,7 +62,6 @@ void TitleBarButton::paintEvent(QPaintEvent *) break; } case User: { - // color = QColor("#333"); color = "#999"; painter.setRenderHint(QPainter::Antialiasing); @@ -88,7 +88,6 @@ void TitleBarButton::paintEvent(QPaintEvent *) break; } case Settings: { - // color = QColor("#333"); color = "#999"; painter.setRenderHint(QPainter::Antialiasing); painter.setRenderHint(QPainter::HighQualityAntialiasing); From b23b583cb30b34db67bae201b341f0c9a379eaed Mon Sep 17 00:00:00 2001 From: Vilgot Fredenberg Date: Mon, 9 Apr 2018 10:55:57 +0200 Subject: [PATCH 53/69] We need to escape > for it to render (#321) githubs .md is different hence the change --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5b90c116..fb41a4d2 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ download the [boost library](https://sourceforge.net/projects/boost/files/boost/ #### Using MSYS2 Building using MSYS2 can be quite easier process. Check out MSYS2 at [msys2.org](http://www.msys2.org/). -Be sure to add "-j " as a make argument so it will use all your cpu cores to build. [example setup](https://i.imgur.com/qlESlS1.png) +Be sure to add "-j " as a make argument so it will use all your cpu cores to build. [example setup](https://i.imgur.com/qlESlS1.png) You can also add "-o2" to optimize the final binary size but increase compilation time, and add "-pipe" to use more ram in compilation but increase compilation speed 1. open appropriate MSYS2 terminal and do `pacman -S mingw-w64--boost mingw-w64--qt5 mingw-w64--rapidjson` where `` is x86_64 or i686 2. go into the project directory From efdcc64f898baa955d415be6a6030a2141643697 Mon Sep 17 00:00:00 2001 From: fourtf Date: Tue, 10 Apr 2018 01:54:30 +0200 Subject: [PATCH 54/69] Fixes #326 Shift + EMOTE TAB doesnt work --- src/widgets/helper/resizingtextedit.cpp | 30 ++++++++++++++++--------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/widgets/helper/resizingtextedit.cpp b/src/widgets/helper/resizingtextedit.cpp index 609dafc5..4b88ec29 100644 --- a/src/widgets/helper/resizingtextedit.cpp +++ b/src/widgets/helper/resizingtextedit.cpp @@ -75,13 +75,8 @@ void ResizingTextEdit::keyPressEvent(QKeyEvent *event) this->keyPressed.invoke(event); - if (event->key() == Qt::Key_Backtab) { - // Ignore for now. We want to use it for autocomplete later - return; - } - - bool doComplete = - event->key() == Qt::Key_Tab && (event->modifiers() & Qt::ControlModifier) == Qt::NoModifier; + bool doComplete = (event->key() == Qt::Key_Tab || event->key() == Qt::Key_Backtab) && + (event->modifiers() & Qt::ControlModifier) == Qt::NoModifier; if (doComplete) { // check if there is a completer @@ -110,9 +105,16 @@ void ResizingTextEdit::keyPressEvent(QKeyEvent *event) } // scrolling through selections - if (!this->completer->setCurrentRow(this->completer->currentRow() + 1)) { - // wrap over and start again - this->completer->setCurrentRow(0); + if (event->key() == Qt::Key_Tab) { + if (!this->completer->setCurrentRow(this->completer->currentRow() + 1)) { + // wrap over and start again + this->completer->setCurrentRow(0); + } + } else { + if (!this->completer->setCurrentRow(this->completer->currentRow() - 1)) { + // wrap over and start again + this->completer->setCurrentRow(this->completer->completionCount() - 1); + } } this->completer->complete(); @@ -122,7 +124,13 @@ void ResizingTextEdit::keyPressEvent(QKeyEvent *event) // (hemirt) // this resets the selection in the completion list, it should probably only trigger on actual // chat input (space, character) and not on every key input (pressing alt for example) - this->completionInProgress = false; + // (fourtf) + // fixed for shift+tab, there might be a better solution but nobody is gonna bother anyways + if (event->key() != Qt::Key_Shift && event->key() != Qt::Key_Control && + event->key() != Qt::Key_Alt && event->key() != Qt::Key_Super_L && + event->key() != Qt::Key_Super_R) { + this->completionInProgress = false; + } if (!event->isAccepted()) { QTextEdit::keyPressEvent(event); From 33b94d757f41c9254eeb62b7b636bb9d13b0c8d0 Mon Sep 17 00:00:00 2001 From: fourtf Date: Tue, 10 Apr 2018 02:02:49 +0200 Subject: [PATCH 55/69] Fixes #325 Option tab stays open when closing the main window --- src/widgets/window.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/widgets/window.cpp b/src/widgets/window.cpp index b0163014..83755584 100644 --- a/src/widgets/window.cpp +++ b/src/widgets/window.cpp @@ -11,6 +11,7 @@ #include "widgets/settingsdialog.hpp" #include "widgets/split.hpp" +#include #include #include #include @@ -163,6 +164,8 @@ void Window::closeEvent(QCloseEvent *event) } this->closed.invoke(); + + QApplication::exit(); } } // namespace widgets From 829c028009067ae194b5d1f326d83680ade6523a Mon Sep 17 00:00:00 2001 From: fourtf Date: Tue, 10 Apr 2018 02:07:25 +0200 Subject: [PATCH 56/69] disabled message layouting limits --- src/widgets/helper/channelview.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/widgets/helper/channelview.cpp b/src/widgets/helper/channelview.cpp index a0733740..74b6b7c3 100644 --- a/src/widgets/helper/channelview.cpp +++ b/src/widgets/helper/channelview.cpp @@ -151,13 +151,13 @@ void ChannelView::queueUpdate() void ChannelView::layoutMessages() { - if (!this->layoutCooldown->isActive()) { - this->actuallyLayoutMessages(); + // if (!this->layoutCooldown->isActive()) { + this->actuallyLayoutMessages(); - this->layoutCooldown->start(); - } else { - this->layoutQueued = true; - } + // this->layoutCooldown->start(); + // } else { + // this->layoutQueued = true; + // } } void ChannelView::actuallyLayoutMessages() From 93163518ccd51249877e14cb3380c09912e425a0 Mon Sep 17 00:00:00 2001 From: fourtf Date: Tue, 10 Apr 2018 02:13:41 +0200 Subject: [PATCH 57/69] Fixes #276 Color of the moderator buttons are black if the timestamp is disabled --- src/messages/layouts/messagelayoutelement.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/messages/layouts/messagelayoutelement.cpp b/src/messages/layouts/messagelayoutelement.cpp index 61147a09..61b50117 100644 --- a/src/messages/layouts/messagelayoutelement.cpp +++ b/src/messages/layouts/messagelayoutelement.cpp @@ -241,7 +241,7 @@ void TextIconLayoutElement::paint(QPainter &painter) { QFont font = singletons::FontManager::getInstance().getFont(FontStyle::Tiny, this->scale); - painter.setBrush(singletons::ThemeManager::getInstance().messages.textColors.regular); + painter.setPen(singletons::ThemeManager::getInstance().messages.textColors.system); painter.setFont(font); QTextOption option; From 93f999620776f177a844b7e21e83c4d9e92ff564 Mon Sep 17 00:00:00 2001 From: fourtf Date: Tue, 10 Apr 2018 02:42:41 +0200 Subject: [PATCH 58/69] Fixes #291 links clickable area --- src/messages/layouts/messagelayout.cpp | 2 +- src/messages/layouts/messagelayoutcontainer.cpp | 5 +++++ src/messages/messageelement.cpp | 4 ++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/messages/layouts/messagelayout.cpp b/src/messages/layouts/messagelayout.cpp index 48bac932..3e6cc521 100644 --- a/src/messages/layouts/messagelayout.cpp +++ b/src/messages/layouts/messagelayout.cpp @@ -210,7 +210,7 @@ void MessageLayout::updateBuffer(QPixmap *buffer, int messageIndex, Selection &s QTextOption option; option.setAlignment(Qt::AlignRight | Qt::AlignTop); - painter.drawText(QRectF(1, 1, this->container.width - 3, 1000), + painter.drawText(QRectF(1, 1, this->container.getWidth() - 3, 1000), QString::number(++this->bufferUpdatedCount), option); #endif } diff --git a/src/messages/layouts/messagelayoutcontainer.cpp b/src/messages/layouts/messagelayoutcontainer.cpp index c592b238..1ced1263 100644 --- a/src/messages/layouts/messagelayoutcontainer.cpp +++ b/src/messages/layouts/messagelayoutcontainer.cpp @@ -179,6 +179,11 @@ MessageLayoutElement *MessageLayoutContainer::getElementAt(QPoint point) void MessageLayoutContainer::paintElements(QPainter &painter) { for (const std::unique_ptr &element : this->elements) { +#ifdef OHHEYITSFOURTF + painter.setPen(QColor(0, 255, 0)); + painter.drawRect(element->getRect()); +#endif + element->paint(painter); } } diff --git a/src/messages/messageelement.cpp b/src/messages/messageelement.cpp index faf3c00b..46d8cb63 100644 --- a/src/messages/messageelement.cpp +++ b/src/messages/messageelement.cpp @@ -186,8 +186,8 @@ void TextElement::addToContainer(MessageLayoutContainer &container, MessageEleme int charWidth = metrics.width(text[i]); if (!container.fitsInLine(width + charWidth)) { - container.addElementNoLineBreak(getTextLayoutElement( - text.mid(wordStart, i - wordStart), width - lastWidth, false)); + container.addElementNoLineBreak( + getTextLayoutElement(text.mid(wordStart, i - wordStart), width, false)); container.breakLine(); wordStart = i; From 7093a95e29509a0593a01f28c241d363c521b41c Mon Sep 17 00:00:00 2001 From: fourtf Date: Tue, 10 Apr 2018 03:17:44 +0200 Subject: [PATCH 59/69] fixed issue with selecting text and word wrapping --- src/messages/messageelement.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/messages/messageelement.cpp b/src/messages/messageelement.cpp index 46d8cb63..7334a16a 100644 --- a/src/messages/messageelement.cpp +++ b/src/messages/messageelement.cpp @@ -203,8 +203,8 @@ void TextElement::addToContainer(MessageLayoutContainer &container, MessageEleme width += charWidth; } - container.addElement(getTextLayoutElement(text.mid(wordStart), word.width - lastWidth, - this->hasTrailingSpace())); + container.addElement( + getTextLayoutElement(text.mid(wordStart), width, this->hasTrailingSpace())); container.breakLine(); } } From 739c17c0c88caf04b8ba3d6b6897bd6cf0e2740e Mon Sep 17 00:00:00 2001 From: fourtf Date: Tue, 10 Apr 2018 03:29:00 +0200 Subject: [PATCH 60/69] selections now render over all images --- src/messages/layouts/messagelayout.cpp | 10 ++++----- .../layouts/messagelayoutcontainer.cpp | 22 +++++++++---------- .../layouts/messagelayoutcontainer.hpp | 2 +- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/messages/layouts/messagelayout.cpp b/src/messages/layouts/messagelayout.cpp index 3e6cc521..658f6ad7 100644 --- a/src/messages/layouts/messagelayout.cpp +++ b/src/messages/layouts/messagelayout.cpp @@ -166,6 +166,11 @@ void MessageLayout::paint(QPainter &painter, int y, int messageIndex, Selection painter.fillRect(0, y, pixmap->width(), pixmap->height(), themeManager.messages.disabled); } + // draw selection + if (!selection.isEmpty()) { + this->container.paintSelection(painter, messageIndex, selection, y); + } + // draw last read message line if (isLastReadMessage) { QColor color = isWindowFocused ? themeManager.tabs.selected.backgrounds.regular.color() @@ -193,11 +198,6 @@ void MessageLayout::updateBuffer(QPixmap *buffer, int messageIndex, Selection &s ? themeManager.messages.backgrounds.highlighted : themeManager.messages.backgrounds.regular); - // draw selection - if (!selection.isEmpty()) { - this->container.paintSelection(painter, messageIndex, selection); - } - // draw message this->container.paintElements(painter); diff --git a/src/messages/layouts/messagelayoutcontainer.cpp b/src/messages/layouts/messagelayoutcontainer.cpp index 1ced1263..e6459a02 100644 --- a/src/messages/layouts/messagelayoutcontainer.cpp +++ b/src/messages/layouts/messagelayoutcontainer.cpp @@ -196,7 +196,7 @@ void MessageLayoutContainer::paintAnimatedElements(QPainter &painter, int yOffse } void MessageLayoutContainer::paintSelection(QPainter &painter, int messageIndex, - Selection &selection) + Selection &selection, int yOffset) { singletons::ThemeManager &themeManager = singletons::ThemeManager::getInstance(); QColor selectionColor = themeManager.messages.selection; @@ -211,8 +211,8 @@ void MessageLayoutContainer::paintSelection(QPainter &painter, int messageIndex, for (Line &line : this->lines) { QRect rect = line.rect; - rect.setTop(std::max(0, rect.top())); - rect.setBottom(std::min(this->height, rect.bottom())); + rect.setTop(std::max(0, rect.top()) + yOffset); + rect.setBottom(std::min(this->height, rect.bottom()) + yOffset); rect.setLeft(this->elements[line.startIndex]->getRect().left()); rect.setRight(this->elements[line.endIndex - 1]->getRect().right()); @@ -270,8 +270,8 @@ void MessageLayoutContainer::paintSelection(QPainter &painter, int messageIndex, Line &line = this->lines[lineIndex2]; QRect rect = line.rect; - rect.setTop(std::max(0, rect.top())); - rect.setBottom(std::min(this->height, rect.bottom())); + rect.setTop(std::max(0, rect.top()) + yOffset); + rect.setBottom(std::min(this->height, rect.bottom()) + yOffset); rect.setLeft(this->elements[line.startIndex]->getRect().left()); rect.setRight(this->elements[line.endIndex - 1]->getRect().right()); @@ -290,8 +290,8 @@ void MessageLayoutContainer::paintSelection(QPainter &painter, int messageIndex, QRect rect = line.rect; - rect.setTop(std::max(0, rect.top())); - rect.setBottom(std::min(this->height, rect.bottom())); + rect.setTop(std::max(0, rect.top()) + yOffset); + rect.setBottom(std::min(this->height, rect.bottom()) + yOffset); rect.setLeft(x); rect.setRight(r); @@ -316,8 +316,8 @@ void MessageLayoutContainer::paintSelection(QPainter &painter, int messageIndex, if (line.endCharIndex < /*=*/selection.max.charIndex) { QRect rect = line.rect; - rect.setTop(std::max(0, rect.top())); - rect.setBottom(std::min(this->height, rect.bottom())); + rect.setTop(std::max(0, rect.top()) + yOffset); + rect.setBottom(std::min(this->height, rect.bottom()) + yOffset); rect.setLeft(this->elements[line.startIndex]->getRect().left()); rect.setRight(this->elements[line.endIndex - 1]->getRect().right()); @@ -340,8 +340,8 @@ void MessageLayoutContainer::paintSelection(QPainter &painter, int messageIndex, QRect rect = line.rect; - rect.setTop(std::max(0, rect.top())); - rect.setBottom(std::min(this->height, rect.bottom())); + rect.setTop(std::max(0, rect.top()) + yOffset); + rect.setBottom(std::min(this->height, rect.bottom()) + yOffset); rect.setLeft(this->elements[line.startIndex]->getRect().left()); rect.setRight(r); diff --git a/src/messages/layouts/messagelayoutcontainer.hpp b/src/messages/layouts/messagelayoutcontainer.hpp index 85537811..69cf1660 100644 --- a/src/messages/layouts/messagelayoutcontainer.hpp +++ b/src/messages/layouts/messagelayoutcontainer.hpp @@ -68,7 +68,7 @@ struct MessageLayoutContainer { // painting void paintElements(QPainter &painter); void paintAnimatedElements(QPainter &painter, int yOffset); - void paintSelection(QPainter &painter, int messageIndex, Selection &selection); + void paintSelection(QPainter &painter, int messageIndex, Selection &selection, int yOffset); // selection int getSelectionIndex(QPoint point); From bcf0ebd8ef7d494d0cb202ec4f40ab80929b626d Mon Sep 17 00:00:00 2001 From: fourtf Date: Tue, 10 Apr 2018 15:48:56 +0200 Subject: [PATCH 61/69] Fixes #270 Copying text is broken --- src/messages/layouts/messagelayoutcontainer.cpp | 17 ++++++++++------- src/widgets/helper/channelview.cpp | 8 ++++++-- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/messages/layouts/messagelayoutcontainer.cpp b/src/messages/layouts/messagelayoutcontainer.cpp index e6459a02..596842d8 100644 --- a/src/messages/layouts/messagelayoutcontainer.cpp +++ b/src/messages/layouts/messagelayoutcontainer.cpp @@ -134,7 +134,8 @@ void MessageLayoutContainer::breakLine() } this->lineStart = this->elements.size(); - this->currentX = (int)(this->scale * 8); + // this->currentX = (int)(this->scale * 8); + this->currentX = 0; this->currentY += this->lineHeight; this->height = this->currentY + (this->margin.bottom * this->scale); this->lineHeight = 0; @@ -409,19 +410,21 @@ int MessageLayoutContainer::getLastCharacterIndex() const void MessageLayoutContainer::addSelectionText(QString &str, int from, int to) { int index = 0; - bool xd = true; + bool first = true; for (std::unique_ptr &ele : this->elements) { int c = ele->getSelectionIndexCount(); - if (xd) { + qDebug() << c; + + if (first) { if (index + c > from) { - ele->addCopyTextToString(str, index - from, to - from); - xd = false; + ele->addCopyTextToString(str, from - index, to - from); + first = false; } } else { - if (index + c > from) { - ele->addCopyTextToString(str, 0, index - to); + if (index + c > to) { + ele->addCopyTextToString(str, 0, to - index); break; } else { ele->addCopyTextToString(str); diff --git a/src/widgets/helper/channelview.cpp b/src/widgets/helper/channelview.cpp index 74b6b7c3..3deceb9f 100644 --- a/src/widgets/helper/channelview.cpp +++ b/src/widgets/helper/channelview.cpp @@ -279,14 +279,18 @@ QString ChannelView::getSelectedText() return result; } - for (int msg = selection.min.messageIndex; msg <= selection.min.messageIndex; msg++) { + qDebug() << "xd >>>>"; + for (int msg = selection.min.messageIndex; msg <= selection.max.messageIndex; msg++) { MessageLayoutPtr layout = messagesSnapshot[msg]; int from = msg == selection.min.messageIndex ? selection.min.charIndex : 0; int to = msg == selection.max.messageIndex ? selection.max.charIndex - : layout->getLastCharacterIndex(); + : layout->getLastCharacterIndex() + 1; + + qDebug() << "from:" << from << ", to:" << to; layout->addSelectionText(result, from, to); } + qDebug() << "xd <<<<"; return result; } From d0f1ea8502f45e6d3e4782053c0f0f1c929dc0eb Mon Sep 17 00:00:00 2001 From: fourtf Date: Tue, 10 Apr 2018 15:52:47 +0200 Subject: [PATCH 62/69] fixed text copying if a single word is selected --- src/messages/layouts/messagelayoutcontainer.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/messages/layouts/messagelayoutcontainer.cpp b/src/messages/layouts/messagelayoutcontainer.cpp index 596842d8..b9e78186 100644 --- a/src/messages/layouts/messagelayoutcontainer.cpp +++ b/src/messages/layouts/messagelayoutcontainer.cpp @@ -419,8 +419,12 @@ void MessageLayoutContainer::addSelectionText(QString &str, int from, int to) if (first) { if (index + c > from) { - ele->addCopyTextToString(str, from - index, to - from); + ele->addCopyTextToString(str, from - index, to - index); first = false; + + if (index + c > to) { + break; + } } } else { if (index + c > to) { From c744659ce06fff596e695548dce296622cdd3eb1 Mon Sep 17 00:00:00 2001 From: fourtf Date: Tue, 10 Apr 2018 15:59:53 +0200 Subject: [PATCH 63/69] Open the last selected tab on restart --- src/singletons/windowmanager.cpp | 10 ++++++++++ src/widgets/notebook.cpp | 14 ++++++++++++++ src/widgets/notebook.hpp | 10 ++-------- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/singletons/windowmanager.cpp b/src/singletons/windowmanager.cpp index 1530062b..c99fce47 100644 --- a/src/singletons/windowmanager.cpp +++ b/src/singletons/windowmanager.cpp @@ -186,6 +186,11 @@ void WindowManager::initialize() tab->getTab()->useDefaultTitle = false; } + // selected + if (tab_obj.value("selected").toBool(false)) { + window.getNotebook().select(tab); + } + // load splits int colNr = 0; for (QJsonValue column_val : tab_obj.value("splits").toArray()) { @@ -251,6 +256,11 @@ void WindowManager::save() tab_obj.insert("title", tab->getTab()->getTitle()); } + // selected + if (window->getNotebook().getSelectedPage() == tab) { + tab_obj.insert("selected", true); + } + // splits QJsonArray columns_arr; std::vector> columns = tab->getColumns(); diff --git a/src/widgets/notebook.cpp b/src/widgets/notebook.cpp index 3faa0409..086eb4a9 100644 --- a/src/widgets/notebook.cpp +++ b/src/widgets/notebook.cpp @@ -119,6 +119,20 @@ void Notebook::removeCurrentPage() this->removePage(this->selectedPage); } +SplitContainer *Notebook::getOrAddSelectedPage() +{ + if (selectedPage == nullptr) { + this->addNewPage(true); + } + + return selectedPage; +} + +SplitContainer *Notebook::getSelectedPage() +{ + return selectedPage; +} + void Notebook::select(SplitContainer *page) { if (page == this->selectedPage) { diff --git a/src/widgets/notebook.hpp b/src/widgets/notebook.hpp index 9f0bd4f1..af1c207c 100644 --- a/src/widgets/notebook.hpp +++ b/src/widgets/notebook.hpp @@ -30,14 +30,8 @@ public: void select(SplitContainer *page); void selectIndex(int index); - SplitContainer *getOrAddSelectedPage() - { - if (selectedPage == nullptr) { - this->addNewPage(true); - } - - return selectedPage; - } + SplitContainer *getOrAddSelectedPage(); + SplitContainer *getSelectedPage(); void performLayout(bool animate = true); From ad0a1f3c564806b74b36f9d30f64e4e7bcef928d Mon Sep 17 00:00:00 2001 From: fourtf Date: Tue, 10 Apr 2018 16:53:40 +0200 Subject: [PATCH 64/69] Fixed tabs not highlighting on new messages/highlights --- src/singletons/thememanager.cpp | 25 ++++++++++++++++--------- src/widgets/helper/channelview.cpp | 8 ++++++-- src/widgets/helper/channelview.hpp | 2 +- src/widgets/notebook.hpp | 2 -- src/widgets/splitcontainer.cpp | 9 ++++----- 5 files changed, 27 insertions(+), 19 deletions(-) diff --git a/src/singletons/thememanager.cpp b/src/singletons/thememanager.cpp index d133ee88..97de43f2 100644 --- a/src/singletons/thememanager.cpp +++ b/src/singletons/thememanager.cpp @@ -86,19 +86,26 @@ void ThemeManager::actuallyUpdate(double hue, double multiplier) this->messages.textColors.regular = isLight ? "#000" : "#fff"; /// TABS - // text, {regular, hover, unfocused} - if (lightWin) { this->tabs.regular = {fg, {bg, QColor("#ccc"), bg}}; - this->tabs.newMessage = {fg, {bg, QColor("#ccc"), bg}}; - this->tabs.highlighted = {fg, {bg, QColor("#ccc"), bg}}; - this->tabs.selected = {QColor("#fff"), {QColor("#333"), QColor("#333"), QColor("#666")}}; + this->tabs.newMessage = { + fg, + {QBrush(blendColors(themeColor, "#ccc", 0.9), Qt::FDiagPattern), + QBrush(blendColors(themeColor, "#ccc", 0.9), Qt::FDiagPattern), + QBrush(blendColors(themeColorNoSat, "#ccc", 0.9), Qt::FDiagPattern)}}; + this->tabs.highlighted = {fg, {QColor("#ccc"), QColor("#ccc"), QColor("#bbb")}}; + this->tabs.selected = {QColor("#fff"), + {QColor("#777"), QColor("#777"), QColor("#888")}}; } else { this->tabs.regular = {fg, {bg, QColor("#555"), bg}}; - this->tabs.newMessage = {fg, {bg, QColor("#555"), bg}}; - this->tabs.highlighted = {fg, {bg, QColor("#555"), bg}}; - // this->tabs.selected = {"#000", {themeColor, themeColor, themeColorNoSat}}; - this->tabs.selected = {QColor("#000"), {QColor("#999"), QColor("#999"), QColor("#888")}}; + this->tabs.newMessage = { + fg, + {QBrush(blendColors(themeColor, "#666", 0.7), Qt::FDiagPattern), + QBrush(blendColors(themeColor, "#666", 0.5), Qt::FDiagPattern), + QBrush(blendColors(themeColorNoSat, "#666", 0.7), Qt::FDiagPattern)}}; + this->tabs.highlighted = {fg, {QColor("#777"), QColor("#777"), QColor("#666")}}; + this->tabs.selected = {QColor("#000"), + {QColor("#999"), QColor("#999"), QColor("#888")}}; } } diff --git a/src/widgets/helper/channelview.cpp b/src/widgets/helper/channelview.cpp index 3deceb9f..07999172 100644 --- a/src/widgets/helper/channelview.cpp +++ b/src/widgets/helper/channelview.cpp @@ -359,8 +359,12 @@ void ChannelView::setChannel(ChannelPtr newChannel) } } - if (message->flags & ~Message::DoNotTriggerNotification) { - this->highlightedMessageReceived.invoke(); + if (!(message->flags & Message::DoNotTriggerNotification)) { + if (message->flags & Message::Highlighted) { + this->tabHighlightRequested.invoke(HighlightState::Highlighted); + } else { + this->tabHighlightRequested.invoke(HighlightState::NewMessage); + } } this->scrollBar.addHighlight(message->getScrollBarHighlight()); diff --git a/src/widgets/helper/channelview.hpp b/src/widgets/helper/channelview.hpp index 0db184ac..b231c406 100644 --- a/src/widgets/helper/channelview.hpp +++ b/src/widgets/helper/channelview.hpp @@ -51,7 +51,7 @@ public: pajlada::Signals::Signal mouseDown; pajlada::Signals::NoArgSignal selectionChanged; - pajlada::Signals::NoArgSignal highlightedMessageReceived; + pajlada::Signals::Signal tabHighlightRequested; pajlada::Signals::Signal linkClicked; protected: diff --git a/src/widgets/notebook.hpp b/src/widgets/notebook.hpp index af1c207c..f200cbcb 100644 --- a/src/widgets/notebook.hpp +++ b/src/widgets/notebook.hpp @@ -19,8 +19,6 @@ class Notebook : public BaseWidget Q_OBJECT public: - enum HighlightType { none, highlighted, newMessage }; - explicit Notebook(Window *parent, bool _showButtons); SplitContainer *addNewPage(bool select = false); diff --git a/src/widgets/splitcontainer.cpp b/src/widgets/splitcontainer.cpp index de37c605..8cefb5b5 100644 --- a/src/widgets/splitcontainer.cpp +++ b/src/widgets/splitcontainer.cpp @@ -66,6 +66,8 @@ int SplitContainer::splitCount() const std::pair SplitContainer::removeFromLayout(Split *widget) { + widget->getChannelView().tabHighlightRequested.disconnectAll(); + // remove reference to chat widget from chatWidgets vector auto it = std::find(std::begin(this->splits), std::end(this->splits), widget); if (it != std::end(this->splits)) { @@ -150,6 +152,8 @@ std::pair SplitContainer::removeFromLayout(Split *widget) void SplitContainer::addToLayout(Split *widget, std::pair position) { this->splits.push_back(widget); + widget->getChannelView().tabHighlightRequested.connect( + [this](HighlightState state) { this->tab->setHighlightState(state); }); this->refreshTitle(); @@ -506,11 +510,6 @@ Split *SplitContainer::createChatWidget() { auto split = new Split(this); - split->getChannelView().highlightedMessageReceived.connect([this] { - // fourtf: error potentionally here - this->tab->setHighlightState(HighlightState::Highlighted); // - }); - return split; } From dff6cbb3e1404ed5bf7b8340305d18a75d525fe2 Mon Sep 17 00:00:00 2001 From: fourtf Date: Tue, 10 Apr 2018 17:14:13 +0200 Subject: [PATCH 65/69] fixed split columns not loading properly --- src/singletons/windowmanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/singletons/windowmanager.cpp b/src/singletons/windowmanager.cpp index c99fce47..1c610c99 100644 --- a/src/singletons/windowmanager.cpp +++ b/src/singletons/windowmanager.cpp @@ -204,7 +204,7 @@ void WindowManager::initialize() channelName_val.toString())); } - tab->addToLayout(split, std::make_pair(colNr, -1)); + tab->addToLayout(split, std::make_pair(colNr, 10000000)); } colNr++; } From 2ede50af0e9f1513e147ddf9c75023779a1b3755 Mon Sep 17 00:00:00 2001 From: fourtf Date: Wed, 11 Apr 2018 00:18:33 +0200 Subject: [PATCH 66/69] added version header --- chatterino.pro | 3 ++- src/version.hpp | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 src/version.hpp diff --git a/chatterino.pro b/chatterino.pro index 62a5b2c2..880fb1ee 100644 --- a/chatterino.pro +++ b/chatterino.pro @@ -296,7 +296,8 @@ HEADERS += \ src/util/streamlink.hpp \ src/providers/twitch/twitchhelpers.hpp \ src/util/debugcount.hpp \ - src/widgets/helper/debugpopup.hpp + src/widgets/helper/debugpopup.hpp \ + src/version.hpp RESOURCES += \ resources/resources.qrc diff --git a/src/version.hpp b/src/version.hpp new file mode 100644 index 00000000..d382a521 --- /dev/null +++ b/src/version.hpp @@ -0,0 +1,3 @@ +#pragma once + +#define CHATTERINO_VERSION "2.0.0" From 6bdb9f9c9bf21c2e1216f16c5b446ec4b91e88d7 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Wed, 11 Apr 2018 00:44:23 +0200 Subject: [PATCH 67/69] also add the boost lib folder in case we need to link something --- chatterino.pro | 11 +---------- dependencies/boost.pri | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 10 deletions(-) create mode 100644 dependencies/boost.pri diff --git a/chatterino.pro b/chatterino.pro index 880fb1ee..4ab4b8e7 100644 --- a/chatterino.pro +++ b/chatterino.pro @@ -34,6 +34,7 @@ include(dependencies/humanize.pri) include(dependencies/fmt.pri) DEFINES += IRC_NAMESPACE=Communi include(dependencies/libcommuni.pri) +include(dependencies/boost.pri) # Optional feature: QtWebEngine exists ($(QTDIR)/include/QtWebEngine/QtWebEngine) { @@ -42,16 +43,6 @@ exists ($(QTDIR)/include/QtWebEngine/QtWebEngine) { DEFINES += "USEWEBENGINE" } -# Include boost -win32 { - isEmpty(BOOST_DIRECTORY) { - message(Using default boost directory C:\\local\\boost\\) - BOOST_DIRECTORY = C:\local\boost\ - } - - INCLUDEPATH += $$BOOST_DIRECTORY -} - win32 { LIBS += -luser32 } diff --git a/dependencies/boost.pri b/dependencies/boost.pri new file mode 100644 index 00000000..26a61697 --- /dev/null +++ b/dependencies/boost.pri @@ -0,0 +1,14 @@ +pajlada { + BOOST_DIRECTORY = C:\dev\projects\boost_1_66_0\ +} + +win32 { + isEmpty(BOOST_DIRECTORY) { + message(Using default boost directory C:\\local\\boost\\) + BOOST_DIRECTORY = C:\local\boost\ + } + + INCLUDEPATH += $$BOOST_DIRECTORY + + LIBS += -L$$BOOST_DIRECTORY\lib +} From 52afa7b5b7549c37b01f6848d1c52f4426615d5e Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Wed, 11 Apr 2018 01:06:13 +0200 Subject: [PATCH 68/69] Ensure we disconnect from signals on exit in SplitHeader --- src/widgets/helper/splitheader.cpp | 4 ++-- src/widgets/helper/splitheader.hpp | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/widgets/helper/splitheader.cpp b/src/widgets/helper/splitheader.cpp index e4f9dc0e..f6786302 100644 --- a/src/widgets/helper/splitheader.cpp +++ b/src/widgets/helper/splitheader.cpp @@ -136,9 +136,9 @@ void SplitHeader::initializeChannelSignals() TwitchChannel *twitchChannel = dynamic_cast(channel.get()); if (twitchChannel) { - twitchChannel->updateLiveInfo.connect([this]() { + this->managedConnections.emplace_back(twitchChannel->updateLiveInfo.connect([this]() { this->updateChannelText(); // - }); + })); } } diff --git a/src/widgets/helper/splitheader.hpp b/src/widgets/helper/splitheader.hpp index 80d81ab5..e4095eae 100644 --- a/src/widgets/helper/splitheader.hpp +++ b/src/widgets/helper/splitheader.hpp @@ -14,6 +14,9 @@ #include #include #include +#include + +#include namespace chatterino { namespace widgets { @@ -64,6 +67,8 @@ private: QString tooltip; bool isLive; + std::vector managedConnections; + public slots: void addDropdownItems(RippleEffectButton *label); From 5fb42af9d001855fb660afefbfef56b6d1932ede Mon Sep 17 00:00:00 2001 From: fourtf Date: Wed, 11 Apr 2018 19:45:19 +0200 Subject: [PATCH 69/69] minor changes for linux --- README.md | 3 +-- dependencies/rapidjson.pri | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index fb41a4d2..63494570 100644 --- a/README.md +++ b/README.md @@ -37,8 +37,7 @@ You can also add "-o2" to optimize the final binary size but increase compilatio *most likely works the same for other Debian-like distros* 1. install QT Creator `sudo apt-get install qtcreator qtmultimedia5-dev` 2. install boost-dev `sudo apt-get install libboost-dev` -3. copy `include/rapidjson` from [rapidjson](https://github.com/miloyip/rapidjson/releases/latest) into the chatterino directory so that the file `/rapidjson/document.h` exists -4. open `chatterino.pro` with QT Creator and build +3. open `chatterino.pro` with QT Creator and build #### Ubuntu 18.04 *most likely works the same for other Debian-like distros* diff --git a/dependencies/rapidjson.pri b/dependencies/rapidjson.pri index 1111cfc4..2573a858 100644 --- a/dependencies/rapidjson.pri +++ b/dependencies/rapidjson.pri @@ -1,4 +1,2 @@ # rapidjson -win32 { - INCLUDEPATH += $$PWD/../lib/rapidjson/include/ -} +INCLUDEPATH += $$PWD/../lib/rapidjson/include/