From 9185893037cfaab80b2e031df6646ee67dff77f8 Mon Sep 17 00:00:00 2001 From: Tomatix Date: Tue, 15 Mar 2022 20:01:07 +0100 Subject: [PATCH] #134 More work done on the new server config editing. In-table editing and icons to better see what's a network and a server. Known issue when adding servers to networks that are expanded in the tree view, need to collapse and re-expand the network to see it. Saving to JSON and deleting servers/networks is not done yet. --- CMakeLists.txt | 2 +- IConfig/AddServer.cpp | 27 +++- IConfig/AddServer.h | 11 +- IConfig/AddServer.ui | 42 ++--- IConfig/CMakeLists.txt | 4 +- IConfig/IConfigServers.cpp | 26 ++- IConfig/IConfigServers.h | 2 + IConfig/IConfigServers.ui | 16 +- IConfig/ServerItem.cpp | 18 ++- IConfig/ServerItem.h | 44 +++++- IConfig/ServerModel.cpp | 253 ++++++++++++++++++++++++++---- IConfig/ServerModel.h | 32 +++- IConfig/ServerOptionsDelegate.cpp | 80 ++++++++++ IConfig/ServerOptionsDelegate.h | 26 +++ Resources/Icons/network.png | Bin 0 -> 3208 bytes Resources/resources.qrc | 1 + 16 files changed, 512 insertions(+), 72 deletions(-) create mode 100644 IConfig/ServerOptionsDelegate.cpp create mode 100644 IConfig/ServerOptionsDelegate.h create mode 100644 Resources/Icons/network.png diff --git a/CMakeLists.txt b/CMakeLists.txt index dc5093e..5e044a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ set(BUILD_TYPE "packaged") set(VERSION_MAJOR 1) set(VERSION_MINOR 1) set(VERSION_PATCH 0) -set(VERSION_APPEND "dev6") +set(VERSION_APPEND "dev7") # # CMake build environment setup diff --git a/IConfig/AddServer.cpp b/IConfig/AddServer.cpp index 39620ab..b096e57 100644 --- a/IConfig/AddServer.cpp +++ b/IConfig/AddServer.cpp @@ -1,7 +1,18 @@ +/* + * IdealIRC - Internet Relay Chat client + * Copyright (C) 2022 Tom-Andre Barstad. + * This software is licensed under the Software Attribution License. + * See LICENSE for more information. +*/ + #include "AddServer.h" #include "ui_AddServer.h" +#include +#include +#include +#include -AddServer::AddServer(QWidget *parent) : +AddServer::AddServer(const QStringList& networkList, QWidget *parent) : QDialog(parent), ui(new Ui::AddServer) { @@ -15,6 +26,9 @@ AddServer::AddServer(QWidget *parent) : connect(ui->edName, &QLineEdit::textChanged, EnableOrDisableSave); connect(ui->edAddress, &QLineEdit::textChanged, EnableOrDisableSave); + + for (const auto& networkName : networkList) + ui->edNetwork->addItem(networkName); } AddServer::~AddServer() @@ -47,15 +61,24 @@ bool AddServer::isServer() const return ui->rdServer->isChecked(); } +int AddServer::networkIndex() const +{ + // 0th index is the "No network" selection, make that into a "-1" index instead... and the rest must also follow. + return ui->edNetwork->currentIndex() - 1; +} + void AddServer::on_btnCancel_clicked() { close(); } - void AddServer::on_btnSave_clicked() { emit saved(); close(); } +void AddServer::on_rdNetwork_toggled(bool checked) +{ + ui->edNetwork->setEnabled(!checked); +} diff --git a/IConfig/AddServer.h b/IConfig/AddServer.h index c095643..3893bff 100644 --- a/IConfig/AddServer.h +++ b/IConfig/AddServer.h @@ -1,3 +1,10 @@ +/* + * IdealIRC - Internet Relay Chat client + * Copyright (C) 2022 Tom-Andre Barstad. + * This software is licensed under the Software Attribution License. + * See LICENSE for more information. +*/ + #ifndef ADDSERVER_H #define ADDSERVER_H @@ -12,7 +19,7 @@ class AddServer : public QDialog Q_OBJECT public: - explicit AddServer(QWidget *parent = nullptr); + explicit AddServer(const QStringList& networkList, QWidget *parent = nullptr); ~AddServer(); QString name() const; @@ -20,6 +27,7 @@ public: QString password() const; bool ssl() const; bool isServer() const; + int networkIndex() const; signals: void saved(); @@ -27,6 +35,7 @@ signals: private slots: void on_btnCancel_clicked(); void on_btnSave_clicked(); + void on_rdNetwork_toggled(bool checked); private: Ui::AddServer *ui; diff --git a/IConfig/AddServer.ui b/IConfig/AddServer.ui index a0d74a3..1e79c80 100644 --- a/IConfig/AddServer.ui +++ b/IConfig/AddServer.ui @@ -7,7 +7,7 @@ 0 0 365 - 160 + 162 @@ -21,34 +21,39 @@ - + - Server - - - true + Network - + - Network + Server + + + true - - - Qt::Horizontal + + + + 0 + 0 + - - - 40 - 20 - + + - + + + <No network> + + + @@ -138,8 +143,9 @@ - rdServer rdNetwork + rdServer + edNetwork edName edAddress chkSSL diff --git a/IConfig/CMakeLists.txt b/IConfig/CMakeLists.txt index daa6887..8d751fe 100644 --- a/IConfig/CMakeLists.txt +++ b/IConfig/CMakeLists.txt @@ -18,10 +18,12 @@ list(APPEND ${component}_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/AddServer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/AddServer.h ${CMAKE_CURRENT_SOURCE_DIR}/AddServer.ui - ${CMAKE_CURRENT_SOURCE_DIR}/ServerItem.h ${CMAKE_CURRENT_SOURCE_DIR}/ServerItem.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ServerItem.h ${CMAKE_CURRENT_SOURCE_DIR}/ServerModel.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ServerModel.h + ${CMAKE_CURRENT_SOURCE_DIR}/ServerOptionsDelegate.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ServerOptionsDelegate.h ) add_library(${component} STATIC ${${component}_SOURCES}) diff --git a/IConfig/IConfigServers.cpp b/IConfig/IConfigServers.cpp index 45ec7d5..0e5b7c0 100644 --- a/IConfig/IConfigServers.cpp +++ b/IConfig/IConfigServers.cpp @@ -36,6 +36,21 @@ IConfigServers::IConfigServers(QWidget *parent) : ui->chkSSL->setChecked(cf_SSL); ui->servers->setModel(&smodel); + ui->servers->setItemDelegateForColumn(2, &m_serverOptionsDelegate); + ui->servers->setItemDelegateForColumn(3, &m_serverOptionsDelegate); + + for (const auto& index : smodel.getEditorColumns()) { + ui->servers->openPersistentEditor(index); + } + + connect(&smodel, &ServerModel::newEntry, + [this](const QModelIndex& sslIdx, const QModelIndex& passwordIdx) { + ui->servers->openPersistentEditor(sslIdx); + ui->servers->openPersistentEditor(passwordIdx); + }); + + ui->servers->setColumnWidth(2, 50); // SSL column + ui->servers->setColumnWidth(3, 100); // Password column } IConfigServers::~IConfigServers() @@ -112,17 +127,20 @@ void IConfigServers::on_servers_clicked(const QModelIndex& index) void IConfigServers::on_btnAddServer_clicked() { if (!addServerDlg) { - addServerDlg = new AddServer(this); + addServerDlg = new AddServer(smodel.getNetworks(), this); addServerDlg->show(); connect(addServerDlg, &QDialog::destroyed, - [this](){ + [this] { addServerDlg = nullptr; }); connect(addServerDlg, &AddServer::saved, - [this](){ - + [this] { + if (addServerDlg->isServer()) + smodel.addServer(addServerDlg->name(), addServerDlg->address(), addServerDlg->password(), addServerDlg->ssl(), addServerDlg->networkIndex()); + else + smodel.addNetwork(addServerDlg->name(), addServerDlg->address(), addServerDlg->password(), addServerDlg->ssl()); }); } } diff --git a/IConfig/IConfigServers.h b/IConfig/IConfigServers.h index 1f6943f..0c1ea47 100644 --- a/IConfig/IConfigServers.h +++ b/IConfig/IConfigServers.h @@ -9,6 +9,7 @@ #define ICONFIGSERVERS_H #include "ServerModel.h" +#include "ServerOptionsDelegate.h" #include namespace Ui { @@ -39,6 +40,7 @@ private slots: private: Ui::IConfigServers *ui; AddServer* addServerDlg{}; + ServerOptionsDelegate m_serverOptionsDelegate; ServerModel smodel; QString cf_Realname; QString cf_Username; diff --git a/IConfig/IConfigServers.ui b/IConfig/IConfigServers.ui index 4d19c7e..e717d03 100644 --- a/IConfig/IConfigServers.ui +++ b/IConfig/IConfigServers.ui @@ -169,8 +169,20 @@ - QAbstractItemView::NoEditTriggers + QAbstractItemView::DoubleClicked + + true + + + true + + + 150 + + + false + @@ -178,7 +190,7 @@ - Add server... + Add... diff --git a/IConfig/ServerItem.cpp b/IConfig/ServerItem.cpp index ef921c8..433ba87 100644 --- a/IConfig/ServerItem.cpp +++ b/IConfig/ServerItem.cpp @@ -1,17 +1,19 @@ +/* + * IdealIRC - Internet Relay Chat client + * Copyright (C) 2022 Tom-Andre Barstad. + * This software is licensed under the Software Attribution License. + * See LICENSE for more information. +*/ + #include "ServerItem.h" -namespace Key { -constexpr auto Name = "Name"; -constexpr auto Host = "Host"; -constexpr auto Port = "Port"; -constexpr auto Password = "Password"; -constexpr auto SSL = "SSL"; -} +namespace Key = ServerJsonKey; -ServerItem::ServerItem(const QJsonObject& data, int row, ServerItem* parentItem) +ServerItem::ServerItem(const QJsonObject& data, int row, ServerItem* parentItem, bool isNetwork) : m_data(data) , m_row(row) , m_parent(parentItem) + , m_isNetwork{ isNetwork } {} QString ServerItem::name() const diff --git a/IConfig/ServerItem.h b/IConfig/ServerItem.h index 7284c7d..f239079 100644 --- a/IConfig/ServerItem.h +++ b/IConfig/ServerItem.h @@ -1,3 +1,10 @@ +/* + * IdealIRC - Internet Relay Chat client + * Copyright (C) 2022 Tom-Andre Barstad. + * This software is licensed under the Software Attribution License. + * See LICENSE for more information. +*/ + #ifndef SERVERITEM_H #define SERVERITEM_H @@ -5,25 +12,60 @@ #include #include +namespace ServerJsonKey +{ +constexpr auto Servers = "Servers"; +constexpr auto Networks = "Networks"; +constexpr auto Name = "Name"; +constexpr auto Host = "Host"; +constexpr auto Port = "Port"; +constexpr auto Password = "Password"; +constexpr auto SSL = "SSL"; +} + class ServerItem { public: - ServerItem(const QJsonObject& data, int row, ServerItem* parentItem); + ServerItem(const QJsonObject& data, int row, ServerItem* parentItem, bool isNetwork); QString name() const; + void setName(const QString& name) { m_data[ServerJsonKey::Name] = name; } + QString address() const; + void setAddress(const QString& address) + { + auto hostport = address.split(':'); + + if (hostport.size() == 1) + hostport << (ssl() ? "6697" : "6667"); + + if (hostport[0].isEmpty()) + hostport[0] = "server.name"; + + m_data[ServerJsonKey::Host] = hostport[0]; + m_data[ServerJsonKey::Port] = hostport[1].toUShort(); + } + QString password() const; + void setPassword(const QString& password) { m_data[ServerJsonKey::Password] = password; } + bool ssl() const; + void setSsl(bool enable) { m_data[ServerJsonKey::SSL] = enable; } ServerItem* parent() const { return m_parent; } int row() const { return m_row; } + void incRow() { ++m_row; } + QList& children() { return m_children; } + bool isNetwork() const { return m_isNetwork; } + private: QJsonObject m_data; QList m_children; int m_row; ServerItem* m_parent; + bool m_isNetwork; }; #endif // SERVERITEM_H diff --git a/IConfig/ServerModel.cpp b/IConfig/ServerModel.cpp index 121d852..3403350 100644 --- a/IConfig/ServerModel.cpp +++ b/IConfig/ServerModel.cpp @@ -8,9 +8,31 @@ #include "ServerModel.h" #include "config.h" #include -#include #include #include +#include +#include + +namespace { +QJsonObject createJsonObject(const QString& name, const QString& address, const QString& password, bool isSsl) +{ + namespace Key = ServerJsonKey; + + const auto hostport{ address.split(':') }; + const auto host{ hostport[0] }; + const auto port{ hostport.count() > 1 ? hostport[1].toShort() : 6667 }; + + QJsonObject obj; + + obj[Key::Name] = name; + obj[Key::Host] = host; + obj[Key::Port] = port; + obj[Key::SSL] = isSsl; + obj[Key::Password] = password; + + return obj; +} +} ServerModel::ServerModel(QObject* parent) : QAbstractItemModel(parent) @@ -36,50 +58,58 @@ ServerModel::ServerModel(QObject* parent) : } -void ServerModel::createItems(const QJsonObject& json) +void ServerModel::saveToJsonFile(const QString& fileName) const { - constexpr auto Servers = "Servers"; - constexpr auto Networks = "Networks"; - const auto servers = json[Servers].toArray(); - const auto networks = json[Networks].toArray(); +} - int rootRow{ 0 }; +Qt::ItemFlags ServerModel::flags(const QModelIndex& index) const +{ + /* Don't care about invalid indexes */ + if (!index.isValid()) + return Qt::NoItemFlags; - for (const auto& server : servers) { - m_items << ServerItem(server.toObject(), rootRow++, nullptr); - } + /* Columns containing widgets for editing */ + if (index.column() > 1) + return Qt::ItemIsEnabled | Qt::ItemIsEditable; - for (const auto& network : networks) { - const auto networkObj = network.toObject(); - const auto childServers = networkObj[Servers].toArray(); + /* Directly editable columns */ + Qt::ItemFlags flags{ Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled }; - m_items << ServerItem(networkObj, rootRow++, nullptr); - auto& networkItem = m_items.back(); + const auto* item = static_cast(index.internalPointer()); + if (!item->isNetwork()) + flags |= Qt::ItemNeverHasChildren; - int childRow{ 0 }; - for (const auto& cs : childServers) { - auto& networkServers = networkItem.children(); - networkServers << ServerItem(cs.toObject(), childRow++, &networkItem); - } - } + return flags; } QVariant ServerModel::data(const QModelIndex& index, int role) const { - if (!index.isValid() || role != Qt::DisplayRole) + if (!index.isValid()) return {}; - auto* item = static_cast(index.internalPointer()); + if (role == Qt::DisplayRole || role == Qt::EditRole) { + const auto* item = static_cast(index.internalPointer()); - if (index.column() == 0) - return item->name(); + if (index.column() == 0) + return item->name(); - else if (index.column() == 1) - return item->address(); + else if (index.column() == 1) + return item->address(); - else - return {}; + else + return {}; + } + + if (role == Qt::DecorationRole && index.column() == 0) { + const auto* item = static_cast(index.internalPointer()); + if (item->isNetwork()) + return QIcon(":/Icons/network.png"); + else + return QIcon(":/Icons/serverwindow.png"); + } + + return {}; } QVariant ServerModel::headerData(int section, Qt::Orientation orientation, int role) const @@ -87,7 +117,9 @@ QVariant ServerModel::headerData(int section, Qt::Orientation orientation, int r if (role == Qt::DisplayRole && orientation == Qt::Horizontal) { QStringList labels { tr("Name"), - tr("Address") + tr("Address"), + "", + "" }; return labels[section]; @@ -97,6 +129,36 @@ QVariant ServerModel::headerData(int section, Qt::Orientation orientation, int r } } +bool ServerModel::setData(const QModelIndex& index, const QVariant& value, int role) +{ + if (!index.isValid() || role != Qt::EditRole) + return false; + + auto* item = static_cast(index.internalPointer()); + + bool ret{ true }; + switch (index.column()) { + case 0: + if (value.toString().isEmpty()) + ret = false; + else + item->setName(value.toString()); + break; + + case 1: + if (value.toString().isEmpty()) + ret = false; + else + item->setAddress(value.toString()); + break; + + default: + ret = false; + } + + return ret; +} + int ServerModel::rowCount(const QModelIndex& parent) const { if (!parent.isValid()) @@ -135,3 +197,134 @@ QModelIndex ServerModel::parent(const QModelIndex& index) const return createIndex(parentItem->row(), 0, parentItem); } + +void ServerModel::addServer(const QString& name, const QString& address, const QString& password, bool isSsl, int networkIdx) +{ + QList* items{}; + ServerItem* parentNetworkItem{}; + int pos{}; + + QModelIndex modelIdx; + + /* Network server */ + if (networkIdx > -1) { + modelIdx = networkIndex(networkIdx); + parentNetworkItem = static_cast(modelIdx.internalPointer()); + items = &(parentNetworkItem->children()); + pos = items->count(); + } + + /* Non-network server */ + else { + items = &m_items; + + for (auto& item : m_items) { + if (item.isNetwork()) + item.incRow(); // Increment row number for each network, since any non-network server is inserted before these. + else + ++pos; // Finds the end position of non-network servers. Add server there (bottom of non-networks; before networks are listed.) + } + } + + // TODO this fails to update the tree with new child item (network server) + const auto obj{ createJsonObject(name, address, password, isSsl) }; + beginInsertRows(modelIdx, pos, pos); + items->insert(pos, ServerItem(obj, pos, parentNetworkItem, false)); + endInsertRows(); + + emit newEntry( + createIndex(pos, 2, &((*items)[pos])), // SSL + createIndex(pos, 3, &((*items)[pos])) // Password + ); +} + +void ServerModel::addNetwork(const QString& name, const QString& address, const QString& password, bool isSsl) +{ + const auto obj{ createJsonObject(name, address, password, isSsl) }; + + const auto idx{ m_items.count() }; + beginInsertRows(QModelIndex{}, idx, idx); + m_items << ServerItem(obj, idx, nullptr, true); + endInsertRows(); + + emit newEntry( + createIndex(idx, 2, &(m_items.back())), // SSL + createIndex(idx, 3, &(m_items.back())) // Password + ); +} + +QStringList ServerModel::getNetworks() const +{ + QStringList networks; + + for (const auto& item : m_items) { + if (item.isNetwork()) + networks << item.name(); + } + + return networks; +} + +QList ServerModel::getEditorColumns() +{ + QList indexList; + + for (auto& topItem : m_items) { + indexList << createIndex(topItem.row(), 2, &topItem); + indexList << createIndex(topItem.row(), 3, &topItem); + + if (topItem.isNetwork()) { + auto& items = topItem.children(); + for (auto& item : items) { + indexList << createIndex(item.row(), 2, &item); + indexList << createIndex(item.row(), 3, &item); + } + } + } + + return indexList; +} + +QModelIndex ServerModel::networkIndex(int row, int col) +{ + int rc{ 0 }; + for (auto& item : m_items) { + if (!item.isNetwork()) + continue; + + if (rc == row) + return createIndex(row, col, &item); + else + ++rc; + } + + return {}; +} + +void ServerModel::createItems(const QJsonObject& json) +{ + namespace Key = ServerJsonKey; + + const auto servers = json[Key::Servers].toArray(); + const auto networks = json[Key::Networks].toArray(); + + int rootRow{ 0 }; + + for (const auto& server : servers) { + m_items << ServerItem(server.toObject(), rootRow++, nullptr, false); + } + + for (const auto& network : networks) { + const auto networkObj = network.toObject(); + const auto childServers = networkObj[Key::Servers].toArray(); + + m_items << ServerItem(networkObj, rootRow++, nullptr, true); + auto& networkItem = m_items.back(); + + int childRow{ 0 }; + for (const auto& cs : childServers) { + auto& networkServers = networkItem.children(); + networkServers << ServerItem(cs.toObject(), childRow++, &networkItem, false); + } + } +} diff --git a/IConfig/ServerModel.h b/IConfig/ServerModel.h index 6045d4e..cbb9078 100644 --- a/IConfig/ServerModel.h +++ b/IConfig/ServerModel.h @@ -16,7 +16,7 @@ #include /** - * @brief Model of servers.ini + * @brief Model of servers.json */ class ServerModel : public QAbstractItemModel { @@ -25,20 +25,44 @@ class ServerModel : public QAbstractItemModel public: explicit ServerModel(QObject* parent = nullptr); + /// Save model to a json file + void saveToJsonFile(const QString& fileName) const; + + Qt::ItemFlags flags(const QModelIndex &index) const; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - int rowCount(const QModelIndex& parent = QModelIndex()) const override; - int columnCount(const QModelIndex& parent = QModelIndex()) const override + bool setData(const QModelIndex &index, const QVariant& value, int role = Qt::EditRole) override; + + int rowCount(const QModelIndex& parent = {}) const override; + int columnCount(const QModelIndex& parent = {}) const override { - return 2; + return 4; }; QModelIndex index(int row, int column, const QModelIndex& parent = {}) const override; QModelIndex parent(const QModelIndex& index) const override; + /// Add a server to the model. networkIdx = -1 means server is not part of a network. + void addServer(const QString& name, const QString& address, const QString& password, bool isSsl, int networkIdx); + + /// Add a network to the model. + void addNetwork(const QString& name, const QString& address, const QString& password, bool isSsl); + + QStringList getNetworks() const; + + QList getEditorColumns(); + +signals: + void newEntry(const QModelIndex& sslIdx, const QModelIndex& passwordIdx); + private: + QModelIndex networkIndex(int row, int col = 0); void createItems(const QJsonObject& json); + + // I don't like this being mutable, but the nature of Qt's item model seems to have forced my hand. + // Or I've probably not done the correct implementation design. In any way, it works, but smells a bit... + // This is the top-level items as shown in the UI, same order. mutable QList m_items; }; diff --git a/IConfig/ServerOptionsDelegate.cpp b/IConfig/ServerOptionsDelegate.cpp new file mode 100644 index 0000000..b86b681 --- /dev/null +++ b/IConfig/ServerOptionsDelegate.cpp @@ -0,0 +1,80 @@ +/* + * IdealIRC - Internet Relay Chat client + * Copyright (C) 2022 Tom-Andre Barstad. + * This software is licensed under the Software Attribution License. + * See LICENSE for more information. +*/ + +#include "ServerOptionsDelegate.h" +#include "ServerItem.h" +#include +#include +#include + +ServerOptionsDelegate::ServerOptionsDelegate(QObject* parent) + : QStyledItemDelegate(parent) +{} + +QWidget* ServerOptionsDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const +{ + if (!index.isValid()) + return nullptr; + + if (index.column() == 2) { + auto* btn = new QPushButton(tr("SSL"), parent); + btn->setCheckable(true); + return btn; + } + else if (index.column() == 3) { + auto* btn = new QPushButton(tr("Password"), parent); + auto* item = static_cast(index.internalPointer()); + connect(btn, &QPushButton::pressed, + [item, parent] { + auto password = QInputDialog::getText( + parent, + tr("Enter password"), + tr("New password for %1:").arg(item->name()), + QLineEdit::Password + ); + + item->setPassword(password); + }); + + return btn; + } + else { + return nullptr; + } +} + +void ServerOptionsDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const +{ + const auto* item = static_cast(index.internalPointer()); + + if (index.column() == 2) { + auto* btn = qobject_cast(editor); + if (btn) + btn->setChecked(item->ssl()); + else + qCritical() << "SSL button is not a QPushButton?!"; + } + +} + +void ServerOptionsDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const +{ + auto* item = static_cast(index.internalPointer()); + + if (index.column() == 2) { + auto* btn = qobject_cast(editor); + if (btn) + item->setSsl(btn->isChecked()); + else + qCritical() << "SSL button is not a QPushButton?!"; + } +} + +void ServerOptionsDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& /*index*/) const +{ + editor->setGeometry(option.rect); +} diff --git a/IConfig/ServerOptionsDelegate.h b/IConfig/ServerOptionsDelegate.h new file mode 100644 index 0000000..231270f --- /dev/null +++ b/IConfig/ServerOptionsDelegate.h @@ -0,0 +1,26 @@ +/* + * IdealIRC - Internet Relay Chat client + * Copyright (C) 2022 Tom-Andre Barstad. + * This software is licensed under the Software Attribution License. + * See LICENSE for more information. +*/ + +#ifndef SERVEROPTIONSDELEGATE_H +#define SERVEROPTIONSDELEGATE_H + +#include + +class ServerOptionsDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + explicit ServerOptionsDelegate(QObject* parent = nullptr); + + QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override; + void setEditorData(QWidget* editor, const QModelIndex& index) const override; + void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override; + void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const override; +}; + +#endif // SERVEROPTIONSDELEGATE_H diff --git a/Resources/Icons/network.png b/Resources/Icons/network.png new file mode 100644 index 0000000000000000000000000000000000000000..6761a6f7361205d6a0b81e55f0e514f2ba019336 GIT binary patch literal 3208 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/serverwindow.png Icons/connect.png Icons/disconnect.png + Icons/network.png