NOT STABLE! DO NOT USE! WORK IN PROGRESS! NOT CLEANED UP! NOT TESTED! YOU HAVE BEEN WARNED!
Known regressions:
* Networks always use the Default Identity from the _new_ dialog (accessible via the new SettingsDlg)
* No core config wizard. Will be back soon.
* No session save/restore, Will be back soon.
* Some more things, that you'll notice anyway.
src/client/client.pri
src/client/clientsettings.cpp
src/client/clientsettings.h
+src/client/clientsyncer.cpp
+src/client/clientsyncer.h
src/client/mappedselectionmodel.cpp
src/client/mappedselectionmodel.h
src/client/modelpropertymapper.cpp
src/common/message.h
src/common/network.cpp
src/common/network.h
-src/common/networkinfo.cpp
-src/common/networkinfo.h
src/common/settings.cpp
src/common/settings.h
src/common/signalproxy.cpp
src/core/ircserverhandler.h
src/core/networkconnection.cpp
src/core/networkconnection.h
-src/core/server.cpp
-src/core/server.h
+src/core/sessionthread.cpp
+src/core/sessionthread.h
src/core/sqlitestorage.cpp
src/core/sqlitestorage.h
src/core/storage.cpp
src/qtui/settingspages/identitiessettingspage.h
src/qtui/settingspages/identitiessettingspage.ui
src/qtui/settingspages/networkssettingspage.ui
-src/qtui/settingspages/nickeditdlg.ui
src/qtui/settingspages/nickeditdlgnew.ui
src/qtui/settingspages/saveidentitiesdlg.ui
src/qtui/settingspages/servereditdlg.ui
LIBS *= -L../modules/$$dirname(mod) -l$$basename(mod)
PRE_TARGETDEPS *= ../modules/$$mod
}
+PRE_TARGETDEPS *= ../../version.inc
#CONTRIB += libqxt # not needed
#include(../contrib/contrib.pri)
}
void Client::destroy() {
- delete instanceptr;
+ //delete instanceptr;
+ instanceptr->deleteLater();
}
void Client::init(AbstractUi *ui) {
_networkModel(0),
_bufferModel(0),
_nickModel(0),
- connectedToCore(false)
+ _connectedToCore(false),
+ _syncedToCore(false)
{
}
Client::~Client() {
+ disconnectFromCore();
}
void Client::init() {
- blockSize = 0;
_networkModel = new NetworkModel(this);
connect(this, SIGNAL(bufferUpdated(BufferInfo)),
_bufferModel = new BufferModel(_networkModel);
_nickModel = new NickModel(_networkModel);
-
+
SignalProxy *p = signalProxy();
p->attachSignal(this, SIGNAL(sendSessionData(const QString &, const QVariant &)),
SIGNAL(clientSessionDataChanged(const QString &, const QVariant &)));
p->attachSlot(SIGNAL(coreSessionDataChanged(const QString &, const QVariant &)),
this, SLOT(recvSessionData(const QString &, const QVariant &)));
- p->attachSlot(SIGNAL(coreState(const QVariant &)),
- this, SLOT(recvCoreState(const QVariant &)));
- p->attachSlot(SIGNAL(networkConnected(uint)),
- this, SLOT(networkConnected(uint)));
- p->attachSlot(SIGNAL(networkDisconnected(uint)),
- this, SLOT(networkDisconnected(uint)));
+ //p->attachSlot(SIGNAL(networkConnected(uint)),
+ //FIXME this, SLOT(networkConnected(uint)));
+ //p->attachSlot(SIGNAL(networkDisconnected(uint)),
+ //FIXME this, SLOT(networkDisconnected(uint)));
p->attachSlot(SIGNAL(displayMsg(const Message &)),
this, SLOT(recvMessage(const Message &)));
p->attachSlot(SIGNAL(displayStatusMsg(QString, QString)),
p->attachSlot(SIGNAL(identityCreated(const Identity &)), this, SLOT(coreIdentityCreated(const Identity &)));
p->attachSlot(SIGNAL(identityRemoved(IdentityId)), this, SLOT(coreIdentityRemoved(IdentityId)));
- connect(mainUi, SIGNAL(connectToCore(const QVariantMap &)), this, SLOT(connectToCore(const QVariantMap &)));
+ connect(p, SIGNAL(disconnected()), this, SLOT(disconnectFromCore()));
+
+ //connect(mainUi, SIGNAL(connectToCore(const QVariantMap &)), this, SLOT(connectToCore(const QVariantMap &)));
connect(mainUi, SIGNAL(disconnectFromCore()), this, SLOT(disconnectFromCore()));
connect(this, SIGNAL(connected()), mainUi, SLOT(connectedToCore()));
connect(this, SIGNAL(disconnected()), mainUi, SLOT(disconnectedFromCore()));
QList<Network *> Client::networks() {
- return instance()->_network.values();
+ return instance()->_networks.values();
}
Network *Client::network(uint networkid) {
- if(instance()->_network.contains(networkid))
- return instance()->_network[networkid];
+ if(instance()->_networks.contains(networkid))
+ return instance()->_networks[networkid];
else
return 0;
}
return instance()->_buffers.values();
}
-Buffer *Client::buffer(uint bufferUid) {
+
+// FIXME remove
+Buffer *Client::buffer(BufferId bufferUid) {
if(instance()->_buffers.contains(bufferUid))
return instance()->_buffers[bufferUid];
else
return 0;
}
+// FIXME remove
Buffer *Client::buffer(BufferInfo id) {
Buffer *buff = buffer(id.uid());
return buff;
}
+
NetworkModel *Client::networkModel() {
return instance()->_networkModel;
}
return instance()->_signalProxy;
}
+bool Client::isConnected() {
+ return instance()->_connectedToCore;
+}
+
+bool Client::isSynced() {
+ return instance()->_syncedToCore;
+}
/*** Identity handling ***/
else return 0;
}
-
void Client::createIdentity(const Identity &id) {
emit instance()->requestCreateIdentity(id);
}
/*** ***/
-
-bool Client::isConnected() {
- return instance()->connectedToCore;
-}
-
void Client::fakeInput(uint bufferUid, QString message) {
Buffer *buff = buffer(bufferUid);
if(!buff)
fakeInput(bufferInfo, message);
}
-void Client::connectToCore(const QVariantMap &conn) {
- // TODO implement SSL
- coreConnectionInfo = conn;
- if(isConnected()) {
- emit coreConnectionError(tr("Already connected to Core!"));
- return;
- }
-
- if(socket != 0)
- socket->deleteLater();
-
- if(conn["Host"].toString().isEmpty()) {
- clientMode = LocalCore;
- socket = new QBuffer(this);
- connect(socket, SIGNAL(readyRead()), this, SLOT(coreHasData()));
- socket->open(QIODevice::ReadWrite);
- //QVariant state = connectToLocalCore(coreConnectionInfo["User"].toString(), coreConnectionInfo["Password"].toString());
- //syncToCore(state);
- coreSocketConnected();
- } else {
- clientMode = RemoteCore;
- emit coreConnectionMsg(tr("Connecting..."));
- Q_ASSERT(!socket);
- QTcpSocket *sock = new QTcpSocket(this);
- socket = sock;
- connect(sock, SIGNAL(readyRead()), this, SLOT(coreHasData()));
- connect(sock, SIGNAL(connected()), this, SLOT(coreSocketConnected()));
- connect(signalProxy(), SIGNAL(disconnected()), this, SLOT(coreSocketDisconnected()));
- connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(coreSocketError(QAbstractSocket::SocketError)));
- sock->connectToHost(conn["Host"].toString(), conn["Port"].toUInt());
- }
-}
-
-void Client::disconnectFromCore() {
- socket->close();
-}
+/*** core connection stuff ***/
-void Client::setCoreConfiguration(const QVariantMap &settings) {
- SignalProxy::writeDataToDevice(socket, settings);
+void Client::setConnectedToCore(QIODevice *sock) {
+ socket = sock;
+ signalProxy()->addPeer(socket);
+ _connectedToCore = true;
}
-void Client::coreSocketConnected() {
- connect(this, SIGNAL(recvPartialItem(uint, uint)), this, SIGNAL(coreConnectionProgress(uint, uint)));
- emit coreConnectionMsg(tr("Synchronizing to core..."));
- QVariantMap clientInit;
- clientInit["GuiProtocol"] = GUI_PROTOCOL;
- clientInit["User"] = coreConnectionInfo["User"].toString();
- clientInit["Password"] = coreConnectionInfo["Password"].toString();
- SignalProxy::writeDataToDevice(socket, clientInit);
+void Client::setSyncedToCore() {
+ _syncedToCore = true;
+ emit connected();
+ emit coreConnectionStateChanged(true);
}
-void Client::coreSocketDisconnected() {
- instance()->connectedToCore = false;
+void Client::disconnectFromCore() {
+ if(socket) {
+ socket->close();
+ socket->deleteLater();
+ }
+ _connectedToCore = false;
+ _syncedToCore = false;
emit disconnected();
emit coreConnectionStateChanged(false);
- socket->deleteLater();
- blockSize = 0;
- /* Clear internal data. Hopefully nothing relies on it at this point. */
+ // Clear internal data. Hopefully nothing relies on it at this point.
_networkModel->clear();
QHash<BufferId, Buffer *>::iterator bufferIter = _buffers.begin();
Q_ASSERT(_buffers.isEmpty());
- QHash<NetworkId, Network*>::iterator netIter = _network.begin();
- while(netIter != _network.end()) {
+ QHash<NetworkId, Network*>::iterator netIter = _networks.begin();
+ while(netIter != _networks.end()) {
Network *net = netIter.value();
disconnect(net, SIGNAL(destroyed()), this, 0);
- netIter = _network.erase(netIter);
+ netIter = _networks.erase(netIter);
net->deleteLater();
}
- Q_ASSERT(_network.isEmpty());
+ Q_ASSERT(_networks.isEmpty());
QHash<IdentityId, Identity*>::iterator idIter = _identities.begin();
while(idIter != _identities.end()) {
}
Q_ASSERT(_identities.isEmpty());
- coreConnectionInfo.clear();
sessionData.clear();
layoutQueue.clear();
layoutTimer->stop();
}
-void Client::recvCoreState(const QVariant &state) {
- disconnect(this, SIGNAL(recvPartialItem(uint, uint)), this, SIGNAL(coreConnectionProgress(uint, uint)));
- disconnect(socket, 0, this, 0); // rest of communication happens through SignalProxy
- signalProxy()->addPeer(socket);
- syncToCore(state);
-}
-
-// TODO: auth errors
-void Client::syncToCore(const QVariant &coreState) {
- if(!coreState.toMap().contains("SessionState")) {
- emit coreConnectionError(tr("Invalid data received from core!"));
- disconnectFromCore();
- return;
- }
-
- QVariantMap sessionState = coreState.toMap()["SessionState"].toMap();
-
- // store sessionData
- QVariantMap sessData = sessionState["SessionData"].toMap();
- foreach(QString key, sessData.keys())
- recvSessionData(key, sessData[key]);
-
- // create identities
- foreach(QVariant vid, sessionState["Identities"].toList()) {
- coreIdentityCreated(vid.value<Identity>());
- }
-
- // store Buffer details
- QVariantList coreBuffers = sessionState["Buffers"].toList();
- /* make lookups by id faster */
- foreach(QVariant vid, coreBuffers) {
- buffer(vid.value<BufferInfo>()); // create all buffers, so we see them in the network views
- }
-
- // create network objects
- QVariantList networkids = sessionState["Networks"].toList();
- foreach(QVariant networkid, networkids) {
- networkConnected(networkid.toUInt());
- }
-
- instance()->connectedToCore = true;
- updateCoreConnectionProgress();
-
+void Client::setCoreConfiguration(const QVariantMap &settings) {
+ SignalProxy::writeDataToDevice(socket, settings);
}
-void Client::updateCoreConnectionProgress() {
- // we'll do this in three steps:
- // 1.) networks
- // 2.) channels
- // 3.) ircusers
-
- int numNets = networks().count();
- int numNetsWaiting = 0;
-
- int numIrcUsers = 0;
- int numIrcUsersWaiting = 0;
-
- int numChannels = 0;
- int numChannelsWaiting = 0;
-
- foreach(Network *net, networks()) {
- if(! net->initialized())
- numNetsWaiting++;
-
- numIrcUsers += net->ircUsers().count();
- foreach(IrcUser *user, net->ircUsers()) {
- if(! user->initialized())
- numIrcUsersWaiting++;
- }
-
- numChannels += net->ircChannels().count();
- foreach(IrcChannel *channel, net->ircChannels()) {
- if(! channel->initialized())
- numChannelsWaiting++;
- }
- }
-
- if(numNetsWaiting > 0) {
- emit coreConnectionMsg(tr("Requesting network states..."));
- emit coreConnectionProgress(numNets - numNetsWaiting, numNets);
- return;
- }
-
- if(numIrcUsersWaiting > 0) {
- emit coreConnectionMsg(tr("Requesting User states..."));
- emit coreConnectionProgress(numIrcUsers - numIrcUsersWaiting, numIrcUsers);
- return;
- }
-
- if(numChannelsWaiting > 0) {
- emit coreConnectionMsg(tr("Requesting Channel states..."));
- emit coreConnectionProgress(numChannels - numChannelsWaiting, numChannels);
- return;
- }
-
- emit coreConnectionProgress(1,1);
- emit connected();
- emit coreConnectionStateChanged(true);
- foreach(Network *net, networks()) {
- disconnect(net, 0, this, SLOT(updateCoreConnectionProgress()));
- }
-
- // signalProxy()->dumpProxyStats();
-}
+/*** Session data ***/
void Client::recvSessionData(const QString &key, const QVariant &data) {
sessionData[key] = data;
return instance()->sessionData.keys();
}
-void Client::coreSocketError(QAbstractSocket::SocketError) {
- emit coreConnectionError(socket->errorString());
- socket->deleteLater();
-}
-
-void Client::coreHasData() {
- QVariant item;
- if(SignalProxy::readDataFromDevice(socket, blockSize, item)) {
- emit recvPartialItem(1,1);
- QVariantMap msg = item.toMap();
- if (!msg["StartWizard"].toBool()) {
- recvCoreState(msg["Reply"]);
- } else {
- qWarning("Core not configured!");
- qDebug() << "Available storage providers: " << msg["StorageProviders"].toStringList();
- emit showConfigWizard(msg);
- }
- blockSize = 0;
- return;
- }
- if(blockSize > 0) {
- emit recvPartialItem(socket->bytesAvailable(), blockSize);
- }
-}
+/*** ***/
+/*
void Client::networkConnected(uint netid) {
// TODO: create statusBuffer / switch to networkids
//BufferInfo id = statusBufferInfo(net);
Network *netinfo = new Network(netid, this);
netinfo->setProxy(signalProxy());
networkModel()->attachNetwork(netinfo);
-
- if(!isConnected()) {
- connect(netinfo, SIGNAL(initDone()), this, SLOT(updateCoreConnectionProgress()));
- connect(netinfo, SIGNAL(ircUserInitDone()), this, SLOT(updateCoreConnectionProgress()));
- connect(netinfo, SIGNAL(ircChannelInitDone()), this, SLOT(updateCoreConnectionProgress()));
- }
connect(netinfo, SIGNAL(destroyed()), this, SLOT(networkDestroyed()));
- _network[netid] = netinfo;
+ _networks[netid] = netinfo;
}
-void Client::networkDisconnected(uint networkid) {
- if(!_network.contains(networkid)) {
+void Client::networkDisconnected(NetworkId networkid) {
+ if(!_networks.contains(networkid)) {
qWarning() << "Client::networkDisconnected(uint): unknown Network" << networkid;
return;
}
- Network *net = _network.take(networkid);
- if(!net->initialized()) {
+ Network *net = _networks.take(networkid);
+ if(!net->isInitialized()) {
qDebug() << "Network" << networkid << "disconnected while not yet initialized!";
updateCoreConnectionProgress();
}
net->deleteLater();
}
+*/
+
+void Client::addNetwork(NetworkId netid) {
+ Network *net = new Network(netid, instance());
+ addNetwork(net);
+}
+
+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;
+ //if(net->networkId() == 1) net->requestConnect(); // FIXME
+}
+
+/*** ***/
void Client::updateBufferInfo(BufferInfo id) {
emit bufferUpdated(id);
void Client::networkDestroyed() {
Network *netinfo = static_cast<Network *>(sender());
- uint networkId = netinfo->networkId();
- if(_network.contains(networkId))
- _network.remove(networkId);
+ NetworkId networkId = netinfo->networkId();
+ if(_networks.contains(networkId))
+ _networks.remove(networkId);
}
void Client::recvMessage(const Message &msg) {
class AbstractUiMsg;
class NetworkModel;
class BufferModel;
+class IrcUser;
+class IrcChannel;
class NickModel;
class SignalProxy;
static void init(AbstractUi *);
static QList<Network *> networks();
- static Network *network(uint networkid);
+ static Network *network(NetworkId networkid);
static QList<BufferInfo> allBufferInfos();
static QList<Buffer *> buffers();
- static Buffer *buffer(uint bufferUid);
+ static Buffer *buffer(BufferId bufferUid);
static Buffer *buffer(BufferInfo);
static QList<IdentityId> identityIds();
*/
static void removeIdentity(IdentityId id);
+ static void addNetwork(NetworkId id);
+ static void addNetwork(Network *);
+
+
static NetworkModel *networkModel();
static BufferModel *bufferModel();
static NickModel *nickModel();
static AbstractUiMsg *layoutMsg(const Message &);
static bool isConnected();
+ static bool isSynced();
- static void fakeInput(uint bufferUid, QString message);
+ static void fakeInput(BufferId bufferUid, QString message);
static void fakeInput(BufferInfo bufferInfo, QString message);
static void storeSessionData(const QString &key, const QVariant &data);
void requestBacklog(BufferInfo, QVariant, QVariant);
void requestNetworkStates();
- void recvPartialItem(uint avail, uint size);
- void coreConnectionError(QString errorMsg);
- void coreConnectionMsg(const QString &msg);
- void coreConnectionProgress(uint part, uint total);
-
void showConfigWizard(const QVariantMap &coredata);
void connected();
public slots:
//void selectBuffer(Buffer *);
- //void connectToLocalCore();
- void connectToCore(const QVariantMap &);
+
+ void setConnectedToCore(QIODevice *socket);
+ void setSyncedToCore();
void disconnectFromCore();
void setCoreConfiguration(const QVariantMap &settings);
+
private slots:
- void recvCoreState(const QVariant &state);
void recvSessionData(const QString &key, const QVariant &data);
- void coreSocketError(QAbstractSocket::SocketError);
- void coreHasData();
- void coreSocketConnected();
- void coreSocketDisconnected();
+ //void coreSocketError(QAbstractSocket::SocketError);
void userInput(BufferInfo, QString);
- void networkConnected(uint);
- void networkDisconnected(uint);
+ //void networkConnected(NetworkId);
+ //void networkDisconnected(NetworkId);
- void updateCoreConnectionProgress();
void recvMessage(const Message &message);
void recvStatusMsg(QString network, QString message);
void recvBacklogData(BufferInfo, QVariantList, bool);
virtual ~Client();
void init();
- void syncToCore(const QVariant &coreState);
+ void syncToCore(const QVariantMap &sessionState);
static QPointer<Client> instanceptr;
ClientMode clientMode;
- quint32 blockSize;
- bool connectedToCore;
+ bool _connectedToCore, _syncedToCore;
- QVariantMap coreConnectionInfo;
QHash<BufferId, Buffer *> _buffers;
- QHash<NetworkId, Network *> _network;
+ QHash<NetworkId, Network *> _networks;
QHash<IdentityId, Identity *> _identities;
QTimer *layoutTimer;
QVariantMap sessionData;
-
+ friend class ClientSyncer;
};
#endif
DEPMOD = common
-QT_MOD = core network gui # gui is needed just for QColor... FIXME!
-SRCS += buffer.cpp treemodel.cpp networkmodel.cpp buffermodel.cpp client.cpp clientsettings.cpp mappedselectionmodel.cpp modelpropertymapper.cpp \
- nickmodel.cpp selectionmodelsynchronizer.cpp
-HDRS += buffer.h treemodel.h networkmodel.h buffermodel.h client.h clientsettings.h quasselui.h mappedselectionmodel.h modelpropertymapper.h \
- nickmodel.h selectionmodelsynchronizer.h
+QT_MOD = core network gui
+SRCS += buffer.cpp treemodel.cpp networkmodel.cpp buffermodel.cpp client.cpp clientsettings.cpp clientsyncer.cpp \
+ mappedselectionmodel.cpp modelpropertymapper.cpp nickmodel.cpp selectionmodelsynchronizer.cpp
+HDRS += buffer.h treemodel.h networkmodel.h buffermodel.h client.h clientsettings.h clientsyncer.h quasselui.h \
+ mappedselectionmodel.h modelpropertymapper.h nickmodel.h selectionmodelsynchronizer.h
/***********************************************************************************************/
-AccountSettings::AccountSettings() : ClientSettings("Accounts") {
+CoreAccountSettings::CoreAccountSettings() : ClientSettings("CoreAccounts") {
}
-QStringList AccountSettings::knownAccounts() {
- return localChildGroups();
+QStringList CoreAccountSettings::knownAccounts() {
+ return localChildKeys("Accounts");
}
-QString AccountSettings::lastAccount() {
+QString CoreAccountSettings::lastAccount() {
return localValue("LastAccount", "").toString();
}
-void AccountSettings::setLastAccount(const QString &account) {
+void CoreAccountSettings::setLastAccount(const QString &account) {
setLocalValue("LastAccount", account);
}
-QString AccountSettings::autoConnectAccount() {
+QString CoreAccountSettings::autoConnectAccount() {
return localValue("AutoConnectAccount", "").toString();
}
-void AccountSettings::setAutoConnectAccount(const QString &account) {
+void CoreAccountSettings::setAutoConnectAccount(const QString &account) {
setLocalValue("AutoConnectAccount", account);
}
-void AccountSettings::setValue(const QString &account, const QString &key, const QVariant &data) {
- setLocalValue(QString("%1/%2").arg(account).arg(key), data);
+void CoreAccountSettings::storeAccount(const QString name, const QVariantMap &data) {
+ setLocalValue(QString("Accounts/%2").arg(name), data);
}
-QVariant AccountSettings::value(const QString &account, const QString &key, const QVariant &def) {
- return localValue(QString("%1/%2").arg(account).arg(key), def);
+QVariantMap CoreAccountSettings::retrieveAccount(const QString &name) {
+ return localValue(QString("Accounts/%2").arg(name), QVariant()).toMap();
}
-void AccountSettings::removeAccount(const QString &account) {
- removeLocalKey(account);
+void CoreAccountSettings::storeAllAccounts(const QHash<QString, QVariantMap> accounts) {
+ removeLocalKey(QString("Accounts"));
+ foreach(QString name, accounts.keys()) {
+ storeAccount(name, accounts[name]);
+ }
+}
+
+QHash<QString, QVariantMap> CoreAccountSettings::retrieveAllAccounts() {
+ QHash<QString, QVariantMap> accounts;
+ foreach(QString name, knownAccounts()) {
+ accounts[name] = retrieveAccount(name);
+ }
+ return accounts;
+}
+
+void CoreAccountSettings::removeAccount(const QString &account) {
+ removeLocalKey(QString("Accounts/%1").arg(account));
}
};
-class AccountSettings : public ClientSettings {
+class CoreAccountSettings : public ClientSettings {
public:
- AccountSettings();
+ CoreAccountSettings();
QStringList knownAccounts();
QString lastAccount();
QString autoConnectAccount();
void setAutoConnectAccount(const QString &account);
- void setValue(const QString &account, const QString &key, const QVariant &data);
- QVariant value(const QString &account, const QString &key, const QVariant &def = QVariant());
+ void storeAccount(const QString name, const QVariantMap &data);
+ QVariantMap retrieveAccount(const QString &name);
+ void storeAllAccounts(const QHash<QString, QVariantMap> accounts);
+ QHash<QString, QVariantMap> retrieveAllAccounts();
void removeAccount(const QString &account);
};
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005-08 by the Quassel IRC Team *
+ * devel@quassel-irc.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) version 3. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include "clientsyncer.h"
+
+#include "client.h"
+#include "global.h"
+#include "identity.h"
+#include "ircuser.h"
+#include "ircchannel.h"
+#include "network.h"
+#include "signalproxy.h"
+
+
+ClientSyncer::ClientSyncer(QObject *parent) : QObject(parent) {
+ socket = 0;
+ blockSize = 0;
+
+ connect(Client::signalProxy(), SIGNAL(disconnected()), this, SLOT(coreSocketDisconnected()));
+
+}
+
+ClientSyncer::~ClientSyncer() {
+
+
+}
+
+
+void ClientSyncer::coreHasData() {
+ QVariant item;
+ while(SignalProxy::readDataFromDevice(socket, blockSize, item)) {
+ emit recvPartialItem(1,1);
+ QVariantMap msg = item.toMap();
+ if(!msg.contains("MsgType")) {
+ // This core is way too old and does not even speak our init protocol...
+ emit connectionError(tr("The Quassel Core you try to connect to is too old! Please consider upgrading."));
+ disconnectFromCore();
+ return;
+ }
+ if(msg["MsgType"] == "ClientInitAck") {
+ clientInitAck(msg);
+ } else if(msg["MsgType"] == "ClientInitReject") {
+ emit connectionError(msg["Error"].toString());
+ disconnectFromCore();
+ return;
+ } else if(msg["MsgType"] == "ClientLoginReject") {
+ emit loginFailed(msg["Error"].toString());
+ } else if(msg["MsgType"] == "ClientLoginAck") {
+ // prevent multiple signal connections
+ disconnect(this, SIGNAL(recvPartialItem(quint32, quint32)), this, SIGNAL(sessionProgress(quint32, quint32)));
+ connect(this, SIGNAL(recvPartialItem(quint32, quint32)), this, SIGNAL(sessionProgress(quint32, quint32)));
+ emit loginSuccess();
+ } else if(msg["MsgType"] == "SessionInit") {
+ sessionStateReceived(msg["SessionState"].toMap());
+ } else {
+ emit connectionError(tr("<b>Invalid data received from core!</b><br>Disconnecting."));
+ disconnectFromCore();
+ return;
+ }
+ /*
+ if (!msg["StartWizard"].toBool()) {
+ recvCoreState(msg["Reply"]);
+ } else {
+ qWarning("Core not configured!");
+ qDebug() << "Available storage providers: " << msg["StorageProviders"].toStringList();
+ emit showConfigWizard(msg);
+ }
+ blockSize = 0;
+ return;
+ }
+ */
+ }
+ if(blockSize > 0) {
+ emit recvPartialItem(socket->bytesAvailable(), blockSize);
+ }
+}
+
+void ClientSyncer::coreSocketError(QAbstractSocket::SocketError) {
+ emit connectionError(socket->errorString());
+ socket->deleteLater();
+}
+
+void ClientSyncer::disconnectFromCore() {
+ if(socket) socket->close();
+}
+
+void ClientSyncer::connectToCore(const QVariantMap &conn) {
+ // TODO implement SSL
+ coreConnectionInfo = conn;
+ //if(isConnected()) {
+ // emit coreConnectionError(tr("Already connected to Core!"));
+ // return;
+ // }
+
+ if(socket != 0) {
+ socket->deleteLater();
+ socket = 0;
+ }
+ if(conn["Host"].toString().isEmpty()) {
+ emit connectionError(tr("Internal connections not yet supported."));
+ return; // FIXME implement internal connections
+ //clientMode = LocalCore;
+ socket = new QBuffer(this);
+ connect(socket, SIGNAL(readyRead()), this, SLOT(coreHasData()));
+ socket->open(QIODevice::ReadWrite);
+ //QVariant state = connectToLocalCore(coreConnectionInfo["User"].toString(), coreConnectionInfo["Password"].toString());
+ //syncToCore(state);
+ coreSocketConnected();
+ } else {
+ //clientMode = RemoteCore;
+ //emit coreConnectionMsg(tr("Connecting..."));
+ Q_ASSERT(!socket);
+ QTcpSocket *sock = new QTcpSocket(Client::instance());
+ socket = sock;
+ connect(sock, SIGNAL(readyRead()), this, SLOT(coreHasData()));
+ connect(sock, SIGNAL(connected()), this, SLOT(coreSocketConnected()));
+ connect(sock, SIGNAL(disconnected()), this, SLOT(coreSocketDisconnected()));
+ connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(coreSocketError(QAbstractSocket::SocketError)));
+ connect(sock, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SIGNAL(socketStateChanged(QAbstractSocket::SocketState)));
+ sock->connectToHost(conn["Host"].toString(), conn["Port"].toUInt());
+ }
+}
+
+void ClientSyncer::coreSocketConnected() {
+ //connect(this, SIGNAL(recvPartialItem(uint, uint)), this, SIGNAL(coreConnectionProgress(uint, uint)));
+ // Phase One: Send client info and wait for core info
+
+ //emit coreConnectionMsg(tr("Synchronizing to core..."));
+ QVariantMap clientInit;
+ clientInit["MsgType"] = "ClientInit";
+ clientInit["ClientVersion"] = Global::quasselVersion;
+ clientInit["ClientDate"] = Global::quasselDate;
+ clientInit["ClientBuild"] = Global::quasselBuild; // this is a minimum, since we probably won't update for every commit
+ clientInit["UseSsl"] = false; // FIXME implement SSL
+ SignalProxy::writeDataToDevice(socket, clientInit);
+}
+
+void ClientSyncer::coreSocketDisconnected() {
+ emit socketDisconnected();
+ Client::instance()->disconnectFromCore();
+
+ // FIXME handle disconnects gracefully in here as well!
+
+ coreConnectionInfo.clear();
+ netsToSync.clear();
+ channelsToSync.clear();
+ usersToSync.clear();
+ blockSize = 0;
+ //restartPhaseNull();
+}
+
+void ClientSyncer::clientInitAck(const QVariantMap &msg) {
+ // Core has accepted our version info and sent its own. Let's see if we accept it as well...
+ if(msg["CoreBuild"].toUInt() < Global::coreBuildNeeded) {
+ emit connectionError(tr("<b>The Quassel Core you are trying to connect to is too old!</b><br>"
+ "Need at least a Core Version %1 (Build >= %2) to connect.").arg(Global::quasselVersion).arg(Global::quasselBuild));
+ disconnectFromCore();
+ return;
+ }
+ emit connectionMsg(msg["CoreInfo"].toString());
+ if(msg["LoginEnabled"].toBool()) {
+ emit startLogin();
+ }
+}
+
+void ClientSyncer::loginToCore(const QString &user, const QString &passwd) {
+ emit connectionMsg(tr("Logging in..."));
+ QVariantMap clientLogin;
+ clientLogin["MsgType"] = "ClientLogin";
+ clientLogin["User"] = user;
+ clientLogin["Password"] = passwd;
+ SignalProxy::writeDataToDevice(socket, clientLogin);
+}
+
+void ClientSyncer::sessionStateReceived(const QVariantMap &state) {
+ emit sessionProgress(1, 1);
+ disconnect(this, SIGNAL(recvPartialItem(quint32, quint32)), this, SIGNAL(sessionProgress(quint32, quint32)));
+ disconnect(socket, 0, this, 0); // rest of communication happens through SignalProxy
+ //Client::signalProxy()->addPeer(socket);
+ Client::instance()->setConnectedToCore(socket);
+ syncToCore(state);
+}
+
+void ClientSyncer::syncToCore(const QVariantMap &sessionState) {
+
+ // store sessionData
+ QVariantMap sessData = sessionState["SessionData"].toMap();
+ foreach(QString key, sessData.keys()) Client::instance()->recvSessionData(key, sessData[key]);
+
+ // create identities
+ foreach(QVariant vid, sessionState["Identities"].toList()) {
+ Client::instance()->coreIdentityCreated(vid.value<Identity>());
+ }
+
+ // create buffers
+ // FIXME: get rid of this crap
+ QVariantList bufferinfos = sessionState["BufferInfos"].toList();
+ foreach(QVariant vinfo, bufferinfos) Client::buffer(vinfo.value<BufferInfo>()); // create Buffers and BufferItems
+
+ QVariantList networkids = sessionState["NetworkIds"].toList();
+
+ // prepare sync progress thingys... FIXME: Care about removal of networks
+ numNetsToSync = networkids.count();
+ numChannelsToSync = 0; //sessionState["IrcChannelCount"].toUInt();
+ numUsersToSync = 0; // sessionState["IrcUserCount"].toUInt(); qDebug() << numUsersToSync;
+ emit networksProgress(0, numNetsToSync);
+ emit channelsProgress(0, numChannelsToSync);
+ emit ircUsersProgress(0, numUsersToSync);
+
+ // create network objects
+ foreach(QVariant networkid, networkids) {
+ NetworkId netid = networkid.value<NetworkId>();
+ Network *net = new Network(netid, Client::instance());
+ netsToSync.insert(net);
+ connect(net, SIGNAL(initDone()), this, SLOT(networkInitDone()));
+ connect(net, SIGNAL(ircUserInitDone(IrcUser *)), this, SLOT(ircUserInitDone(IrcUser *)));
+ connect(net, SIGNAL(ircUserAdded(IrcUser *)), this, SLOT(ircUserAdded(IrcUser *)));
+ connect(net, SIGNAL(ircUserRemoved(QObject *)), this, SLOT(ircUserRemoved(QObject *)));
+ connect(net, SIGNAL(ircChannelInitDone(IrcChannel *)), this, SLOT(ircChannelInitDone(IrcChannel *)));
+ connect(net, SIGNAL(ircChannelAdded(IrcChannel *)), this, SLOT(ircChannelAdded(IrcChannel *)));
+ connect(net, SIGNAL(ircChannelRemoved(QObject *)), this, SLOT(ircChannelRemoved(QObject *)));
+ Client::addNetwork(net);
+ }
+}
+
+void ClientSyncer::networkInitDone() {
+ netsToSync.remove(sender());
+ emit networksProgress(numNetsToSync - netsToSync.count(), numNetsToSync);
+ checkSyncState();
+}
+
+void ClientSyncer::ircChannelInitDone(IrcChannel *chan) {
+ channelsToSync.remove(chan);
+ emit channelsProgress(numChannelsToSync - channelsToSync.count(), numChannelsToSync);
+ checkSyncState();
+}
+
+void ClientSyncer::ircChannelAdded(IrcChannel *chan) {
+ if(!chan->isInitialized()) {
+ channelsToSync.insert(chan);
+ numChannelsToSync++;
+ emit channelsProgress(numChannelsToSync - channelsToSync.count(), numChannelsToSync);
+ checkSyncState();
+ }
+}
+
+void ClientSyncer::ircChannelRemoved(QObject *chan) {
+ if(channelsToSync.contains(chan)) {
+ numChannelsToSync--;
+ channelsToSync.remove(chan);
+ emit channelsProgress(numChannelsToSync - channelsToSync.count(), numChannelsToSync);
+ checkSyncState();
+ }
+}
+
+void ClientSyncer::ircUserInitDone(IrcUser *user) {
+ usersToSync.remove(user);
+ emit ircUsersProgress(numUsersToSync - usersToSync.count(), numUsersToSync);
+ checkSyncState();
+}
+
+void ClientSyncer::ircUserAdded(IrcUser *user) {
+ if(!user->isInitialized()) {
+ usersToSync.insert(user);
+ numUsersToSync++;
+ emit ircUsersProgress(numUsersToSync - usersToSync.count(), numUsersToSync);
+ checkSyncState();
+ }
+}
+
+void ClientSyncer::ircUserRemoved(QObject *user) {
+ if(usersToSync.contains(user)) {
+ numUsersToSync--;
+ usersToSync.remove(user);
+ emit ircUsersProgress(numUsersToSync - usersToSync.count(), numUsersToSync);
+ checkSyncState();
+ }
+}
+
+void ClientSyncer::checkSyncState() {
+ if(usersToSync.count() + channelsToSync.count() + netsToSync.count() == 0) {
+ // done syncing!
+ /*
+ qDebug() << "done";
+ foreach(Network *net, _networks.values()) {
+ //disconnect(net, 0, this, SLOT(networkInitDone()));
+ //disconnect(net, 0, this, SLOT(ircUserInitDone(IrcUser *)));
+ //disconnect(net, 0, this, SLOT(ircUserAdded(IrcUser *)));
+ //disconnect(net, 0, this, SLOT(ircUserRemoved(QObject *)));
+ //disconnect(net, 0, this, SLOT(ircChannelInitDone(IrcChannel *)));
+ //disconnect(net, 0, this, SLOT(ircChannelAdded(IrcChannel *)));
+ //disconnect(net, 0, this, SLOT(ircChannelRemoved(QObject *)));
+ qDebug() << "disconnecting";
+ disconnect(net, SIGNAL(initDone()), this, SLOT(networkInitDone()));
+ disconnect(net, SIGNAL(ircUserInitDone(IrcUser *)), this, SLOT(ircUserInitDone(IrcUser *)));
+ disconnect(net, SIGNAL(ircUserAdded(IrcUser *)), this, SLOT(ircUserAdded(IrcUser *)));
+ disconnect(net, SIGNAL(ircUserRemoved(QObject *)), this, SLOT(ircUserRemoved(QObject *)));
+ disconnect(net, SIGNAL(ircChannelInitDone(IrcChannel *)), this, SLOT(ircChannelInitDone(IrcChannel *)));
+ disconnect(net, SIGNAL(ircChannelAdded(IrcChannel *)), this, SLOT(ircChannelAdded(IrcChannel *)));
+ disconnect(net, SIGNAL(ircChannelRemoved(QObject *)), this, SLOT(ircChannelRemoved(QObject *)));
+ }
+ */
+
+ Client::instance()->setSyncedToCore();
+ emit syncFinished();
+ //emit connected();
+ //emit connectionStateChanged(true);
+
+ }
+}
+
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005-08 by the Quassel IRC Team *
+ * devel@quassel-irc.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) version 3. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#ifndef _CLIENTSYNCER_H_
+#define _CLIENTSYNCER_H_
+
+#include <QPointer>
+#include <QString>
+#include <QTcpSocket>
+#include <QVariantMap>
+
+class IrcUser;
+class IrcChannel;
+
+class ClientSyncer : public QObject {
+ Q_OBJECT
+
+ public:
+ ClientSyncer(QObject *parent = 0);
+ ~ClientSyncer();
+
+ signals:
+ void recvPartialItem(quint32 avail, quint32 size);
+ void connectionError(const QString &errorMsg);
+ void connectionMsg(const QString &msg);
+ void sessionProgress(quint32 part, quint32 total);
+ void networksProgress(quint32 part, quint32 total);
+ void channelsProgress(quint32 part, quint32 total);
+ void ircUsersProgress(quint32 part, quint32 total);
+ void socketStateChanged(QAbstractSocket::SocketState);
+ void socketDisconnected();
+
+ void startLogin();
+ void loginFailed(const QString &error);
+ void loginSuccess();
+ void syncFinished();
+
+
+ public slots:
+ void connectToCore(const QVariantMap &);
+ void loginToCore(const QString &user, const QString &passwd);
+ void disconnectFromCore();
+
+ private slots:
+ void coreSocketError(QAbstractSocket::SocketError);
+ void coreHasData();
+ void coreSocketConnected();
+ void coreSocketDisconnected();
+
+ void clientInitAck(const QVariantMap &msg);
+
+ // for sync progress
+ void networkInitDone();
+ void ircUserAdded(IrcUser *);
+ void ircUserRemoved(QObject *);
+ void ircUserInitDone(IrcUser *);
+ void ircChannelAdded(IrcChannel *);
+ void ircChannelRemoved(QObject *);
+ void ircChannelInitDone(IrcChannel *);
+ void checkSyncState();
+
+ void syncToCore(const QVariantMap &sessionState);
+ void sessionStateReceived(const QVariantMap &state);
+
+ private:
+ QPointer<QIODevice> socket;
+ quint32 blockSize;
+ QVariantMap coreConnectionInfo;
+
+ QSet<QObject *> netsToSync, channelsToSync, usersToSync;
+ int numNetsToSync, numChannelsToSync, numUsersToSync;
+
+};
+
+#endif
IrcUserItem *userItem;
for(int i = 0; i < childCount(); i++) {
categoryItem = qobject_cast<UserCategoryItem *>(child(i));
- if(userItem = qobject_cast<IrcUserItem *>(categoryItem->childById((quint64)ircUser))) {
+ if((userItem = qobject_cast<IrcUserItem *>(categoryItem->childById((quint64)ircUser)))) {
userItem->deleteLater();
return;
}
/*****************************************
* Network Items
*****************************************/
-NetworkItem::NetworkItem(const uint &netid, const QString &network, AbstractTreeItem *parent)
+NetworkItem::NetworkItem(const NetworkId &netid, AbstractTreeItem *parent)
: PropertyMapItem(QList<QString>() << "networkName" << "currentServer" << "nickCount", parent),
- _networkId(netid),
- _networkName(network)
+ _networkId(netid)
{
setFlags(Qt::ItemIsEnabled);
}
if(_network)
return _network->networkName();
else
- return _networkName;
+ return QString();
}
QString NetworkItem::currentServer() const {
return index.data(NetworkModel::ItemTypeRole) == NetworkModel::BufferItemType;
}
+/*
Buffer *NetworkModel::getBufferByIndex(const QModelIndex &index) const {
BufferItem *item = static_cast<BufferItem *>(index.internalPointer());
return Client::instance()->buffer(item->id());
}
+*/
// experimental stuff :)
-QModelIndex NetworkModel::networkIndex(uint networkId) {
+QModelIndex NetworkModel::networkIndex(NetworkId networkId) {
return indexById(networkId);
}
-NetworkItem *NetworkModel::network(uint networkId) {
+NetworkItem *NetworkModel::existsNetworkItem(NetworkId networkId) {
return qobject_cast<NetworkItem *>(rootItem->childById(networkId));
}
-NetworkItem *NetworkModel::newNetwork(uint networkId, const QString &networkName) {
- NetworkItem *networkItem = network(networkId);
+NetworkItem *NetworkModel::networkItem(NetworkId networkId) {
+ NetworkItem *netItem = existsNetworkItem(networkId);
- if(networkItem == 0) {
- networkItem = new NetworkItem(networkId, networkName, rootItem);
- appendChild(rootItem, networkItem);
+ if(netItem == 0) {
+ netItem = new NetworkItem(networkId, rootItem);
+ appendChild(rootItem, netItem);
}
- Q_ASSERT(networkItem);
- return networkItem;
+ Q_ASSERT(netItem);
+ return netItem;
}
QModelIndex NetworkModel::bufferIndex(BufferId bufferId) {
return QModelIndex();
}
-BufferItem *NetworkModel::buffer(BufferInfo bufferInfo) {
+BufferItem *NetworkModel::existsBufferItem(const BufferInfo &bufferInfo) {
QModelIndex bufferIdx = bufferIndex(bufferInfo.uid());
if(bufferIdx.isValid())
return static_cast<BufferItem *>(bufferIdx.internalPointer());
return 0;
}
-BufferItem *NetworkModel::newBuffer(BufferInfo bufferInfo) {
- BufferItem *bufferItem = buffer(bufferInfo);
- if(bufferItem == 0) {
- NetworkItem *networkItem = newNetwork(bufferInfo.networkId(), bufferInfo.network());
- bufferItem = new BufferItem(bufferInfo, networkItem);
- appendChild(networkItem, bufferItem);
+BufferItem *NetworkModel::bufferItem(const BufferInfo &bufferInfo) {
+ BufferItem *bufItem = existsBufferItem(bufferInfo);
+ if(bufItem == 0) {
+ NetworkItem *netItem = networkItem(bufferInfo.networkId());
+ bufItem = new BufferItem(bufferInfo, netItem);
+ appendChild(netItem, bufItem);
}
- Q_ASSERT(bufferItem);
- return bufferItem;
+ Q_ASSERT(bufItem);
+ return bufItem;
}
QStringList NetworkModel::mimeTypes() const {
return mimeData->hasFormat("application/Quassel/BufferItemList");
}
-QList< QPair<uint, uint> > NetworkModel::mimeDataToBufferList(const QMimeData *mimeData) {
- QList< QPair<uint, uint> > bufferList;
+QList< QPair<NetworkId, BufferId> > NetworkModel::mimeDataToBufferList(const QMimeData *mimeData) {
+ QList< QPair<NetworkId, BufferId> > bufferList;
if(!mimeContainsBufferList(mimeData))
return bufferList;
QStringList rawBufferList = QString::fromAscii(mimeData->data("application/Quassel/BufferItemList")).split(",");
- uint networkId, bufferUid;
+ NetworkId networkId;
+ BufferId bufferUid;
foreach(QString rawBuffer, rawBufferList) {
if(!rawBuffer.contains(":"))
continue;
- networkId = rawBuffer.section(":", 0, 0).toUInt();
- bufferUid = rawBuffer.section(":", 1, 1).toUInt();
+ networkId = rawBuffer.section(":", 0, 0).toInt();
+ bufferUid = rawBuffer.section(":", 1, 1).toInt();
bufferList.append(qMakePair(networkId, bufferUid));
}
return bufferList;
QStringList bufferlist;
QString netid, uid, bufferid;
foreach(QModelIndex index, indexes) {
- netid = QString::number(index.data(NetworkIdRole).toUInt());
- uid = QString::number(index.data(BufferIdRole).toUInt());
+ netid = QString::number(index.data(NetworkIdRole).value<NetworkId>());
+ uid = QString::number(index.data(BufferIdRole).value<BufferId>());
bufferid = QString("%1:%2").arg(netid).arg(uid);
if(!bufferlist.contains(bufferid))
bufferlist << bufferid;
uint bufferId = bufferList.first().second;
// no self merges (would kill us)
- if(bufferId == parent.data(BufferIdRole).toUInt())
+ if(bufferId == parent.data(BufferIdRole).value<BufferId>())
return false;
Q_ASSERT(rootItem->childById(netId));
return false;
// TODO: warn user about buffermerge!
- qDebug() << "merging" << bufferId << parent.data(BufferIdRole).toInt();
+ qDebug() << "merging" << bufferId << parent.data(BufferIdRole).value<BufferId>();
removeRow(parent.row(), parent.parent());
return true;
}
void NetworkModel::attachNetwork(Network *net) {
- NetworkItem *networkItem = network(net->networkId());
- if(!networkItem) {
- qWarning() << "NetworkModel::attachNetwork(): network is unknown!";
- return;
- }
- networkItem->attachNetwork(net);
+ NetworkItem *netItem = networkItem(net->networkId());
+ netItem->attachNetwork(net);
}
void NetworkModel::bufferUpdated(BufferInfo bufferInfo) {
- BufferItem *bufferItem = newBuffer(bufferInfo);
- QModelIndex itemindex = indexByItem(bufferItem);
+ BufferItem *bufItem = bufferItem(bufferInfo);
+ QModelIndex itemindex = indexByItem(bufItem);
emit dataChanged(itemindex, itemindex);
}
Q_PROPERTY(int nickCount READ nickCount)
public:
- NetworkItem(const uint &netid, const QString &, AbstractTreeItem *parent = 0);
+ NetworkItem(const NetworkId &netid, AbstractTreeItem *parent = 0);
virtual QVariant data(int column, int row) const;
virtual quint64 id() const;
void attachIrcChannel(const QString &channelName);
private:
- uint _networkId;
- QString _networkName;
+ NetworkId _networkId;
QPointer<Network> _network;
};
static QList<QVariant> defaultHeader();
static bool mimeContainsBufferList(const QMimeData *mimeData);
- static QList< QPair<uint, uint> > mimeDataToBufferList(const QMimeData *mimeData);
+ static QList< QPair<NetworkId, BufferId> > mimeDataToBufferList(const QMimeData *mimeData);
virtual QStringList mimeTypes() const;
virtual QMimeData *mimeData(const QModelIndexList &) const;
void attachNetwork(Network *network);
bool isBufferIndex(const QModelIndex &) const;
- Buffer *getBufferByIndex(const QModelIndex &) const;
+ //Buffer *getBufferByIndex(const QModelIndex &) const;
QModelIndex bufferIndex(BufferId bufferId);
public slots:
void bufferActivity(BufferItem::ActivityLevel, BufferInfo bufferInfo);
private:
- QModelIndex networkIndex(uint networkId);
- NetworkItem *network(uint networkId);
- NetworkItem *newNetwork(uint networkId, const QString &networkName);
-
- BufferItem *buffer(BufferInfo bufferInfo);
- BufferItem *newBuffer(BufferInfo bufferInfo);
+ QModelIndex networkIndex(NetworkId networkId);
+ NetworkItem *networkItem(NetworkId networkId);
+ NetworkItem *existsNetworkItem(NetworkId networkId);
+ BufferItem *bufferItem(const BufferInfo &bufferInfo);
+ BufferItem *existsBufferItem(const BufferInfo &bufferInfo);
};
//! Register our custom types with Qt's Meta Object System.
/** This makes them available for QVariant and in signals/slots, among other things.
+ *
*/
void Global::registerMetaTypes() {
// Complex types
qRegisterMetaType<IdentityId>("IdentityId");
qRegisterMetaType<BufferId>("BufferId");
qRegisterMetaType<NetworkId>("NetworkId");
+ qRegisterMetaType<UserId>("UserId");
qRegisterMetaTypeStreamOperators<IdentityId>("IdentityId");
qRegisterMetaTypeStreamOperators<BufferId>("BufferId");
qRegisterMetaTypeStreamOperators<NetworkId>("NetworkId");
+ qRegisterMetaTypeStreamOperators<UserId>("UserId");
}
+// Static variables
+
+QString Global::quasselVersion;
+QString Global::quasselDate;
+uint Global::quasselBuild;
+uint Global::clientBuildNeeded;
+QString Global::clientVersionNeeded;
+uint Global::coreBuildNeeded;
+QString Global::coreVersionNeeded;
+
Global::RunMode Global::runMode;
uint Global::defaultPort;
-
/***************************************************************************
- * Copyright (C) 2005 by the Quassel Project *
+ * Copyright (C) 2005-08 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
// Enable some shortcuts and stuff
//#define DEVELMODE
-/** The protocol version we use fo the communication between core and GUI */
-#define GUI_PROTOCOL 5
-
-//#define DEFAULT_PORT 4242
-
/* Some global stuff */
namespace Global {
+
+ extern QString quasselVersion;
+ extern QString quasselDate;
+ extern uint quasselBuild;
+
+ //! Minimum client build number the core needs
+ extern uint clientBuildNeeded;
+ extern QString clientVersionNeeded;
+
+ //! Minimum core build number the client needs
+ extern uint coreBuildNeeded;
+ extern QString coreVersionNeeded;
+
// We need different config (QSettings) files for client and gui, since the core cannot work with GUI types
// Set these here. They're used in ClientSettings and CoreSettings.
const QString coreApplicationName = "Quassel Core";
}
void Identity::init() {
- _initialized = false;
setObjectName(QString::number(id()));
}
return (id() > 0);
}
-bool Identity::initialized() const {
- return _initialized;
-}
-
-void Identity::setInitialized() {
- _initialized = true;
-}
-
IdentityId Identity::id() const {
return _identityId;
}
QString partReason() const;
QString quitReason() const;
- bool initialized() const;
- void setInitialized();
-
public slots:
void setId(IdentityId id);
void setIdentityName(const QString &name);
void partReasonSet(const QString &);
void quitReasonSet(const QString &);
- void updatedRemotely();
-
private:
- bool _initialized;
IdentityId _identityId;
QString _identityName, _realName;
QStringList _nicks;
return isvalid;
}
-bool IrcChannel::initialized() const {
- return _initialized;
-}
-
QString IrcChannel::name() const {
return _name;
}
// if you wonder why there is no counterpart to ircUserParted:
// the joines are propagted by the ircuser. the signal ircUserParted is only for convenience
emit ircUserParted(ircuser);
- if(network->isMyNick(ircuser))
+ if(network->isMe(ircuser))
deleteLater();
}
}
emit ircUserNickSet(ircUser, nick);
}
-void IrcChannel::setInitialized() {
- _initialized = true;
- emit initDone();
-}
-
bool isKnownUser(IrcUser *ircuser) const;
bool isValidChannelUserMode(const QString &mode) const;
- bool initialized() const;
-
QString name() const;
QString topic() const;
// init seters
void initSetUserModes(const QVariantMap &usermodes);
- void setInitialized();
-
signals:
void topicSet(QString topic);
void userModesSet(QString nick, QString modes);
void ircUserModeRemoved(IrcUser *ircuser, QString mode);
void ircUserModesSet(IrcUser *ircuser, QString modes);
- void initDone();
-
private slots:
void ircUserDestroyed();
void ircUserNickSet(QString nick);
// ====================
// PUBLIC:
// ====================
-bool IrcUser::initialized() const {
- return _initialized;
-}
QString IrcUser::user() const {
return _user;
}
}
-void IrcUser::setInitialized() {
- _initialized = true;
- emit initDone();
-}
-
IrcUser(const QString &hostmask, Network *network);
virtual ~IrcUser();
- bool initialized() const;
-
QString user() const;
QString host() const;
QString nick() const;
// init seters
void initSetChannels(const QStringList channels);
- void setInitialized();
-
signals:
void userSet(QString user);
void hostSet(QString host);
// void setUsermodes(const QSet<QString> &usermodes);
// QSet<QString> usermodes() const;
- void initDone();
-
private slots:
void updateObjectName();
void channelDestroyed();
Global::registerMetaTypes();
+#include "../../version.inc"
+
#if defined BUILD_CORE
Global::runMode = Global::CoreOnly;
QCoreApplication app(argc, argv);
// ====================
// Public:
// ====================
-Network::Network(const uint &networkid, QObject *parent)
- : SyncableObject(parent),
+Network::Network(const NetworkId &networkid, QObject *parent) : SyncableObject(parent),
_networkId(networkid),
- _initialized(false),
+ _identity(0),
_myNick(QString()),
- _networkName(QString()),
+ _networkName(QString("<not initialized>")),
_currentServer(QString()),
_prefixes(QString()),
_prefixModes(QString()),
// }
//}
-uint Network::networkId() const {
+NetworkId Network::networkId() const {
return _networkId;
}
-bool Network::initialized() const {
- return _initialized;
-}
-
SignalProxy *Network::proxy() const {
return _proxy;
}
void Network::setProxy(SignalProxy *proxy) {
_proxy = proxy;
- proxy->synchronize(this);
+ //proxy->synchronize(this); // we should to this explicitly from the outside!
}
bool Network::isMyNick(const QString &nick) const {
return (myNick().toLower() == nick.toLower());
}
-bool Network::isMyNick(IrcUser *ircuser) const {
+bool Network::isMe(IrcUser *ircuser) const {
return (ircuser->nick().toLower() == myNick().toLower());
}
return _myNick;
}
+IdentityId Network::identity() const {
+ return _identity;
+}
+
QStringList Network::nicks() const {
// we don't use _ircUsers.keys() since the keys may be
// not up to date after a nick change
return _ircChannels.keys();
}
+QList<QVariantMap> Network::serverList() const {
+ return _serverList;
+}
+
QString Network::prefixes() {
if(_prefixes.isNull())
determinePrefixes();
if(!_ircUsers.contains(nick)) {
IrcUser *ircuser = new IrcUser(hostmask, this);
// mark IrcUser as already initialized to keep the SignalProxy from requesting initData
- if(initialized())
- ircuser->setInitialized();
+ //if(isInitialized())
+ // ircuser->setInitialized();
if(proxy())
proxy()->synchronize(ircuser);
else
qWarning() << "unable to synchronize new IrcUser" << hostmask << "forgot to call Network::setProxy(SignalProxy *)?";
connect(ircuser, SIGNAL(nickSet(QString)), this, SLOT(ircUserNickChanged(QString)));
- connect(ircuser, SIGNAL(initDone()), this, SIGNAL(ircUserInitDone()));
+ connect(ircuser, SIGNAL(initDone()), this, SLOT(ircUserInitDone()));
connect(ircuser, SIGNAL(destroyed()), this, SLOT(ircUserDestroyed()));
_ircUsers[nick] = ircuser;
emit ircUserAdded(hostmask);
+ emit ircUserAdded(ircuser);
}
return _ircUsers[nick];
}
return;
_ircUsers.remove(nick);
- ircuser->deleteLater();
emit ircUserRemoved(nick);
+ emit ircUserRemoved(ircuser);
+ ircuser->deleteLater();
}
void Network::removeIrcUser(QString nick) {
return _ircUsers.values();
}
+quint32 Network::ircUserCount() const {
+ return _ircUsers.count();
+}
+
IrcChannel *Network::newIrcChannel(const QString &channelname) {
if(!_ircChannels.contains(channelname.toLower())) {
IrcChannel *channel = new IrcChannel(channelname, this);
// mark IrcUser as already initialized to keep the SignalProxy from requesting initData
- if(initialized())
- channel->setInitialized();
+ //if(isInitialized())
+ // channel->setInitialized();
if(proxy())
proxy()->synchronize(channel);
else
qWarning() << "unable to synchronize new IrcChannel" << channelname << "forgot to call Network::setProxy(SignalProxy *)?";
- connect(channel, SIGNAL(initDone()), this, SIGNAL(ircChannelInitDone()));
+ connect(channel, SIGNAL(initDone()), this, SLOT(ircChannelInitDone()));
connect(channel, SIGNAL(destroyed()), this, SLOT(channelDestroyed()));
_ircChannels[channelname.toLower()] = channel;
emit ircChannelAdded(channelname);
+ emit ircChannelAdded(channel);
}
return _ircChannels[channelname.toLower()];
}
return _ircChannels.values();
}
-QTextCodec *Network::codecForEncoding() const {
- return _codecForEncoding;
+quint32 Network::ircChannelCount() const {
+ return _ircChannels.count();
}
-void Network::setCodecForEncoding(const QString &name) {
- setCodecForEncoding(QTextCodec::codecForName(name.toAscii()));
+QByteArray Network::codecForEncoding() const {
+ if(_codecForEncoding) return _codecForEncoding->name();
+ return QByteArray();
+}
+
+void Network::setCodecForEncoding(const QByteArray &name) {
+ setCodecForEncoding(QTextCodec::codecForName(name));
}
void Network::setCodecForEncoding(QTextCodec *codec) {
_codecForEncoding = codec;
}
-QTextCodec *Network::codecForDecoding() const {
- return _codecForDecoding;
+QByteArray Network::codecForDecoding() const {
+ if(_codecForDecoding) return _codecForDecoding->name();
+ else return QByteArray();
}
-void Network::setCodecForDecoding(const QString &name) {
- setCodecForDecoding(QTextCodec::codecForName(name.toAscii()));
+void Network::setCodecForDecoding(const QByteArray &name) {
+ setCodecForDecoding(QTextCodec::codecForName(name));
}
void Network::setCodecForDecoding(QTextCodec *codec) {
emit myNickSet(nickname);
}
+void Network::setIdentity(IdentityId id) {
+ _identity = id;
+ emit identitySet(id);
+}
+
+void Network::setServerList(const QList<QVariantMap> &serverList) {
+ _serverList = serverList;
+ emit serverListSet(serverList);
+}
+
void Network::addSupport(const QString ¶m, const QString &value) {
if(!_supports.contains(param)) {
_supports[param] = value;
return supports;
}
+QVariantList Network::initServerList() const {
+ QList<QVariant> list;
+ foreach(QVariantMap serverdata, serverList()) list << QVariant(serverdata);
+ return list;
+}
+
QStringList Network::initIrcUsers() const {
QStringList hostmasks;
foreach(IrcUser *ircuser, ircUsers()) {
}
}
+void Network::initSetServerList(const QVariantList & serverList) {
+ QList<QVariantMap> slist;
+ foreach(QVariant v, serverList) slist << v.toMap();
+ setServerList(slist);
+}
+
void Network::initSetIrcUsers(const QStringList &hostmasks) {
if(!_ircUsers.empty())
return;
return;
if(newnick.toLower() != oldnick) _ircUsers[newnick.toLower()] = _ircUsers.take(oldnick);
-
+
if(myNick().toLower() == oldnick)
setMyNick(newnick);
}
+void Network::ircUserInitDone() {
+ IrcUser *ircuser = static_cast<IrcUser *>(sender());
+ Q_ASSERT(ircuser);
+ emit ircUserInitDone(ircuser);
+}
+
+void Network::ircChannelInitDone() {
+ IrcChannel *ircchannel = static_cast<IrcChannel *>(sender());
+ Q_ASSERT(ircchannel);
+ emit ircChannelInitDone(ircchannel);
+}
+
void Network::ircUserDestroyed() {
IrcUser *ircuser = static_cast<IrcUser *>(sender());
Q_ASSERT(ircuser);
void Network::channelDestroyed() {
IrcChannel *channel = static_cast<IrcChannel *>(sender());
Q_ASSERT(channel);
+ emit ircChannelRemoved(sender());
_ircChannels.remove(_ircChannels.key(channel));
}
-void Network::setInitialized() {
- _initialized = true;
- emit initDone();
+void Network::requestConnect() {
+ 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 :)
}
// ====================
#ifndef _NETWORK_H_
#define _NETWORK_H_
+#include <QDebug>
#include <QString>
#include <QStringList>
#include <QList>
#include <QHash>
#include <QVariantMap>
#include <QPointer>
+#include <QMutex>
#include "types.h"
#include "syncableobject.h"
class IrcUser;
class IrcChannel;
+// TODO: ConnectionInfo to propagate and sync the current state of NetworkConnection, encodings etcpp
class Network : public SyncableObject {
Q_OBJECT
Q_PROPERTY(QString networkName READ networkName WRITE setNetworkName STORED false)
Q_PROPERTY(QString currentServer READ currentServer WRITE setCurrentServer STORED false)
Q_PROPERTY(QString myNick READ myNick WRITE setMyNick STORED false)
+ Q_PROPERTY(QByteArray codecForEncoding READ codecForEncoding WRITE setCodecForEncoding STORED false)
+ 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 STORED false)
public:
- Network(const uint &networkid, QObject *parent = 0);
+ Network(const NetworkId &networkid, QObject *parent = 0);
//virtual ~Network();
NetworkId networkId() const;
- bool initialized() const;
SignalProxy *proxy() const;
void setProxy(SignalProxy *proxy);
bool isMyNick(const QString &nick) const;
- bool isMyNick(IrcUser *ircuser) const;
+ bool isMe(IrcUser *ircuser) const;
bool isChannelName(const QString &channelname) const;
QString networkName() const;
QString currentServer() const;
QString myNick() const;
+ IdentityId identity() const;
QStringList nicks() const;
QStringList channels() const;
+ QList<QVariantMap> serverList() const;
QString prefixes();
QString prefixModes();
IrcUser *ircUser(QString nickname) const;
IrcUser *ircUser(const QByteArray &nickname) const;
QList<IrcUser *> ircUsers() const;
+ quint32 ircUserCount() const;
IrcChannel *newIrcChannel(const QString &channelname);
IrcChannel *newIrcChannel(const QByteArray &channelname);
IrcChannel *ircChannel(QString channelname);
IrcChannel *ircChannel(const QByteArray &channelname);
-
QList<IrcChannel *> ircChannels() const;
+ quint32 ircChannelCount() const;
- QTextCodec *codecForEncoding() const;
- QTextCodec *codecForDecoding() const;
- void setCodecForEncoding(const QString &codecName);
+ QByteArray codecForEncoding() const;
+ QByteArray codecForDecoding() const;
void setCodecForEncoding(QTextCodec *codec);
- void setCodecForDecoding(const QString &codecName);
void setCodecForDecoding(QTextCodec *codec);
QString decodeString(const QByteArray &text) const;
void setNetworkName(const QString &networkName);
void setCurrentServer(const QString ¤tServer);
void setMyNick(const QString &mynick);
+ void setIdentity(IdentityId);
+
+ void setServerList(const QList<QVariantMap> &serverList);
+
+ void setCodecForEncoding(const QByteArray &codecName);
+ void setCodecForDecoding(const QByteArray &codecName);
void addSupport(const QString ¶m, const QString &value = QString());
void removeSupport(const QString ¶m);
//init geters
QVariantMap initSupports() const;
+ QVariantList initServerList() const;
QStringList initIrcUsers() const;
QStringList initIrcChannels() const;
//init seters
void initSetSupports(const QVariantMap &supports);
+ void initSetServerList(const QVariantList &serverList);
void initSetIrcUsers(const QStringList &hostmasks);
void initSetChannels(const QStringList &channels);
// these slots are to keep the hashlists of all users and the
// channel lists up to date
void ircUserNickChanged(QString newnick);
- void setInitialized();
+
+ void requestConnect();
private slots:
void ircUserDestroyed();
void channelDestroyed();
void removeIrcUser(IrcUser *ircuser);
-
+ void ircUserInitDone();
+ void ircChannelInitDone();
+
signals:
void networkNameSet(const QString &networkName);
void currentServerSet(const QString ¤tServer);
void myNickSet(const QString &mynick);
+ void identitySet(IdentityId);
+
+ void serverListSet(const QList<QVariantMap> &serverList);
+
+ void codecForEncodingSet(const QString &codecName);
+ void codecForDecodingSet(const QString &codecName);
void supportAdded(const QString ¶m, const QString &value);
void supportRemoved(const QString ¶m);
-
- void ircUserAdded(QString hostmask);
- void ircChannelAdded(QString channelname);
- void ircUserRemoved(QString nick);
-
- void initDone();
- void ircUserInitDone();
- void ircChannelInitDone();
-
+ void ircUserAdded(const QString &hostmask);
+ void ircUserAdded(IrcUser *);
+ void ircChannelAdded(const QString &channelname);
+ void ircChannelAdded(IrcChannel *);
+
+ void ircUserRemoved(const QString &nick);
+
+ // needed for client sync progress
+ void ircUserRemoved(QObject *);
+ void ircChannelRemoved(QObject *);
+
+ void ircUserInitDone(IrcUser *);
+ void ircChannelInitDone(IrcChannel *);
+
+ void connectRequested(NetworkId = 0);
+
private:
- uint _networkId;
- bool _initialized;
-
+ NetworkId _networkId;
+ IdentityId _identity;
+
QString _myNick;
QString _networkName;
QString _currentServer;
QHash<QString, IrcChannel *> _ircChannels; // stores all known channels
QHash<QString, QString> _supports; // stores results from RPL_ISUPPORT
+ QList<QVariantMap> _serverList;
//QVariantMap networkSettings;
//QVariantMap identity;
// dispatch Sync Signal if necessary
QByteArray signature(caller->metaObject()->method(_id).signature());
if(synchronize() && proxy->syncMap(qobject_cast<SyncableObject *>(caller)).contains(signature)) {
- // qDebug() << "__SYNC__ >>>"
- // << caller->metaObject()->className()
- // << caller->objectName()
- // << proxy->methodName(caller, _id)
- // << params;
+ //qDebug() << "__SYNC__ >>>"
+ // << caller->metaObject()->className()
+ // << caller->objectName()
+ // << signature
+ // << params;
// params.prepend(QVariant(_id));
params.prepend(signature);
params.prepend(caller->objectName());
if(!proxy->syncMap(qobject_cast<SyncableObject *>(caller)).contains(signature))
return false;
- if(proxy->proxyMode() == SignalProxy::Server && !signature.startsWith("request"))
+ if(proxy->proxyMode() == SignalProxy::Server && !signature.contains("Requested"))
return true;
- if(proxy->proxyMode() == SignalProxy::Client && signature.startsWith("request"))
+ if(proxy->proxyMode() == SignalProxy::Client && signature.contains("Requested"))
return true;
return false;
return _classInfo[obj->metaObject()]->argTypes[methodId];
}
-bool SignalProxy::hasUpdateSignal(QObject *obj) {
- if(!_classInfo.contains(obj->metaObject()))
- return false;
- return _classInfo[obj->metaObject()]->hasUpdateSignal;
-}
-
void SignalProxy::setMethodName(QObject *obj, int methodId) {
const QMetaObject *meta = obj->metaObject();
QByteArray method(::methodName(meta->method(methodId)));
return;
ClassInfo *classInfo = new ClassInfo();
- classInfo->hasUpdateSignal = (obj->metaObject()->indexOfSignal(QMetaObject::normalizedSignature("updatedRemotely()")) != -1);
_classInfo[obj->metaObject()] = classInfo;
}
}
void SignalProxy::setInitialized(SyncableObject *obj) {
- QMetaObject::invokeMethod(obj, "setInitialized");
+ obj->setInitialized();
+ emit objectInitialized(obj);
}
-bool SignalProxy::initialized(SyncableObject *obj) {
- bool init;
- if(!QMetaObject::invokeMethod(obj, "initialized", Q_RETURN_ARG(bool, init)))
- init = false;
- return init;
+bool SignalProxy::isInitialized(SyncableObject *obj) const {
+ return obj->isInitialized();
}
void SignalProxy::requestInit(SyncableObject *obj) {
- if(proxyMode() == Server || initialized(obj))
+ if(proxyMode() == Server || isInitialized(obj))
return;
QVariantList params;
qWarning("SignalProxy::handleSync(): invokeMethod for \"%s\" failed ", methodName(receiver, slotId).constData());
return;
}
- if(hasUpdateSignal(receiver))
- QMetaObject::invokeMethod(receiver, "updatedRemotely");
+ QMetaObject::invokeMethod(receiver, "updatedRemotely");
}
void SignalProxy::handleInitRequest(QIODevice *sender, const QVariantList ¶ms) {
}
void SignalProxy::setInitData(SyncableObject *obj, const QVariantMap &properties) {
- if(initialized(obj))
+ if(isInitialized(obj))
return;
obj->fromVariantMap(properties);
setInitialized(obj);
void synchronize(SyncableObject *obj);
void setInitialized(SyncableObject *obj);
- bool initialized(SyncableObject *obj);
+ bool isInitialized(SyncableObject *obj) const;
void requestInit(SyncableObject *obj);
void detachObject(QObject *obj);
static bool readDataFromDevice(QIODevice *dev, quint32 &blockSize, QVariant &item);
static QString methodBaseName(const QMetaMethod &method);
-
+
const QList<int> &argTypes(QObject *obj, int methodId);
- bool hasUpdateSignal(QObject *obj);
const QByteArray &methodName(QObject *obj, int methodId);
const QHash<QByteArray, int> &syncMap(SyncableObject *obj);
ArgHash argTypes;
MethodNameHash methodNames;
QHash<QByteArray, int> syncMap;
- bool hasUpdateSignal;
};
void dumpProxyStats();
void peerRemoved(QIODevice *obj);
void connected();
void disconnected();
+ void objectInitialized(SyncableObject *);
private:
void initServer();
void _detachSlots(QObject *receiver);
void _stopSync(SyncableObject *obj);
+ public:
void dumpSyncMap(SyncableObject *object);
+ private:
// Hash of used QIODevices
QHash<QIODevice*, quint32> _peerByteCount;
#include "util.h"
SyncableObject::SyncableObject(QObject *parent) : QObject(parent) {
-
+ _initialized = false;
}
SyncableObject::SyncableObject(const SyncableObject &other, QObject *parent) : QObject(parent) {
- Q_UNUSED(other);
+ _initialized = other._initialized;
+
+}
+
+bool SyncableObject::isInitialized() const {
+ return _initialized;
+}
+void SyncableObject::setInitialized() {
+ _initialized = true;
+ emit initDone();
}
QVariantMap SyncableObject::toVariantMap() {
/** The default implementation takes dynamic properties as well as getters that have
* names starting with "init" and stores them in a QVariantMap. Override this method in
* derived classes in order to store the object state in a custom form.
- * \Note: This is used by SignalProxy to transmit the state of the object to clients
+ * \note This is used by SignalProxy to transmit the state of the object to clients
* that request the initial object state. Later updates use a different mechanism
* and assume that the state is completely covered by properties and init* getters.
* DO NOT OVERRIDE THIS unless you know exactly what you do!
+ *
* \return The object's state in a QVariantMap
*/
virtual QVariantMap toVariantMap();
*/
virtual void fromVariantMap(const QVariantMap &map);
+ virtual bool isInitialized() const;
+
+ public slots:
+ virtual void setInitialized();
+
+ signals:
+ void initDone();
+ void updatedRemotely();
+
private:
bool setInitValue(const QString &property, const QVariant &value);
+ bool _initialized;
+
};
#endif
/** This function takes a string and first checks if it is encoded in utf8, in which case it is
* decoded appropriately. Otherwise, the specified text codec is used to transform the string.
* \param input The input string containing encoded data
- * \param encoding The text codec we use if the input is not utf8
+ * \param codec The text codec we use if the input is not utf8
* \return The decoded string.
*/
QString decodeString(const QByteArray &input, QTextCodec *codec = 0);
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
+#include <QMetaObject>
+#include <QMetaMethod>
+#include <QMutexLocker>
+#include <QCoreApplication>
+
#include "core.h"
#include "coresession.h"
#include "coresettings.h"
#include "signalproxy.h"
#include "sqlitestorage.h"
-#include <QMetaObject>
-#include <QMetaMethod>
-
-#include <QCoreApplication>
-
Core *Core::instanceptr = 0;
+QMutex Core::mutex;
Core *Core::instance() {
if(instanceptr) return instanceptr;
Core::Core()
: storage(0)
{
+ startTime = QDateTime::currentDateTime(); // for uptime :)
}
void Core::init() {
- // TODO: Remove this again at some point
- // Check if old core settings need to be migrated in order to make the switch to the
- // new location less painful.
- CoreSettings cs;
- QVariant foo = cs.databaseSettings();
-
- if(!foo.isValid()) {
- // ok, no settings stored yet. check for old ones.
-#ifdef Q_WS_MAC
- QSettings os("quassel-irc.org", "Quassel IRC", this);
-#else
- QSettings os("Quassel IRC Development Team", "Quassel IRC");
-#endif
- QVariant bar = os.value("Core/DatabaseSettings");
- if(bar.isValid()) {
- // old settings available -- migrate!
- qWarning() << "\n\nOld settings detected. Will migrate core settings to the new location...\nNOTE: GUI style settings won't be migrated!\n";
-#ifdef Q_WS_MAC
- QSettings ncs("quassel-irc.org", "Quassel Core");
-#else
- QSettings ncs("Quassel Project", "Quassel Core");
-#endif
- ncs.setValue("Core/CoreState", os.value("Core/CoreState"));
- ncs.setValue("Core/DatabaseSettings", os.value("Core/DatabaseSettings"));
- os.beginGroup("SessionData");
- foreach(QString group, os.childGroups()) {
- ncs.setValue(QString("CoreUser/%1/SessionData/Identities").arg(group), os.value(QString("%1/Identities").arg(group)));
- ncs.setValue(QString("CoreUser/%1/SessionData/Networks").arg(group), os.value(QString("%1/Networks").arg(group)));
- }
- os.endGroup();
-#ifdef Q_WS_MAC
- QSettings ngs("quassel-irc.org", "Quassel Client");
-#else
- QSettings ngs("Quassel Project", "Quassel Client");
-#endif
- os.beginGroup("Accounts");
- foreach(QString key, os.childKeys()) {
- ngs.setValue(QString("Accounts/%1").arg(key), os.value(key));
- }
- foreach(QString group, os.childGroups()) {
- ngs.setValue(QString("Accounts/%1/AccountData").arg(group), os.value(QString("%1/AccountData").arg(group)));
- }
- os.endGroup();
- os.beginGroup("Geometry");
- foreach(QString key, os.childKeys()) {
- ngs.setValue(QString("UI/%1").arg(key), os.value(key));
- }
- os.endGroup();
-
- ncs.sync();
- ngs.sync();
- qWarning() << "Migration successfully finished. You may now delete $HOME/.config/Quassel IRC Development Team/ (on Linux).\n\n";
- }
- }
- // END
-
configured = false;
+ CoreSettings cs;
if(!(configured = initStorage(cs.databaseSettings().toMap()))) {
qWarning("Core is currently not configured!");
}
-
+
connect(&server, SIGNAL(newConnection()), this, SLOT(incomingConnection()));
startListening(cs.port());
guiUser = 0;
// FIXME register new storageProviders here
if(engine == "sqlite" && SqliteStorage::isAvailable()) {
storage = new SqliteStorage(this);
+ connect(storage, SIGNAL(bufferInfoUpdated(UserId, const BufferInfo &)), this, SIGNAL(bufferInfoUpdated(UserId, const BufferInfo &)));
} else {
qWarning() << "Selected StorageBackend is not available:" << dbSettings["Type"].toString();
return configured = false;
return configured = storage->init(dbSettings);
}
-bool Core::initStorage(QVariantMap dbSettings) {
- return initStorage(dbSettings, false);
-}
-
Core::~Core() {
+ // FIXME properly shutdown the sessions
qDeleteAll(sessions);
}
void Core::restoreState() {
+ return;
+ /*
Q_ASSERT(!instance()->sessions.count());
CoreSettings s;
QList<QVariant> users = s.coreState().toList();
QVariantMap m = v.toMap();
if(m.contains("UserId")) {
CoreSession *sess = createSession(m["UserId"].toUInt());
- sess->restoreState(m["State"]);
+ sess->restoreState(m["State"]); // FIXME multithreading
}
}
qDebug() << "...done.";
}
+ */
}
void Core::saveState() {
+ /*
CoreSettings s;
QList<QVariant> users;
foreach(CoreSession *sess, instance()->sessions.values()) {
QVariantMap m;
- m["UserId"] = sess->userId();
+ m["UserId"] = sess->user(); // FIXME multithreading
m["State"] = sess->state();
users << m;
}
s.setCoreState(users);
+ */
+}
+
+/*** Storage Access ***/
+
+NetworkId Core::networkId(UserId user, const QString &network) {
+ QMutexLocker locker(&mutex);
+ return instance()->storage->getNetworkId(user, network);
}
-CoreSession *Core::session(UserId uid) {
- Core *core = instance();
- if(core->sessions.contains(uid)) return core->sessions[uid];
- else return 0;
+BufferInfo Core::bufferInfo(UserId user, const QString &network, const QString &buffer) {
+ //QMutexLocker locker(&mutex);
+ return instance()->storage->getBufferInfo(user, network, buffer);
}
-CoreSession *Core::localSession() {
- Core *core = instance();
- if(core->guiUser && core->sessions.contains(core->guiUser)) return core->sessions[core->guiUser];
- else return 0;
+MsgId Core::storeMessage(const Message &message) {
+ QMutexLocker locker(&mutex);
+ return instance()->storage->logMessage(message);
}
-CoreSession *Core::createSession(UserId uid) {
- Core *core = instance();
- Q_ASSERT(!core->sessions.contains(uid));
- CoreSession *sess = new CoreSession(uid, core->storage);
- core->sessions[uid] = sess;
- return sess;
+QList<Message> Core::requestMsgs(BufferInfo buffer, int lastmsgs, int offset) {
+ QMutexLocker locker(&mutex);
+ return instance()->storage->requestMsgs(buffer, lastmsgs, offset);
+}
+
+QList<Message> Core::requestMsgs(BufferInfo buffer, QDateTime since, int offset) {
+ QMutexLocker locker(&mutex);
+ return instance()->storage->requestMsgs(buffer, since, offset);
+}
+
+QList<Message> Core::requestMsgRange(BufferInfo buffer, int first, int last) {
+ QMutexLocker locker(&mutex);
+ return instance()->storage->requestMsgRange(buffer, first, last);
+}
+
+QList<BufferInfo> Core::requestBuffers(UserId user, QDateTime since) {
+ QMutexLocker locker(&mutex);
+ return instance()->storage->requestBuffers(user, since);
}
+/*** Network Management ***/
+
bool Core::startListening(uint port) {
if(!server.listen(QHostAddress::Any, port)) {
qWarning(QString(QString("Could not open GUI client port %1: %2").arg(port).arg(server.errorString())).toAscii());
QTcpSocket *socket = server.nextPendingConnection();
connect(socket, SIGNAL(disconnected()), this, SLOT(clientDisconnected()));
connect(socket, SIGNAL(readyRead()), this, SLOT(clientHasData()));
- blockSizes.insert(socket, (quint32)0);
- qDebug() << "Client connected from " << socket->peerAddress().toString();
-
+ QVariantMap clientInfo;
+ blocksizes.insert(socket, (quint32)0);
+ qDebug() << "Client connected from" << qPrintable(socket->peerAddress().toString());
+
if (!configured) {
server.close();
qDebug() << "Closing server for basic setup.";
void Core::clientHasData() {
QTcpSocket *socket = dynamic_cast<QTcpSocket*>(sender());
- Q_ASSERT(socket && blockSizes.contains(socket));
- quint32 bsize = blockSizes.value(socket);
+ Q_ASSERT(socket && blocksizes.contains(socket));
QVariant item;
- if(SignalProxy::readDataFromDevice(socket, bsize, item)) {
+ while(SignalProxy::readDataFromDevice(socket, blocksizes[socket], item)) {
+ QVariantMap msg = item.toMap();
+ if(!msg.contains("MsgType")) {
+ // Client is way too old, does not even use the current init format
+ qWarning() << qPrintable(tr("Antique client trying to connect... refusing."));
+ socket->close();
+ return;
+ }
+ // OK, so we have at least an init message format we can understand
+ if(msg["MsgType"] == "ClientInit") {
+ QVariantMap reply;
+ reply["CoreVersion"] = Global::quasselVersion;
+ reply["CoreDate"] = Global::quasselDate;
+ reply["CoreBuild"] = Global::quasselBuild;
+ // TODO: Make the core info configurable
+ int uptime = startTime.secsTo(QDateTime::currentDateTime());
+ int updays = uptime / 86400; uptime %= 86400;
+ int uphours = uptime / 3600; uptime %= 3600;
+ int upmins = uptime / 60;
+ reply["CoreInfo"] = tr("<b>Quassel Core Version %1 (Build >= %2)</b><br>"
+ "Up %3d%4h%5m (since %6)").arg(Global::quasselVersion).arg(Global::quasselBuild)
+ .arg(updays).arg(uphours,2,10,QChar('0')).arg(upmins,2,10,QChar('0')).arg(startTime.toString(Qt::TextDate));
+
+ reply["SupportSsl"] = false;
+ reply["LoginEnabled"] = true;
+ // TODO: check if we are configured, start wizard otherwise
+
+ // Just version information -- check it!
+ if(msg["ClientBuild"].toUInt() < Global::clientBuildNeeded) {
+ reply["MsgType"] = "ClientInitReject";
+ reply["Error"] = tr("<b>Your Quassel Client is too old!</b><br>"
+ "This core needs at least client version %1 (Build >= %2).<br>"
+ "Please consider upgrading your client.").arg(Global::quasselVersion).arg(Global::quasselBuild);
+ SignalProxy::writeDataToDevice(socket, reply);
+ qWarning() << qPrintable(tr("Client %1 too old, rejecting.").arg(socket->peerAddress().toString()));
+ socket->close(); return;
+ }
+ clientInfo[socket] = msg; // store for future reference
+ reply["MsgType"] = "ClientInitAck";
+ SignalProxy::writeDataToDevice(socket, reply);
+ } else if(msg["MsgType"] == "ClientLogin") {
+ QVariantMap reply;
+ if(!clientInfo.contains(socket)) {
+ reply["MsgType"] = "ClientLoginReject";
+ reply["Error"] = tr("<b>Client not initialized!</b><br>You need to send an init message before trying to login.");
+ SignalProxy::writeDataToDevice(socket, reply);
+ qWarning() << qPrintable(tr("Client %1 did not send an init message before trying to login, rejecting.").arg(socket->peerAddress().toString()));
+ socket->close(); return;
+ }
+ mutex.lock();
+ UserId uid = storage->validateUser(msg["User"].toString(), msg["Password"].toString());
+ mutex.unlock();
+ if(!uid) {
+ reply["MsgType"] = "ClientLoginReject";
+ reply["Error"] = tr("<b>Invalid username or password!</b><br>The username/password combination you supplied could not be found in the database.");
+ SignalProxy::writeDataToDevice(socket, reply);
+ continue;
+ }
+ reply["MsgType"] = "ClientLoginAck";
+ SignalProxy::writeDataToDevice(socket, reply);
+ qDebug() << qPrintable(tr("Client %1 initialized and authentificated successfully as \"%2\".").arg(socket->peerAddress().toString(), msg["User"].toString()));
+ setupClientSession(socket, uid);
+ }
+ //socket->close(); return;
+ /*
// we need to auth the client
try {
QVariantMap msg = item.toMap();
qWarning() << "Client init error:" << e.msg();
socket->close();
return;
- }
+ } */
}
- blockSizes[socket] = bsize = 0; // FIXME blockSizes aufr�um0rn!
}
-// FIXME: no longer called, since connection handling is now in SignalProxy
-// No, it is called as long as core is not configured. (kaffeedoktor)
+// Potentially called during the initialization phase (before handing the connection off to the session)
void Core::clientDisconnected() {
QTcpSocket *socket = dynamic_cast<QTcpSocket*>(sender());
- blockSizes.remove(socket);
- qDebug() << "Client disconnected.";
-
- // make server listen again if still not configured
+ blocksizes.remove(socket);
+ clientInfo.remove(socket);
+ qDebug() << qPrintable(tr("Client %1 disconnected.").arg(socket->peerAddress().toString()));
+ socket->deleteLater();
+ socket = 0;
+
+ // make server listen again if still not configured FIXME
if (!configured) {
startListening();
}
-
- // TODO remove unneeded sessions - if necessary/possible...
-}
-
-QVariant Core::connectLocalClient(QString user, QString passwd) {
- UserId uid = instance()->storage->validateUser(user, passwd);
- QVariant reply = instance()->initSession(uid);
- instance()->guiUser = uid;
- qDebug() << "Local client connected.";
- return reply;
-}
-void Core::disconnectLocalClient() {
- qDebug() << "Local client disconnected.";
- instance()->guiUser = 0;
+ // TODO remove unneeded sessions - if necessary/possible...
+ // Suggestion: kill sessions if they are not connected to any network and client.
}
-void Core::processClientInit(QTcpSocket *socket, const QVariantMap &msg) {
- // Auth
- QVariantMap reply;
- UserId uid = storage->validateUser(msg["User"].toString(), msg["Password"].toString()); // throws exception if this failed
- reply["StartWizard"] = false;
- reply["Reply"] = initSession(uid);
- disconnect(socket, 0, this, 0);
- sessions[uid]->addClient(socket);
+
+ //disconnect(socket, 0, this, 0);
+ /*
+ sessions[uid]->addClient(socket); // FIXME multithreading
qDebug() << "Client initialized successfully.";
SignalProxy::writeDataToDevice(socket, reply);
-}
+ */
+
void Core::processCoreSetup(QTcpSocket *socket, QVariantMap &msg) {
if(msg["HasSettings"].toBool()) {
storage->addUser(auth["User"].toString(), auth["Password"].toString());
startListening();
// continue the normal procedure
- processClientInit(socket, auth);
+ //processClientInit(socket, auth);
}
} else {
// notify client to start wizard
}
}
-QVariant Core::initSession(UserId uid) {
+void Core::setupClientSession(QTcpSocket *socket, UserId uid) {
// Find or create session for validated user
- CoreSession *sess;
- if(sessions.contains(uid))
- sess = sessions[uid];
- else
- sess = createSession(uid);
- QVariantMap reply;
- reply["SessionState"] = sess->sessionState();
- return reply;
+ SessionThread *sess;
+ if(sessions.contains(uid)) sess = sessions[uid];
+ else sess = createSession(uid);
+ // Hand over socket, session then sends state itself
+ disconnect(socket, 0, this, 0);
+ if(!sess) {
+ qWarning() << qPrintable(tr("Could not initialize session for client %1!").arg(socket->peerAddress().toString()));
+ socket->close();
+ }
+ sess->addClient(socket);
+}
+
+SessionThread *Core::createSession(UserId uid) {
+ if(sessions.contains(uid)) {
+ qWarning() << "Calling createSession() when a session for the user already exists!";
+ return 0;
+ }
+ SessionThread *sess = new SessionThread(uid, this);
+ sessions[uid] = sess;
+ sess->start();
+ return sess;
}
QStringList Core::availableStorageProviders() {
#ifndef _CORE_H_
#define _CORE_H_
+#include <QDateTime>
+#include <QMutex>
#include <QString>
#include <QVariant>
#include <QTcpServer>
#include <QTcpSocket>
+#include "bufferinfo.h"
+#include "message.h"
#include "global.h"
+#include "sessionthread.h"
#include "types.h"
class CoreSession;
+class SessionThread;
class Storage;
class Core : public QObject {
static Core * instance();
static void destroy();
- static CoreSession * session(UserId);
- static CoreSession * localSession();
- static CoreSession * createSession(UserId);
-
- static QVariant connectLocalClient(QString user, QString passwd);
- static void disconnectLocalClient();
-
static void saveState();
static void restoreState();
+ /*** Storage access ***/
+ // These methods are threadsafe.
+
+ //! Get the NetworkId for a network name.
+ /** \note This method is threadsafe.
+ *
+ * \param user The core user
+ * \param network The name of the network
+ * \return The NetworkId corresponding to the given network.
+ */
+ static NetworkId networkId(UserId user, const QString &network);
+
+ //! Get the unique BufferInfo for the given combination of network and buffername for a user.
+ /** \note This method is threadsafe.
+ *
+ * \param user The core user who owns this buffername
+ * \param network The network name
+ * \param buffer The buffer name (if empty, the net's status buffer is returned)
+ * \return The BufferInfo corresponding to the given network and buffer name, or 0 if not found
+ */
+ static BufferInfo bufferInfo(UserId user, const QString &network, const QString &buffer = "");
+
+ //! Store a Message in the backlog.
+ /** \note This method is threadsafe.
+ *
+ * \param msg The message object to be stored
+ * \return The globally unique id for the stored message
+ */
+ static MsgId storeMessage(const Message &message);
+
+ //! Request a certain number (or all) messages stored in a given buffer.
+ /** \note This method is threadsafe.
+ *
+ * \param buffer The buffer we request messages from
+ * \param lastmsgs The number of messages we would like to receive, or -1 if we'd like all messages from that buffername
+ * \param offset Do not return (but DO count) messages with MsgId >= offset, if offset >= 0
+ * \return The requested list of messages
+ */
+ static QList<Message> requestMsgs(BufferInfo buffer, int lastmsgs = -1, int offset = -1);
+
+ //! Request messages stored in a given buffer since a certain point in time.
+ /** \note This method is threadsafe.
+ *
+ * \param buffer The buffer we request messages from
+ * \param since Only return messages newer than this point in time
+ * \param offset Do not return messages with MsgId >= offset, if offset >= 0
+ * \return The requested list of messages
+ */
+ static QList<Message> requestMsgs(BufferInfo buffer, QDateTime since, int offset = -1);
+
+ //! Request a range of messages stored in a given buffer.
+ /** \note This method is threadsafe.
+ *
+ * \param buffer The buffer we request messages from
+ * \param first Return messages with first <= MsgId <= last
+ * \param last Return messages with first <= MsgId <= last
+ * \return The requested list of messages
+ */
+ static QList<Message> requestMsgRange(BufferInfo buffer, int first, int last);
+
+ //! Request a list of all buffers known to a user since a certain point in time.
+ /** This method is used to get a list of all buffers we have stored a backlog from.
+ * Optionally, a QDateTime can be given, so that only buffers are listed that were active
+ * since that point in time.
+ * \note This method is threadsafe.
+ *
+ * \param user The user whose buffers we request
+ * \param since If this is defined, older buffers will be ignored
+ * \return A list of the BufferInfos for all buffers as requested
+ */
+ static QList<BufferInfo> requestBuffers(UserId user, QDateTime since = QDateTime());
+
+ signals:
+ //! Sent when a BufferInfo is updated in storage.
+ void bufferInfoUpdated(UserId user, const BufferInfo &info);
+
private slots:
bool startListening(uint port = Global::defaultPort);
void stopListening();
void clientHasData();
void clientDisconnected();
- bool initStorage(QVariantMap dbSettings, bool setup);
- bool initStorage(QVariantMap dbSettings);
+ bool initStorage(QVariantMap dbSettings, bool setup = false);
private:
Core();
~Core();
void init();
static Core *instanceptr;
-
- //! Initiate a session for the user with the given credentials if one does not already exist.
- /** This function is called during the init process for a new client. If there is no session for the
- * given user, one is created.
- * \param userId The user
- * \return A QVariant containing the session data, e.g. global data and buffers
- */
- QVariant initSession(UserId userId);
- void processClientInit(QTcpSocket *socket, const QVariantMap &msg);
+
+ SessionThread *createSession(UserId userId);
+ void setupClientSession(QTcpSocket *socket, UserId uid);
void processCoreSetup(QTcpSocket *socket, QVariantMap &msg);
-
+
QStringList availableStorageProviders();
UserId guiUser;
- QHash<UserId, CoreSession *> sessions;
+ QHash<UserId, SessionThread *> sessions;
Storage *storage;
QTcpServer server; // TODO: implement SSL
- QHash<QTcpSocket *, quint32> blockSizes;
-
+ QHash<QTcpSocket *, quint32> blocksizes;
+ QHash<QTcpSocket *, QVariantMap> clientInfo;
+
+ QDateTime startTime;
+
bool configured;
+
+ static QMutex mutex;
};
#endif
DEPMOD = common
QT_MOD = core network sql script
SRCS = core.cpp coresession.cpp coresettings.cpp networkconnection.cpp sqlitestorage.cpp abstractsqlstorage.cpp storage.cpp basichandler.cpp \
- ircserverhandler.cpp userinputhandler.cpp ctcphandler.cpp coreusersettings.cpp
+ ircserverhandler.cpp userinputhandler.cpp ctcphandler.cpp coreusersettings.cpp sessionthread.cpp
HDRS = core.h coresession.h coresettings.h networkconnection.h sqlitestorage.h abstractsqlstorage.h storage.h basichandler.h \
- ircserverhandler.h userinputhandler.h ctcphandler.h coreusersettings.h
+ ircserverhandler.h userinputhandler.h ctcphandler.h coreusersettings.h sessionthread.h
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
+#include "core.h"
#include "coresession.h"
#include "networkconnection.h"
#include <QtScript>
-CoreSession::CoreSession(UserId uid, Storage *_storage, QObject *parent)
- : QObject(parent),
- user(uid),
+CoreSession::CoreSession(UserId uid, QObject *parent) : QObject(parent),
+ _user(uid),
_signalProxy(new SignalProxy(SignalProxy::Server, 0, this)),
- storage(_storage),
scriptEngine(new QScriptEngine(this))
{
SignalProxy *p = signalProxy();
- CoreUserSettings s(user);
+ CoreUserSettings s(user());
sessionData = s.sessionData();
foreach(IdentityId id, s.identityIds()) {
createIdentity(i);
}
- p->attachSlot(SIGNAL(requestNetworkStates()), this, SLOT(networkStateRequested()));
+ //p->attachSlot(SIGNAL(requestNetworkStates()), this, SLOT(networkStateRequested()));
p->attachSlot(SIGNAL(requestConnect(QString)), this, SLOT(connectToNetwork(QString)));
- p->attachSlot(SIGNAL(sendInput(BufferInfo, QString)), this, SLOT(msgFromGui(BufferInfo, QString)));
+ p->attachSlot(SIGNAL(sendInput(BufferInfo, QString)), this, SLOT(msgFromClient(BufferInfo, QString)));
p->attachSlot(SIGNAL(requestBacklog(BufferInfo, QVariant, QVariant)), this, SLOT(sendBacklog(BufferInfo, QVariant, QVariant)));
p->attachSignal(this, SIGNAL(displayMsg(Message)));
p->attachSignal(this, SIGNAL(displayStatusMsg(QString, QString)));
p->attachSignal(this, SIGNAL(backlogData(BufferInfo, QVariantList, bool)));
p->attachSignal(this, SIGNAL(bufferInfoUpdated(BufferInfo)));
- p->attachSignal(storage, SIGNAL(bufferInfoUpdated(BufferInfo)));
+
p->attachSignal(this, SIGNAL(sessionDataChanged(const QString &, const QVariant &)), SIGNAL(coreSessionDataChanged(const QString &, const QVariant &)));
p->attachSlot(SIGNAL(clientSessionDataChanged(const QString &, const QVariant &)), this, SLOT(storeSessionData(const QString &, const QVariant &)));
foreach(Identity *id, _identities.values()) {
p->synchronize(id);
}
+
+ // 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<QVariantMap> slist;
+ foreach(QVariant v, network["Servers"].toList()) slist << v.toMap();
+ net->setServerList(slist);
+ net->setProxy(p);
+ _networks[netid] = net;
+ p->synchronize(net);
+ }
+
+ emit initialized();
}
CoreSession::~CoreSession() {
}
-UserId CoreSession::userId() const {
- return user;
+UserId CoreSession::user() const {
+ return _user;
+}
+
+Network *CoreSession::network(NetworkId id) const {
+ if(_networks.contains(id)) return _networks[id];
+ return 0;
+}
+
+NetworkConnection *CoreSession::networkConnection(NetworkId id) const {
+ if(_connections.contains(id)) return _connections[id];
+ return 0;
+}
+
+Identity *CoreSession::identity(IdentityId id) const {
+ if(_identities.contains(id)) return _identities[id];
+ return 0;
}
-QVariant CoreSession::state() const {
+QVariant CoreSession::state() const { // FIXME
QVariantMap res;
+ /*
QList<QVariant> conn;
foreach(NetworkConnection *net, connections.values()) {
if(net->isConnected()) {
}
}
res["ConnectedServers"] = conn;
+ */
return res;
}
-void CoreSession::restoreState(const QVariant &previousState) {
+void CoreSession::restoreState(const QVariant &previousState) { // FIXME
// Session restore
+ /*
QVariantMap state = previousState.toMap();
if(state.contains("ConnectedServers")) {
foreach(QVariant v, state["ConnectedServers"].toList()) {
if(!net.isEmpty()) connectToNetwork(net, m["State"]);
}
}
+ */
}
void CoreSession::storeSessionData(const QString &key, const QVariant &data) {
- CoreUserSettings s(user);
- mutex.lock();
+ CoreUserSettings s(user());
s.setSessionValue(key, data);
sessionData[key] = data;
- mutex.unlock();
emit sessionDataChanged(key, data);
emit sessionDataChanged(key);
}
QVariant CoreSession::retrieveSessionData(const QString &key, const QVariant &def) {
QVariant data;
- mutex.lock();
if(!sessionData.contains(key)) data = def;
else data = sessionData[key];
- mutex.unlock();
return data;
}
-// FIXME switch to NetworkIDs
-void CoreSession::connectToNetwork(QString networkname, const QVariant &previousState) {
- uint networkid = getNetworkId(networkname);
- if(networkid == 0) {
- qWarning() << "unable to connect to Network" << networkname << "(User:" << userId() << "): unable to determine NetworkId";
+void CoreSession::updateBufferInfo(UserId uid, const BufferInfo &bufinfo) {
+ if(uid == user()) emit bufferInfoUpdated(bufinfo);
+}
+
+// FIXME remove
+void CoreSession::connectToNetwork(QString netname, const QVariant &previousState) {
+ Network *net = 0;
+ foreach(Network *n, _networks.values()) {
+ if(n->networkName() == netname) {
+ net = n; break;
+ }
+ }
+ if(!net) {
+ qWarning() << "Connect to unknown network requested, ignoring!";
+ return;
+ }
+ connectToNetwork(net->networkId(), previousState);
+}
+
+void CoreSession::connectToNetwork(NetworkId id, const QVariant &previousState) {
+ Network *net = network(id);
+ if(!net) {
+ qWarning() << "Connect to unknown network requested! net:" << id << "user:" << user();
return;
}
- if(!connections.contains(networkid)) {
- NetworkConnection *connection = new NetworkConnection(userId(), networkid, networkname, previousState);
- connections[networkid] = connection;
- attachNetworkConnection(connection);
- connection->start();
+
+ NetworkConnection *conn = networkConnection(id);
+ if(!conn) {
+ conn = new NetworkConnection(net, this, previousState);
+ _connections[id] = conn;
+ attachNetworkConnection(conn);
+ conn->connectToIrc();
}
- emit connectToIrc(networkname);
}
-void CoreSession::attachNetworkConnection(NetworkConnection *network) {
- 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(network, SIGNAL(connected(uint)), this, SLOT(networkConnected(uint)));
- connect(network, SIGNAL(disconnected(uint)), this, SLOT(networkDisconnected(uint)));
- connect(network, SIGNAL(displayMsg(Message::Type, QString, QString, QString, quint8)), this, SLOT(recvMessageFromServer(Message::Type, QString, QString, QString, quint8)));
- connect(network, SIGNAL(displayStatusMsg(QString)), this, SLOT(recvStatusMsgFromServer(QString)));
-
- // connect serversignals to proxy
- signalProxy()->attachSignal(network, SIGNAL(networkState(QString, QVariantMap)), SIGNAL(networkState(QString, QVariantMap)));
- signalProxy()->attachSignal(network, SIGNAL(connected(uint)), SIGNAL(networkConnected(uint)));
- signalProxy()->attachSignal(network, SIGNAL(disconnected(uint)), SIGNAL(networkDisconnected(uint)));
+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)));
+
+ 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::networkStateRequested() {
}
-void CoreSession::addClient(QIODevice *device) {
- signalProxy()->addPeer(device);
+void CoreSession::addClient(QObject *dev) { // this is QObject* so we can use it in signal connections
+ QIODevice *device = qobject_cast<QIODevice *>(dev);
+ if(!device) {
+ qWarning() << "Invoking CoreSession::addClient with a QObject that is not a QIODevice!";
+ } else {
+ signalProxy()->addPeer(device);
+ QVariantMap reply;
+ reply["MsgType"] = "SessionInit";
+ reply["SessionState"] = sessionState();
+ SignalProxy::writeDataToDevice(device, reply);
+ }
}
SignalProxy *CoreSession::signalProxy() const {
}
void CoreSession::networkConnected(uint networkid) {
- storage->getBufferInfo(userId(), connections[networkid]->networkName()); // create status buffer
+ Core::bufferInfo(user(), networkConnection(networkid)->networkName()); // create status buffer
}
void CoreSession::networkDisconnected(uint networkid) {
- Q_ASSERT(connections.contains(networkid));
- connections.take(networkid)->deleteLater();
- Q_ASSERT(!connections.contains(networkid));
+ // FIXME
+ // connection should only go away on explicit /part, and handle reconnections etcpp internally otherwise
+ Q_ASSERT(_connections.contains(networkid));
+ _connections.take(networkid)->deleteLater();
+ Q_ASSERT(!_connections.contains(networkid));
}
-void CoreSession::msgFromGui(BufferInfo bufid, QString msg) {
- emit msgFromGui(bufid.networkId(), bufid.buffer(), msg);
+// FIXME switch to BufferId
+void CoreSession::msgFromClient(BufferInfo bufinfo, QString msg) {
+ NetworkConnection *conn = networkConnection(bufinfo.networkId());
+ if(conn) {
+ conn->userInput(bufinfo.buffer(), msg);
+ } else {
+ qWarning() << "Trying to send to unconnected network!";
+ }
}
// ALL messages coming pass through these functions before going to the GUI.
Q_ASSERT(s);
BufferInfo buf;
if((flags & Message::PrivMsg) && !(flags & Message::Self)) {
- buf = storage->getBufferInfo(user, s->networkName(), nickFromMask(sender));
+ buf = Core::bufferInfo(user(), s->networkName(), nickFromMask(sender));
} else {
- buf = storage->getBufferInfo(user, s->networkName(), target);
+ buf = Core::bufferInfo(user(), s->networkName(), target);
}
Message msg(buf, type, text, sender, flags);
- msg.setMsgId(storage->logMessage(msg));
+ msg.setMsgId(Core::storeMessage(msg));
Q_ASSERT(msg.msgId());
emit displayMsg(msg);
}
emit displayStatusMsg(s->networkName(), msg);
}
-
-uint CoreSession::getNetworkId(const QString &net) const {
- return storage->getNetworkId(user, net);
-}
-
QList<BufferInfo> CoreSession::buffers() const {
- return storage->requestBuffers(user);
+ return Core::requestBuffers(user());
}
QVariantMap v;
QVariantList bufs;
- foreach(BufferInfo id, storage->requestBuffers(user))
- bufs.append(QVariant::fromValue(id));
- v["Buffers"] = bufs;
-
- mutex.lock();
- v["SessionData"] = sessionData;
- mutex.unlock();
-
- QVariantList networks;
- foreach(NetworkId networkid, connections.keys())
- networks.append(QVariant(networkid));
- v["Networks"] = QVariant(networks);
+ foreach(BufferInfo id, buffers()) bufs << QVariant::fromValue(id);
+ v["BufferInfos"] = bufs;
+ QVariantList networkids;
+ foreach(NetworkId id, _networks.keys()) networkids << QVariant::fromValue(id);
+ v["NetworkIds"] = networkids;
+
+ quint32 ircusercount = 0;
+ quint32 ircchannelcount = 0;
+ foreach(Network *net, _networks.values()) {
+ ircusercount += net->ircUserCount();
+ ircchannelcount += net->ircChannelCount();
+ }
+ v["IrcUserCount"] = ircusercount;
+ v["IrcChannelCount"] = ircchannelcount;
+ qDebug() << "nets:" << _networks.count() << " chans:" << ircchannelcount << " users:" << ircusercount;
QList<QVariant> idlist;
foreach(Identity *i, _identities.values()) idlist << QVariant::fromValue<Identity>(*i);
v["Identities"] = idlist;
- // v["Payload"] = QByteArray(100000000, 'a'); // for testing purposes
+ v["SessionData"] = sessionData;
+
+ //v["Payload"] = QByteArray(100000000, 'a'); // for testing purposes
return v;
}
} else {
- msglist = storage->requestMsgs(id, v1.toInt(), v2.toInt());
+ msglist = Core::requestMsgs(id, v1.toInt(), v2.toInt());
}
// Send messages out in smaller packages - we don't want to make the signal data too large!
void CoreSession::initScriptEngine() {
signalProxy()->attachSlot(SIGNAL(scriptRequest(QString)), this, SLOT(scriptRequest(QString)));
signalProxy()->attachSignal(this, SIGNAL(scriptResult(QString)));
-
- QScriptValue storage_ = scriptEngine->newQObject(storage);
- scriptEngine->globalObject().setProperty("storage", storage_);
+
+ // FIXME
+ //QScriptValue storage_ = scriptEngine->newQObject(storage);
+ //scriptEngine->globalObject().setProperty("storage", storage_);
}
void CoreSession::scriptRequest(QString script) {
newId->setId(i);
_identities[i] = newId;
signalProxy()->synchronize(newId);
- CoreUserSettings s(user);
+ CoreUserSettings s(user());
s.storeIdentity(*newId);
emit identityCreated(*newId);
}
}
_identities[id.id()]->update(id);
- CoreUserSettings s(user);
+ CoreUserSettings s(user());
s.storeIdentity(id);
}
Identity *i = _identities.take(id);
if(i) {
emit identityRemoved(id);
- CoreUserSettings s(user);
+ CoreUserSettings s(user());
s.removeIdentity(id);
i->deleteLater();
}
#ifndef _CORESESSION_H_
#define _CORESESSION_H_
-#include <QObject>
#include <QString>
#include <QVariant>
#include "message.h"
class Identity;
-class NetworkConnection;
+class NetworkConnection; // FIXME get rid of
+class Network;
class SignalProxy;
-class Storage;
class QScriptEngine;
Q_OBJECT
public:
- CoreSession(UserId, Storage *, QObject *parent = 0);
- virtual ~CoreSession();
+ CoreSession(UserId, QObject *parent = 0);
+ ~CoreSession();
- NetworkId getNetworkId(const QString &network) const;
QList<BufferInfo> buffers() const;
- UserId userId() const;
+ UserId user() const;
+ Network *network(NetworkId) const;
+ NetworkConnection *networkConnection(NetworkId) const;
+ Identity *identity(IdentityId) const;
+
QVariant sessionState();
//! Retrieve a piece of session-wide data.
void networkStateRequested();
- void addClient(QIODevice *connection);
+ void addClient(QObject *socket);
void connectToNetwork(QString, const QVariant &previousState = QVariant());
- //void connectToNetwork(NetworkId);
+ void connectToNetwork(NetworkId, const QVariant &previousState = QVariant());
//void processSignal(ClientSignal, QVariant, QVariant, QVariant);
void sendBacklog(BufferInfo, QVariant, QVariant);
- void msgFromGui(BufferInfo, QString message);
+ void msgFromClient(BufferInfo, QString message);
//! Create an identity and propagate the changes to the clients.
/** \param identity The identity to be created.
void removeIdentity(IdentityId identity);
signals:
- void msgFromGui(uint netid, QString buf, QString message);
+ void initialized();
+
+ //void msgFromGui(uint netid, QString buf, QString message);
void displayMsg(Message message);
void displayStatusMsg(QString, QString);
- void connectToIrc(QString net);
- void disconnectFromIrc(QString net);
+ //void connectToIrc(QString net);
+ //void disconnectFromIrc(QString net);
void backlogData(BufferInfo, QVariantList, bool done);
void networkConnected(uint networkid);
void networkDisconnected(uint networkid);
+ //! Called when storage updated a BufferInfo.
+ /** This emits bufferInfoUpdated() via SignalProxy, iff it's one of our buffers.
+ * \param user The buffer's owner (not necessarily us)
+ * \param bufferInfo The updated BufferInfo
+ */
+ void updateBufferInfo(UserId user, const BufferInfo &bufferInfo);
+
void scriptRequest(QString script);
-
+
private:
void initScriptEngine();
-
- UserId user;
-
+
+ UserId _user;
+
SignalProxy *_signalProxy;
- Storage *storage;
- QHash<NetworkId, NetworkConnection *> connections;
-
+ QHash<NetworkId, NetworkConnection *> _connections;
+ QHash<NetworkId, Network *> _networks;
+ QHash<IdentityId, Identity *> _identities;
+
QVariantMap sessionData;
- QMutex mutex;
QScriptEngine *scriptEngine;
- QHash<IdentityId, Identity *> _identities;
};
#endif
Q_OBJECT
public:
- IrcServerHandler(NetworkConnection *parent = 0);
+ IrcServerHandler(NetworkConnection *parent);
~IrcServerHandler();
void handleServerMsg(QByteArray rawMsg);
#include "ircuser.h"
#include "network.h"
+#include "identity.h"
#include "ircserverhandler.h"
#include "userinputhandler.h"
#include "ctcphandler.h"
-NetworkConnection::NetworkConnection(UserId uid, NetworkId networkId, QString net, const QVariant &state)
- : _userId(uid),
- _networkId(networkId),
+NetworkConnection::NetworkConnection(Network *network, CoreSession *session, const QVariant &state) : QObject(network),
+ _network(network),
+ _coreSession(session),
_ircServerHandler(new IrcServerHandler(this)),
_userInputHandler(new UserInputHandler(this)),
_ctcpHandler(new CtcpHandler(this)),
- _network(new Network(networkId, this)),
_previousState(state)
{
- connect(network(), SIGNAL(currentServerSet(const QString &)), this, SLOT(sendPerform()));
- network()->setCodecForEncoding("ISO-8859-15"); // FIXME
- network()->setCodecForDecoding("ISO-8859-15"); // FIXME
- network()->setNetworkName(net);
- network()->setProxy(coreSession()->signalProxy());
+ connect(network, SIGNAL(currentServerSet(const QString &)), this, SLOT(sendPerform()));
+
+ connect(&socket, SIGNAL(connected()), this, SLOT(socketConnected()));
+ connect(&socket, SIGNAL(disconnected()), this, SLOT(quit()));
+ connect(&socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError)));
+ connect(&socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(socketStateChanged(QAbstractSocket::SocketState)));
+ connect(&socket, SIGNAL(readyRead()), this, SLOT(socketHasData()));
+
}
NetworkConnection::~NetworkConnection() {
delete _ctcpHandler;
}
-void NetworkConnection::run() {
- connect(&socket, SIGNAL(connected()), this, SLOT(socketConnected()));
- connect(&socket, SIGNAL(disconnected()), this, SLOT(quit()));
- connect(&socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError)));
- connect(&socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(socketStateChanged(QAbstractSocket::SocketState)));
- connect(&socket, SIGNAL(readyRead()), this, SLOT(socketHasData()));
- connect(this, SIGNAL(finished()), this, SLOT(threadFinished()));
+bool NetworkConnection::isConnected() const {
+ return socket.state() == QAbstractSocket::ConnectedState;
+}
+
+uint NetworkConnection::networkId() const {
+ return network()->networkId();
+}
+
+QString NetworkConnection::networkName() const {
+ return network()->networkName();
+}
+
+Network *NetworkConnection::network() const {
+ return _network;
+}
- exec();
+CoreSession *NetworkConnection::coreSession() const {
+ return _coreSession;
+}
+
+IrcServerHandler *NetworkConnection::ircServerHandler() const {
+ return _ircServerHandler;
+}
+
+UserInputHandler *NetworkConnection::userInputHandler() const {
+ return _userInputHandler;
+}
+
+CtcpHandler *NetworkConnection::ctcpHandler() const {
+ return _ctcpHandler;
}
QString NetworkConnection::serverDecode(const QByteArray &string) const {
}
-void NetworkConnection::connectToIrc(QString net) {
- if(net != networkName())
- return; // not me!
-
- CoreSession *sess = coreSession();
- networkSettings = sess->retrieveSessionData("Networks").toMap()[net].toMap();
- identity = sess->retrieveSessionData("Identities").toMap()[networkSettings["Identity"].toString()].toMap();
-
- //FIXME this will result in a pretty fuckup if there are no servers in the list
- QList<QVariant> servers = networkSettings["Servers"].toList();
- QString host = servers[0].toMap()["Address"].toString();
- quint16 port = servers[0].toMap()["Port"].toUInt();
+void NetworkConnection::connectToIrc() {
+ QList<QVariantMap> serverList = network()->serverList();
+ Identity *identity = coreSession()->identity(network()->identity());
+ if(!serverList.count()) {
+ qWarning() << "Server list empty, ignoring connect request!";
+ return;
+ }
+ if(!identity) {
+ qWarning() << "Invalid identity configures, ignoring connect request!";
+ return;
+ }
+
+ // TODO implement cycling / random servers
+ QString host = serverList[0]["Address"].toString();
+ quint16 port = serverList[0]["Port"].toUInt();
displayStatusMsg(QString("Connecting to %1:%2...").arg(host).arg(port));
socket.connectToHost(host, port);
}
_previousState = QVariant();
}
-QVariant NetworkConnection::state() {
+QVariant NetworkConnection::state() const {
IrcUser *me = network()->ircUser(network()->myNick());
if(!me) return QVariant(); // this shouldn't really happen, I guess
return me->channels();
}
-void NetworkConnection::disconnectFromIrc(QString net) {
- if(net != networkName())
- return; // not me!
+void NetworkConnection::disconnectFromIrc() {
socket.disconnectFromHost();
}
}
void NetworkConnection::socketError( QAbstractSocket::SocketError err ) {
- //qDebug() << "Socket Error!";
+ qDebug() << "Socket Error!";
}
void NetworkConnection::socketConnected() {
emit connected(networkId());
- putRawLine(QString("NICK :%1").arg(identity["NickList"].toStringList()[0])); // FIXME: try more nicks if error occurs
- putRawLine(QString("USER %1 8 * :%2").arg(identity["Ident"].toString()).arg(identity["RealName"].toString()));
-}
-
-void NetworkConnection::threadFinished() {
- // the Socket::disconnected() is connect to this::quit()
- // so after the event loop is finished we're beeing called
- // and propagate the disconnect
- emit disconnected(networkId());
+ Identity *identity = coreSession()->identity(network()->identity());
+ if(!identity) {
+ qWarning() << "Identity invalid!";
+ disconnectFromIrc();
+ return;
+ }
+ putRawLine(QString("NICK :%1").arg(identity->nicks()[0])); // FIXME: try more nicks if error occurs
+ putRawLine(QString("USER %1 8 * :%2").arg(identity->ident(), identity->realName()));
}
void NetworkConnection::socketStateChanged(QAbstractSocket::SocketState state) {
//qDebug() << "Socket state changed: " << state;
}
-void NetworkConnection::userInput(uint netid, QString buf, QString msg) {
- if(netid != networkId())
- return; // not me!
+// FIXME switch to BufferId
+void NetworkConnection::userInput(QString buf, QString msg) {
userInputHandler()->handleUserInput(buf, msg);
}
putRawLine(msg);
}
-
-uint NetworkConnection::networkId() const {
- return _networkId;
-}
-
-QString NetworkConnection::networkName() const {
- return network()->networkName();
-}
-
-CoreSession *NetworkConnection::coreSession() const {
- return Core::session(userId());
-}
-
/* Exception classes for message handling */
NetworkConnection::ParseError::ParseError(QString cmd, QString prefix, QStringList params) {
Q_UNUSED(prefix);
#include <QString>
#include <QStringList>
#include <QTcpSocket>
-#include <QThread>
#include <QTimer>
#include "message.h"
#include "signalproxy.h"
+class CoreSession;
class Network;
class IrcServerHandler;
class UserInputHandler;
class CtcpHandler;
-class CoreSession;
-/*!
- * This is a server object, managing a single connection to an IRC server, handling the associated channels and so on.
- * We have this running in its own thread mainly to not block other server objects or the core if something goes wrong,
- * e.g. if some scripts starts running wild...
- */
-
-class NetworkConnection : public QThread {
+class NetworkConnection : public QObject {
Q_OBJECT
public:
- NetworkConnection(UserId uid, NetworkId networkId, QString network, const QVariant &previousState = QVariant());
+ NetworkConnection(Network *network, CoreSession *session, const QVariant &previousState = QVariant());
~NetworkConnection();
- UserId userId() const { return _userId; }
-
- // networkState state();
- bool isConnected() const { return socket.state() == QAbstractSocket::ConnectedState; }
-
NetworkId networkId() const;
- QString networkName() const; // hasbeen getNetwork()
+ QString networkName() const;
+ Network *network() const;
+ CoreSession *coreSession() const;
+
+ bool isConnected() const;
- Network *network() const { return _network; }
- IrcServerHandler *ircServerHandler() const { return _ircServerHandler; }
- UserInputHandler *userInputHandler() const { return _userInputHandler; }
- CtcpHandler *ctcpHandler() const { return _ctcpHandler; }
+ IrcServerHandler *ircServerHandler() const;
+ UserInputHandler *userInputHandler() const;
+ CtcpHandler *ctcpHandler() const;
- QVariant state(); ///< Return data necessary to restore the server's state upon core restart
+ //! Return data necessary to restore the connection state upon core restart
+ QVariant state() const;
//! Decode a string using the server (network) decoding.
QString serverDecode(const QByteArray &string) const;
public slots:
// void setServerOptions();
- void connectToIrc(QString net);
- void disconnectFromIrc(QString net);
- void userInput(uint netid, QString buffer, QString msg);
+ void connectToIrc();
+ void disconnectFromIrc();
+ void userInput(QString buffer, QString msg);
void putRawLine(QString input);
void putCmd(QString cmd, QStringList params, QString prefix = 0);
private slots:
- void threadFinished();
void sendPerform();
signals:
- void networkState(QString net, QVariantMap data);
+ // #void networkState(QString net, QVariantMap data);
void recvRawServerMsg(QString);
void displayStatusMsg(QString);
//void displayMsg(Message msg);
void displayMsg(Message::Type, QString target, QString text, QString sender = "", quint8 flags = Message::None);
- void connected(uint networkId);
- void disconnected(uint networkId);
+ void connected(NetworkId networkId);
+ void disconnected(NetworkId networkId);
void connectionInitialized(); ///< Emitted after receipt of 001 to indicate that we can now send data to the IRC server
- void synchronizeClients();
-
- void queryRequested(QString network, QString nick);
+ //void queryRequested(QString network, QString nick);
private slots:
- void run();
void socketHasData();
void socketError(QAbstractSocket::SocketError);
void socketConnected();
void socketStateChanged(QAbstractSocket::SocketState);
private:
- UserId _userId;
- NetworkId _networkId;
-
QTcpSocket socket;
+ Network *_network;
+ CoreSession *_coreSession;
+
IrcServerHandler *_ircServerHandler;
UserInputHandler *_userInputHandler;
CtcpHandler *_ctcpHandler;
- Network *_network;
-
QVariantMap networkSettings;
QVariantMap identity;
QVariant _previousState;
- CoreSession *coreSession() const;
-
class ParseError : public Exception {
public:
ParseError(QString cmd, QString prefix, QStringList params);
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005-08 by the Quassel IRC Team *
+ * devel@quassel-irc.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) version 3. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include <QMutexLocker>
+
+#include "sessionthread.h"
+
+#include "coresession.h"
+
+SessionThread::SessionThread(UserId uid, QObject *parent) : QThread(parent) {
+ _user = uid;
+ _session = 0;
+ _sessionInitialized = false;
+ connect(this, SIGNAL(initialized()), this, SLOT(setSessionInitialized()));
+}
+
+SessionThread::~SessionThread() {
+ // FIXME
+ quit();
+ wait();
+ if(session()) _session->deleteLater();
+}
+
+CoreSession *SessionThread::session() {
+ return _session;
+}
+
+UserId SessionThread::user() {
+ return _user;
+}
+
+bool SessionThread::isSessionInitialized() {
+ return _sessionInitialized;
+}
+
+void SessionThread::setSessionInitialized() {
+ _sessionInitialized = true;
+ foreach(QIODevice *socket, clientQueue) {
+ addClientToSession(socket);
+ }
+ clientQueue.clear();
+}
+
+void SessionThread::addClient(QIODevice *socket) {
+ if(isSessionInitialized()) {
+ addClientToSession(socket);
+ } else {
+ clientQueue.append(socket);
+ }
+}
+
+void SessionThread::addClientToSession(QIODevice *socket) {
+ socket->setParent(0);
+ socket->moveToThread(session()->thread());
+ if(!QMetaObject::invokeMethod(session(), "addClient", Q_ARG(QObject *, socket))) {
+ qWarning() << qPrintable(tr("Could not initialize session!"));
+ socket->close();
+ }
+}
+
+void SessionThread::run() {
+ _session = new CoreSession(user());
+ emit initialized();
+ exec();
+}
+
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005-08 by the Quassel IRC Team *
+ * devel@quassel-irc.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) version 3. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#ifndef _SESSIONTHREAD_H_
+#define _SESSIONTHREAD_H_
+
+#include <QMutex>
+#include <QThread>
+
+#include "types.h"
+
+class CoreSession;
+class QIODevice;
+
+class SessionThread : public QThread {
+ Q_OBJECT
+
+ public:
+ SessionThread(UserId user, QObject *parent = 0);
+ ~SessionThread();
+
+ void run();
+
+ CoreSession *session();
+ UserId user();
+
+ public slots:
+ void addClient(QIODevice *socket);
+
+ private slots:
+ void setSessionInitialized();
+
+ signals:
+ void initialized();
+
+ private:
+ CoreSession *_session;
+ UserId _user;
+ QList<QIODevice *> clientQueue;
+ bool _sessionInitialized;
+
+ bool isSessionInitialized();
+ void addClientToSession(QIODevice *socket);
+};
+
+#endif
if(query.first()) {
return query.value(0).toUInt();
} else {
- throw AuthError();
return 0;
}
}
getBufferInfoQuery->exec();
if(getBufferInfoQuery->first()) {
bufferid = BufferInfo(getBufferInfoQuery->value(0).toUInt(), networkId, 0, network, buffer);
- emit bufferInfoUpdated(bufferid);
+ emit bufferInfoUpdated(user, bufferid);
}
} else {
bufferid = BufferInfo(getBufferInfoQuery->value(0).toUInt(), networkId, 0, network, buffer);
inline virtual QString databaseName() { return backlogFile(); }
virtual int installedSchemaVersion();
-signals:
- void bufferInfoUpdated(BufferInfo);
-
private:
static QString backlogFile();
void createBuffer(UserId user, const QString &network, const QString &buffer);
signals:
//! Sent when a new BufferInfo is created, or an existing one changed somehow.
- void bufferInfoUpdated(BufferInfo);
+ void bufferInfoUpdated(UserId user, const BufferInfo &);
//! Sent when a new user has been added
void userAdded(UserId, const QString &username);
//! Sent when a user has been renamed
void userRemoved(UserId);
public:
- /* Exceptions */
- struct AuthError : public Exception {};
+
};
<file>oxygen/22x22/actions/media-seek-forward.png</file>
<file>oxygen/22x22/actions/media-skip-backward.png</file>
<file>oxygen/22x22/actions/media-skip-forward.png</file>
- <file>oxygen/22x22/actions/network-connect.png</file>
- <file>oxygen/22x22/actions/network-disconnect.png</file>
+ <file alias="network-connect">oxygen/22x22/actions/network-connect.png</file>
+ <file alias="network-disconnect">oxygen/22x22/actions/network-disconnect.png</file>
<file>oxygen/22x22/actions/news-subscribe.png</file>
<file>oxygen/22x22/actions/news-unsubscribe.png</file>
<file>oxygen/22x22/actions/object-rotate-left.png</file>
<file>oxygen/22x22/actions/zoom-original.png</file>
<file>oxygen/22x22/actions/zoom-out.png</file>
</qresource>
+ <qresource prefix="/22x22/status" >
+ <file alias="dialog-error">oxygen/22x22/status/dialog-error.png</file>
+ <file>oxygen/22x22/status/dialog-information.png</file>
+ <file>oxygen/22x22/status/dialog-password.png</file>
+ <file>oxygen/22x22/status/dialog-warning.png</file>
+ <file>oxygen/22x22/status/script-error.png</file>
+ <file>oxygen/22x22/status/security-high.png</file>
+ <file>oxygen/22x22/status/security-low.png</file>
+ <file>oxygen/22x22/status/security-medium.png</file>
+ </qresource>
<qresource prefix="/icons" >
<file>quassel-icon.png</file>
</qresource>
#include "chatline-old.h"
#include "qtui.h"
-//!\brief Construct a ChatLine object from a message.
+//! Construct a ChatLine object from a message.
/**
* \param m The message to be layouted and rendered
- * \param net The network name
- * \param buf The buffer name
*/
ChatLine::ChatLine(Message m) {
hght = 0;
/***************************************************************************
- * Copyright (C) 2005-08 by the Quassel Project *
+ * Copyright (C) 2005-08 by the Quassel IRC Team *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
-#include <QtGui>
+#include <QDebug>
+#include <QMessageBox>
+
#include "coreconnectdlg.h"
-#include "client.h"
+
#include "clientsettings.h"
-#include "configwizard.h"
-#include "global.h"
+#include "clientsyncer.h"
+
+CoreConnectDlg::CoreConnectDlg(QWidget *parent, bool autoconnect) : QDialog(parent) {
+ ui.setupUi(this);
-CoreConnectDlg::CoreConnectDlg(QWidget *parent, bool /*doAutoConnect*/) : QDialog(parent) {
- ui.setupUi(this); //qDebug() << "new dlg";
+ clientSyncer = new ClientSyncer(this);
setAttribute(Qt::WA_DeleteOnClose);
- coreState = 0;
- /* We show ui.internalCore in any case, because we might want to run as monolithic client anyway at another time
- if(Global::runMode == Global::Monolithic) {
- connect(ui.internalCore, SIGNAL(toggled(bool)), ui.hostEdit, SLOT(setDisabled(bool)));
- connect(ui.internalCore, SIGNAL(toggled(bool)), ui.port, SLOT(setDisabled(bool)));
- ui.internalCore->setChecked(true);
- } else {
- //ui.internalCore->hide();
- }
- */
- connect(ui.newAccount, SIGNAL(clicked()), this, SLOT(createAccount()));
- connect(ui.delAccount, SIGNAL(clicked()), this, SLOT(removeAccount()));
- connect(ui.buttonBox1, SIGNAL(accepted()), this, SLOT(doConnect()));
- connect(ui.hostEdit, SIGNAL(textChanged(const QString &)), this, SLOT(checkInputValid()));
- connect(ui.userEdit, SIGNAL(textChanged(const QString &)), this, SLOT(checkInputValid()));
- connect(ui.internalCore, SIGNAL(toggled(bool)), this, SLOT(checkInputValid()));
- connect(ui.internalCore, SIGNAL(toggled(bool)), ui.hostEdit, SLOT(setDisabled(bool)));
- connect(ui.internalCore, SIGNAL(toggled(bool)), ui.port, SLOT(setDisabled(bool)));
- connect(ui.accountList, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(accountChanged(const QString &)));
- connect(ui.autoConnect, SIGNAL(clicked(bool)), this, SLOT(autoConnectToggled(bool)));
-
- connect(Client::instance(), SIGNAL(coreConnectionMsg(const QString &)), ui.connectionStatus, SLOT(setText(const QString &)));
- connect(Client::instance(), SIGNAL(coreConnectionProgress(uint, uint)), this, SLOT(updateProgressBar(uint, uint)));
- connect(Client::instance(), SIGNAL(coreConnectionError(QString)), this, SLOT(coreConnectionError(QString)));
- connect(Client::instance(), SIGNAL(connected()), this, SLOT(coreConnected()));
-
- connect(Client::instance(), SIGNAL(showConfigWizard(const QVariantMap &)), this, SLOT(showConfigWizard(const QVariantMap &)));
-
- AccountSettings s;
+ doingAutoConnect = false;
+
+ ui.stackedWidget->setCurrentWidget(ui.accountPage);
+ ui.accountButtonBox->setFocus();
+
+ CoreAccountSettings s;
QString lastacc = s.lastAccount();
- ui.accountList->addItems(s.knownAccounts());
- if(!ui.accountList->count()) {
- //if(doAutoConnect) reject();
-
- setAccountEditEnabled(false);
- QString newacc = QInputDialog::getText(this, tr("Create Account"), tr(
- "In order to connect to a Quassel Core, you need to create an account.<br>"
- "Please enter a name for this account now:"), QLineEdit::Normal, tr("Default"));
- if(!newacc.isEmpty()) {
- ui.accountList->addItem(newacc);
- ui.hostEdit->setText("localhost");
- ui.port->setValue(Global::defaultPort);
- ui.internalCore->setChecked(false);
- setAccountEditEnabled(true);
- }
- /*
- // FIXME We create a default account here that just connects to the internal core
- curacc = "Default";
- ui.accountList->addItem("Default");
- ui.internalCore->setChecked(true);
- ui.userEdit->setText("Default");
- ui.passwdEdit->setText("password");
- ui.rememberPasswd->setChecked(true);
- accountChanged(curacc);
- ui.passwdEdit->setText("password");
- ui.accountList->setCurrentIndex(0);
- ui.autoConnect->setChecked(true);
- autoConnectToggled(true);
- */
- } else {
- if(!lastacc.isEmpty()) {
- //if(doAutoConnect) { qDebug() << "auto";
- // AccountSettings s;
- // int idx = ui.accountList->findText(s.autoConnectAccount());
- // if(idx < 0) reject();
- // else {
- // ui.accountList->setCurrentIndex(idx);
- // doConnect();
- // }
- //} else {
- int idx = ui.accountList->findText(lastacc);
- ui.accountList->setCurrentIndex(idx);
- //}
- }
+ autoConnectAccount = s.autoConnectAccount();
+ accounts = s.retrieveAllAccounts();
+ ui.accountList->addItems(accounts.keys());
+ QList<QListWidgetItem *> l = ui.accountList->findItems(lastacc, Qt::MatchExactly);
+ if(l.count()) ui.accountList->setCurrentItem(l[0]);
+ else ui.accountList->setCurrentRow(0);
+
+ setAccountWidgetStates();
+
+ connect(clientSyncer, SIGNAL(socketStateChanged(QAbstractSocket::SocketState)),this, SLOT(initPhaseSocketState(QAbstractSocket::SocketState)));
+ connect(clientSyncer, SIGNAL(connectionError(const QString &)), this, SLOT(initPhaseError(const QString &)));
+ connect(clientSyncer, SIGNAL(connectionMsg(const QString &)), this, SLOT(initPhaseMsg(const QString &)));
+ connect(clientSyncer, SIGNAL(startLogin()), this, SLOT(startLogin()));
+ connect(clientSyncer, SIGNAL(loginFailed(const QString &)), this, SLOT(loginFailed(const QString &)));
+ connect(clientSyncer, SIGNAL(loginSuccess()), this, SLOT(startSync()));
+ connect(clientSyncer, SIGNAL(sessionProgress(quint32, quint32)), this, SLOT(coreSessionProgress(quint32, quint32)));
+ connect(clientSyncer, SIGNAL(networksProgress(quint32, quint32)), this, SLOT(coreNetworksProgress(quint32, quint32)));
+ connect(clientSyncer, SIGNAL(channelsProgress(quint32, quint32)), this, SLOT(coreChannelsProgress(quint32, quint32)));
+ connect(clientSyncer, SIGNAL(ircUsersProgress(quint32, quint32)), this, SLOT(coreIrcUsersProgress(quint32, quint32)));
+ connect(clientSyncer, SIGNAL(syncFinished()), this, SLOT(accept()));
+
+ connect(ui.user, SIGNAL(textChanged(const QString &)), this, SLOT(setLoginWidgetStates()));
+ connect(ui.password, SIGNAL(textChanged(const QString &)), this, SLOT(setLoginWidgetStates()));
+
+ connect(ui.loginButtonBox, SIGNAL(rejected()), this, SLOT(restartPhaseNull()));
+ connect(ui.syncButtonBox->button(QDialogButtonBox::Abort), SIGNAL(clicked()), this, SLOT(restartPhaseNull()));
+
+ if(autoconnect && ui.accountList->count() && !autoConnectAccount.isEmpty() && autoConnectAccount == ui.accountList->currentItem()->text()) {
+ doingAutoConnect = true;
+ on_accountButtonBox_accepted();
}
}
CoreConnectDlg::~CoreConnectDlg() {
- //qDebug() << "destroy";
+ if(ui.accountList->selectedItems().count()) {
+ CoreAccountSettings s;
+ s.setLastAccount(ui.accountList->selectedItems()[0]->text());
+ }
}
-void CoreConnectDlg::setAccountEditEnabled(bool en) {
- ui.accountList->setEnabled(en);
- ui.hostEdit->setEnabled(en && !ui.internalCore->isChecked());
- ui.userEdit->setEnabled(en);
- ui.passwdEdit->setEnabled(en);
- ui.port->setEnabled(en && !ui.internalCore->isChecked());
- ui.editAccount->setEnabled(en);
- ui.delAccount->setEnabled(en);
- ui.internalCore->setEnabled(en);
- ui.rememberPasswd->setEnabled(en);
- ui.autoConnect->setEnabled(en);
- ui.buttonBox1->button(QDialogButtonBox::Ok)->setEnabled(en && checkInputValid());
+
+/****************************************************
+ * Account Management
+ ***************************************************/
+
+void CoreConnectDlg::on_accountList_itemSelectionChanged() {
+ setAccountWidgetStates();
}
-void CoreConnectDlg::accountChanged(const QString &text) {
- AccountSettings s;
- if(!curacc.isEmpty()) {
- QVariantMap oldAcc;
- oldAcc["User"] = ui.userEdit->text();
- oldAcc["Host"] = ui.hostEdit->text();
- oldAcc["Port"] = ui.port->value();
- oldAcc["InternalCore"] = ui.internalCore->isChecked();
- if(ui.rememberPasswd->isChecked()) oldAcc["Password"] = ui.passwdEdit->text();
- s.setValue(curacc, "AccountData", oldAcc);
- }
- ui.autoConnect->setChecked(false);
- if(!text.isEmpty()) { // empty text: just save stuff
- curacc = text;
- s.setLastAccount(curacc);
- QVariantMap newAcc = s.value(curacc, "AccountData").toMap();
- ui.userEdit->setText(newAcc["User"].toString());
- ui.hostEdit->setText(newAcc["Host"].toString());
- ui.port->setValue(newAcc["Port"].toInt());
- ui.internalCore->setChecked(newAcc["InternalCore"].toBool());
- if(newAcc.contains("Password")) {
- ui.passwdEdit->setText(newAcc["Password"].toString());
- ui.rememberPasswd->setChecked(true);
- } else ui.rememberPasswd->setChecked(false);
- if(s.autoConnectAccount() == curacc) ui.autoConnect->setChecked(true);
+void CoreConnectDlg::setAccountWidgetStates() {
+ QList<QListWidgetItem *> selectedItems = ui.accountList->selectedItems();
+ ui.editAccount->setEnabled(selectedItems.count());
+ ui.deleteAccount->setEnabled(selectedItems.count());
+ ui.autoConnect->setEnabled(selectedItems.count());
+ if(selectedItems.count()) {
+ ui.autoConnect->setChecked(selectedItems[0]->text() == autoConnectAccount);
}
}
-void CoreConnectDlg::autoConnectToggled(bool autoConnect) {
- AccountSettings s;
- if(autoConnect) s.setAutoConnectAccount(curacc);
- else s.setAutoConnectAccount("");
+void CoreConnectDlg::on_autoConnect_clicked(bool state) {
+ if(!state) {
+ autoConnectAccount = QString();
+ } else {
+ if(ui.accountList->selectedItems().count()) {
+ autoConnectAccount = ui.accountList->selectedItems()[0]->text();
+ } else {
+ qWarning() << "Checked auto connect without an enabled item!"; // should never happen!
+ autoConnectAccount = QString();
+ }
+ }
+ setAccountWidgetStates();
}
-bool CoreConnectDlg::checkInputValid() {
- bool res = (ui.internalCore->isChecked() || ui.hostEdit->text().count()) && ui.userEdit->text().count();
- ui.buttonBox1->button(QDialogButtonBox::Ok)->setEnabled(res);
- return res;
+void CoreConnectDlg::on_addAccount_clicked() {
+ QStringList existing;
+ for(int i = 0; i < ui.accountList->count(); i++) existing << ui.accountList->item(i)->text();
+ CoreAccountEditDlg dlg(QString(), QVariantMap(), existing, this);
+ if(dlg.exec() == QDialog::Accepted) {
+ accounts[dlg.accountName()] = dlg.accountData();
+ ui.accountList->addItem(dlg.accountName());
+ ui.accountList->setCurrentItem(ui.accountList->findItems(dlg.accountName(), Qt::MatchExactly)[0]);
+ }
}
-void CoreConnectDlg::createAccount() {
- QString accname = QInputDialog::getText(this, tr("Create Account"), tr("Please enter a name for the new account:"));
- if(accname.isEmpty()) return;
- if(ui.accountList->findText(accname) >= 0) {
- QMessageBox::warning(this, tr("Account name already exists!"), tr("An account named '%1' already exists, and account names must be unique!").arg(accname));
- return;
+void CoreConnectDlg::on_editAccount_clicked() {
+ QStringList existing;
+ for(int i = 0; i < ui.accountList->count(); i++) existing << ui.accountList->item(i)->text();
+ QString current = ui.accountList->currentItem()->text();
+ QVariantMap acct = accounts[current];
+ CoreAccountEditDlg dlg(current, acct, existing, this);
+ if(dlg.exec() == QDialog::Accepted) {
+ if(current != dlg.accountName()) {
+ if(autoConnectAccount == current) autoConnectAccount = dlg.accountName();
+ accounts.remove(current);
+ current = dlg.accountName();
+ ui.accountList->currentItem()->setText(current);
+ }
+ accounts[current] = dlg.accountData();
}
- QVariantMap defdata;
- ui.accountList->addItem(accname);
- ui.accountList->setCurrentIndex(ui.accountList->findText(accname));
- setAccountEditEnabled(true);
+ //ui.accountList->setCurrent
}
-void CoreConnectDlg::removeAccount() {
- QString acc = ui.accountList->currentText();
- int res = QMessageBox::warning(this, tr("Delete account?"), tr("Do you really want to delete the data for the account '%1'?<br>"
- "Note that this only affects your local account settings and will not remove "
- "any data from the core.").arg(acc),
- QMessageBox::Yes|QMessageBox::No, QMessageBox::No);
- if(res == QMessageBox::Yes) {
- AccountSettings s;
- s.removeAccount(acc);
- curacc = "";
- ui.accountList->removeItem(ui.accountList->findText(acc));
- if(!ui.accountList->count()) setAccountEditEnabled(false);
+void CoreConnectDlg::on_deleteAccount_clicked() {
+ QString current = ui.accountList->currentItem()->text();
+ int ret = QMessageBox::question(this, tr("Remove Account Settings"),
+ tr("Do you really want to remove your local settings for this Quassel Core account?<br>"
+ "Note: This will <em>not</em> remove or change any data on the Core itself!"),
+ QMessageBox::Yes|QMessageBox::No, QMessageBox::No);
+ if(ret == QMessageBox::Yes) {
+ int idx = ui.accountList->currentRow();
+ delete ui.accountList->item(idx);
+ ui.accountList->setCurrentRow(qMin(idx, ui.accountList->count()));
+ accounts.remove(current);
}
}
-bool CoreConnectDlg::willDoInternalAutoConnect() {
- AccountSettings s;
- if(Global::runMode != Global::Monolithic) return false;
- if(ui.autoConnect->isChecked() && s.autoConnectAccount() == curacc && ui.internalCore->isChecked()) {
- return true;
- }
- return false;
+void CoreConnectDlg::on_accountList_itemDoubleClicked(QListWidgetItem *item) {
+ Q_UNUSED(item);
+ on_accountButtonBox_accepted();
+}
+
+void CoreConnectDlg::on_accountButtonBox_accepted() {
+ // save accounts
+ CoreAccountSettings s;
+ s.storeAllAccounts(accounts);
+ s.setAutoConnectAccount(autoConnectAccount);
+
+ ui.stackedWidget->setCurrentWidget(ui.loginPage);
+ accountName = ui.accountList->currentItem()->text();
+ account = s.retrieveAccount(accountName);
+ s.setLastAccount(accountName);
+ connectToCore();
+}
+
+/*****************************************************
+ * Connecting to the Core
+ ****************************************************/
+
+/*** Phase One: initializing the core connection ***/
+
+void CoreConnectDlg::connectToCore() {
+ ui.connectIcon->setPixmap(QPixmap::fromImage(QImage(":/22x22/actions/network-disconnect")));
+ ui.connectLabel->setText(tr("Connect to %1").arg(account["Host"].toString()));
+ ui.coreInfoLabel->setText("");
+ ui.loginStack->setCurrentWidget(ui.loginEmptyPage);
+ ui.loginButtonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
+ ui.loginButtonBox->button(QDialogButtonBox::Ok)->setDisabled(true);
+ disconnect(ui.loginButtonBox, 0, this, 0);
+ connect(ui.loginButtonBox, SIGNAL(rejected()), this, SLOT(restartPhaseNull()));
+
+
+ //connect(Client::instance(), SIGNAL(coreConnectionPhaseOne(const QVariantMap &)), this, SLOT(phaseOneFinished
+ clientSyncer->connectToCore(account);
+}
+
+void CoreConnectDlg::initPhaseError(const QString &error) {
+ doingAutoConnect = false;
+ ui.connectIcon->setPixmap(QPixmap::fromImage(QImage(":/22x22/status/dialog-error")));
+ //ui.connectLabel->setBrush(QBrush("red"));
+ ui.connectLabel->setText(tr("<div style=color:red;>Connection to %1 failed!</div>").arg(account["Host"].toString()));
+ ui.coreInfoLabel->setText(error);
+ ui.loginButtonBox->setStandardButtons(QDialogButtonBox::Retry|QDialogButtonBox::Cancel);
+ disconnect(ui.loginButtonBox, 0, this, 0);
+ connect(ui.loginButtonBox, SIGNAL(accepted()), this, SLOT(restartPhaseNull()));
+ connect(ui.loginButtonBox, SIGNAL(rejected()), this, SLOT(reject()));
+}
+
+void CoreConnectDlg::initPhaseMsg(const QString &msg) {
+ ui.coreInfoLabel->setText(msg);
}
-void CoreConnectDlg::doAutoConnect() {
- AccountSettings s;
- if(s.autoConnectAccount() == curacc) {
- doConnect();
+void CoreConnectDlg::initPhaseSocketState(QAbstractSocket::SocketState state) {
+ QString s;
+ QString host = account["Host"].toString();
+ switch(state) {
+ case QAbstractSocket::UnconnectedState: s = tr("Not connected to %1.").arg(host); break;
+ case QAbstractSocket::HostLookupState: s = tr("Looking up %1...").arg(host); break;
+ case QAbstractSocket::ConnectingState: s = tr("Connecting to %1...").arg(host); break;
+ case QAbstractSocket::ConnectedState: s = tr("Connected to %1").arg(host); break;
+ default: s = tr("Unknown connection state to %1"); break;
}
+ ui.connectLabel->setText(s);
}
-void CoreConnectDlg::doConnect() {
- accountChanged(); // save current account info
- QVariantMap conninfo;
- ui.stackedWidget->setCurrentIndex(1);
- if(ui.internalCore->isChecked()) {
- // FIXME
- coreConnectionError(tr("Can't connect to internal core at the moment [serious breakage due to switch to dynamic signals]. Please check back later."));
- return;
- if(Global::runMode != Global::Monolithic) {
- coreConnectionError(tr("Can't connect to internal core, since we are running as a standalone GUI!"));
- return;
+void CoreConnectDlg::restartPhaseNull() {
+ doingAutoConnect = false;
+ ui.stackedWidget->setCurrentWidget(ui.accountPage);
+ clientSyncer->disconnectFromCore();
+}
+
+/*********************************************************
+ * Phase Two: Login
+ *********************************************************/
+
+void CoreConnectDlg::startLogin() {
+ ui.connectIcon->setPixmap(QPixmap::fromImage(QImage(":/22x22/actions/network-connect")));
+ ui.loginStack->setCurrentWidget(ui.loginCredentialsPage);
+ ui.loginStack->setMinimumSize(ui.loginStack->sizeHint()); ui.loginStack->updateGeometry();
+ ui.loginButtonBox->setStandardButtons(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
+ if(!account["User"].toString().isEmpty()) {
+ ui.user->setText(account["User"].toString());
+ if(account["RememberPasswd"].toBool()) {
+ ui.password->setText(account["Password"].toString());
+ ui.rememberPasswd->setChecked(true);
+ } else {
+ ui.rememberPasswd->setChecked(false);
+ ui.password->setFocus();
}
- ui.connectionGroupBox->setTitle(tr("Connecting to internal core"));
- ui.connectionProgress->hide();
+ } else ui.user->setFocus();
+ disconnect(ui.loginButtonBox, 0, this, 0);
+ connect(ui.loginButtonBox, SIGNAL(accepted()), this, SLOT(doLogin()));
+ connect(ui.loginButtonBox, SIGNAL(rejected()), this, SLOT(restartPhaseNull()));
+ if(doingAutoConnect) doLogin();
+}
+
+void CoreConnectDlg::doLogin() {
+ ui.loginGroup->setTitle(tr("Logging in..."));
+ ui.user->setDisabled(true);
+ ui.password->setDisabled(true);
+ ui.rememberPasswd->setDisabled(true);
+ ui.loginButtonBox->button(QDialogButtonBox::Ok)->setDisabled(true);
+ account["User"] = ui.user->text();
+ account["RememberPasswd"] = ui.rememberPasswd->isChecked();
+ if(ui.rememberPasswd->isChecked()) account["Password"] = ui.password->text();
+ else account.remove("Password");
+ CoreAccountSettings s;
+ s.storeAccount(accountName, account);
+ clientSyncer->loginToCore(account["User"].toString(), account["Password"].toString());
+}
+
+void CoreConnectDlg::setLoginWidgetStates() {
+ ui.loginButtonBox->button(QDialogButtonBox::Ok)->setDisabled(ui.user->text().isEmpty() || ui.password->text().isEmpty());
+}
+
+void CoreConnectDlg::loginFailed(const QString &error) {
+ ui.loginGroup->setTitle(tr("Login"));
+ ui.user->setEnabled(true);
+ ui.password->setEnabled(true);
+ ui.rememberPasswd->setEnabled(true);
+ ui.coreInfoLabel->setText(error);
+ ui.loginButtonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
+ ui.password->setFocus();
+ doingAutoConnect = false;
+}
+
+/************************************************************
+ * Phase Three: Syncing
+ ************************************************************/
+
+void CoreConnectDlg::startSync() {
+ ui.sessionProgress->setRange(0, 1);
+ ui.sessionProgress->setValue(0);
+ ui.networksProgress->setRange(0, 1);
+ ui.networksProgress->setValue(0);
+ ui.channelsProgress->setRange(0, 1);
+ ui.channelsProgress->setValue(0);
+ ui.ircUsersProgress->setRange(0, 1);
+ ui.ircUsersProgress->setValue(0);
+
+ ui.stackedWidget->setCurrentWidget(ui.syncPage);
+ // clean up old page
+ ui.loginGroup->setTitle(tr("Login"));
+ ui.user->setEnabled(true);
+ ui.password->setEnabled(true);
+ ui.rememberPasswd->setEnabled(true);
+ ui.loginButtonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
+}
+
+
+void CoreConnectDlg::coreSessionProgress(quint32 val, quint32 max) {
+ ui.sessionProgress->setRange(0, max);
+ ui.sessionProgress->setValue(val);
+
+}
+
+void CoreConnectDlg::coreNetworksProgress(quint32 val, quint32 max) {
+ if(max == 0) {
+ ui.networksProgress->setFormat("0/0");
+ ui.networksProgress->setRange(0, 1);
+ ui.networksProgress->setValue(1);
} else {
- ui.connectionGroupBox->setTitle(tr("Connecting to %1").arg(ui.hostEdit->text()));
- conninfo["Host"] = ui.hostEdit->text();
- conninfo["Port"] = ui.port->value();
- }
- conninfo["User"] = ui.userEdit->text();
- conninfo["Password"] = ui.passwdEdit->text();
- ui.profileLabel->hide(); ui.guiProfile->hide();
- ui.newGuiProfile->hide(); ui.alwaysUseProfile->hide();
- ui.connectionProgress->show();
- try {
- Client::instance()->connectToCore(conninfo);
- } catch(Exception e) {
- QString msg;
- //if(!e.msg().isEmpty()) msg = tr("<br>%1").arg(e.msg()); // FIXME throw more detailed (vulgo: any) error msg
- coreConnectionError(tr("Invalid user or password. Pleasy try again.%1").arg(msg));
- //QMessageBox::warning(this, tr("Unknown account"), tr("Invalid user or password. Pleasy try again.%1").arg(msg));
- //cancelConnect();
- return;
+ ui.networksProgress->setFormat("%v/%m");
+ ui.networksProgress->setRange(0, max);
+ ui.networksProgress->setValue(val);
}
}
-void CoreConnectDlg::cancelConnect() {
- ui.stackedWidget->setCurrentIndex(0);
+void CoreConnectDlg::coreChannelsProgress(quint32 val, quint32 max) {
+ if(max == 0) {
+ ui.channelsProgress->setFormat("0/0");
+ ui.channelsProgress->setRange(0, 1);
+ ui.channelsProgress->setValue(1);
+ } else {
+ ui.channelsProgress->setFormat("%v/%m");
+ ui.channelsProgress->setRange(0, max);
+ ui.channelsProgress->setValue(val);
+ }
}
-void CoreConnectDlg::setStartState() { /*
- ui.hostName->show(); ui.hostPort->show(); ui.hostLabel->show(); ui.portLabel->show();
- ui.statusText->setText(tr("Connect to Quassel Core running on:"));
- ui.buttonBox->button(QDialogButtonBox::Ok)->show();
- ui.hostName->setEnabled(true); ui.hostPort->setEnabled(true);
- ui.hostName->setSelection(0, ui.hostName->text().length()); */
- ui.stackedWidget->setCurrentIndex(0);
+void CoreConnectDlg::coreIrcUsersProgress(quint32 val, quint32 max) {
+ if(max == 0) {
+ ui.ircUsersProgress->setFormat("0/0");
+ ui.ircUsersProgress->setRange(0, 1);
+ ui.ircUsersProgress->setValue(1);
+ } else {
+ ui.ircUsersProgress->setFormat("%v/%m");
+ ui.ircUsersProgress->setRange(0, max);
+ ui.ircUsersProgress->setValue(val);
+ }
}
-void CoreConnectDlg::hostEditChanged(QString /*txt*/) {
- //ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(txt.length());
-}
+/*****************************************************************************************
+ * CoreAccountEditDlg
+ *****************************************************************************************/
-void CoreConnectDlg::hostSelected() { /*
- ui.hostName->hide(); ui.hostPort->hide(); ui.hostLabel->hide(); ui.portLabel->hide();
- ui.statusText->setText(tr("Connecting to %1:%2" ).arg(ui.hostName->text()).arg(ui.hostPort->value()));
- ui.buttonBox->button(QDialogButtonBox::Ok)->hide();
- connect(ClientProxy::instance(), SIGNAL(coreConnected()), this, SLOT(coreConnected()));
- connect(ClientProxy::instance(), SIGNAL(coreConnectionError(QString)), this, SLOT(coreConnectionError(QString)));
- Client::instance()->connectToCore(ui.hostName->text(), ui.hostPort->value());
-*/
+CoreAccountEditDlg::CoreAccountEditDlg(const QString &name, const QVariantMap &acct, const QStringList &_existing, QWidget *parent) : QDialog(parent) {
+ ui.setupUi(this);
+ existing = _existing;
+ account = acct;
+ if(!name.isEmpty()) {
+ existing.removeAll(name);
+ ui.host->setText(acct["Host"].toString());
+ ui.port->setValue(acct["Port"].toUInt());
+ ui.useInternal->setChecked(acct["UseInternal"].toBool());
+ ui.accountName->setText(name);
+ } else {
+ setWindowTitle(tr("Add Core Account"));
+ }
}
-void CoreConnectDlg::coreConnected() { /*
- ui.hostLabel->hide(); ui.hostName->hide(); ui.portLabel->hide(); ui.hostPort->hide();
- ui.statusText->setText(tr("Synchronizing..."));
- QSettings s;
- s.setValue("GUI/CoreHost", ui.hostName->text());
- s.setValue("GUI/CorePort", ui.hostPort->value());
- s.setValue("GUI/CoreAutoConnect", ui.autoConnect->isChecked());
- connect(ClientProxy::instance(), SIGNAL(recvPartialItem(quint32, quint32)), this, SLOT(updateProgressBar(quint32, quint32)));
- connect(ClientProxy::instance(), SIGNAL(csCoreState(QVariant)), this, SLOT(recvCoreState(QVariant)));
- ui.progressBar->show();
- QVariantMap initmsg;
- initmsg["GUIProtocol"] = GUI_PROTOCOL;
- // FIXME guiProxy->send(GS_CLIENT_INIT, QVariant(initmsg)); */
- ui.connectionStatus->setText(tr("Connected to core."));
- accept();
+QString CoreAccountEditDlg::accountName() const {
+ return ui.accountName->text();
}
-void CoreConnectDlg::coreConnectionError(QString err) {
- ui.stackedWidget->setCurrentIndex(0);
- show(); // just in case we started hidden
- QMessageBox::warning(this, tr("Connection Error"), tr("<b>Could not connect to Quassel Core!</b><br>\n") + err, QMessageBox::Retry);
- //disconnect(ClientProxy::instance(), 0, this, 0); FIXME?
- //ui.autoConnect->setChecked(false);
- setStartState();
+QVariantMap CoreAccountEditDlg::accountData() {
+ account["Host"] = ui.host->text();
+ account["Port"] = ui.port->value();
+ account["UseInternal"] = ui.useInternal->isChecked();
+ return account;
}
-void CoreConnectDlg::updateProgressBar(uint partial, uint total) {
- ui.connectionProgress->setMaximum(total);
- ui.connectionProgress->setValue(partial);
- //qDebug() << "progress:" << partial << total;
+void CoreAccountEditDlg::setWidgetStates() {
+ bool ok = !accountName().isEmpty() && !existing.contains(accountName()) && (ui.useInternal->isChecked() || !ui.host->text().isEmpty());
+ ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(ok);
}
-void CoreConnectDlg::recvCoreState(QVariant state) {
- //ui.progressBar->hide();
- coreState = state;
- accept();
+void CoreAccountEditDlg::on_host_textChanged(const QString &text) {
+ Q_UNUSED(text);
+ setWidgetStates();
}
-QVariant CoreConnectDlg::getCoreState() {
- return coreState;
+void CoreAccountEditDlg::on_accountName_textChanged(const QString &text) {
+ Q_UNUSED(text);
+ setWidgetStates();
}
-void CoreConnectDlg::showConfigWizard(const QVariantMap &coredata) {
- QStringList storageProviders = coredata["StorageProviders"].toStringList();
- ConfigWizard *wizard = new ConfigWizard(storageProviders, this);
- wizard->exec();
- QVariantMap reply;
- reply["GuiProtocol"] = GUI_PROTOCOL;
- reply["HasSettings"] = true;
- reply["User"] = wizard->field("adminuser.name").toString();
- reply["Password"] = wizard->field("adminuser.password").toString();
- QString sp = storageProviders.value(wizard->field("storage.provider").toInt());
- reply["Type"] = sp;
- if (sp.compare("Sqlite", Qt::CaseInsensitive)) {
- reply["Host"] = wizard->field("storage.host").toString();
- reply["Port"] = wizard->field("storage.port").toString();
- reply["Database"] = wizard->field("storage.database").toString();
- reply["User"] = wizard->field("storage.user").toString();
- reply["Password"] = wizard->field("storage.password").toString();
- }
- Client::instance()->setCoreConfiguration(reply);
+void CoreAccountEditDlg::on_useRemote_toggled(bool state) {
+ Q_UNUSED(state);
+ setWidgetStates();
}
/***************************************************************************
- * Copyright (C) 2005-08 by the Quassel Project *
+ * Copyright (C) 2005-08 by the Quassel IRC Team *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
-#ifndef _CORECONNECTDLG_H
-#define _CORECONNECTDLG_H
+#ifndef _CORECONNECTDLG_H_
+#define _CORECONNECTDLG_H_
+
+#include <QAbstractSocket>
#include "ui_coreconnectdlg.h"
+#include "ui_coreaccounteditdlg.h"
+
+class ClientSyncer;
-class CoreConnectDlg: public QDialog {
+class CoreConnectDlg : public QDialog {
Q_OBJECT
public:
- CoreConnectDlg(QWidget *parent, bool doAutoConnect = false);
+ CoreConnectDlg(QWidget *parent = 0, bool = false);
~CoreConnectDlg();
- QVariant getCoreState();
-
- bool willDoInternalAutoConnect();
-
- public slots:
- void doAutoConnect();
private slots:
- void createAccount();
- void removeAccount();
- void accountChanged(const QString & = "");
- void setAccountEditEnabled(bool);
- void autoConnectToggled(bool);
- bool checkInputValid();
- void hostEditChanged(QString);
- void hostSelected();
- void doConnect();
-
- void coreConnected();
- void coreConnectionError(QString);
- //void coreConnectionMsg(const QString &);
- //void coreConnectionProgress(uint partial, uint total);
- void updateProgressBar(uint partial, uint total);
- void recvCoreState(QVariant);
-
- void showConfigWizard(const QVariantMap &coredata);
+
+ /*** Phase Null: Accounts ***/
+ void restartPhaseNull();
+
+ void on_accountList_itemSelectionChanged();
+ void on_autoConnect_clicked(bool);
+
+ void on_addAccount_clicked();
+ void on_editAccount_clicked();
+ void on_deleteAccount_clicked();
+
+ void on_accountList_itemDoubleClicked(QListWidgetItem *item);
+ void on_accountButtonBox_accepted();
+
+ void setAccountWidgetStates();
+
+ /*** Phase One: Connection ***/
+ void connectToCore();
+
+ void initPhaseError(const QString &error);
+ void initPhaseMsg(const QString &msg);
+ void initPhaseSocketState(QAbstractSocket::SocketState);
+
+ /*** Phase Two: Login ***/
+ void startLogin();
+ void doLogin();
+ void loginFailed(const QString &);
+
+ void setLoginWidgetStates();
+
+ /*** Phase Three: Sync ***/
+ void startSync();
+
+ void coreSessionProgress(quint32, quint32);
+ void coreNetworksProgress(quint32, quint32);
+ void coreChannelsProgress(quint32, quint32);
+ void coreIrcUsersProgress(quint32, quint32);
private:
Ui::CoreConnectDlg ui;
- QVariant coreState;
- void cancelConnect();
- void setStartState();
- QVariantMap accountData;
- QString curacc;
+ QString autoConnectAccount;
+ QHash<QString, QVariantMap> accounts;
+ QVariantMap account;
+ QString accountName;
+
+ bool doingAutoConnect;
+
+ ClientSyncer *clientSyncer;
+};
+
+class CoreAccountEditDlg : public QDialog {
+ Q_OBJECT
+
+ public:
+ CoreAccountEditDlg(const QString &name, const QVariantMap &data, const QStringList &existing = QStringList(), QWidget *parent = 0);
+
+ QString accountName() const;
+ QVariantMap accountData();
+
+ private slots:
+ void on_host_textChanged(const QString &);
+ void on_accountName_textChanged(const QString &);
+ void on_useRemote_toggled(bool);
+
+ void setWidgetStates();
+
+ private:
+ Ui::CoreAccountEditDlg ui;
+
+ QStringList existing;
+ QVariantMap account;
};
#endif
// attach the BufferWidget to the PropertyMapper
Client::bufferModel()->mapProperty(0, NetworkModel::BufferIdRole, ui.bufferWidget, "currentBuffer");
connect(Client::networkModel(), SIGNAL(bufferAboutToBeRemoved(BufferId)),
- ui.bufferWidget, SLOT(removeBuffer(BufferId)));
+ ui.bufferWidget, SLOT(removeBuffer(BufferId)));
// attach the NickList to the PropertyMapper
Client::bufferModel()->mapProperty(0, NetworkModel::BufferIdRole, nickListWidget, "currentBuffer");
coreConnectDlg = new CoreConnectDlg(this, autoConnect);
connect(coreConnectDlg, SIGNAL(finished(int)), this, SLOT(coreConnectionDlgFinished(int)));
coreConnectDlg->setModal(true);
- if(!autoConnect || !coreConnectDlg->willDoInternalAutoConnect())
+ //if(!autoConnect || !coreConnectDlg->willDoInternalAutoConnect())
coreConnectDlg->show(); // avoid flicker and show dlg only if we do remote connect, which needs a progress bar
- if(autoConnect) coreConnectDlg->doAutoConnect();
+ //if(autoConnect) coreConnectDlg->doAutoConnect();
}
void MainWin::coreConnectionDlgFinished(int /*code*/) {
-
coreConnectDlg->close();
+ //exit(1);
}
topicwidget.h debugconsole.h
FORMNAMES = identitiesdlg.ui identitieseditdlg.ui networkeditdlg.ui mainwin.ui nickeditdlg.ui serverlistdlg.ui \
- servereditdlg.ui coreconnectdlg.ui bufferviewwidget.ui bufferwidget.ui nicklistwidget.ui settingsdlg.ui \
+ servereditdlg.ui coreaccounteditdlg.ui coreconnectdlg.ui bufferviewwidget.ui bufferwidget.ui nicklistwidget.ui settingsdlg.ui \
buffermgmtpage.ui connectionpage.ui usermgmtpage.ui topicwidget.ui debugconsole.ui
for(ui, FORMNAMES) {
--- /dev/null
+<ui version="4.0" >
+ <class>CoreAccountEditDlg</class>
+ <widget class="QDialog" name="CoreAccountEditDlg" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>395</width>
+ <height>242</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Edit Core Account</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <item>
+ <layout class="QVBoxLayout" >
+ <item>
+ <widget class="QGroupBox" name="groupBox" >
+ <property name="title" >
+ <string>Account Details</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <item>
+ <layout class="QHBoxLayout" >
+ <item>
+ <widget class="QLabel" name="label" >
+ <property name="text" >
+ <string>Account Name:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="accountName" />
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" >
+ <widget class="QRadioButton" name="useInternal" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="text" >
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" colspan="2" >
+ <widget class="QLabel" name="label_4" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="text" >
+ <string>Use built-in Quassel Core</string>
+ </property>
+ <property name="buddy" >
+ <cstring>useInternal</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QRadioButton" name="useRemote" >
+ <property name="text" >
+ <string/>
+ </property>
+ <property name="checked" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QLabel" name="label_2" >
+ <property name="text" >
+ <string>Remote host:</string>
+ </property>
+ <property name="buddy" >
+ <cstring>useRemote</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2" >
+ <widget class="QLabel" name="label_3" >
+ <property name="text" >
+ <string>Port:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" >
+ <widget class="QLineEdit" name="host" />
+ </item>
+ <item row="2" column="2" >
+ <widget class="QSpinBox" name="port" >
+ <property name="minimum" >
+ <number>1</number>
+ </property>
+ <property name="maximum" >
+ <number>65535</number>
+ </property>
+ <property name="value" >
+ <number>4242</number>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1" colspan="2" >
+ <widget class="QCheckBox" name="useSSL" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="text" >
+ <string>Use secure connection (SSL)</string>
+ </property>
+ <property name="icon" >
+ <iconset resource="../../icons/icons.qrc" >:/16x16/actions/oxygen/16x16/actions/document-encrypt.png</iconset>
+ </property>
+ <property name="checked" >
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="../../icons/icons.qrc" />
+ </resources>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>CoreAccountEditDlg</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>263</x>
+ <y>230</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>157</x>
+ <y>207</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>CoreAccountEditDlg</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>331</x>
+ <y>230</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>286</x>
+ <y>207</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>useInternal</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>host</receiver>
+ <slot>setDisabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>30</x>
+ <y>79</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>92</x>
+ <y>143</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>useInternal</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>port</receiver>
+ <slot>setDisabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>39</x>
+ <y>78</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>331</x>
+ <y>144</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>useRemote</sender>
+ <signal>clicked(bool)</signal>
+ <receiver>host</receiver>
+ <slot>setFocus()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>26</x>
+ <y>113</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>184</x>
+ <y>146</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
<rect>
<x>0</x>
<y>0</y>
- <width>462</width>
- <height>249</height>
+ <width>511</width>
+ <height>389</height>
</rect>
</property>
- <property name="sizePolicy" >
- <sizepolicy vsizetype="MinimumExpanding" hsizetype="Preferred" >
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
<property name="windowTitle" >
<string>Connect to Quassel Core</string>
</property>
- <property name="windowIcon" >
- <iconset/>
- </property>
- <property name="modal" >
- <bool>false</bool>
- </property>
<layout class="QVBoxLayout" >
- <property name="spacing" >
- <number>6</number>
- </property>
- <property name="leftMargin" >
- <number>0</number>
- </property>
- <property name="topMargin" >
- <number>0</number>
- </property>
- <property name="rightMargin" >
- <number>0</number>
- </property>
- <property name="bottomMargin" >
- <number>0</number>
- </property>
<item>
- <widget class="QStackedWidget" name="stackedWidget" >
- <property name="currentIndex" >
+ <layout class="QVBoxLayout" >
+ <property name="spacing" >
<number>0</number>
</property>
- <widget class="QWidget" name="page" >
- <layout class="QGridLayout" >
- <item row="0" column="0" >
- <widget class="QGroupBox" name="groupBox" >
- <property name="title" >
- <string>Account Settings</string>
- </property>
- <layout class="QGridLayout" >
- <item rowspan="2" row="0" column="0" >
- <widget class="QLabel" name="label_5" >
- <property name="text" >
- <string>Account:</string>
- </property>
- </widget>
- </item>
- <item rowspan="2" row="0" column="1" colspan="2" >
- <widget class="QComboBox" name="accountList" >
- <property name="editable" >
- <bool>false</bool>
- </property>
- <property name="insertPolicy" >
- <enum>QComboBox::InsertAlphabetically</enum>
- </property>
- </widget>
- </item>
- <item rowspan="2" row="0" column="3" >
- <widget class="QToolButton" name="editAccount" >
- <property name="text" >
- <string>...</string>
- </property>
- <property name="icon" >
- <iconset resource="../../icons/icons.qrc" >:/22x22/actions/oxygen/22x22/actions/configure.png</iconset>
- </property>
- <property name="iconSize" >
- <size>
- <width>22</width>
- <height>22</height>
- </size>
- </property>
- </widget>
- </item>
- <item rowspan="2" row="0" column="4" >
- <widget class="QToolButton" name="newAccount" >
- <property name="text" >
- <string>...</string>
- </property>
- <property name="icon" >
- <iconset resource="../../icons/icons.qrc" >:/22x22/actions/oxygen/22x22/actions/list-add.png</iconset>
- </property>
- <property name="iconSize" >
- <size>
- <width>22</width>
- <height>22</height>
- </size>
- </property>
- </widget>
- </item>
- <item rowspan="2" row="0" column="5" colspan="2" >
- <widget class="QToolButton" name="delAccount" >
- <property name="text" >
- <string>...</string>
- </property>
- <property name="icon" >
- <iconset resource="../../icons/icons.qrc" >:/22x22/actions/oxygen/22x22/actions/edit-delete.png</iconset>
- </property>
- <property name="iconSize" >
- <size>
- <width>22</width>
- <height>22</height>
- </size>
- </property>
- </widget>
- </item>
- <item row="1" column="6" >
- <spacer>
- <property name="orientation" >
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" >
- <size>
- <width>20</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="2" column="0" >
- <widget class="QLabel" name="label_2" >
- <property name="text" >
- <string>Host:</string>
- </property>
- </widget>
- </item>
- <item row="2" column="1" colspan="2" >
- <widget class="QLineEdit" name="hostEdit" />
- </item>
- <item row="2" column="3" colspan="4" >
- <widget class="QCheckBox" name="internalCore" >
- <property name="enabled" >
- <bool>false</bool>
- </property>
- <property name="text" >
- <string>Use internal</string>
- </property>
- <property name="checked" >
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item row="3" column="0" >
- <widget class="QLabel" name="label" >
- <property name="text" >
- <string>Port:</string>
- </property>
- </widget>
- </item>
- <item row="3" column="1" >
- <widget class="QSpinBox" name="port" >
- <property name="minimum" >
- <number>1024</number>
- </property>
- <property name="maximum" >
- <number>65535</number>
- </property>
- <property name="value" >
- <number>4242</number>
- </property>
- </widget>
- </item>
- <item row="3" column="2" >
- <spacer>
- <property name="orientation" >
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" >
- <size>
- <width>211</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="4" column="0" >
- <widget class="QLabel" name="label_3" >
- <property name="text" >
- <string>User:</string>
- </property>
- </widget>
- </item>
- <item row="4" column="1" colspan="2" >
- <widget class="QLineEdit" name="userEdit" />
- </item>
- <item row="5" column="0" >
- <widget class="QLabel" name="label_4" >
- <property name="text" >
- <string>Password:</string>
- </property>
- </widget>
- </item>
- <item row="5" column="1" colspan="2" >
- <widget class="QLineEdit" name="passwdEdit" >
- <property name="echoMode" >
- <enum>QLineEdit::Password</enum>
- </property>
- </widget>
- </item>
- <item row="5" column="3" colspan="4" >
- <widget class="QCheckBox" name="rememberPasswd" >
- <property name="text" >
- <string>Remember</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item row="1" column="0" >
- <spacer>
- <property name="orientation" >
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" >
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="2" column="0" >
- <layout class="QHBoxLayout" >
- <property name="spacing" >
- <number>6</number>
- </property>
- <property name="leftMargin" >
- <number>0</number>
- </property>
- <property name="topMargin" >
- <number>0</number>
- </property>
- <property name="rightMargin" >
- <number>0</number>
- </property>
- <property name="bottomMargin" >
- <number>0</number>
- </property>
+ <item>
+ <widget class="QStackedWidget" name="stackedWidget" >
+ <property name="currentIndex" >
+ <number>2</number>
+ </property>
+ <widget class="QWidget" name="accountPage" >
+ <layout class="QVBoxLayout" >
<item>
- <widget class="QCheckBox" name="autoConnect" >
- <property name="text" >
- <string>Always use this account</string>
- </property>
- <property name="checked" >
- <bool>false</bool>
+ <widget class="QGroupBox" name="groupBox" >
+ <property name="title" >
+ <string>Connect to Quassel Core</string>
</property>
+ <layout class="QHBoxLayout" >
+ <item>
+ <widget class="QListWidget" name="accountList" >
+ <property name="sortingEnabled" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" >
+ <item>
+ <widget class="QPushButton" name="editAccount" >
+ <property name="text" >
+ <string>Edit...</string>
+ </property>
+ <property name="icon" >
+ <iconset resource="../../icons/icons.qrc" >:/16x16/actions/oxygen/16x16/actions/configure.png</iconset>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="addAccount" >
+ <property name="text" >
+ <string>Add...</string>
+ </property>
+ <property name="icon" >
+ <iconset resource="../../icons/icons.qrc" >:/16x16/actions/oxygen/16x16/actions/list-add.png</iconset>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="deleteAccount" >
+ <property name="text" >
+ <string>Delete</string>
+ </property>
+ <property name="icon" >
+ <iconset resource="../../icons/icons.qrc" >:/16x16/actions/oxygen/16x16/actions/list-remove.png</iconset>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
</widget>
</item>
<item>
- <spacer>
- <property name="orientation" >
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" >
- <size>
- <width>101</width>
- <height>31</height>
- </size>
- </property>
- </spacer>
+ <layout class="QHBoxLayout" >
+ <item>
+ <widget class="QCheckBox" name="autoConnect" >
+ <property name="text" >
+ <string>Always use this account</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="accountButtonBox" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
</item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="loginPage" >
+ <layout class="QVBoxLayout" >
<item>
- <widget class="QDialogButtonBox" name="buttonBox1" >
- <property name="orientation" >
- <enum>Qt::Horizontal</enum>
+ <widget class="QGroupBox" name="groupBox_2" >
+ <property name="title" >
+ <string>Initializing your connection</string>
</property>
+ <layout class="QHBoxLayout" >
+ <item>
+ <layout class="QVBoxLayout" >
+ <item>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" >
+ <widget class="QLabel" name="connectIcon" >
+ <property name="text" >
+ <string/>
+ </property>
+ <property name="pixmap" >
+ <pixmap resource="../../icons/icons.qrc" >:/22x22/actions/network-disconnect</pixmap>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QLabel" name="connectLabel" >
+ <property name="text" >
+ <string>Connected to apollo.mindpool.net.</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ <property name="wordWrap" >
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>358</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="1" colspan="2" >
+ <widget class="QLabel" name="coreInfoLabel" >
+ <property name="text" >
+ <string>Core Info</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ <property name="wordWrap" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QStackedWidget" name="loginStack" >
+ <property name="currentIndex" >
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="loginCredentialsPage" >
+ <layout class="QVBoxLayout" >
+ <item>
+ <layout class="QVBoxLayout" >
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="loginGroup" >
+ <property name="title" >
+ <string>Login</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="leftMargin" >
+ <number>9</number>
+ </property>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="label_2" >
+ <property name="text" >
+ <string>User:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QLineEdit" name="user" >
+ <property name="text" >
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" >
+ <widget class="QLabel" name="label_3" >
+ <property name="text" >
+ <string>Password:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" >
+ <widget class="QLineEdit" name="password" >
+ <property name="echoMode" >
+ <enum>QLineEdit::Password</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1" >
+ <widget class="QCheckBox" name="rememberPasswd" >
+ <property name="text" >
+ <string>Remember</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="loginEmptyPage" />
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="loginButtonBox" >
<property name="standardButtons" >
<set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
- </item>
- </layout>
- </widget>
- <widget class="QWidget" name="page_2" >
- <layout class="QVBoxLayout" >
- <item>
- <widget class="QGroupBox" name="connectionGroupBox" >
- <property name="title" >
- <string>Connecting to...</string>
- </property>
- <layout class="QVBoxLayout" >
- <item>
- <widget class="QLabel" name="connectionStatus" >
- <property name="text" >
- <string>Connecting...</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QProgressBar" name="connectionProgress" >
- <property name="value" >
- <number>0</number>
- </property>
- <property name="orientation" >
- <enum>Qt::Horizontal</enum>
- </property>
- </widget>
- </item>
- <item>
- <layout class="QHBoxLayout" >
- <item>
- <widget class="QLabel" name="profileLabel" >
- <property name="text" >
- <string>GUI Profile:</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QComboBox" name="guiProfile" >
- <property name="sizePolicy" >
- <sizepolicy vsizetype="Fixed" hsizetype="MinimumExpanding" >
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- </widget>
- </item>
+ </widget>
+ <widget class="QWidget" name="syncPage" >
+ <layout class="QVBoxLayout" >
+ <item>
+ <widget class="QGroupBox" name="groupBox_3" >
+ <property name="title" >
+ <string>Initializing your session...</string>
+ </property>
+ <layout class="QVBoxLayout" >
<item>
- <widget class="QPushButton" name="newGuiProfile" >
- <property name="sizePolicy" >
- <sizepolicy vsizetype="Fixed" hsizetype="Maximum" >
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text" >
- <string>New...</string>
- </property>
- </widget>
+ <layout class="QVBoxLayout" >
+ <item>
+ <widget class="QLabel" name="label_6" >
+ <property name="text" >
+ <string><b>Please be patient while your client synchronizes with the Quassel Core!</b></string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignHCenter|Qt::AlignTop</set>
+ </property>
+ <property name="wordWrap" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" >
+ <widget class="QLabel" name="progressLabel" >
+ <property name="text" >
+ <string>Session state:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QProgressBar" name="sessionProgress" >
+ <property name="maximum" >
+ <number>1</number>
+ </property>
+ <property name="value" >
+ <number>0</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="label" >
+ <property name="text" >
+ <string>Network states:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QProgressBar" name="networksProgress" >
+ <property name="maximum" >
+ <number>1</number>
+ </property>
+ <property name="value" >
+ <number>0</number>
+ </property>
+ <property name="format" >
+ <string>0/0</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" >
+ <widget class="QLabel" name="label_4" >
+ <property name="text" >
+ <string>Channel states:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" >
+ <widget class="QProgressBar" name="channelsProgress" >
+ <property name="maximum" >
+ <number>1</number>
+ </property>
+ <property name="value" >
+ <number>0</number>
+ </property>
+ <property name="format" >
+ <string>0/0</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" >
+ <widget class="QLabel" name="label_5" >
+ <property name="text" >
+ <string>User states:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1" >
+ <widget class="QProgressBar" name="ircUsersProgress" >
+ <property name="minimum" >
+ <number>0</number>
+ </property>
+ <property name="maximum" >
+ <number>1</number>
+ </property>
+ <property name="value" >
+ <number>0</number>
+ </property>
+ <property name="format" >
+ <string>0/0</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>483</width>
+ <height>61</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
</item>
</layout>
- </item>
- <item>
- <widget class="QCheckBox" name="alwaysUseProfile" >
- <property name="text" >
- <string>Always use this profile</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <spacer>
- <property name="orientation" >
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" >
- <size>
- <width>20</width>
- <height>31</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <layout class="QHBoxLayout" >
- <item>
- <spacer>
- <property name="orientation" >
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" >
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
+ </widget>
</item>
<item>
- <widget class="QDialogButtonBox" name="buttonBox2" >
+ <widget class="QDialogButtonBox" name="syncButtonBox" >
<property name="standardButtons" >
- <set>QDialogButtonBox::Abort|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
+ <set>QDialogButtonBox::Abort</set>
+ </property>
+ <property name="centerButtons" >
+ <bool>true</bool>
</property>
</widget>
</item>
</layout>
- </item>
- </layout>
- </widget>
- </widget>
+ </widget>
+ </widget>
+ </item>
+ </layout>
</item>
</layout>
</widget>
+ <tabstops>
+ <tabstop>accountButtonBox</tabstop>
+ <tabstop>accountList</tabstop>
+ <tabstop>editAccount</tabstop>
+ <tabstop>addAccount</tabstop>
+ <tabstop>deleteAccount</tabstop>
+ <tabstop>autoConnect</tabstop>
+ <tabstop>loginButtonBox</tabstop>
+ <tabstop>user</tabstop>
+ <tabstop>password</tabstop>
+ <tabstop>rememberPasswd</tabstop>
+ <tabstop>syncButtonBox</tabstop>
+ </tabstops>
<resources>
- <include location="../../images/icons.qrc" />
<include location="../../icons/icons.qrc" />
</resources>
<connections>
<connection>
- <sender>buttonBox1</sender>
+ <sender>accountButtonBox</sender>
<signal>rejected()</signal>
<receiver>CoreConnectDlg</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel" >
- <x>507</x>
- <y>273</y>
+ <x>279</x>
+ <y>434</y>
</hint>
<hint type="destinationlabel" >
- <x>297</x>
- <y>151</y>
+ <x>286</x>
+ <y>237</y>
</hint>
</hints>
</connection>
<rect>
<x>0</x>
<y>0</y>
- <width>430</width>
- <height>444</height>
+ <width>465</width>
+ <height>482</height>
</rect>
</property>
<property name="windowTitle" >
<string>Server List</string>
</property>
<property name="windowIcon" >
- <iconset resource="../images/icons.qrc" >:/default/server.png</iconset>
+ <iconset/>
</property>
<property name="sizeGripEnabled" >
<bool>false</bool>
<bool>false</bool>
</property>
<layout class="QVBoxLayout" >
- <property name="margin" >
- <number>8</number>
- </property>
<property name="spacing" >
<number>6</number>
</property>
+ <property name="leftMargin" >
+ <number>8</number>
+ </property>
+ <property name="topMargin" >
+ <number>8</number>
+ </property>
+ <property name="rightMargin" >
+ <number>8</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>8</number>
+ </property>
<item>
- <layout class="QHBoxLayout" >
- <property name="margin" >
- <number>0</number>
+ <widget class="QLabel" name="label" >
+ <property name="text" >
+ <string><html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'DejaVu Sans'; font-size:11pt; font-weight:400; font-style:normal;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600; color:#ff0000;">Big Fat Warning: </span><span style=" font-size:14pt; color:#000000;">The settings in here now need a Core restart in order to take effect! This dialog is doomed and will go away as soon as its replacement is finished.</span></p></body></html></string>
</property>
+ <property name="alignment" >
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ <property name="wordWrap" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
<item>
<widget class="QTreeWidget" name="networkTree" >
<property name="dragEnabled" >
<property name="sortingEnabled" >
<bool>false</bool>
</property>
+ <column>
+ <property name="text" >
+ <string>1</string>
+ </property>
+ </column>
</widget>
</item>
<item>
<layout class="QVBoxLayout" >
- <property name="margin" >
- <number>0</number>
- </property>
<property name="spacing" >
<number>6</number>
</property>
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
<item>
<widget class="QPushButton" name="addButton" >
<property name="text" >
<string>&Add...</string>
</property>
<property name="icon" >
- <iconset resource="../images/icons.qrc" >:/default/edit_add.png</iconset>
+ <iconset/>
</property>
</widget>
</item>
<string>&Edit...</string>
</property>
<property name="icon" >
- <iconset resource="../images/icons.qrc" >:/default/edit.png</iconset>
+ <iconset/>
</property>
</widget>
</item>
<string>&Delete</string>
</property>
<property name="icon" >
- <iconset resource="../images/icons.qrc" >:/default/edit_remove.png</iconset>
+ <iconset/>
</property>
</widget>
</item>
</item>
<item>
<layout class="QHBoxLayout" >
- <property name="margin" >
- <number>0</number>
- </property>
<property name="spacing" >
<number>6</number>
</property>
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
<item>
<widget class="QCheckBox" name="showOnStartup" >
<property name="text" >
<string>&Connect</string>
</property>
<property name="icon" >
- <iconset resource="../images/icons.qrc" >:/default/connect_creating.png</iconset>
+ <iconset/>
</property>
<property name="default" >
<bool>false</bool>
<string>C&lose</string>
</property>
<property name="icon" >
- <iconset resource="../images/icons.qrc" >:/default/button_cancel.png</iconset>
+ <iconset/>
</property>
<property name="default" >
<bool>true</bool>
--- /dev/null
+// Versioning, should be kept current :)
+// This is included in main.cpp
+
+{ using namespace Global;
+
+ quasselVersion = "0.2.0-pre";
+ quasselDate = "2008-01-12";
+ quasselBuild = 344;
+
+ //! Minimum client build number the core needs
+ clientBuildNeeded = 344;
+ clientVersionNeeded = quasselVersion;
+
+ //! Minimum core build number the client needs
+ coreBuildNeeded = 344;
+ coreVersionNeeded = quasselVersion;
+
+}