diff --git a/src/providers/irc/AbstractIrcServer.hpp b/src/providers/irc/AbstractIrcServer.hpp index 5127b8a6..c02b8bd4 100644 --- a/src/providers/irc/AbstractIrcServer.hpp +++ b/src/providers/irc/AbstractIrcServer.hpp @@ -28,6 +28,7 @@ public: // channels ChannelPtr getOrAddChannel(const QString &dirtyChannelName); ChannelPtr getChannelOrEmpty(const QString &dirtyChannelName); + std::vector> getChannels(); // signals pajlada::Signals::NoArgSignal connected; diff --git a/src/providers/irc/Irc2.cpp b/src/providers/irc/Irc2.cpp index 44f88f85..551f9ef1 100644 --- a/src/providers/irc/Irc2.cpp +++ b/src/providers/irc/Irc2.cpp @@ -1,6 +1,9 @@ #include "Irc2.hpp" +#include +#include "common/Credentials.hpp" #include "common/SignalVectorModel.hpp" +#include "util/RapidjsonHelpers.hpp" #include "util/StandardItemHelper.hpp" namespace chatterino { @@ -45,15 +48,68 @@ namespace { static std::atomic_int currentId; +//inline QString escape(QString str) +//{ +// return str.replace(":", "::"); +//} + +//inline QString getCredentialName(const IrcConnection_ &conn) +//{ +// //return escape(conn.host) + escape(conn. +//} + +//QString IrcConnection_::getPassword() +//{ +// return +//} + +//void IrcConnection_::setPassword(const QString &str) +//{ +// //Credentials::set("irc", +//} + Irc::Irc() { + this->connections.itemInserted.connect([this](auto &&args) { + // make sure only one id can only exist for one server + assert(this->servers_.find(args.item.id) == this->servers_.end()); + + if (auto ab = this->abandonedChannels_.find(args.item.id); + ab != this->abandonedChannels_.end()) + { + // add new server with abandoned channels + this->servers_.emplace(args.item.id, std::make_unique( + args.item, ab->second)); + this->abandonedChannels_.erase(ab); + } + else + { + // add new server + this->servers_.emplace(args.item.id, + std::make_unique(args.item)); + } + }); + + this->connections.itemRemoved.connect([this](auto &&args) { + // restore + if (auto server = this->servers_.find(args.item.id); + server != this->servers_.end()) + { + this->abandonedChannels_[args.item.id] = + server->second->getChannels(); + this->servers_.erase(server); + } + }); } IrcConnection_ IrcConnection_::unique() { IrcConnection_ c; + c.host = "localhost"; c.id = currentId++; c.port = 6697; + c.user = "xD"; + c.nick = "xD"; return c; } @@ -64,6 +120,29 @@ QAbstractTableModel *Irc::newConnectionModel(QObject *parent) return model; } +IrcServer *Irc::getServerOfChannel(Channel *channel) +{ + for (auto &&server : this->servers_) + for (auto weak : server.second->getChannels()) + if (auto shared = weak.lock()) + if (shared.get() == channel) + return server.second.get(); + + return nullptr; +} + +ChannelPtr Irc::getOrAddChannel(int id, QString name) +{ + if (auto server = this->servers_.find(id); server != this->servers_.end()) + { + return server->second->getOrAddChannel(name); + } + else + { + return Channel::getEmpty(); + } +} + Irc &Irc::getInstance() { static Irc irc; diff --git a/src/providers/irc/Irc2.hpp b/src/providers/irc/Irc2.hpp index ef3d7a92..f50c6b73 100644 --- a/src/providers/irc/Irc2.hpp +++ b/src/providers/irc/Irc2.hpp @@ -1,7 +1,11 @@ #pragma once +#include #include +#include "providers/irc/IrcChannel2.hpp" +#include "providers/irc/IrcServer.hpp" + class QAbstractTableModel; namespace chatterino { @@ -31,8 +35,20 @@ public: UnsortedSignalVector connections; QAbstractTableModel *newConnectionModel(QObject *parent); + IrcServer *getServerOfChannel(Channel *channel); + ChannelPtr getOrAddChannel(int serverId, QString name); + signals: void connectionUpdated(int id); + +private: + // Servers have a unique id. + // When a server gets changed it gets removed and then added again. + // So we store the channels of that server in abandonedChannels_ temporarily. + // Or if the server got removed permanently then it's still stored there. + std::unordered_map> servers_; + std::unordered_map>> + abandonedChannels_; }; } // namespace chatterino diff --git a/src/providers/irc/IrcChannel2.cpp b/src/providers/irc/IrcChannel2.cpp index bbdee208..b938841d 100644 --- a/src/providers/irc/IrcChannel2.cpp +++ b/src/providers/irc/IrcChannel2.cpp @@ -2,8 +2,9 @@ namespace chatterino { -// IrcChannel::IrcChannel() -//{ -//} -// +IrcChannel::IrcChannel(const QString &name) + : Channel(name, Channel::Type::Irc) +{ +} + } // namespace chatterino diff --git a/src/providers/irc/IrcChannel2.hpp b/src/providers/irc/IrcChannel2.hpp index ca6c9e24..53da3e23 100644 --- a/src/providers/irc/IrcChannel2.hpp +++ b/src/providers/irc/IrcChannel2.hpp @@ -1,11 +1,13 @@ #pragma once +#include "common/Channel.hpp" + namespace chatterino { -// class IrcChannel -//{ -// public: -// IrcChannel(); -//}; -// +class IrcChannel : public Channel +{ +public: + explicit IrcChannel(const QString &name); +}; + } // namespace chatterino diff --git a/src/providers/irc/IrcServer.cpp b/src/providers/irc/IrcServer.cpp index be562361..ff256a2b 100644 --- a/src/providers/irc/IrcServer.cpp +++ b/src/providers/irc/IrcServer.cpp @@ -2,11 +2,63 @@ #include +#include "providers/irc/Irc2.hpp" +#include "providers/irc/IrcChannel2.hpp" + namespace chatterino { -// IrcServer::IrcServer(const QString &hostname, int port) -//{ -// this->initConnection(); -//} -// +IrcServer::IrcServer(const IrcConnection_ &data) + : data_(new IrcConnection_(data)) +{ + this->connect(); +} + +IrcServer::IrcServer(const IrcConnection_ &data, + const std::vector> &restoreChannels) + : IrcServer(data) +{ + for (auto &&weak : restoreChannels) + { + if (auto shared = weak.lock()) + { + this->channels[shared->getName()] = weak; + } + } +} + +IrcServer::~IrcServer() +{ + delete this->data_; +} + +int IrcServer::getId() +{ + return this->data_->id; +} + +void IrcServer::initializeConnection(IrcConnection *connection, bool isRead, + bool isWrite) +{ + assert(isRead && isWrite); + + connection->setSecure(this->data_->ssl); + connection->setHost(this->data_->host); + connection->setPort(this->data_->port); + + connection->setUserName(this->data_->user); + connection->setNickName(this->data_->nick); + connection->setRealName(this->data_->nick); + connection->setPassword(this->data_->password); +} + +std::shared_ptr IrcServer::createChannel(const QString &channelName) +{ + return std::make_shared(channelName); +} + +bool IrcServer::hasSeparateWriteConnection() const +{ + return false; +} + } // namespace chatterino diff --git a/src/providers/irc/IrcServer.hpp b/src/providers/irc/IrcServer.hpp index c8faf434..bb921831 100644 --- a/src/providers/irc/IrcServer.hpp +++ b/src/providers/irc/IrcServer.hpp @@ -5,20 +5,28 @@ namespace chatterino { -// class IrcServer -//{ -// public: -// IrcServer(const QString &hostname, int port); +struct IrcConnection_; -// void setAccount(std::shared_ptr newAccount); -// std::shared_ptr getAccount() const; +class IrcServer : public AbstractIrcServer +{ +public: + explicit IrcServer(const IrcConnection_ &data); + IrcServer(const IrcConnection_ &data, + const std::vector> &restoreChannels); + ~IrcServer() override; -// protected: -// virtual void initializeConnection(Communi::IrcConnection *connection, bool -// isReadConnection); + int getId(); + + // AbstractIrcServer interface +protected: + void initializeConnection(IrcConnection *connection, bool isRead, + bool isWrite) override; + std::shared_ptr createChannel(const QString &channelName) override; + bool hasSeparateWriteConnection() const override; + +private: + // pointer so we don't have to circle include Irc2.hpp + IrcConnection_ *data_; +}; -// virtual void privateMessageReceived(Communi::IrcPrivateMessage *message); -// virtual void messageReceived(Communi::IrcMessage *message); -//}; -// } // namespace chatterino