From 6623fd2d46dadd0168e4e28d1db6944c26c2a773 Mon Sep 17 00:00:00 2001 From: Manuel Nickschas Date: Fri, 1 Feb 2008 17:29:48 +0000 Subject: [PATCH] This is it, the long-awaited huge commit with the new Network handling. Besides the new settings page, the underlying structures have muchly improved. To connect to a network, please use the new settings page (F7) for now; I'll add a more convenient way soon. Ah, and connection failures are now reported and handled sanely (auto reconnect is not yet implemented though) :) Your old settings will be mostly migrated. Good luck. --- src/client/client.cpp | 121 +++++---- src/client/client.h | 6 +- src/client/modelpropertymapper.cpp | 3 +- src/common/global.cpp | 7 +- src/common/network.cpp | 97 +++++-- src/common/network.h | 37 ++- src/core/coresession.cpp | 192 +++++++++----- src/core/coresession.h | 20 ++ src/core/coreusersettings.cpp | 42 ++- src/core/coreusersettings.h | 11 +- src/core/networkconnection.cpp | 85 +++++-- src/core/networkconnection.h | 10 +- src/core/userinputhandler.cpp | 1 - src/icons/icons.qrc | 4 +- src/qtui/mainwin.cpp | 7 +- .../settingspages/identitiessettingspage.cpp | 7 +- .../settingspages/identitiessettingspage.h | 6 +- .../settingspages/networkssettingspage.cpp | 240 +++++++++++++----- src/qtui/settingspages/networkssettingspage.h | 18 +- src/qtui/settingspages/saveidentitiesdlg.ui | 136 +++++----- src/qtui/ui/mainwin.ui | 6 + src/qtui/ui/settingsdlg.ui | 4 +- 22 files changed, 723 insertions(+), 337 deletions(-) diff --git a/src/client/client.cpp b/src/client/client.cpp index c63632d9..4832549c 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -103,13 +103,13 @@ void Client::init() { p->attachSignal(this, SIGNAL(requestRemoveIdentity(IdentityId)), SIGNAL(removeIdentity(IdentityId))); p->attachSlot(SIGNAL(identityCreated(const Identity &)), this, SLOT(coreIdentityCreated(const Identity &))); p->attachSlot(SIGNAL(identityRemoved(IdentityId)), this, SLOT(coreIdentityRemoved(IdentityId))); -/* + p->attachSignal(this, SIGNAL(requestCreateNetwork(const NetworkInfo &)), SIGNAL(createNetwork(const NetworkInfo &))); p->attachSignal(this, SIGNAL(requestUpdateNetwork(const NetworkInfo &)), SIGNAL(updateNetwork(const NetworkInfo &))); p->attachSignal(this, SIGNAL(requestRemoveNetwork(NetworkId)), SIGNAL(removeNetwork(NetworkId))); - p->attachSlot(SIGNAL(networkCreated(const NetworkInfo &)), this, SLOT(coreNetworkCreated(const NetworkInfo &))); + p->attachSlot(SIGNAL(networkCreated(NetworkId)), this, SLOT(coreNetworkCreated(NetworkId))); p->attachSlot(SIGNAL(networkRemoved(NetworkId)), this, SLOT(coreNetworkRemoved(NetworkId))); -*/ + connect(p, SIGNAL(disconnected()), this, SLOT(disconnectFromCore())); //connect(mainUi, SIGNAL(connectToCore(const QVariantMap &)), this, SLOT(connectToCore(const QVariantMap &))); @@ -199,6 +199,72 @@ const Network * Client::network(NetworkId networkid) { else return 0; } +/* +void Client::networkConnected(uint netid) { + // TODO: create statusBuffer / switch to networkids + //BufferInfo id = statusBufferInfo(net); + //Buffer *b = buffer(id); + //b->setActive(true); + + Network *netinfo = new Network(netid, this); + netinfo->setProxy(signalProxy()); + networkModel()->attachNetwork(netinfo); + connect(netinfo, SIGNAL(destroyed()), this, SLOT(networkDestroyed())); + _networks[netid] = netinfo; +} + +void Client::networkDisconnected(NetworkId networkid) { + if(!_networks.contains(networkid)) { + qWarning() << "Client::networkDisconnected(uint): unknown Network" << networkid; + return; +} + + Network *net = _networks.take(networkid); + if(!net->isInitialized()) { + qDebug() << "Network" << networkid << "disconnected while not yet initialized!"; + updateCoreConnectionProgress(); +} + net->deleteLater(); +} +*/ + +void Client::createNetwork(const NetworkInfo &info) { + emit instance()->requestCreateNetwork(info); +} + +void Client::updateNetwork(const NetworkInfo &info) { + emit instance()->requestUpdateNetwork(info); +} + +void Client::removeNetwork(NetworkId id) { + emit instance()->requestRemoveNetwork(id); +} + +void Client::addNetwork(Network *net) { + net->setProxy(signalProxy()); + signalProxy()->synchronize(net); + networkModel()->attachNetwork(net); + connect(net, SIGNAL(destroyed()), instance(), SLOT(networkDestroyed())); + instance()->_networks[net->networkId()] = net; + emit instance()->networkCreated(net->networkId()); +} + +void Client::coreNetworkCreated(NetworkId id) { + if(_networks.contains(id)) { + qWarning() << "Creation of already existing network requested!"; + return; + } + Network *net = new Network(id, this); + addNetwork(net); +} + +void Client::coreNetworkRemoved(NetworkId id) { + if(!_networks.contains(id)) return; + Network *net = _networks.take(id); + emit networkRemoved(net->networkId()); + net->deleteLater(); +} + /*** Identity handling ***/ QList Client::identityIds() { @@ -336,55 +402,6 @@ QStringList Client::sessionDataKeys() { /*** ***/ -// FIXME -void Client::disconnectFromNetwork(NetworkId id) { - if(!instance()->_networks.contains(id)) return; - Network *net = instance()->_networks[id]; - net->requestDisconnect(); -} - -/* -void Client::networkConnected(uint netid) { - // TODO: create statusBuffer / switch to networkids - //BufferInfo id = statusBufferInfo(net); - //Buffer *b = buffer(id); - //b->setActive(true); - - Network *netinfo = new Network(netid, this); - netinfo->setProxy(signalProxy()); - networkModel()->attachNetwork(netinfo); - connect(netinfo, SIGNAL(destroyed()), this, SLOT(networkDestroyed())); - _networks[netid] = netinfo; -} - -void Client::networkDisconnected(NetworkId networkid) { - if(!_networks.contains(networkid)) { - qWarning() << "Client::networkDisconnected(uint): unknown Network" << networkid; - return; - } - - Network *net = _networks.take(networkid); - if(!net->isInitialized()) { - qDebug() << "Network" << networkid << "disconnected while not yet initialized!"; - updateCoreConnectionProgress(); - } - net->deleteLater(); -} -*/ - -void Client::addNetwork(Network *net) { - net->setProxy(signalProxy()); - signalProxy()->synchronize(net); - networkModel()->attachNetwork(net); - connect(net, SIGNAL(destroyed()), instance(), SLOT(networkDestroyed())); - instance()->_networks[net->networkId()] = net; - emit instance()->networkCreated(net->networkId()); -} - -void Client::createNetwork(const NetworkInfo &info) { - - -} /*** ***/ diff --git a/src/client/client.h b/src/client/client.h index f2b3ec3c..220e8c83 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -103,8 +103,6 @@ public: static QVariant retrieveSessionData(const QString &key, const QVariant &def = QVariant()); static QStringList sessionDataKeys(); - static void disconnectFromNetwork(NetworkId); - enum ClientMode { LocalCore, RemoteCore }; signals: @@ -150,7 +148,7 @@ signals: void requestCreateNetwork(const NetworkInfo &info); void requestUpdateNetwork(const NetworkInfo &info); - void requestRemoveNetwork(const NetworkInfo &info); + void requestRemoveNetwork(NetworkId); public slots: //void selectBuffer(Buffer *); @@ -180,6 +178,8 @@ private slots: void networkDestroyed(); void coreIdentityCreated(const Identity &); void coreIdentityRemoved(IdentityId); + void coreNetworkCreated(NetworkId); + void coreNetworkRemoved(NetworkId); private: Client(QObject *parent = 0); diff --git a/src/client/modelpropertymapper.cpp b/src/client/modelpropertymapper.cpp index a10a73d3..a855568f 100644 --- a/src/client/modelpropertymapper.cpp +++ b/src/client/modelpropertymapper.cpp @@ -115,6 +115,5 @@ void ModelPropertyMapper::dataChanged(const QModelIndex &topLeft, const QModelIn } void ModelPropertyMapper::targetDestroyed() { - QObject *obj = static_cast(sender()); - removeMapping(0, 0, obj, QByteArray()); + removeMapping(0, 0, sender(), QByteArray()); } diff --git a/src/common/global.cpp b/src/common/global.cpp index ce71aeb0..26abdf95 100644 --- a/src/common/global.cpp +++ b/src/common/global.cpp @@ -24,6 +24,7 @@ #include "logger.h" #include "message.h" #include "identity.h" +#include "network.h" #include "bufferinfo.h" #include "types.h" #include "syncableobject.h" @@ -71,15 +72,17 @@ void Global::registerMetaTypes() { qRegisterMetaType("QVariant"); qRegisterMetaType("Message"); qRegisterMetaType("BufferInfo"); + qRegisterMetaType("NetworkInfo"); qRegisterMetaType("Identity"); + qRegisterMetaType("Network::ConnectionState"); qRegisterMetaTypeStreamOperators("QVariant"); qRegisterMetaTypeStreamOperators("Message"); qRegisterMetaTypeStreamOperators("BufferInfo"); + qRegisterMetaTypeStreamOperators("NetworkInfo"); qRegisterMetaTypeStreamOperators("Identity"); + qRegisterMetaTypeStreamOperators("Network::ConnectionState"); - // Basic types (typedefs) - // These use the standard stream operators qRegisterMetaType("IdentityId"); qRegisterMetaType("BufferId"); qRegisterMetaType("NetworkId"); diff --git a/src/common/network.cpp b/src/common/network.cpp index e899969a..da1be33a 100644 --- a/src/common/network.cpp +++ b/src/common/network.cpp @@ -38,6 +38,7 @@ Network::Network(const NetworkId &networkid, QObject *parent) : SyncableObject(p _networkName(QString("")), _currentServer(QString()), _connected(false), + _connectionState(Disconnected), _prefixes(QString()), _prefixModes(QString()), _proxy(0), @@ -48,15 +49,16 @@ Network::Network(const NetworkId &networkid, QObject *parent) : SyncableObject(p } // I think this is unnecessary since IrcUsers have us as their daddy :) -/* + Network::~Network() { - QHashIterator ircuser(_ircUsers); - while (ircuser.hasNext()) { - ircuser.next(); - delete ircuser.value(); - } +// QHashIterator ircuser(_ircUsers); +// while (ircuser.hasNext()) { +// ircuser.next(); +// delete ircuser.value(); +// } +// qDebug() << "Destroying net" << networkName() << networkId(); } -*/ + NetworkId Network::networkId() const { return _networkId; @@ -93,6 +95,10 @@ bool Network::isConnected() const { return _connected; } +Network::ConnectionState Network::connectionState() const { + return _connectionState; +} + NetworkInfo Network::networkInfo() const { NetworkInfo info; info.networkName = networkName(); @@ -106,11 +112,13 @@ NetworkInfo Network::networkInfo() const { void Network::setNetworkInfo(const NetworkInfo &info) { // we don't set our ID! - if(!info.networkName.isEmpty()) setNetworkName(info.networkName); - if(info.identity > 0) setIdentity(info.identity); - if(!info.codecForEncoding.isEmpty()) setCodecForEncoding(QTextCodec::codecForName(info.codecForEncoding)); - if(!info.codecForDecoding.isEmpty()) setCodecForDecoding(QTextCodec::codecForName(info.codecForDecoding)); - if(info.serverList.count()) setServerList(info.serverList); + if(!info.networkName.isEmpty() && info.networkName != networkName()) setNetworkName(info.networkName); + if(info.identity > 0 && info.identity != identity()) setIdentity(info.identity); + if(!info.codecForEncoding.isEmpty() && info.codecForEncoding != codecForEncoding()) + setCodecForEncoding(QTextCodec::codecForName(info.codecForEncoding)); + if(!info.codecForDecoding.isEmpty() && info.codecForDecoding != codecForDecoding()) + setCodecForDecoding(QTextCodec::codecForName(info.codecForDecoding)); + if(info.serverList.count()) setServerList(info.serverList); // FIXME compare components } QString Network::prefixToMode(const QString &prefix) { @@ -165,7 +173,7 @@ QStringList Network::channels() const { return _ircChannels.keys(); } -QList Network::serverList() const { +QVariantList Network::serverList() const { return _serverList; } @@ -361,6 +369,11 @@ void Network::setConnected(bool connected) { emit connectedSet(connected); } +void Network::setConnectionState(ConnectionState state) { + _connectionState = (ConnectionState)state; + emit connectionStateSet(_connectionState); +} + void Network::setMyNick(const QString &nickname) { _myNick = nickname; emit myNickSet(nickname); @@ -371,7 +384,7 @@ void Network::setIdentity(IdentityId id) { emit identitySet(id); } -void Network::setServerList(const QList &serverList) { +void Network::setServerList(const QVariantList &serverList) { _serverList = serverList; emit serverListSet(serverList); } @@ -401,9 +414,7 @@ QVariantMap Network::initSupports() const { } QVariantList Network::initServerList() const { - QList list; - foreach(QVariantMap serverdata, serverList()) list << QVariant(serverdata); - return list; + return serverList(); } QStringList Network::initIrcUsers() const { @@ -427,9 +438,7 @@ void Network::initSetSupports(const QVariantMap &supports) { } void Network::initSetServerList(const QVariantList & serverList) { - QList slist; - foreach(QVariant v, serverList) slist << v.toMap(); - setServerList(slist); + setServerList(serverList); } void Network::initSetIrcUsers(const QStringList &hostmasks) { @@ -497,16 +506,32 @@ void Network::channelDestroyed() { _ircChannels.remove(_ircChannels.key(channel)); } -void Network::requestConnect() { +void Network::requestConnect() const { if(!proxy()) return; if(proxy()->proxyMode() == SignalProxy::Client) emit connectRequested(); // on the client this triggers calling this slot on the core - else emit connectRequested(networkId()); // and this is for CoreSession :) + else { + if(connectionState() != Disconnected) { + qWarning() << "Requesting connect while not being disconnected!"; + return; + } + emit connectRequested(networkId()); // and this is for CoreSession :) + } } -void Network::requestDisconnect() { +void Network::requestDisconnect() const { if(!proxy()) return; if(proxy()->proxyMode() == SignalProxy::Client) emit disconnectRequested(); // on the client this triggers calling this slot on the core - else emit disconnectRequested(networkId()); // and this is for CoreSession :) + else { + if(connectionState() == Disconnected) { + qWarning() << "Requesting disconnect while not being connected!"; + return; + } + emit disconnectRequested(networkId()); // and this is for CoreSession :) + } +} + +void Network::emitConnectionError(const QString &errorMsg) { + emit connectionError(errorMsg); } // ==================== @@ -563,3 +588,27 @@ bool NetworkInfo::operator==(const NetworkInfo &other) const { bool NetworkInfo::operator!=(const NetworkInfo &other) const { return !(*this == other); } + +QDataStream &operator<<(QDataStream &out, const NetworkInfo &info) { + QVariantMap i; + i["NetworkId"] = QVariant::fromValue(info.networkId); + i["NetworkName"] = info.networkName; + i["Identity"] = QVariant::fromValue(info.identity); + i["CodecForEncoding"] = info.codecForEncoding; + i["CodecForDecoding"] = info.codecForDecoding; + i["ServerList"] = info.serverList; + out << i; + return out; +} + +QDataStream &operator>>(QDataStream &in, NetworkInfo &info) { + QVariantMap i; + in >> i; + info.networkId = i["NetworkId"].value(); + info.networkName = i["NetworkName"].toString(); + info.identity = i["Identity"].value(); + info.codecForEncoding = i["CodecForEncoding"].toByteArray(); + info.codecForDecoding = i["CodecForDecoding"].toByteArray(); + info.serverList = i["ServerList"].toList(); + return in; +} diff --git a/src/common/network.h b/src/common/network.h index 84b9b4bf..4c04ceb0 100644 --- a/src/common/network.h +++ b/src/common/network.h @@ -44,6 +44,7 @@ struct NetworkInfo; class Network : public SyncableObject { Q_OBJECT + Q_ENUMS(ConnectionState Network::ConnectionState) Q_PROPERTY(QString networkName READ networkName WRITE setNetworkName STORED false) Q_PROPERTY(QString currentServer READ currentServer WRITE setCurrentServer STORED false) @@ -52,10 +53,13 @@ class Network : public SyncableObject { Q_PROPERTY(QByteArray codecForDecoding READ codecForDecoding WRITE setCodecForDecoding STORED false) Q_PROPERTY(IdentityId identityId READ identity WRITE setIdentity STORED false) Q_PROPERTY(bool isConnected READ isConnected WRITE setConnected STORED false) + Q_PROPERTY(Network::ConnectionState connectionState READ connectionState WRITE setConnectionState STORED false) public: + enum ConnectionState { Disconnected, Connecting, Initializing, Initialized, Disconnecting }; + Network(const NetworkId &networkid, QObject *parent = 0); - // ~Network(); + ~Network(); NetworkId networkId() const; @@ -68,6 +72,7 @@ public: bool isChannelName(const QString &channelname) const; bool isConnected() const; + Network::ConnectionState connectionState() const; QString prefixToMode(const QString &prefix); QString prefixToMode(const QCharRef &prefix); @@ -80,7 +85,7 @@ public: IdentityId identity() const; QStringList nicks() const; QStringList channels() const; - QList serverList() const; + QVariantList serverList() const; NetworkInfo networkInfo() const; void setNetworkInfo(const NetworkInfo &); @@ -117,10 +122,11 @@ public slots: void setNetworkName(const QString &networkName); void setCurrentServer(const QString ¤tServer); void setConnected(bool isConnected); + void setConnectionState(Network::ConnectionState state); void setMyNick(const QString &mynick); void setIdentity(IdentityId); - void setServerList(const QList &serverList); + void setServerList(const QVariantList &serverList); void setCodecForEncoding(const QByteArray &codecName); void setCodecForDecoding(const QByteArray &codecName); @@ -149,8 +155,10 @@ public slots: // channel lists up to date void ircUserNickChanged(QString newnick); - void requestConnect(); - void requestDisconnect(); + void requestConnect() const; + void requestDisconnect() const; + + void emitConnectionError(const QString &); private slots: void ircUserDestroyed(); @@ -163,10 +171,12 @@ signals: void networkNameSet(const QString &networkName); void currentServerSet(const QString ¤tServer); void connectedSet(bool isConnected); + void connectionStateSet(Network::ConnectionState); + void connectionError(const QString &errorMsg); void myNickSet(const QString &mynick); void identitySet(IdentityId); - void serverListSet(const QList &serverList); + void serverListSet(QVariantList serverList); void codecForEncodingSet(const QString &codecName); void codecForDecodingSet(const QString &codecName); @@ -188,8 +198,8 @@ signals: void ircUserInitDone(IrcUser *); void ircChannelInitDone(IrcChannel *); - void connectRequested(NetworkId = 0); - void disconnectRequested(NetworkId = 0); + void connectRequested(NetworkId id = 0) const; + void disconnectRequested(NetworkId id = 0) const; private: NetworkId _networkId; @@ -199,6 +209,7 @@ private: QString _networkName; QString _currentServer; bool _connected; + ConnectionState _connectionState; QString _prefixes; QString _prefixModes; @@ -207,7 +218,7 @@ private: QHash _ircChannels; // stores all known channels QHash _supports; // stores results from RPL_ISUPPORT - QList _serverList; + QVariantList _serverList; QStringList _perform; //QVariantMap networkSettings; @@ -222,15 +233,19 @@ private: //! Stores all editable information about a network (as opposed to runtime state). struct NetworkInfo { NetworkId networkId; - IdentityId identity; QString networkName; + IdentityId identity; QByteArray codecForEncoding; QByteArray codecForDecoding; - QList serverList; + QVariantList serverList; bool operator==(const NetworkInfo &other) const; bool operator!=(const NetworkInfo &other) const; }; +QDataStream &operator<<(QDataStream &out, const NetworkInfo &info); +QDataStream &operator>>(QDataStream &in, NetworkInfo &info); + +Q_DECLARE_METATYPE(NetworkInfo); #endif diff --git a/src/core/coresession.cpp b/src/core/coresession.cpp index eb6f3ccb..112f60c2 100644 --- a/src/core/coresession.cpp +++ b/src/core/coresession.cpp @@ -46,29 +46,6 @@ CoreSession::CoreSession(UserId uid, bool restoreState, QObject *parent) : QObje CoreUserSettings s(user()); sessionData = s.sessionData(); - foreach(IdentityId id, s.identityIds()) { - Identity *i = new Identity(s.identity(id), this); - if(!i->isValid()) { - qWarning() << QString("Invalid identity! Removing..."); - s.removeIdentity(id); - delete i; - continue; - } - if(_identities.contains(i->id())) { - qWarning() << "Duplicate identity, ignoring!"; - delete i; - continue; - } - _identities[i->id()] = i; - } - if(!_identities.count()) { - Identity i(1); - i.setToDefaults(); - i.setIdentityName(tr("Default Identity")); - createIdentity(i); - } - - //p->attachSlot(SIGNAL(requestNetworkStates()), this, SLOT(networkStateRequested())); p->attachSlot(SIGNAL(requestConnect(QString)), this, SLOT(connectToNetwork(QString))); p->attachSlot(SIGNAL(disconnectFromNetwork(NetworkId)), this, SLOT(disconnectFromNetwork(NetworkId))); // FIXME p->attachSlot(SIGNAL(sendInput(BufferInfo, QString)), this, SLOT(msgFromClient(BufferInfo, QString))); @@ -87,38 +64,14 @@ CoreSession::CoreSession(UserId uid, bool restoreState, QObject *parent) : QObje p->attachSlot(SIGNAL(updateIdentity(const Identity &)), this, SLOT(updateIdentity(const Identity &))); p->attachSlot(SIGNAL(removeIdentity(IdentityId)), this, SLOT(removeIdentity(IdentityId))); - initScriptEngine(); - - foreach(Identity *id, _identities.values()) { - p->synchronize(id); - } + p->attachSignal(this, SIGNAL(networkCreated(NetworkId))); + p->attachSignal(this, SIGNAL(networkRemoved(NetworkId))); + p->attachSlot(SIGNAL(createNetwork(const NetworkInfo &)), this, SLOT(createNetwork(const NetworkInfo &))); + p->attachSlot(SIGNAL(updateNetwork(const NetworkInfo &)), this, SLOT(updateNetwork(const NetworkInfo &))); + p->attachSlot(SIGNAL(removeNetwork(NetworkId)), this, SLOT(removeNetwork(NetworkId))); - // Load and init networks. - // FIXME For now we use the old info from sessionData... - - QVariantMap networks = retrieveSessionData("Networks").toMap(); - foreach(QString netname, networks.keys()) { - QVariantMap network = networks[netname].toMap(); - NetworkId netid = Core::networkId(user(), netname); - Network *net = new Network(netid, this); - connect(net, SIGNAL(connectRequested(NetworkId)), this, SLOT(connectToNetwork(NetworkId))); - net->setNetworkName(netname); - net->setIdentity(1); // FIXME default identity for now - net->setCodecForEncoding("ISO-8859-15"); // FIXME - net->setCodecForDecoding("ISO-8859-15"); // FIXME - QList slist; - foreach(QVariant v, network["Servers"].toList()) { - QVariantMap server; - server["Host"] = v.toMap()["Address"]; - server["Address"] = v.toMap()["Address"]; - server["Port"] = v.toMap()["Port"]; - slist << server; - } - net->setServerList(slist); - net->setProxy(p); - _networks[netid] = net; - p->synchronize(net); - } + loadSettings(); + initScriptEngine(); // Restore session state if(restoreState) restoreSessionState(); @@ -128,6 +81,12 @@ CoreSession::CoreSession(UserId uid, bool restoreState, QObject *parent) : QObje CoreSession::~CoreSession() { saveSessionState(); + foreach(NetworkConnection *conn, _connections.values()) { + conn->deleteLater(); + } + foreach(Network *net, _networks.values()) { + net->deleteLater(); + } } UserId CoreSession::user() const { @@ -149,6 +108,65 @@ Identity *CoreSession::identity(IdentityId id) const { return 0; } +void CoreSession::loadSettings() { + CoreUserSettings s(user()); + + foreach(IdentityId id, s.identityIds()) { + Identity *i = new Identity(s.identity(id), this); + if(!i->isValid()) { + qWarning() << QString("Invalid identity! Removing..."); + s.removeIdentity(id); + delete i; + continue; + } + if(_identities.contains(i->id())) { + qWarning() << "Duplicate identity, ignoring!"; + delete i; + continue; + } + _identities[i->id()] = i; + signalProxy()->synchronize(i); + } + if(!_identities.count()) { + Identity i(1); + i.setToDefaults(); + i.setIdentityName(tr("Default Identity")); + createIdentity(i); + } + + foreach(NetworkId id, s.networkIds()) { + NetworkInfo info = s.networkInfo(id); + createNetwork(info, true); + } + + // FIXME Migrate old settings if available... + if(!_networks.count()) { + QVariantMap networks = retrieveSessionData("Networks").toMap(); + if(networks.keys().count()) { + qWarning() << "Migrating your old network settings to the new format!"; + foreach(QString netname, networks.keys()) { + QVariantMap network = networks[netname].toMap(); + NetworkId netid = Core::networkId(user(), netname); + NetworkInfo info; + info.networkId = netid; + info.networkName = netname; + info.identity = 1; + info.codecForEncoding = "ISO-8859-15"; + info.codecForDecoding = "ISO-8859-15"; + QVariantList slist; + foreach(QVariant v, network["Servers"].toList()) { + QVariantMap server; + server["Host"] = v.toMap()["Address"]; + server["Port"] = v.toMap()["Port"]; + slist << server; + } + info.serverList = slist; + createNetwork(info, true); + } + } + } +} + void CoreSession::saveSessionState() const { QVariantMap res; QVariantList conn; @@ -225,27 +243,25 @@ void CoreSession::connectToNetwork(NetworkId id, const QVariant &previousState) conn = new NetworkConnection(net, this, previousState); _connections[id] = conn; attachNetworkConnection(conn); - conn->connectToIrc(); } + conn->connectToIrc(); } void CoreSession::attachNetworkConnection(NetworkConnection *conn) { - //connect(this, SIGNAL(connectToIrc(QString)), network, SLOT(connectToIrc(QString))); - //connect(this, SIGNAL(disconnectFromIrc(QString)), network, SLOT(disconnectFromIrc(QString))); - //connect(this, SIGNAL(msgFromGui(uint, QString, QString)), network, SLOT(userInput(uint, QString, QString))); - connect(conn, SIGNAL(connected(NetworkId)), this, SLOT(networkConnected(NetworkId))); connect(conn, SIGNAL(disconnected(NetworkId)), this, SLOT(networkDisconnected(NetworkId))); - signalProxy()->attachSignal(conn, SIGNAL(connected(NetworkId)), SIGNAL(networkConnected(NetworkId))); - signalProxy()->attachSignal(conn, SIGNAL(disconnected(NetworkId)), SIGNAL(networkDisconnected(NetworkId))); + + // I guess we don't need these anymore, client-side can just connect the network's signals directly + //signalProxy()->attachSignal(conn, SIGNAL(connected(NetworkId)), SIGNAL(networkConnected(NetworkId))); + //signalProxy()->attachSignal(conn, SIGNAL(disconnected(NetworkId)), SIGNAL(networkDisconnected(NetworkId))); connect(conn, SIGNAL(displayMsg(Message::Type, QString, QString, QString, quint8)), this, SLOT(recvMessageFromServer(Message::Type, QString, QString, QString, quint8))); connect(conn, SIGNAL(displayStatusMsg(QString)), this, SLOT(recvStatusMsgFromServer(QString))); - // TODO add error handling } void CoreSession::disconnectFromNetwork(NetworkId id) { + if(!_connections.contains(id)) return; _connections[id]->disconnectFromIrc(); } @@ -269,19 +285,17 @@ SignalProxy *CoreSession::signalProxy() const { return _signalProxy; } +// FIXME we need a sane way for creating buffers! void CoreSession::networkConnected(NetworkId networkid) { - network(networkid)->setConnected(true); Core::bufferInfo(user(), networkConnection(networkid)->networkName()); // create status buffer } void CoreSession::networkDisconnected(NetworkId networkid) { // FIXME // connection should only go away on explicit /part, and handle reconnections etcpp internally otherwise - network(networkid)->setConnected(false); Q_ASSERT(_connections.contains(networkid)); _connections.take(networkid)->deleteLater(); - Q_ASSERT(!_connections.contains(networkid)); } // FIXME switch to BufferId @@ -385,7 +399,9 @@ void CoreSession::initScriptEngine() { void CoreSession::scriptRequest(QString script) { emit scriptResult(scriptEngine->evaluate(script).toString()); } -#include + +/*** Identity Handling ***/ + void CoreSession::createIdentity(const Identity &id) { // find free ID int i; @@ -423,3 +439,47 @@ void CoreSession::removeIdentity(IdentityId id) { } } +/*** Network Handling ***/ + +void CoreSession::createNetwork(const NetworkInfo &_info, bool useId) { + NetworkInfo info = _info; + int id; + if(useId && info.networkId > 0) id = info.networkId.toInt(); + else { + for(id = 1; id <= _networks.count(); id++) { + if(!_networks.keys().contains(id)) break; + } + //qDebug() << "found free id" << i; + info.networkId = id; + } + Network *net = new Network(id, this); + connect(net, SIGNAL(connectRequested(NetworkId)), this, SLOT(connectToNetwork(NetworkId))); + connect(net, SIGNAL(disconnectRequested(NetworkId)), this, SLOT(disconnectFromNetwork(NetworkId))); + net->setNetworkInfo(info); + net->setProxy(signalProxy()); + _networks[id] = net; + signalProxy()->synchronize(net); + CoreUserSettings s(user()); + s.storeNetworkInfo(info); + emit networkCreated(id); +} + +void CoreSession::updateNetwork(const NetworkInfo &info) { + if(!_networks.contains(info.networkId)) { + qWarning() << "Update request for unknown network received!"; + return; + } + _networks[info.networkId]->setNetworkInfo(info); + CoreUserSettings s(user()); + s.storeNetworkInfo(info); +} + +void CoreSession::removeNetwork(NetworkId id) { + Network *net = _networks.take(id); + if(net) { + emit networkRemoved(id); + CoreUserSettings s(user()); + s.removeNetworkInfo(id); + net->deleteLater(); + } +} diff --git a/src/core/coresession.h b/src/core/coresession.h index 943063b0..1249a86c 100644 --- a/src/core/coresession.h +++ b/src/core/coresession.h @@ -29,6 +29,7 @@ class Identity; class NetworkConnection; // FIXME get rid of class Network; +struct NetworkInfo; class SignalProxy; class QScriptEngine; @@ -90,6 +91,21 @@ public slots: */ void removeIdentity(IdentityId identity); + //! Create a network and propagate the changes to the clients. + /** \param info The network's settings. + */ + void createNetwork(const NetworkInfo &info, bool useId = false); + + //! Update a network and propagate the changes to the clients. + /** \param info The updated network settings. + */ + void updateNetwork(const NetworkInfo &info); + + //! Remove identity and propagate that fact to the clients. + /** \param identity The identity to be removed. + */ + void removeNetwork(NetworkId network); + signals: void initialized(); @@ -120,6 +136,9 @@ signals: */ void identityRemoved(IdentityId identity); + void networkCreated(NetworkId); + void networkRemoved(NetworkId); + private slots: void recvStatusMsgFromServer(QString msg); void recvMessageFromServer(Message::Type, QString target, QString text, QString sender = "", quint8 flags = Message::None); @@ -136,6 +155,7 @@ private slots: void scriptRequest(QString script); private: + void loadSettings(); void initScriptEngine(); UserId _user; diff --git a/src/core/coreusersettings.cpp b/src/core/coreusersettings.cpp index d83d75f2..2170b8f2 100644 --- a/src/core/coreusersettings.cpp +++ b/src/core/coreusersettings.cpp @@ -25,14 +25,6 @@ CoreUserSettings::CoreUserSettings(UserId uid) : CoreSettings(QString("CoreUser/ } -void CoreUserSettings::storeIdentity(const Identity &identity) { - setLocalValue(QString("Identities/%1").arg(identity.id().toInt()), qVariantFromValue(identity)); -} - -void CoreUserSettings::removeIdentity(const Identity &identity) { - removeLocalKey(QString("Identities/%1").arg(identity.id().toInt())); -} - Identity CoreUserSettings::identity(IdentityId id) { QVariant v = localValue(QString("Identities/%1").arg(id.toInt())); if(qVariantCanConvert(v)) { @@ -49,6 +41,40 @@ QList CoreUserSettings::identityIds() { return res; } +void CoreUserSettings::storeIdentity(const Identity &identity) { + setLocalValue(QString("Identities/%1").arg(identity.id().toInt()), qVariantFromValue(identity)); +} + +void CoreUserSettings::removeIdentity(IdentityId id) { + removeLocalKey(QString("Identities/%1").arg(id.toInt())); +} + + +NetworkInfo CoreUserSettings::networkInfo(NetworkId id) { + QVariant v = localValue(QString("Networks/%1").arg(id.toInt())); + if(v.canConvert()) { + return v.value(); + } + return NetworkInfo(); +} + +QList CoreUserSettings::networkIds() { + QList res; + foreach(QString id, localChildKeys("Networks")) { + res << id.toInt(); + } + return res; +} + +void CoreUserSettings::storeNetworkInfo(const NetworkInfo &info) { + setLocalValue(QString("Networks/%1").arg(info.networkId.toInt()), QVariant::fromValue(info)); +} + +void CoreUserSettings::removeNetworkInfo(NetworkId id) { + removeLocalKey(QString("Networks/%1").arg(id.toInt())); +} + + void CoreUserSettings::setSessionState(const QVariant &data) { setLocalValue("SessionState", data); } diff --git a/src/core/coreusersettings.h b/src/core/coreusersettings.h index 3a8c6b39..bf303cfa 100644 --- a/src/core/coreusersettings.h +++ b/src/core/coreusersettings.h @@ -23,6 +23,7 @@ #include "coresettings.h" #include "identity.h" +#include "network.h" #include "types.h" #include @@ -32,11 +33,15 @@ class CoreUserSettings : public CoreSettings { public: CoreUserSettings(UserId user); - void storeIdentity(const Identity &identity); - void removeIdentity(const Identity &identity); - Identity identity(IdentityId id); QList identityIds(); + void storeIdentity(const Identity &identity); + void removeIdentity(IdentityId id); + + NetworkInfo networkInfo(NetworkId id); + QList networkIds(); + void storeNetworkInfo(const NetworkInfo &info); + void removeNetworkInfo(NetworkId id); void setSessionState(const QVariant &data); QVariant sessionState(const QVariant &def = QVariant()); diff --git a/src/core/networkconnection.cpp b/src/core/networkconnection.cpp index a00e4f49..4cca93f9 100644 --- a/src/core/networkconnection.cpp +++ b/src/core/networkconnection.cpp @@ -36,6 +36,7 @@ #include "ctcphandler.h" NetworkConnection::NetworkConnection(Network *network, CoreSession *session, const QVariant &state) : QObject(network), + _connectionState(Network::Disconnected), _network(network), _coreSession(session), _ircServerHandler(new IrcServerHandler(this)), @@ -43,7 +44,7 @@ NetworkConnection::NetworkConnection(Network *network, CoreSession *session, con _ctcpHandler(new CtcpHandler(this)), _previousState(state) { - connect(network, SIGNAL(currentServerSet(const QString &)), this, SLOT(sendPerform())); + connect(network, SIGNAL(currentServerSet(const QString &)), this, SLOT(networkInitialized())); connect(&socket, SIGNAL(connected()), this, SLOT(socketConnected())); connect(&socket, SIGNAL(disconnected()), this, SLOT(socketDisconnected())); @@ -54,13 +55,25 @@ NetworkConnection::NetworkConnection(Network *network, CoreSession *session, con } NetworkConnection::~NetworkConnection() { + disconnectFromIrc(); delete _ircServerHandler; delete _userInputHandler; delete _ctcpHandler; } bool NetworkConnection::isConnected() const { - return socket.state() == QAbstractSocket::ConnectedState; + // return socket.state() == QAbstractSocket::ConnectedState; + return connectionState() == Network::Initialized; +} + +Network::ConnectionState NetworkConnection::connectionState() const { + return _connectionState; +} + +void NetworkConnection::setConnectionState(Network::ConnectionState state) { + _connectionState = state; + network()->setConnectionState(state); + emit connectionStateChanged(state); } NetworkId NetworkConnection::networkId() const { @@ -125,7 +138,7 @@ QByteArray NetworkConnection::userEncode(const QString &userNick, const QString void NetworkConnection::connectToIrc() { - QList serverList = network()->serverList(); + QVariantList serverList = network()->serverList(); Identity *identity = coreSession()->identity(network()->identity()); if(!serverList.count()) { qWarning() << "Server list empty, ignoring connect request!"; @@ -135,14 +148,31 @@ void NetworkConnection::connectToIrc() { qWarning() << "Invalid identity configures, ignoring connect request!"; return; } - // TODO implement cycling / random servers - QString host = serverList[0]["Host"].toString(); - quint16 port = serverList[0]["Port"].toUInt(); + QString host = serverList[0].toMap()["Host"].toString(); + quint16 port = serverList[0].toMap()["Port"].toUInt(); displayStatusMsg(QString("Connecting to %1:%2...").arg(host).arg(port)); socket.connectToHost(host, port); } +void NetworkConnection::networkInitialized() { + sendPerform(); + + // rejoin channels we've been in + QStringList chans = _previousState.toStringList(); + if(chans.count() > 0) { + qDebug() << "autojoining" << chans; + QString list = chans.join(","); + putCmd("join", QStringList(list)); // FIXME check for 512 byte limit! + } + // delete _previousState, we won't need it again + _previousState = QVariant(); + // now we are initialized + setConnectionState(Network::Initialized); + network()->setConnected(true); + emit connected(networkId()); +} + void NetworkConnection::sendPerform() { // TODO: reimplement perform List! //// send performlist @@ -154,15 +184,6 @@ void NetworkConnection::sendPerform() { // } //} - // rejoin channels we've been in - QStringList chans = _previousState.toStringList(); - if(chans.count() > 0) { - qDebug() << "autojoining" << chans; - QString list = chans.join(","); - putCmd("join", QStringList(list)); - } - // delete _previousState, we won't need it again - _previousState = QVariant(); } QVariant NetworkConnection::state() const { @@ -182,13 +203,15 @@ void NetworkConnection::socketHasData() { } } -void NetworkConnection::socketError( QAbstractSocket::SocketError err ) { - Q_UNUSED(err); - qDebug() << "Socket Error!"; +void NetworkConnection::socketError(QAbstractSocket::SocketError) { + qDebug() << qPrintable(tr("Could not connect to %1 (%2)").arg(network()->networkName(), socket.errorString())); + emit connectionError(socket.errorString()); + emit displayMsg(Message::Error, "", tr("Connection failure: %1").arg(socket.errorString())); + network()->emitConnectionError(socket.errorString()); } void NetworkConnection::socketConnected() { - emit connected(networkId()); + //emit connected(networkId()); initialize first! Identity *identity = coreSession()->identity(network()->identity()); if(!identity) { qWarning() << "Identity invalid!"; @@ -199,12 +222,30 @@ void NetworkConnection::socketConnected() { putRawLine(QString("USER %1 8 * :%2").arg(identity->ident(), identity->realName())); } -void NetworkConnection::socketStateChanged(QAbstractSocket::SocketState state) { - Q_UNUSED(state); - //qDebug() << "Socket state changed: " << state; +void NetworkConnection::socketStateChanged(QAbstractSocket::SocketState socketState) { + Network::ConnectionState state; + switch(socketState) { + case QAbstractSocket::UnconnectedState: + state = Network::Disconnected; + break; + case QAbstractSocket::HostLookupState: + case QAbstractSocket::ConnectingState: + state = Network::Connecting; + break; + case QAbstractSocket::ConnectedState: + state = Network::Initializing; + break; + case QAbstractSocket::ClosingState: + state = Network::Disconnecting; + break; + default: + state = Network::Disconnected; + } + setConnectionState(state); } void NetworkConnection::socketDisconnected() { + network()->setConnected(false); emit disconnected(networkId()); } diff --git a/src/core/networkconnection.h b/src/core/networkconnection.h index 59f40c61..9b9c43bb 100644 --- a/src/core/networkconnection.h +++ b/src/core/networkconnection.h @@ -28,6 +28,7 @@ #include #include "message.h" +#include "network.h" #include "signalproxy.h" class CoreSession; @@ -50,6 +51,7 @@ public: CoreSession *coreSession() const; bool isConnected() const; + Network::ConnectionState connectionState() const; IrcServerHandler *ircServerHandler() const; UserInputHandler *userInputHandler() const; @@ -95,10 +97,11 @@ signals: void displayStatusMsg(QString); //void displayMsg(Message msg); void displayMsg(Message::Type, QString target, QString text, QString sender = "", quint8 flags = Message::None); - void connected(NetworkId networkId); + void connected(NetworkId networkId); ///< Emitted after receipt of 001 to indicate that we can now send data to the IRC server void disconnected(NetworkId networkId); - + void connectionStateChanged(Network::ConnectionState); void connectionInitialized(); ///< Emitted after receipt of 001 to indicate that we can now send data to the IRC server + void connectionError(const QString &errorMsg); //void queryRequested(QString network, QString nick); @@ -109,9 +112,12 @@ private slots: void socketConnected(); void socketDisconnected(); void socketStateChanged(QAbstractSocket::SocketState); + void setConnectionState(Network::ConnectionState); + void networkInitialized(); private: QTcpSocket socket; + Network::ConnectionState _connectionState; Network *_network; CoreSession *_coreSession; diff --git a/src/core/userinputhandler.cpp b/src/core/userinputhandler.cpp index 94d81470..2ecb58dd 100644 --- a/src/core/userinputhandler.cpp +++ b/src/core/userinputhandler.cpp @@ -193,7 +193,6 @@ void UserInputHandler::handleWho(QString bufname, QString msg) { } void UserInputHandler::handleWhois(QString bufname, QString msg) { - qDebug() << "WHOIS" << QStringList(msg); emit putCmd("WHOIS", msg.split(' ')); } diff --git a/src/icons/icons.qrc b/src/icons/icons.qrc index 5630df6a..a92e0a77 100644 --- a/src/icons/icons.qrc +++ b/src/icons/icons.qrc @@ -124,7 +124,7 @@ oxygen/16x16/actions/games-highscores.png oxygen/16x16/actions/games-hint.png oxygen/16x16/actions/games-solve.png - oxygen/16x16/actions/gear.png + oxygen/16x16/actions/gear.png oxygen/16x16/actions/get-hot-new-stuff.png oxygen/16x16/actions/go-bottom.png oxygen/16x16/actions/go-down-search.png @@ -417,7 +417,7 @@ oxygen/22x22/actions/games-highscores.png oxygen/22x22/actions/games-hint.png oxygen/22x22/actions/games-solve.png - oxygen/22x22/actions/gear.png + oxygen/22x22/actions/gear.png oxygen/22x22/actions/get-hot-new-stuff.png oxygen/22x22/actions/go-bottom.png oxygen/22x22/actions/go-down-search.png diff --git a/src/qtui/mainwin.cpp b/src/qtui/mainwin.cpp index cdbe71b9..2b4b9b5f 100644 --- a/src/qtui/mainwin.cpp +++ b/src/qtui/mainwin.cpp @@ -202,8 +202,9 @@ void MainWin::setupSettingsDlg() { settingsDlg->registerSettingsPage(new FontsSettingsPage(settingsDlg)); settingsDlg->registerSettingsPage(new IdentitiesSettingsPage(settingsDlg)); -#ifdef SPUTDEV settingsDlg->registerSettingsPage(new NetworksSettingsPage(settingsDlg)); + +#ifdef SPUTDEV connect(settingsDlg, SIGNAL(finished(int)), QApplication::instance(), SLOT(quit())); // FIXME #endif } @@ -289,7 +290,7 @@ void MainWin::connectedToCore() { ui.menuCore->setEnabled(true); ui.actionConnectCore->setEnabled(false); ui.actionDisconnectCore->setEnabled(true); - ui.actionNetworkList->setEnabled(true); + //ui.actionNetworkList->setEnabled(true); ui.bufferWidget->show(); statusBar()->showMessage(tr("Connected to core.")); } @@ -298,7 +299,7 @@ void MainWin::disconnectedFromCore() { ui.menuViews->setEnabled(false); ui.menuCore->setEnabled(false); ui.actionDisconnectCore->setEnabled(false); - ui.actionNetworkList->setEnabled(false); + //ui.actionNetworkList->setEnabled(false); ui.bufferWidget->hide(); ui.actionConnectCore->setEnabled(true); nickListWidget->reset(); diff --git a/src/qtui/settingspages/identitiessettingspage.cpp b/src/qtui/settingspages/identitiessettingspage.cpp index 5aa1712e..c84c33ab 100644 --- a/src/qtui/settingspages/identitiessettingspage.cpp +++ b/src/qtui/settingspages/identitiessettingspage.cpp @@ -375,7 +375,7 @@ void IdentitiesSettingsPage::on_addNick_clicked() { void IdentitiesSettingsPage::on_deleteNick_clicked() { // no confirmation, since a nickname is really nothing hard to recreate if(ui.nicknameList->selectedItems().count()) { - delete ui.nicknameList->selectedItems()[0]; + delete ui.nicknameList->takeItem(ui.nicknameList->row(ui.nicknameList->selectedItems()[0])); ui.nicknameList->setCurrentRow(qMin(ui.nicknameList->currentRow()+1, ui.nicknameList->count()-1)); setWidgetStates(); widgetHasChanged(); @@ -444,8 +444,8 @@ void CreateIdentityDlg::on_identityName_textChanged(const QString &text) { /*********************************************************************************************/ -SaveIdentitiesDlg::SaveIdentitiesDlg(QList tocreate, QList toupdate, QList toremove, QWidget *parent) - : QDialog(parent), toCreate(tocreate), toUpdate(toupdate), toRemove(toremove) { +SaveIdentitiesDlg::SaveIdentitiesDlg(const QList &toCreate, const QList &toUpdate, const QList &toRemove, QWidget *parent) + : QDialog(parent) { //, toCreate(tocreate), toUpdate(toupdate), toRemove(toremove) { ui.setupUi(this); numevents = toCreate.count() + toUpdate.count() + toRemove.count(); rcvevents = 0; @@ -466,6 +466,7 @@ SaveIdentitiesDlg::SaveIdentitiesDlg(QList tocreate, QList toCreate, QList toUpdate, QList toRemove, QWidget *parent = 0); + SaveIdentitiesDlg(const QList &toCreate, const QList &toUpdate, const QList &toRemove, QWidget *parent = 0); private slots: void clientEvent(); @@ -110,8 +110,8 @@ class SaveIdentitiesDlg : public QDialog { private: Ui::SaveIdentitiesDlg ui; - QList toCreate, toUpdate; - QList toRemove; + //QList toCreate, toUpdate; + //QList toRemove; int numevents, rcvevents; diff --git a/src/qtui/settingspages/networkssettingspage.cpp b/src/qtui/settingspages/networkssettingspage.cpp index 1344be48..5170826c 100644 --- a/src/qtui/settingspages/networkssettingspage.cpp +++ b/src/qtui/settingspages/networkssettingspage.cpp @@ -33,6 +33,7 @@ NetworksSettingsPage::NetworksSettingsPage(QWidget *parent) : SettingsPage(tr("G ui.setupUi(this); connectedIcon = QIcon(":/22x22/actions/network-connect"); + connectingIcon = QIcon(":/22x22/actions/gear"); disconnectedIcon = QIcon(":/22x22/actions/network-disconnect"); currentId = 0; @@ -54,16 +55,24 @@ NetworksSettingsPage::NetworksSettingsPage(QWidget *parent) : SettingsPage(tr("G } void NetworksSettingsPage::save() { + setEnabled(false); if(currentId != 0) saveToNetworkInfo(networkInfos[currentId]); - // First, remove the temporarily created networks QList toCreate, toUpdate; QList toRemove; QHash::iterator i = networkInfos.begin(); while(i != networkInfos.end()) { - if((*i).networkId < 0) { + NetworkId id = (*i).networkId; + if(id < 0) { toCreate.append(*i); - i = networkInfos.erase(i); + //if(id == currentId) currentId = 0; + //QList items = ui.networkList->findItems((*i).networkName, Qt::MatchExactly); + //if(items.count()) { + // Q_ASSERT(items[0]->data(Qt::UserRole).value() == id); + // delete items[0]; + //} + //i = networkInfos.erase(i); + ++i; } else { if((*i) != Client::network((*i).networkId)->networkInfo()) { toUpdate.append(*i); @@ -80,6 +89,8 @@ void NetworksSettingsPage::save() { // canceled -> reload everything to be safe load(); } + setChangedState(false); + setEnabled(true); } void NetworksSettingsPage::load() { @@ -96,20 +107,20 @@ void NetworksSettingsPage::reset() { ui.networkList->clear(); networkInfos.clear(); - /* - foreach(Identity *identity, identities.values()) { - identity->deleteLater(); - } - identities.clear(); - deletedIdentities.clear(); - changedIdentities.clear(); - ui.identityList->clear(); - */ } bool NetworksSettingsPage::aboutToSave() { - - return true; // FIXME + if(currentId != 0) saveToNetworkInfo(networkInfos[currentId]); + QList errors; + foreach(NetworkInfo info, networkInfos.values()) { + if(!info.serverList.count()) errors.append(1); + } + if(!errors.count()) return true; + QString error(tr("The following problems need to be corrected before your changes can be applied:
    ")); + if(errors.contains(1)) error += tr("
  • All networks need at least one server defined
  • "); + error += tr("
"); + QMessageBox::warning(this, tr("Invalid Network Settings"), error); + return false; } void NetworksSettingsPage::widgetHasChanged() { @@ -136,7 +147,9 @@ void NetworksSettingsPage::setWidgetStates() { ui.detailsBox->setEnabled(true); ui.renameNetwork->setEnabled(true); ui.deleteNetwork->setEnabled(true); - ui.connectNow->setEnabled(true); + ui.connectNow->setEnabled(id > 0 + && (Client::network(id)->connectionState() == Network::Initialized + || Client::network(id)->connectionState() == Network::Disconnected)); if(Client::network(id) && Client::network(id)->isConnected()) { ui.connectNow->setIcon(disconnectedIcon); ui.connectNow->setText(tr("Disconnect")); @@ -164,6 +177,35 @@ void NetworksSettingsPage::setWidgetStates() { } } +void NetworksSettingsPage::setItemState(NetworkId id, QListWidgetItem *item) { + if(!item) item = networkItem(id); + const Network *net = Client::network(id); + if(!net || net->isInitialized()) item->setFlags(item->flags() | Qt::ItemIsEnabled); + else item->setFlags(item->flags() & ~Qt::ItemIsEnabled); + if(net && net->connectionState() == Network::Initialized) { + item->setIcon(connectedIcon); + } else if(net && net->connectionState() != Network::Disconnected) { + item->setIcon(connectingIcon); + } else { + item->setIcon(disconnectedIcon); + } + if(net) { + // check if we already have another net of this name in the list, and replace it + QList items = ui.networkList->findItems(net->networkName(), Qt::MatchExactly); + if(items.count()) { + foreach(QListWidgetItem *i, items) { + NetworkId oldid = i->data(Qt::UserRole).value(); + if(oldid > 0) continue; // only locally created nets should be replaced + if(oldid == currentId) item->setSelected(true); + delete ui.networkList->takeItem(ui.networkList->row(i)); + networkInfos.remove(oldid); + break; + } + } + item->setText(net->networkName()); + } +} + void NetworksSettingsPage::coreConnectionStateChanged(bool state) { this->setEnabled(state); if(state) { @@ -174,14 +216,6 @@ void NetworksSettingsPage::coreConnectionStateChanged(bool state) { } } -QListWidgetItem *NetworksSettingsPage::networkItem(NetworkId id) const { - for(int i = 0; i < ui.networkList->count(); i++) { - QListWidgetItem *item = ui.networkList->item(i); - if(item->data(Qt::UserRole).value() == id) return item; - } - return 0; -} - void NetworksSettingsPage::clientIdentityAdded(IdentityId id) { const Identity * identity = Client::identity(id); connect(identity, SIGNAL(updatedRemotely()), this, SLOT(clientIdentityUpdated())); @@ -221,17 +255,34 @@ void NetworksSettingsPage::clientIdentityUpdated() { } void NetworksSettingsPage::clientIdentityRemoved(IdentityId id) { - ui.identityList->removeItem(ui.identityList->findData(id.toInt())); + if(currentId != 0) saveToNetworkInfo(networkInfos[currentId]); + //ui.identityList->removeItem(ui.identityList->findData(id.toInt())); foreach(NetworkInfo info, networkInfos.values()) { - if(info.identity == id) info.identity = 1; // set to default + qDebug() << info.networkName << info.networkId << info.identity; + if(info.identity == id) { + if(info.networkId == currentId) ui.identityList->setCurrentIndex(0); + info.identity = 1; // set to default + networkInfos[info.networkId] = info; + if(info.networkId > 0) Client::updateNetwork(info); + } } + ui.identityList->removeItem(ui.identityList->findData(id.toInt())); widgetHasChanged(); } +QListWidgetItem *NetworksSettingsPage::networkItem(NetworkId id) const { + for(int i = 0; i < ui.networkList->count(); i++) { + QListWidgetItem *item = ui.networkList->item(i); + if(item->data(Qt::UserRole).value() == id) return item; + } + return 0; +} void NetworksSettingsPage::clientNetworkAdded(NetworkId id) { insertNetwork(id); connect(Client::network(id), SIGNAL(updatedRemotely()), this, SLOT(clientNetworkUpdated())); + connect(Client::network(id), SIGNAL(connectionStateSet(Network::ConnectionState)), this, SLOT(networkConnectionStateChanged(Network::ConnectionState))); + connect(Client::network(id), SIGNAL(connectionError(const QString &)), this, SLOT(networkConnectionError(const QString &))); } void NetworksSettingsPage::clientNetworkUpdated() { @@ -240,19 +291,36 @@ void NetworksSettingsPage::clientNetworkUpdated() { qWarning() << "Update request for unknown network received!"; return; } - QListWidgetItem *item = networkItem(net->networkId()); - if(!item) return; - item->setText(net->networkName()); - if(net->isInitialized()) item->setFlags(item->flags() | Qt::ItemIsEnabled); - else item->setFlags(item->flags() & ~Qt::ItemIsEnabled); - if(net->isConnected()) { - item->setIcon(connectedIcon); - } else { - item->setIcon(disconnectedIcon); + networkInfos[net->networkId()] = net->networkInfo(); + setItemState(net->networkId()); + if(net->networkId() == currentId) displayNetwork(net->networkId()); + setWidgetStates(); + widgetHasChanged(); +} + +void NetworksSettingsPage::clientNetworkRemoved(NetworkId id) { + if(!networkInfos.contains(id)) return; + if(id == currentId) displayNetwork(0); + NetworkInfo info = networkInfos.take(id); + QList items = ui.networkList->findItems(info.networkName, Qt::MatchExactly); + if(items.count()) { + Q_ASSERT(items[0]->data(Qt::UserRole).value() == id); + delete ui.networkList->takeItem(ui.networkList->row(items[0])); + } + setWidgetStates(); + widgetHasChanged(); +} + +void NetworksSettingsPage::networkConnectionStateChanged(Network::ConnectionState state) { + const Network *net = qobject_cast(sender()); + if(!net) return; + if(net->networkId() == currentId) { + ui.connectNow->setEnabled(state == Network::Initialized || state == Network::Disconnected); } + setItemState(net->networkId()); } -void NetworksSettingsPage::clientNetworkRemoved(NetworkId) { +void NetworksSettingsPage::networkConnectionError(const QString &) { } @@ -263,29 +331,41 @@ QListWidgetItem *NetworksSettingsPage::insertNetwork(NetworkId id) { } QListWidgetItem *NetworksSettingsPage::insertNetwork(const NetworkInfo &info) { - QListWidgetItem *item = new QListWidgetItem(disconnectedIcon, info.networkName); - item->setData(Qt::UserRole, QVariant::fromValue(info.networkId)); - ui.networkList->addItem(item); - const Network *net = Client::network(info.networkId); - if(net->isInitialized()) item->setFlags(item->flags() | Qt::ItemIsEnabled); - else item->setFlags(item->flags() & ~Qt::ItemIsEnabled); - if(net && net->isConnected()) { - item->setIcon(connectedIcon); - } else { - item->setIcon(disconnectedIcon); + QListWidgetItem *item = 0; + QList items = ui.networkList->findItems(info.networkName, Qt::MatchExactly); + if(!items.count()) item = new QListWidgetItem(disconnectedIcon, info.networkName, ui.networkList); + else { + // we overwrite an existing net if it a) has the same name and b) has a negative ID meaning we created it locally before + // -> then we can be sure that this is the core-side replacement for the net we created + foreach(QListWidgetItem *i, items) { + NetworkId id = i->data(Qt::UserRole).value(); + if(id < 0) { item = i; break; } + } + if(!item) item = new QListWidgetItem(disconnectedIcon, info.networkName, ui.networkList); } + item->setData(Qt::UserRole, QVariant::fromValue(info.networkId)); + setItemState(info.networkId, item); widgetHasChanged(); return item; } -void NetworksSettingsPage::displayNetwork(NetworkId id, bool dontsave) { - Q_UNUSED(dontsave); - NetworkInfo info = networkInfos[id]; - ui.identityList->setCurrentIndex(ui.identityList->findData(info.identity.toInt())); - ui.serverList->clear(); - foreach(QVariantMap v, info.serverList) { - ui.serverList->addItem(QString("%1:%2").arg(v["Host"].toString()).arg(v["Port"].toUInt())); +void NetworksSettingsPage::displayNetwork(NetworkId id) { + if(id != 0) { + NetworkInfo info = networkInfos[id]; + ui.identityList->setCurrentIndex(ui.identityList->findData(info.identity.toInt())); + ui.serverList->clear(); + foreach(QVariant v, info.serverList) { + ui.serverList->addItem(QString("%1:%2").arg(v.toMap()["Host"].toString()).arg(v.toMap()["Port"].toUInt())); + } + setItemState(id); + } else { + // just clear widgets + ui.identityList->setCurrentIndex(-1); + ui.serverList->clear(); + ui.performEdit->clear(); + setWidgetStates(); } + currentId = id; } void NetworksSettingsPage::saveToNetworkInfo(NetworkInfo &info) { @@ -339,8 +419,8 @@ void NetworksSettingsPage::on_deleteNetwork_clicked() { QMessageBox::Yes|QMessageBox::No, QMessageBox::No); if(ret == QMessageBox::Yes) { currentId = 0; - networkInfos.remove(netid); qDebug() << netid << networkInfos.count(); - delete ui.networkList->selectedItems()[0]; + networkInfos.remove(netid); + delete ui.networkList->takeItem(ui.networkList->row(ui.networkList->selectedItems()[0])); ui.networkList->setCurrentRow(qMin(ui.networkList->currentRow()+1, ui.networkList->count()-1)); setWidgetStates(); widgetHasChanged(); @@ -362,6 +442,15 @@ void NetworksSettingsPage::on_renameNetwork_clicked() { } } +void NetworksSettingsPage::on_connectNow_clicked() { + if(!ui.networkList->selectedItems().count()) return; + NetworkId id = ui.networkList->selectedItems()[0]->data(Qt::UserRole).value(); + const Network *net = Client::network(id); + if(!net) return; + if(!net->isConnected()) net->requestConnect(); + else net->requestDisconnect(); +} + /*** Server list ***/ void NetworksSettingsPage::on_serverList_itemSelectionChanged() { @@ -403,7 +492,7 @@ void NetworksSettingsPage::on_deleteServer_clicked() { void NetworksSettingsPage::on_upServer_clicked() { int cur = ui.serverList->currentRow(); - QVariantMap foo = networkInfos[currentId].serverList.takeAt(cur); + QVariant foo = networkInfos[currentId].serverList.takeAt(cur); networkInfos[currentId].serverList.insert(cur-1, foo); displayNetwork(currentId); ui.serverList->setCurrentRow(cur-1); @@ -412,7 +501,7 @@ void NetworksSettingsPage::on_upServer_clicked() { void NetworksSettingsPage::on_downServer_clicked() { int cur = ui.serverList->currentRow(); - QVariantMap foo = networkInfos[currentId].serverList.takeAt(cur); + QVariant foo = networkInfos[currentId].serverList.takeAt(cur); networkInfos[currentId].serverList.insert(cur+1, foo); displayNetwork(currentId); ui.serverList->setCurrentRow(cur+1); @@ -447,8 +536,9 @@ void NetworkEditDlgNew::on_networkEdit_textChanged(const QString &text) { * ServerEditDlg *************************************************************************/ -ServerEditDlgNew::ServerEditDlgNew(const QVariantMap &serverData, QWidget *parent) : QDialog(parent) { +ServerEditDlgNew::ServerEditDlgNew(const QVariant &_serverData, QWidget *parent) : QDialog(parent) { ui.setupUi(this); + QVariantMap serverData = _serverData.toMap(); if(serverData.count()) { ui.host->setText(serverData["Host"].toString()); ui.port->setValue(serverData["Port"].toUInt()); @@ -460,7 +550,7 @@ ServerEditDlgNew::ServerEditDlgNew(const QVariantMap &serverData, QWidget *paren on_host_textChanged(); } -QVariantMap ServerEditDlgNew::serverData() const { +QVariant ServerEditDlgNew::serverData() const { QVariantMap _serverData; _serverData["Host"] = ui.host->text(); _serverData["Port"] = ui.port->value(); @@ -481,5 +571,39 @@ SaveNetworksDlg::SaveNetworksDlg(const QList &toCreate, const QList { ui.setupUi(this); + numevents = toCreate.count() + toUpdate.count() + toRemove.count(); + rcvevents = 0; + if(numevents) { + ui.progressBar->setMaximum(numevents); + ui.progressBar->setValue(0); + + connect(Client::instance(), SIGNAL(networkCreated(NetworkId)), this, SLOT(clientEvent())); + connect(Client::instance(), SIGNAL(networkRemoved(NetworkId)), this, SLOT(clientEvent())); + + foreach(NetworkInfo info, toCreate) { + Client::createNetwork(info); + } + foreach(NetworkInfo info, toUpdate) { + const Network *net = Client::network(info.networkId); + if(!net) { + qWarning() << "Invalid client network!"; + numevents--; + continue; + } + // FIXME this only checks for one changed item rather than all! + connect(net, SIGNAL(updatedRemotely()), this, SLOT(clientEvent())); + Client::updateNetwork(info); + } + foreach(NetworkId id, toRemove) { + Client::removeNetwork(id); + } + } else { + qWarning() << "Sync dialog called without stuff to change!"; + accept(); + } } +void SaveNetworksDlg::clientEvent() { + ui.progressBar->setValue(++rcvevents); + if(rcvevents >= numevents) accept(); +} diff --git a/src/qtui/settingspages/networkssettingspage.h b/src/qtui/settingspages/networkssettingspage.h index 89ac4b21..0c10a574 100644 --- a/src/qtui/settingspages/networkssettingspage.h +++ b/src/qtui/settingspages/networkssettingspage.h @@ -48,8 +48,11 @@ class NetworksSettingsPage : public SettingsPage { void widgetHasChanged(); void setWidgetStates(); void coreConnectionStateChanged(bool); + void networkConnectionStateChanged(Network::ConnectionState state); + void networkConnectionError(const QString &msg); - void displayNetwork(NetworkId, bool dontsave = false); + void displayNetwork(NetworkId); + void setItemState(NetworkId, QListWidgetItem *item = 0); void clientNetworkAdded(NetworkId); void clientNetworkRemoved(NetworkId); @@ -64,6 +67,8 @@ class NetworksSettingsPage : public SettingsPage { void on_deleteNetwork_clicked(); void on_renameNetwork_clicked(); + void on_connectNow_clicked(); + void on_serverList_itemSelectionChanged(); void on_addServer_clicked(); void on_deleteServer_clicked(); @@ -77,7 +82,7 @@ class NetworksSettingsPage : public SettingsPage { NetworkId currentId; QHash networkInfos; - QIcon connectedIcon, disconnectedIcon; + QIcon connectedIcon, connectingIcon, disconnectedIcon; void reset(); bool testHasChanged(); @@ -110,9 +115,9 @@ class ServerEditDlgNew : public QDialog { Q_OBJECT public: - ServerEditDlgNew(const QVariantMap &serverData = QVariantMap(), QWidget *parent = 0); + ServerEditDlgNew(const QVariant &serverData = QVariant(), QWidget *parent = 0); - QVariantMap serverData() const; + QVariant serverData() const; private slots: void on_host_textChanged(); @@ -128,8 +133,13 @@ class SaveNetworksDlg : public QDialog { public: SaveNetworksDlg(const QList &toCreate, const QList &toUpdate, const QList &toRemove, QWidget *parent = 0); + private slots: + void clientEvent(); + private: Ui::SaveIdentitiesDlg ui; + + int numevents, rcvevents; }; #endif diff --git a/src/qtui/settingspages/saveidentitiesdlg.ui b/src/qtui/settingspages/saveidentitiesdlg.ui index c0b33038..0ddb0589 100644 --- a/src/qtui/settingspages/saveidentitiesdlg.ui +++ b/src/qtui/settingspages/saveidentitiesdlg.ui @@ -5,8 +5,8 @@ 0 0 - 246 - 104 + 316 + 110 @@ -14,87 +14,91 @@ - - - Syncing data with core, please wait... - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - true - - - - - - - 0 - - - 0 - - - false - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - + + + + + Syncing data with core, please wait... + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + - Qt::Horizontal + Qt::Vertical - 40 - 20 + 20 + 40 - - - - 0 - 0 - + + + 0 - - Abort + + 0 - - :/22x22/actions/oxygen/22x22/actions/dialog-cancel.png + + false - - - Qt::Horizontal - - - - 40 - 20 - - - + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Abort + + + :/22x22/actions/oxygen/22x22/actions/dialog-cancel.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + diff --git a/src/qtui/ui/mainwin.ui b/src/qtui/ui/mainwin.ui index f926cf97..88a59eeb 100644 --- a/src/qtui/ui/mainwin.ui +++ b/src/qtui/ui/mainwin.ui @@ -113,6 +113,9 @@ + + false + &Network List... @@ -201,6 +204,9 @@ + + false + :/icons/quassel-icon.png diff --git a/src/qtui/ui/settingsdlg.ui b/src/qtui/ui/settingsdlg.ui index bdf97be5..a4615f79 100644 --- a/src/qtui/ui/settingsdlg.ui +++ b/src/qtui/ui/settingsdlg.ui @@ -5,8 +5,8 @@ 0 0 - 780 - 580 + 881 + 663 -- 2.20.1