More progress on tab-complete

There are missing parts to the "account-based" emotes that needs to be
completed before emote completion can be considered done. For now, when
I've been testing, I've been manually injecting the oauthClient and
oauthToken to the settings file with the `user_subscriptions` scope
This commit is contained in:
Rasmus Karlsson 2017-07-23 14:16:13 +02:00
parent e4fc6c25e6
commit 3bf111a091
19 changed files with 212 additions and 69 deletions

View file

@ -1,5 +1,7 @@
#include "accountmanager.hpp" #include "accountmanager.hpp"
#include <pajlada/settings/setting.hpp>
namespace chatterino { namespace chatterino {
namespace { namespace {
@ -25,6 +27,9 @@ AccountManager::AccountManager()
if (!envUsername.isEmpty() && !envOauthToken.isEmpty()) { if (!envUsername.isEmpty() && !envOauthToken.isEmpty()) {
this->addTwitchUser(twitch::TwitchUser(envUsername, envOauthToken, "")); this->addTwitchUser(twitch::TwitchUser(envUsername, envOauthToken, ""));
} }
pajlada::Settings::Setting<std::string>::set(
"/accounts/current/roomID", "11148817", pajlada::Settings::SettingOption::DoNotWriteToJSON);
} }
twitch::TwitchUser &AccountManager::getTwitchAnon() twitch::TwitchUser &AccountManager::getTwitchAnon()

View file

@ -9,7 +9,8 @@ namespace chatterino {
// It will create the instances of the major classes, and connect their signals to each other // It will create the instances of the major classes, and connect their signals to each other
Application::Application() Application::Application()
: windowManager(this->channelManager, this->colorScheme) : completionManager(this->emoteManager)
, windowManager(this->channelManager, this->colorScheme, this->completionManager)
, colorScheme(this->windowManager) , colorScheme(this->windowManager)
, emoteManager(this->windowManager, this->resources) , emoteManager(this->windowManager, this->resources)
, resources(this->emoteManager, this->windowManager) , resources(this->emoteManager, this->windowManager)

View file

@ -1,8 +1,11 @@
#include "completionmanager.hpp" #include "completionmanager.hpp"
#include "common.hpp"
#include "emotemanager.hpp"
namespace chatterino { namespace chatterino {
CompletionManager::CompletionManager() CompletionManager::CompletionManager(EmoteManager &_emoteManager)
: emoteManager(_emoteManager)
{ {
} }
@ -10,11 +13,58 @@ CompletionModel *CompletionManager::createModel(const std::string &channelName)
{ {
CompletionModel *ret = new CompletionModel(); CompletionModel *ret = new CompletionModel();
this->updateModel(ret, channelName);
this->emoteManager.bttvGlobalEmoteCodes.updated.connect([=]() {
this->updateModel(ret, channelName); //
});
this->emoteManager.ffzGlobalEmoteCodes.updated.connect([=]() {
this->updateModel(ret, channelName); //
});
this->emoteManager.bttvChannelEmoteCodes[channelName].updated.connect([=]() {
this->updateModel(ret, channelName); //
});
this->emoteManager.ffzChannelEmoteCodes[channelName].updated.connect([=]() {
this->updateModel(ret, channelName); //
});
return ret; return ret;
} }
void CompletionManager::updateModel(CompletionModel *model, const std::string &channelName) void CompletionManager::updateModel(CompletionModel *model, const std::string &channelName)
{ {
model->emotes.clear();
for (const auto &m : this->emoteManager.twitchAccountEmotes) {
for (const auto &emoteName : m.second.emoteCodes) {
model->emotes.push_back(qS(emoteName));
}
}
std::vector<std::string> &bttvGlobalEmoteCodes = this->emoteManager.bttvGlobalEmoteCodes;
for (const auto &m : bttvGlobalEmoteCodes) {
model->emotes.push_back(qS(m));
}
std::vector<std::string> &ffzGlobalEmoteCodes = this->emoteManager.ffzGlobalEmoteCodes;
for (const auto &m : ffzGlobalEmoteCodes) {
model->emotes.push_back(qS(m));
}
std::vector<std::string> &bttvChannelEmoteCodes =
this->emoteManager.bttvChannelEmoteCodes[channelName];
for (const auto &m : bttvChannelEmoteCodes) {
model->emotes.push_back(qS(m));
}
std::vector<std::string> &ffzChannelEmoteCodes =
this->emoteManager.ffzChannelEmoteCodes[channelName];
for (const auto &m : ffzChannelEmoteCodes) {
model->emotes.push_back(qS(m));
}
} }
} // namespace chatterino } // namespace chatterino

View file

@ -1,12 +1,15 @@
#pragma once #pragma once
#include <QAbstractItemModel> #include <QAbstractListModel>
#include <QVector>
#include <string> #include <string>
namespace chatterino { namespace chatterino {
class CompletionModel : public QAbstractItemModel class EmoteManager;
class CompletionModel : public QAbstractListModel
{ {
public: public:
virtual int columnCount(const QModelIndex & /*parent*/) const override virtual int columnCount(const QModelIndex & /*parent*/) const override
@ -16,34 +19,27 @@ public:
virtual QVariant data(const QModelIndex &index, int role) const override virtual QVariant data(const QModelIndex &index, int role) const override
{ {
// TODO: Implement // TODO: Implement more safely
return QVariant(); return QVariant(this->emotes.at(index.row()));
}
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const override
{
// TODO: Implement
return QModelIndex();
}
virtual QModelIndex parent(const QModelIndex &child) const override
{
return QModelIndex();
} }
virtual int rowCount(const QModelIndex &parent) const override virtual int rowCount(const QModelIndex &parent) const override
{ {
return 1; return this->emotes.size();
} }
QVector<QString> emotes;
}; };
class CompletionManager class CompletionManager
{ {
CompletionManager(); CompletionManager(EmoteManager &_emoteManager);
EmoteManager &emoteManager;
public: public:
CompletionModel *createModel(const std::string &channelName); CompletionModel *createModel(const std::string &channelName);
void updateModel(CompletionModel *model, const std::string &channelName); void updateModel(CompletionModel *model, const std::string &channelName = std::string());
friend class Application; friend class Application;
}; };

View file

@ -1,4 +1,5 @@
#include "emotemanager.hpp" #include "emotemanager.hpp"
#include "common.hpp"
#include "resources.hpp" #include "resources.hpp"
#include "util/urlfetch.hpp" #include "util/urlfetch.hpp"
#include "windowmanager.hpp" #include "windowmanager.hpp"
@ -25,6 +26,12 @@ EmoteManager::EmoteManager(WindowManager &_windowManager, Resources &_resources)
, resources(_resources) , resources(_resources)
{ {
// Note: Do not use this->resources in ctor // Note: Do not use this->resources in ctor
pajlada::Settings::Setting<std::string> roomID(
"/accounts/current/roomID", "", pajlada::Settings::SettingOption::DoNotWriteToJSON);
roomID.getValueChangedSignal().connect([this](const std::string &roomID) {
this->refreshTwitchEmotes(roomID); //
});
} }
void EmoteManager::loadGlobalEmotes() void EmoteManager::loadGlobalEmotes()
@ -48,6 +55,7 @@ void EmoteManager::reloadBTTVChannelEmotes(const QString &channelName)
QString linkTemplate = "https:" + rootNode.value("urlTemplate").toString(); QString linkTemplate = "https:" + rootNode.value("urlTemplate").toString();
std::vector<std::string> codes;
for (const QJsonValue &emoteNode : emotesNode) { for (const QJsonValue &emoteNode : emotesNode) {
QJsonObject emoteObject = emoteNode.toObject(); QJsonObject emoteObject = emoteNode.toObject();
@ -67,7 +75,10 @@ void EmoteManager::reloadBTTVChannelEmotes(const QString &channelName)
this->bttvChannelEmotes.insert(code, emote); this->bttvChannelEmotes.insert(code, emote);
channelEmoteMap.insert(code, emote); channelEmoteMap.insert(code, emote);
codes.push_back(code.toStdString());
} }
this->bttvChannelEmoteCodes[channelName.toStdString()] = codes;
}); });
} }
@ -84,6 +95,7 @@ void EmoteManager::reloadFFZChannelEmotes(const QString &channelName)
auto setsNode = rootNode.value("sets").toObject(); auto setsNode = rootNode.value("sets").toObject();
std::vector<std::string> codes;
for (const QJsonValue &setNode : setsNode) { for (const QJsonValue &setNode : setsNode) {
auto emotesNode = setNode.toObject().value("emoticons").toArray(); auto emotesNode = setNode.toObject().value("emoticons").toArray();
@ -105,7 +117,10 @@ void EmoteManager::reloadFFZChannelEmotes(const QString &channelName)
this->ffzChannelEmotes.insert(code, emote); this->ffzChannelEmotes.insert(code, emote);
channelEmoteMap.insert(code, emote); channelEmoteMap.insert(code, emote);
codes.push_back(code.toStdString());
} }
this->ffzChannelEmoteCodes[channelName.toStdString()] = codes;
} }
}); });
} }
@ -279,9 +294,61 @@ void EmoteManager::parseEmojis(std::vector<std::tuple<EmoteData, QString>> &pars
} }
} }
void EmoteManager::refreshTwitchEmotes(const std::string &roomID)
{
std::string oauthClient =
pajlada::Settings::Setting<std::string>::get("/accounts/" + roomID + "/oauthClient");
std::string oauthToken =
pajlada::Settings::Setting<std::string>::get("/accounts/" + roomID + "/oauthToken");
TwitchAccountEmoteData &emoteData = this->twitchAccountEmotes[roomID];
if (emoteData.filled) {
qDebug() << "Already loaded for room id " << qS(roomID);
return;
}
qDebug() << "Loading emotes for room id " << qS(roomID);
if (oauthClient.empty() || oauthToken.empty()) {
qDebug() << "Missing oauth client/token";
return;
}
// api:v5
QString url("https://api.twitch.tv/kraken/users/" + qS(roomID) +
"/emotes?api_version=5&oauth_token=" + qS(oauthToken) +
"&client_id=" + qS(oauthClient));
qDebug() << url;
util::urlFetchJSONTimeout(
url,
[=, &emoteData](QJsonObject &root) {
emoteData.emoteSets.clear();
emoteData.emoteCodes.clear();
auto emoticonSets = root.value("emoticon_sets").toObject();
for (QJsonObject::iterator it = emoticonSets.begin(); it != emoticonSets.end(); ++it) {
std::string emoteSetString = it.key().toStdString();
QJsonArray emoteSetList = it.value().toArray();
for (QJsonValue emoteValue : emoteSetList) {
QJsonObject emoticon = emoteValue.toObject();
std::string id = emoticon["id"].toString().toStdString();
std::string code = emoticon["code"].toString().toStdString();
emoteData.emoteSets[emoteSetString].push_back({id, code});
emoteData.emoteCodes.push_back(code);
}
}
emoteData.filled = true;
},
3000);
}
void EmoteManager::loadBTTVEmotes() void EmoteManager::loadBTTVEmotes()
{ {
// bttv
QNetworkAccessManager *manager = new QNetworkAccessManager(); QNetworkAccessManager *manager = new QNetworkAccessManager();
QUrl url("https://api.betterttv.net/2/emotes"); QUrl url("https://api.betterttv.net/2/emotes");
@ -299,6 +366,7 @@ void EmoteManager::loadBTTVEmotes()
QString linkTemplate = "https:" + root.value("urlTemplate").toString(); QString linkTemplate = "https:" + root.value("urlTemplate").toString();
std::vector<std::string> codes;
for (const QJsonValue &emote : emotes) { for (const QJsonValue &emote : emotes) {
QString id = emote.toObject().value("id").toString(); QString id = emote.toObject().value("id").toString();
QString code = emote.toObject().value("code").toString(); QString code = emote.toObject().value("code").toString();
@ -311,7 +379,10 @@ void EmoteManager::loadBTTVEmotes()
this->bttvGlobalEmotes.insert( this->bttvGlobalEmotes.insert(
code, new LazyLoadedImage(*this, this->windowManager, url, 1, code, code, new LazyLoadedImage(*this, this->windowManager, url, 1, code,
code + "\nGlobal BTTV Emote")); code + "\nGlobal BTTV Emote"));
codes.push_back(code.toStdString());
} }
this->bttvGlobalEmoteCodes = codes;
} }
reply->deleteLater(); reply->deleteLater();
@ -321,7 +392,6 @@ void EmoteManager::loadBTTVEmotes()
void EmoteManager::loadFFZEmotes() void EmoteManager::loadFFZEmotes()
{ {
// ffz
QNetworkAccessManager *manager = new QNetworkAccessManager(); QNetworkAccessManager *manager = new QNetworkAccessManager();
QUrl url("https://api.frankerfacez.com/v1/set/global"); QUrl url("https://api.frankerfacez.com/v1/set/global");
@ -337,6 +407,7 @@ void EmoteManager::loadFFZEmotes()
auto sets = root.value("sets").toObject(); auto sets = root.value("sets").toObject();
std::vector<std::string> codes;
for (const QJsonValue &set : sets) { for (const QJsonValue &set : sets) {
auto emoticons = set.toObject().value("emoticons").toArray(); auto emoticons = set.toObject().value("emoticons").toArray();
@ -354,7 +425,10 @@ void EmoteManager::loadFFZEmotes()
this->ffzGlobalEmotes.insert( this->ffzGlobalEmotes.insert(
code, new LazyLoadedImage(*this, this->windowManager, url1, 1, code, code, new LazyLoadedImage(*this, this->windowManager, url1, 1, code,
code + "\nGlobal FFZ Emote")); code + "\nGlobal FFZ Emote"));
codes.push_back(code.toStdString());
} }
this->ffzGlobalEmoteCodes = codes;
} }
} }

View file

@ -5,6 +5,7 @@
#include "concurrentmap.hpp" #include "concurrentmap.hpp"
#include "emojis.hpp" #include "emojis.hpp"
#include "messages/lazyloadedimage.hpp" #include "messages/lazyloadedimage.hpp"
#include "signalvector.hpp"
#include "twitch/emotevalue.hpp" #include "twitch/emotevalue.hpp"
#include <QMap> #include <QMap>
@ -88,11 +89,26 @@ private:
public: public:
void parseEmojis(std::vector<std::tuple<EmoteData, QString>> &parsedWords, const QString &text); void parseEmojis(std::vector<std::tuple<EmoteData, QString>> &parsedWords, const QString &text);
private:
/// Twitch emotes /// Twitch emotes
// username emote code void refreshTwitchEmotes(const std::string &roomID);
ConcurrentStdMap<QString, std::vector<QString>> twitchAccountEmotes;
struct TwitchAccountEmoteData {
struct TwitchEmote {
std::string id;
std::string code;
};
// emote set
std::map<std::string, std::vector<TwitchEmote>> emoteSets;
std::vector<std::string> emoteCodes;
bool filled = false;
};
std::map<std::string, TwitchAccountEmoteData> twitchAccountEmotes;
private:
// emote code // emote code
ConcurrentMap<QString, twitch::EmoteValue *> _twitchEmotes; ConcurrentMap<QString, twitch::EmoteValue *> _twitchEmotes;
@ -105,6 +121,9 @@ private:
public: public:
ConcurrentMap<QString, EmoteMap> bttvChannels; ConcurrentMap<QString, EmoteMap> bttvChannels;
EmoteMap bttvGlobalEmotes; EmoteMap bttvGlobalEmotes;
SignalVector<std::string> bttvGlobalEmoteCodes;
// roomID
std::map<std::string, SignalVector<std::string>> bttvChannelEmoteCodes;
EmoteMap _bttvChannelEmoteFromCaches; EmoteMap _bttvChannelEmoteFromCaches;
private: private:
@ -116,6 +135,8 @@ private:
public: public:
ConcurrentMap<QString, EmoteMap> ffzChannels; ConcurrentMap<QString, EmoteMap> ffzChannels;
EmoteMap ffzGlobalEmotes; EmoteMap ffzGlobalEmotes;
SignalVector<std::string> ffzGlobalEmoteCodes;
std::map<std::string, SignalVector<std::string>> ffzChannelEmoteCodes;
private: private:
ConcurrentMap<int, EmoteData> _ffzChannelEmoteFromCaches; ConcurrentMap<int, EmoteData> _ffzChannelEmoteFromCaches;

View file

@ -79,8 +79,6 @@ Communi::IrcConnection *IrcManager::createConnection(bool doRead)
this->refreshIgnoredUsers(username, oauthClient, oauthToken); this->refreshIgnoredUsers(username, oauthClient, oauthToken);
} }
this->refreshTwitchEmotes(username, oauthClient, oauthToken);
if (doRead) { if (doRead) {
connection->sendCommand( connection->sendCommand(
Communi::IrcCommand::createCapability("REQ", "twitch.tv/membership")); Communi::IrcCommand::createCapability("REQ", "twitch.tv/membership"));
@ -130,34 +128,6 @@ void IrcManager::refreshIgnoredUsers(const QString &username, const QString &oau
}); });
} }
void IrcManager::refreshTwitchEmotes(const QString &username, const QString &oauthClient,
const QString &oauthToken)
{
QString url("https://api.twitch.tv/kraken/users/" + username +
"/emotes?oauth_token=" + oauthToken + "&client_id=" + oauthClient);
if (true) {
util::urlFetchJSONTimeout(
url,
[=](QJsonObject &root) {
// nextLink =
// root.value("_links").toObject().value("next").toString();
auto blocks = root.value("blocks").toArray();
_twitchBlockedUsersMutex.lock();
for (QJsonValue block : blocks) {
QJsonObject user = block.toObject().value("user").toObject();
// display_name
_twitchBlockedUsers.insert(user.value("name").toString().toLower(), true);
}
_twitchBlockedUsersMutex.unlock();
qDebug() << "XD";
},
3000, &this->networkAccessManager);
}
}
void IrcManager::beginConnecting() void IrcManager::beginConnecting()
{ {
uint32_t generation = ++this->connectionGeneration; uint32_t generation = ++this->connectionGeneration;
@ -305,6 +275,7 @@ void IrcManager::handleRoomStateMessage(Communi::IrcMessage *message)
if (iterator != tags.end()) { if (iterator != tags.end()) {
std::string roomID = iterator.value().toString().toStdString(); std::string roomID = iterator.value().toString().toStdString();
this->resources.loadChannelData(roomID); this->resources.loadChannelData(roomID);
} }
} }

View file

@ -76,8 +76,6 @@ private:
void refreshIgnoredUsers(const QString &username, const QString &oauthClient, void refreshIgnoredUsers(const QString &username, const QString &oauthClient,
const QString &oauthToken); const QString &oauthToken);
void refreshTwitchEmotes(const QString &username, const QString &oauthClient,
const QString &oauthToken);
void beginConnecting(); void beginConnecting();

View file

@ -37,6 +37,7 @@ static int index = 0;
ChatWidget::ChatWidget(ChannelManager &_channelManager, NotebookPage *parent) ChatWidget::ChatWidget(ChannelManager &_channelManager, NotebookPage *parent)
: BaseWidget(parent) : BaseWidget(parent)
, channelManager(_channelManager) , channelManager(_channelManager)
, completionManager(parent->completionManager)
, channel(_channelManager.emptyChannel) , channel(_channelManager.emptyChannel)
, vbox(this) , vbox(this)
, header(this) , header(this)

View file

@ -21,6 +21,7 @@ namespace chatterino {
class ChannelManager; class ChannelManager;
class ColorScheme; class ColorScheme;
class CompletionManager;
namespace widgets { namespace widgets {
@ -59,9 +60,11 @@ public:
protected: protected:
virtual void paintEvent(QPaintEvent *) override; virtual void paintEvent(QPaintEvent *) override;
private: public:
ChannelManager &channelManager; ChannelManager &channelManager;
CompletionManager &completionManager;
private:
void setChannel(std::shared_ptr<Channel> newChannel); void setChannel(std::shared_ptr<Channel> newChannel);
void detachChannel(); void detachChannel();

View file

@ -1,6 +1,7 @@
#include "widgets/chatwidgetinput.hpp" #include "widgets/chatwidgetinput.hpp"
#include "chatwidget.hpp" #include "chatwidget.hpp"
#include "colorscheme.hpp" #include "colorscheme.hpp"
#include "completionmanager.hpp"
#include "ircmanager.hpp" #include "ircmanager.hpp"
#include "settingsmanager.hpp" #include "settingsmanager.hpp"
@ -45,8 +46,8 @@ ChatWidgetInput::ChatWidgetInput(ChatWidget *_chatWidget)
this->refreshTheme(); this->refreshTheme();
this->setMessageLengthVisible(SettingsManager::getInstance().showMessageLength.get()); this->setMessageLengthVisible(SettingsManager::getInstance().showMessageLength.get());
// TODO: Fill in this QCompleter model using our CompletionManager auto completer = new QCompleter(
auto completer = new QCompleter(); this->chatWidget->completionManager.createModel(this->chatWidget->channelName));
this->textInput.setCompleter(completer); this->textInput.setCompleter(completer);

View file

@ -19,10 +19,12 @@
namespace chatterino { namespace chatterino {
namespace widgets { namespace widgets {
MainWindow::MainWindow(ChannelManager &_channelManager, ColorScheme &_colorScheme) MainWindow::MainWindow(ChannelManager &_channelManager, ColorScheme &_colorScheme,
CompletionManager &_completionManager)
: BaseWidget(_colorScheme, nullptr) : BaseWidget(_colorScheme, nullptr)
, channelManager(_channelManager) , channelManager(_channelManager)
, colorScheme(_colorScheme) , colorScheme(_colorScheme)
, completionManager(_completionManager)
, notebook(this->channelManager, this) , notebook(this->channelManager, this)
, windowGeometry("/windows/0/geometry") , windowGeometry("/windows/0/geometry")
{ {

View file

@ -17,6 +17,7 @@ namespace chatterino {
class ChannelManager; class ChannelManager;
class ColorScheme; class ColorScheme;
class CompletionManager;
namespace widgets { namespace widgets {
@ -25,7 +26,8 @@ class MainWindow : public BaseWidget
Q_OBJECT Q_OBJECT
public: public:
explicit MainWindow(ChannelManager &_channelManager, ColorScheme &_colorScheme); explicit MainWindow(ChannelManager &_channelManager, ColorScheme &_colorScheme,
CompletionManager &_completionManager);
~MainWindow(); ~MainWindow();
void layoutVisibleChatWidgets(Channel *channel = nullptr); void layoutVisibleChatWidgets(Channel *channel = nullptr);
@ -48,6 +50,7 @@ private:
ChannelManager &channelManager; ChannelManager &channelManager;
ColorScheme &colorScheme; ColorScheme &colorScheme;
CompletionManager &completionManager;
Notebook notebook; Notebook notebook;
bool loaded = false; bool loaded = false;
@ -144,6 +147,8 @@ private:
}; };
pajlada::Settings::Setting<QRectWrapper, QRectWrapper> windowGeometry; pajlada::Settings::Setting<QRectWrapper, QRectWrapper> windowGeometry;
friend class Notebook;
}; };
} // namespace widgets } // namespace widgets

View file

@ -1,5 +1,6 @@
#include "widgets/notebook.hpp" #include "widgets/notebook.hpp"
#include "colorscheme.hpp" #include "colorscheme.hpp"
#include "widgets/mainwindow.hpp"
#include "widgets/notebookbutton.hpp" #include "widgets/notebookbutton.hpp"
#include "widgets/notebookpage.hpp" #include "widgets/notebookpage.hpp"
#include "widgets/notebooktab.hpp" #include "widgets/notebooktab.hpp"
@ -18,9 +19,10 @@
namespace chatterino { namespace chatterino {
namespace widgets { namespace widgets {
Notebook::Notebook(ChannelManager &_channelManager, BaseWidget *parent) Notebook::Notebook(ChannelManager &_channelManager, MainWindow *parent)
: BaseWidget(parent) : BaseWidget(parent)
, channelManager(_channelManager) , channelManager(_channelManager)
, completionManager(parent->completionManager)
, addButton(this) , addButton(this)
, settingsButton(this) , settingsButton(this)
, userButton(this) , userButton(this)

View file

@ -12,10 +12,12 @@
namespace chatterino { namespace chatterino {
class ChannelManager; class ChannelManager;
class ColorScheme; class CompletionManager;
namespace widgets { namespace widgets {
class MainWindow;
class Notebook : public BaseWidget class Notebook : public BaseWidget
{ {
Q_OBJECT Q_OBJECT
@ -23,7 +25,7 @@ class Notebook : public BaseWidget
public: public:
enum HighlightType { none, highlighted, newMessage }; enum HighlightType { none, highlighted, newMessage };
explicit Notebook(ChannelManager &_channelManager, BaseWidget *parent); explicit Notebook(ChannelManager &_channelManager, MainWindow *parent);
NotebookPage *addPage(bool select = false); NotebookPage *addPage(bool select = false);
@ -50,9 +52,11 @@ public slots:
void usersButtonClicked(); void usersButtonClicked();
void addPageButtonClicked(); void addPageButtonClicked();
private: public:
ChannelManager &channelManager; ChannelManager &channelManager;
CompletionManager &completionManager;
private:
QList<NotebookPage *> pages; QList<NotebookPage *> pages;
NotebookButton addButton; NotebookButton addButton;

View file

@ -25,6 +25,7 @@ std::pair<int, int> NotebookPage::dropPosition = std::pair<int, int>(-1, -1);
NotebookPage::NotebookPage(ChannelManager &_channelManager, Notebook *parent, NotebookTab *_tab) NotebookPage::NotebookPage(ChannelManager &_channelManager, Notebook *parent, NotebookTab *_tab)
: BaseWidget(parent->colorScheme, parent) : BaseWidget(parent->colorScheme, parent)
, channelManager(_channelManager) , channelManager(_channelManager)
, completionManager(parent->completionManager)
, tab(_tab) , tab(_tab)
, dropPreview(this) , dropPreview(this)
{ {

View file

@ -18,6 +18,7 @@
namespace chatterino { namespace chatterino {
class ChannelManager; class ChannelManager;
class CompletionManager;
namespace widgets { namespace widgets {
@ -29,6 +30,7 @@ public:
NotebookPage(ChannelManager &_channelManager, Notebook *parent, NotebookTab *_tab); NotebookPage(ChannelManager &_channelManager, Notebook *parent, NotebookTab *_tab);
ChannelManager &channelManager; ChannelManager &channelManager;
CompletionManager &completionManager;
std::pair<int, int> removeFromLayout(ChatWidget *widget); std::pair<int, int> removeFromLayout(ChatWidget *widget);
void addToLayout(ChatWidget *widget, std::pair<int, int> position); void addToLayout(ChatWidget *widget, std::pair<int, int> position);

View file

@ -10,9 +10,11 @@
namespace chatterino { namespace chatterino {
WindowManager::WindowManager(ChannelManager &_channelManager, ColorScheme &_colorScheme) WindowManager::WindowManager(ChannelManager &_channelManager, ColorScheme &_colorScheme,
CompletionManager &_completionManager)
: channelManager(_channelManager) : channelManager(_channelManager)
, colorScheme(_colorScheme) , colorScheme(_colorScheme)
, completionManager(_completionManager)
{ {
} }
@ -56,7 +58,8 @@ widgets::MainWindow &WindowManager::getMainWindow()
std::lock_guard<std::mutex> lock(this->windowMutex); std::lock_guard<std::mutex> lock(this->windowMutex);
if (this->mainWindow == nullptr) { if (this->mainWindow == nullptr) {
this->mainWindow = new widgets::MainWindow(this->channelManager, this->colorScheme); this->mainWindow = new widgets::MainWindow(this->channelManager, this->colorScheme,
this->completionManager);
} }
return *this->mainWindow; return *this->mainWindow;

View file

@ -8,14 +8,17 @@ namespace chatterino {
class ChannelManager; class ChannelManager;
class ColorScheme; class ColorScheme;
class CompletionManager;
class WindowManager class WindowManager
{ {
public: public:
explicit WindowManager(ChannelManager &_channelManager, ColorScheme &_colorScheme); explicit WindowManager(ChannelManager &_channelManager, ColorScheme &_colorScheme,
CompletionManager &_completionManager);
ChannelManager &channelManager; ChannelManager &channelManager;
ColorScheme &colorScheme; ColorScheme &colorScheme;
CompletionManager &completionManager;
void layoutVisibleChatWidgets(Channel *channel = nullptr); void layoutVisibleChatWidgets(Channel *channel = nullptr);
void repaintVisibleChatWidgets(Channel *channel = nullptr); void repaintVisibleChatWidgets(Channel *channel = nullptr);