From c4d0efacffdf910b1c2ff448120ed080611ebeaf Mon Sep 17 00:00:00 2001 From: fourtf Date: Tue, 10 Sep 2019 23:55:43 +0200 Subject: [PATCH] added loading and saving of irc servers --- src/Application.cpp | 3 + src/common/SignalVectorModel.hpp | 5 + src/providers/irc/Irc2.cpp | 108 +++++++++++++++++--- src/providers/irc/Irc2.hpp | 18 +++- src/singletons/Paths.cpp | 2 +- src/widgets/dialogs/IrcConnectionEditor.cpp | 46 +++++++-- src/widgets/dialogs/IrcConnectionEditor.hpp | 19 +++- src/widgets/dialogs/IrcConnectionEditor.ui | 89 ++++++++++++++-- src/widgets/dialogs/IrcConnectionPopup.cpp | 4 +- src/widgets/dialogs/SelectChannelDialog.cpp | 78 +++++++------- 10 files changed, 292 insertions(+), 80 deletions(-) diff --git a/src/Application.cpp b/src/Application.cpp index 37b26394b..332272246 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -13,6 +13,7 @@ #include "providers/bttv/BttvEmotes.hpp" #include "providers/chatterino/ChatterinoBadges.hpp" #include "providers/ffz/FfzEmotes.hpp" +#include "providers/irc/Irc2.hpp" #include "providers/twitch/PubsubClient.hpp" #include "providers/twitch/TwitchServer.hpp" #include "singletons/Emotes.hpp" @@ -69,6 +70,8 @@ Application::Application(Settings &_settings, Paths &_paths) this->fonts->fontChanged.connect( [this]() { this->windows->layoutChannelViews(); }); + Irc::getInstance().load(); + this->twitch.server = this->twitch2; this->twitch.pubsub = this->twitch2->pubsub; } diff --git a/src/common/SignalVectorModel.hpp b/src/common/SignalVectorModel.hpp index d79263830..73e64d099 100644 --- a/src/common/SignalVectorModel.hpp +++ b/src/common/SignalVectorModel.hpp @@ -185,6 +185,11 @@ public: Qt::ItemFlags flags(const QModelIndex &index) const override { int row = index.row(), column = index.column(); + + if (row < 0 || column < 0) { + return Qt::NoItemFlags; + } + assert(row >= 0 && row < this->rows_.size() && column >= 0 && column < this->columnCount_); diff --git a/src/providers/irc/Irc2.cpp b/src/providers/irc/Irc2.cpp index 5f92ad590..d2857b433 100644 --- a/src/providers/irc/Irc2.cpp +++ b/src/providers/irc/Irc2.cpp @@ -3,17 +3,26 @@ #include #include "common/Credentials.hpp" #include "common/SignalVectorModel.hpp" +#include "singletons/Paths.hpp" +#include "util/CombinePath.hpp" #include "util/RapidjsonHelpers.hpp" #include "util/StandardItemHelper.hpp" +#include + namespace chatterino { namespace { + QString configPath() + { + return combinePath(getPaths()->settingsDirectory, "irc.json"); + } + class Model : public SignalVectorModel { public: Model(QObject *parent) - : SignalVectorModel(7, parent) + : SignalVectorModel(8, parent) { } @@ -39,7 +48,7 @@ namespace { void getRowFromItem(const IrcConnection_ &item, std::vector &row) { - setStringItem(row[0], item.host); + setStringItem(row[0], item.host, false); setStringItem(row[1], QString::number(item.port)); setBoolItem(row[2], item.ssl); setStringItem(row[3], item.user); @@ -50,8 +59,6 @@ namespace { }; } // namespace -static std::atomic_int currentId; - //inline QString escape(QString str) //{ // return str.replace(":", "::"); @@ -120,19 +127,8 @@ Irc::Irc() this->servers_.erase(server); } }); -} -IrcConnection_ IrcConnection_::unique() -{ - IrcConnection_ c; - c.host = "localhost"; - c.id = currentId++; - c.port = 6667; - c.ssl = false; - c.user = "xD"; - c.nick = "xD"; - c.real = "xD"; - return c; + this->connections.delayedItemsChanged.connect([this] { this->save(); }); } QAbstractTableModel *Irc::newConnectionModel(QObject *parent) @@ -160,4 +156,84 @@ Irc &Irc::getInstance() return irc; } +int Irc::uniqueId() +{ + /// XXX: also check for channels + int i = this->currentId_ + 1; + auto it = this->servers_.find(i); + + while (it != this->servers_.end()) + { + i++; + it = this->servers_.find(i); + } + + return (this->currentId_ = i); +} + +void Irc::save() +{ + QJsonDocument doc; + QJsonObject root; + QJsonArray servers; + + for (auto &&conn : this->connections) + { + QJsonObject obj; + obj.insert("host", conn.host); + obj.insert("port", conn.port); + obj.insert("ssl", conn.ssl); + obj.insert("username", conn.user); + obj.insert("nickname", conn.nick); + obj.insert("realname", conn.real); + //obj.insert("password", conn.password); + obj.insert("id", conn.id); + servers.append(obj); + } + + root.insert("servers", servers); + doc.setObject(root); + + QSaveFile file(configPath()); + file.open(QIODevice::WriteOnly); + file.write(doc.toJson()); + file.commit(); +} + +void Irc::load() +{ + if (this->loaded_) + return; + this->loaded_ = true; + + QString config = configPath(); + QFile file(configPath()); + file.open(QIODevice::ReadOnly); + auto doc = QJsonDocument::fromJson(file.readAll()); + + auto object = doc.object(); + std::unordered_set ids; + + for (auto server : doc.object().value("servers").toArray()) + { + auto obj = server.toObject(); + IrcConnection_ conn; + conn.host = obj.value("host").toString(conn.host); + conn.port = obj.value("port").toInt(conn.port); + conn.ssl = obj.value("ssl").toBool(conn.ssl); + conn.user = obj.value("username").toString(conn.user); + conn.nick = obj.value("nickname").toString(conn.nick); + conn.real = obj.value("realname").toString(conn.real); + // conn.password = obj.value("password").toString(conn.password); + conn.id = obj.value("id").toInt(conn.id); + + // duplicate id's are not allowed :( + if (ids.find(conn.id) == ids.end()) + { + this->connections.appendItem(conn); + ids.insert(conn.id); + } + } +} + } // namespace chatterino diff --git a/src/providers/irc/Irc2.hpp b/src/providers/irc/Irc2.hpp index ec99c8511..ff23e4f68 100644 --- a/src/providers/irc/Irc2.hpp +++ b/src/providers/irc/Irc2.hpp @@ -10,21 +10,21 @@ class QAbstractTableModel; namespace chatterino { +//enum IrcAuthType { Anonymous, /*Sals,*/ Pass, MsgNickServ, NickServ }; + struct IrcConnection_ { QString host; - int port; - bool ssl; + int port = 6667; + bool ssl = false; QString user; QString nick; QString real; + // IrcAuthType authType = Anonymous; QString password; int id; - - // makes an IrcConnection with a unique id - static IrcConnection_ unique(); }; class Irc @@ -39,10 +39,18 @@ public: ChannelPtr getOrAddChannel(int serverId, QString name); + void save(); + void load(); + + int uniqueId(); + signals: void connectionUpdated(int id); private: + int currentId_{}; + bool loaded_{}; + // 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. diff --git a/src/singletons/Paths.cpp b/src/singletons/Paths.cpp index 0ba547135..eea60a6b2 100644 --- a/src/singletons/Paths.cpp +++ b/src/singletons/Paths.cpp @@ -135,7 +135,7 @@ void Paths::initSubDirectories() this->messageLogDirectory = makePath("Logs"); this->miscDirectory = makePath("Misc"); this->twitchProfileAvatars = makePath("ProfileAvatars"); - QDir().mkdir(this->twitchProfileAvatars + "/twitch"); + //QDir().mkdir(this->twitchProfileAvatars + "/twitch"); } Paths *getPaths() diff --git a/src/widgets/dialogs/IrcConnectionEditor.cpp b/src/widgets/dialogs/IrcConnectionEditor.cpp index 14ba38151..8a2134423 100644 --- a/src/widgets/dialogs/IrcConnectionEditor.cpp +++ b/src/widgets/dialogs/IrcConnectionEditor.cpp @@ -1,16 +1,50 @@ #include "IrcConnectionEditor.hpp" #include "ui_IrcConnectionEditor.h" -IrcConnectionEditor::IrcConnectionEditor(bool isAdd, QWidget *parent) - : QDialog(parent) - , ui(new Ui::IrcConnectionEditor) +namespace chatterino { + +IrcConnectionEditor::IrcConnectionEditor(const IrcConnection_ &data, bool isAdd, + QWidget *parent) + + : QDialog(parent, Qt::WindowStaysOnTopHint) + , ui_(new Ui::IrcConnectionEditor) + , data_(data) { - ui->setupUi(this); + this->ui_->setupUi(this); this->setWindowTitle(QString(isAdd ? "Add " : "Edit ") + "Irc Connection"); -} + + QObject::connect(this->ui_->userNameLineEdit, &QLineEdit::textChanged, this, + [this](const QString &text) { + this->ui_->nickNameLineEdit->setPlaceholderText(text); + this->ui_->realNameLineEdit->setPlaceholderText(text); + }); + + this->ui_->serverLineEdit->setText(data.host); + this->ui_->portSpinBox->setValue(data.port); + this->ui_->securityCheckBox->setChecked(data.ssl); + this->ui_->userNameLineEdit->setText(data.user); + this->ui_->nickNameLineEdit->setText(data.nick); + this->ui_->realNameLineEdit->setText(data.real); + this->ui_->passwordLineEdit->setText(data.password); +} // namespace chatterino IrcConnectionEditor::~IrcConnectionEditor() { - delete ui; + delete ui_; } + +IrcConnection_ IrcConnectionEditor::data() +{ + auto data = this->data_; + data.host = this->ui_->serverLineEdit->text(); + data.port = this->ui_->portSpinBox->value(); + data.ssl = this->ui_->securityCheckBox->isChecked(); + data.user = this->ui_->userNameLineEdit->text(); + data.nick = this->ui_->nickNameLineEdit->text(); + data.real = this->ui_->realNameLineEdit->text(); + data.password = this->ui_->passwordLineEdit->text(); + return data; +} + +} // namespace chatterino diff --git a/src/widgets/dialogs/IrcConnectionEditor.hpp b/src/widgets/dialogs/IrcConnectionEditor.hpp index fc700ecfc..8ec7574da 100644 --- a/src/widgets/dialogs/IrcConnectionEditor.hpp +++ b/src/widgets/dialogs/IrcConnectionEditor.hpp @@ -1,19 +1,32 @@ #pragma once -#include +#include + +#include "providers/irc/Irc2.hpp" +#include "widgets/BaseWindow.hpp" namespace Ui { class IrcConnectionEditor; } +namespace chatterino { + +struct IrcConnection_; + class IrcConnectionEditor : public QDialog { Q_OBJECT public: - explicit IrcConnectionEditor(bool isAdd = false, QWidget *parent = nullptr); + explicit IrcConnectionEditor(const IrcConnection_ &data, bool isAdd = false, + QWidget *parent = nullptr); ~IrcConnectionEditor(); + IrcConnection_ data(); + private: - Ui::IrcConnectionEditor *ui; + Ui::IrcConnectionEditor *ui_; + IrcConnection_ data_; }; + +} // namespace chatterino diff --git a/src/widgets/dialogs/IrcConnectionEditor.ui b/src/widgets/dialogs/IrcConnectionEditor.ui index a7fcc3ef5..53e8faab0 100644 --- a/src/widgets/dialogs/IrcConnectionEditor.ui +++ b/src/widgets/dialogs/IrcConnectionEditor.ui @@ -1,13 +1,13 @@ IrcConnectionEditor - + 0 0 264 - 258 + 350 @@ -19,12 +19,16 @@ - Server: + Host: - + + + irc.example.com + + @@ -94,21 +98,78 @@ + + + Real Name: + + + + + + + + + + Login method: + + + + Password: - + QLineEdit::Password + + + + Qt::Vertical + + + + 20 + 20 + + + + + + + + + Anonymous + + + + + PASS + + + + + + + + Qt::Vertical + + + + 20 + 20 + + + + @@ -121,6 +182,16 @@ + + serverLineEdit + portSpinBox + securityCheckBox + userNameLineEdit + nickNameLineEdit + realNameLineEdit + comboBox + passwordLineEdit + @@ -130,8 +201,8 @@ accept() - 248 - 254 + 254 + 248 157 @@ -146,8 +217,8 @@ reject() - 316 - 260 + 254 + 248 286 diff --git a/src/widgets/dialogs/IrcConnectionPopup.cpp b/src/widgets/dialogs/IrcConnectionPopup.cpp index c06827299..0386c74df 100644 --- a/src/widgets/dialogs/IrcConnectionPopup.cpp +++ b/src/widgets/dialogs/IrcConnectionPopup.cpp @@ -26,7 +26,9 @@ IrcConnectionPopup::IrcConnectionPopup(QWidget *parent) this->setScaleIndependantSize(800, 500); view->addButtonPressed.connect([] { - Irc::getInstance().connections.appendItem(IrcConnection_::unique()); + auto unique = IrcConnection_{}; + unique.id = Irc::getInstance().uniqueId(); + Irc::getInstance().connections.appendItem(unique); }); // init layout diff --git a/src/widgets/dialogs/SelectChannelDialog.cpp b/src/widgets/dialogs/SelectChannelDialog.cpp index 6a8f027f4..5126355a1 100644 --- a/src/widgets/dialogs/SelectChannelDialog.cpp +++ b/src/widgets/dialogs/SelectChannelDialog.cpp @@ -138,34 +138,52 @@ SelectChannelDialog::SelectChannelDialog(QWidget *parent) auto view = this->ui_.irc.servers = new EditableModelView( Irc::getInstance().newConnectionModel(this)); - view->setTitles( - {"real", "port", "ssl", "user", "nick", "real", "password"}); + view->setTitles({"host", "port", "ssl", "user", "nick", "real", + "password", "login command"}); view->getTableView()->horizontalHeader()->resizeSection(0, 140); - view->getTableView()->horizontalHeader()->resizeSection(1, 30); + view->getTableView()->horizontalHeader()->resizeSection(1, 40); view->getTableView()->horizontalHeader()->resizeSection(2, 30); + //view->getTableView()->horizontalHeader()->setVisible(false); + + view->getTableView()->horizontalHeader()->setSectionHidden(1, true); + view->getTableView()->horizontalHeader()->setSectionHidden(2, true); + view->getTableView()->horizontalHeader()->setSectionHidden(6, true); + view->getTableView()->horizontalHeader()->setSectionHidden(7, true); view->addButtonPressed.connect([] { - Irc::getInstance().connections.appendItem( - IrcConnection_::unique()); + auto unique = IrcConnection_{}; + unique.id = Irc::getInstance().uniqueId(); + Irc::getInstance().connections.appendItem(unique); }); + QObject::connect( + view->getTableView(), &QTableView::clicked, + [](const QModelIndex &index) { + auto data = + Irc::getInstance() + .connections.getVector()[size_t(index.row())]; + + auto editor = new IrcConnectionEditor(data); + if (editor->exec() == QDialog::Accepted) + { + auto data = editor->data(); + auto &&conns = + Irc::getInstance().connections.getVector(); + int i = 0; + for (auto &&conn : conns) + { + if (conn.id == data.id) + { + Irc::getInstance().connections.removeItem(i); + Irc::getInstance().connections.insertItem(data, + i); + } + i++; + } + } + }); + outerBox->addWidget(view); - - // auto box = outerBox.emplace().withoutMargin(); - - // auto conns = box.emplace(); - // conns->addActions({new QAction("hackint")}); - - // auto buttons = box.emplace().withoutMargin(); - - // buttons.emplace("Add").onClick(this, [this]() { - // (new IrcConnectionPopup(this)) - // ->show(); // XXX: don't show multiple - // }); - - // buttons.emplace("Edit"); - // buttons.emplace("Remove"); - // buttons->addStretch(1); } { @@ -174,24 +192,6 @@ SelectChannelDialog::SelectChannelDialog(QWidget *parent) this->ui_.irc.channel = box.emplace().getElement(); } - // auto vbox = obj.setLayoutType(); - // auto form = vbox.emplace(); - - // auto servers = new QComboBox; - // auto accounts = new QComboBox; - //servers->setEditable(true); - //servers->addItems( - // {"irc://irc.hackint.org:6697", "irc://irc.somethingelse.com:6667"}); - - // form->addRow("Server:", servers); - // form->addRow("Account:", accounts); - // form->addRow("Channel:", new QLineEdit()); - - // form->addRow("User name:", new QLineEdit()); - // form->addRow("First nick choice:", new QLineEdit()); - // form->addRow("Second nick choice:", new QLineEdit()); - // form->addRow("Third nick choice:", new QLineEdit()); - auto tab = notebook->addPage(obj.getElement()); tab->setCustomTitle("Irc"); }