#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.
master
Tomatix 2 years ago
parent c26715cf65
commit 9185893037
  1. 2
      CMakeLists.txt
  2. 27
      IConfig/AddServer.cpp
  3. 11
      IConfig/AddServer.h
  4. 42
      IConfig/AddServer.ui
  5. 4
      IConfig/CMakeLists.txt
  6. 26
      IConfig/IConfigServers.cpp
  7. 2
      IConfig/IConfigServers.h
  8. 16
      IConfig/IConfigServers.ui
  9. 18
      IConfig/ServerItem.cpp
  10. 44
      IConfig/ServerItem.h
  11. 253
      IConfig/ServerModel.cpp
  12. 32
      IConfig/ServerModel.h
  13. 80
      IConfig/ServerOptionsDelegate.cpp
  14. 26
      IConfig/ServerOptionsDelegate.h
  15. BIN
      Resources/Icons/network.png
  16. 1
      Resources/resources.qrc

@ -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

@ -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 <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
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);
}

@ -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;

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>365</width>
<height>160</height>
<height>162</height>
</rect>
</property>
<property name="windowTitle">
@ -21,34 +21,39 @@
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QRadioButton" name="rdServer">
<widget class="QRadioButton" name="rdNetwork">
<property name="text">
<string>Server</string>
</property>
<property name="checked">
<bool>true</bool>
<string>Network</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="rdNetwork">
<widget class="QRadioButton" name="rdServer">
<property name="text">
<string>Network</string>
<string>Server</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<widget class="QComboBox" name="edNetwork">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
<property name="placeholderText">
<string/>
</property>
</spacer>
<item>
<property name="text">
<string>&lt;No network&gt;</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
@ -138,8 +143,9 @@
</layout>
</widget>
<tabstops>
<tabstop>rdServer</tabstop>
<tabstop>rdNetwork</tabstop>
<tabstop>rdServer</tabstop>
<tabstop>edNetwork</tabstop>
<tabstop>edName</tabstop>
<tabstop>edAddress</tabstop>
<tabstop>chkSSL</tabstop>

@ -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})

@ -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());
});
}
}

@ -9,6 +9,7 @@
#define ICONFIGSERVERS_H
#include "ServerModel.h"
#include "ServerOptionsDelegate.h"
#include <QWidget>
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;

@ -169,8 +169,20 @@
<item>
<widget class="QTreeView" name="servers">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
<set>QAbstractItemView::DoubleClicked</set>
</property>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<property name="animated">
<bool>true</bool>
</property>
<attribute name="headerDefaultSectionSize">
<number>150</number>
</attribute>
<attribute name="headerStretchLastSection">
<bool>false</bool>
</attribute>
</widget>
</item>
<item>
@ -178,7 +190,7 @@
<item>
<widget class="QPushButton" name="btnAddServer">
<property name="text">
<string>Add server...</string>
<string>Add...</string>
</property>
</widget>
</item>

@ -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

@ -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 <QString>
#include <QJsonObject>
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<ServerItem>& children() { return m_children; }
bool isNetwork() const { return m_isNetwork; }
private:
QJsonObject m_data;
QList<ServerItem> m_children;
int m_row;
ServerItem* m_parent;
bool m_isNetwork;
};
#endif // SERVERITEM_H

@ -8,9 +8,31 @@
#include "ServerModel.h"
#include "config.h"
#include <QJsonArray>
#include <QJsonValue>
#include <QFile>
#include <QDebug>
#include <QTimer>
#include <QIcon>
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<const ServerItem*>(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<const ServerItem*>(index.internalPointer());
if (role == Qt::DisplayRole || role == Qt::EditRole) {
const auto* item = static_cast<const ServerItem*>(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<const ServerItem*>(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<ServerItem*>(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<ServerItem>* items{};
ServerItem* parentNetworkItem{};
int pos{};
QModelIndex modelIdx;
/* Network server */
if (networkIdx > -1) {
modelIdx = networkIndex(networkIdx);
parentNetworkItem = static_cast<ServerItem*>(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<QModelIndex> ServerModel::getEditorColumns()
{
QList<QModelIndex> 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);
}
}
}

@ -16,7 +16,7 @@
#include <QJsonObject>
/**
* @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<QModelIndex> 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<ServerItem> m_items;
};

@ -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 <QInputDialog>
#include <QPushButton>
#include <QDebug>
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<ServerItem*>(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<const ServerItem*>(index.internalPointer());
if (index.column() == 2) {
auto* btn = qobject_cast<QPushButton*>(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<ServerItem*>(index.internalPointer());
if (index.column() == 2) {
auto* btn = qobject_cast<QPushButton*>(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);
}

@ -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 <QStyledItemDelegate>
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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

@ -14,5 +14,6 @@
<file>Icons/serverwindow.png</file>
<file>Icons/connect.png</file>
<file>Icons/disconnect.png</file>
<file>Icons/network.png</file>
</qresource>
</RCC>

Loading…
Cancel
Save