X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fclient%2Fclient.cpp;h=019c67c97f7a2e1d479b18d1e1658b6608edcffa;hp=93c5e2155e6bb209ac39fcb62e44a0c9c7e209bd;hb=fa00b68a21c777682d9feb37ade6b3904fc19d92;hpb=fb011e52bc6613198a65e037f0752f6361339aeb diff --git a/src/client/client.cpp b/src/client/client.cpp index 93c5e215..019c67c9 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2005-08 by the Quassel Project * + * Copyright (C) 2005-09 by the Quassel Project * * devel@quassel-irc.org * * * * This program is free software; you can redistribute it and/or modify * @@ -21,29 +21,45 @@ #include "client.h" #include "abstractmessageprocessor.h" +#include "abstractui.h" #include "bufferinfo.h" #include "buffermodel.h" #include "buffersettings.h" #include "buffersyncer.h" -#include "bufferviewmanager.h" +#include "bufferviewconfig.h" +#include "bufferviewoverlay.h" +#include "clientaliasmanager.h" #include "clientbacklogmanager.h" +#include "clientbufferviewmanager.h" #include "clientirclisthelper.h" -#include "identity.h" +#include "clientidentity.h" +#include "clientignorelistmanager.h" +#include "clientuserinputhandler.h" +#include "coreaccountmodel.h" +#include "coreconnection.h" #include "ircchannel.h" #include "ircuser.h" #include "message.h" #include "messagemodel.h" #include "network.h" +#include "networkconfig.h" #include "networkmodel.h" -#include "quasselui.h" +#include "quassel.h" #include "signalproxy.h" #include "util.h" +#include +#include + QPointer Client::instanceptr = 0; -AccountId Client::_currentCoreAccount = 0; /*** Initialization/destruction ***/ +bool Client::instanceExists() +{ + return instanceptr; +} + Client *Client::instance() { if(!instanceptr) instanceptr = new Client(); @@ -52,31 +68,37 @@ Client *Client::instance() { void Client::destroy() { if(instanceptr) { - delete instanceptr->mainUi; + delete instanceptr->mainUi(); instanceptr->deleteLater(); instanceptr = 0; } } void Client::init(AbstractUi *ui) { - instance()->mainUi = ui; + instance()->_mainUi = ui; instance()->init(); } Client::Client(QObject *parent) : QObject(parent), _signalProxy(new SignalProxy(SignalProxy::Client, this)), - mainUi(0), + _mainUi(0), _networkModel(0), _bufferModel(0), _bufferSyncer(0), + _aliasManager(0), _backlogManager(new ClientBacklogManager(this)), _bufferViewManager(0), + _bufferViewOverlay(new BufferViewOverlay(this)), _ircListHelper(new ClientIrcListHelper(this)), + _inputHandler(0), + _networkConfig(0), + _ignoreListManager(0), _messageModel(0), _messageProcessor(0), - _connectedToCore(false), - _syncedToCore(false) + _coreAccountModel(new CoreAccountModel(this)), + _coreConnection(new CoreConnection(_coreAccountModel, this)), + _debugLog(&_debugLogBuffer) { _signalProxy->synchronize(_ircListHelper); } @@ -86,15 +108,15 @@ Client::~Client() { } void Client::init() { - _currentCoreAccount = 0; _networkModel = new NetworkModel(this); connect(this, SIGNAL(networkRemoved(NetworkId)), _networkModel, SLOT(networkRemoved(NetworkId))); _bufferModel = new BufferModel(_networkModel); - _messageModel = mainUi->createMessageModel(this); - _messageProcessor = mainUi->createMessageProcessor(this); + _messageModel = mainUi()->createMessageModel(this); + _messageProcessor = mainUi()->createMessageProcessor(this); + _inputHandler = new ClientUserInputHandler(this); SignalProxy *p = signalProxy(); @@ -102,47 +124,50 @@ void Client::init() { p->attachSlot(SIGNAL(displayStatusMsg(QString, QString)), this, SLOT(recvStatusMsg(QString, QString))); p->attachSlot(SIGNAL(bufferInfoUpdated(BufferInfo)), _networkModel, SLOT(bufferUpdated(BufferInfo))); - p->attachSignal(this, SIGNAL(sendInput(BufferInfo, QString))); + p->attachSignal(inputHandler(), SIGNAL(sendInput(BufferInfo, QString))); p->attachSignal(this, SIGNAL(requestNetworkStates())); - p->attachSignal(this, SIGNAL(requestCreateIdentity(const Identity &)), SIGNAL(createIdentity(const Identity &))); + p->attachSignal(this, SIGNAL(requestCreateIdentity(const Identity &, const QVariantMap &)), SIGNAL(createIdentity(const Identity &, const QVariantMap &))); p->attachSignal(this, SIGNAL(requestRemoveIdentity(IdentityId)), SIGNAL(removeIdentity(IdentityId))); p->attachSlot(SIGNAL(identityCreated(const Identity &)), this, SLOT(coreIdentityCreated(const Identity &))); p->attachSlot(SIGNAL(identityRemoved(IdentityId)), this, SLOT(coreIdentityRemoved(IdentityId))); - p->attachSignal(this, SIGNAL(requestCreateNetwork(const NetworkInfo &)), SIGNAL(createNetwork(const NetworkInfo &))); + p->attachSignal(this, SIGNAL(requestCreateNetwork(const NetworkInfo &, const QStringList &)), SIGNAL(createNetwork(const NetworkInfo &, const QStringList &))); p->attachSignal(this, SIGNAL(requestRemoveNetwork(NetworkId)), SIGNAL(removeNetwork(NetworkId))); p->attachSlot(SIGNAL(networkCreated(NetworkId)), this, SLOT(coreNetworkCreated(NetworkId))); p->attachSlot(SIGNAL(networkRemoved(NetworkId)), this, SLOT(coreNetworkRemoved(NetworkId))); - connect(p, SIGNAL(disconnected()), this, SLOT(disconnectedFromCore())); - - //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())); + //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())); // attach backlog manager p->synchronize(backlogManager()); connect(backlogManager(), SIGNAL(messagesReceived(BufferId, int)), _messageModel, SLOT(messagesReceived(BufferId, int))); -} -/*** public static methods ***/ + coreAccountModel()->load(); -AccountId Client::currentCoreAccount() { - return _currentCoreAccount; + connect(coreConnection(), SIGNAL(stateChanged(CoreConnection::ConnectionState)), SLOT(connectionStateChanged(CoreConnection::ConnectionState))); + coreConnection()->init(); } -void Client::setCurrentCoreAccount(AccountId id) { - _currentCoreAccount = id; +/*** public static methods ***/ + +AbstractUi *Client::mainUi() { + return instance()->_mainUi; } bool Client::isConnected() { - return instance()->_connectedToCore; + return coreConnection()->state() >= CoreConnection::Connected; } bool Client::isSynced() { - return instance()->_syncedToCore; + return coreConnection()->state() == CoreConnection::Synchronized; +} + +bool Client::internalCore() { + return currentCoreAccount().isInternal(); } /*** Network handling ***/ @@ -156,8 +181,8 @@ const Network * Client::network(NetworkId networkid) { else return 0; } -void Client::createNetwork(const NetworkInfo &info) { - emit instance()->requestCreateNetwork(info); +void Client::createNetwork(const NetworkInfo &info, const QStringList &persistentChannels) { + emit instance()->requestCreateNetwork(info, persistentChannels); } void Client::removeNetwork(NetworkId id) { @@ -205,13 +230,18 @@ QList Client::identityIds() { return instance()->_identities.keys(); } -const Identity * Client::identity(IdentityId id) { +const Identity *Client::identity(IdentityId id) { if(instance()->_identities.contains(id)) return instance()->_identities[id]; else return 0; } -void Client::createIdentity(const Identity &id) { - emit instance()->requestCreateIdentity(id); +void Client::createIdentity(const CertIdentity &id) { + QVariantMap additional; +#ifdef HAVE_SSL + additional["KeyPem"] = id.sslKey().toPem(); + additional["CertPem"] = id.sslCert().toPem(); +#endif + emit instance()->requestCreateIdentity(id, additional); } void Client::updateIdentity(IdentityId id, const QVariantMap &ser) { @@ -247,25 +277,36 @@ void Client::coreIdentityRemoved(IdentityId id) { } } -/*** ***/ -void Client::userInput(BufferInfo bufferInfo, QString message) { - emit instance()->sendInput(bufferInfo, message); +/*** User input handling ***/ + +void Client::userInput(const BufferInfo &bufferInfo, const QString &message) { + // we need to make sure that AliasManager is ready before processing input + if(aliasManager() && aliasManager()->isInitialized()) + inputHandler()->handleUserInput(bufferInfo, message); + else + instance()-> _userInputBuffer.append(qMakePair(bufferInfo, message)); } -/*** core connection stuff ***/ +void Client::sendBufferedUserInput() { + for(int i = 0; i < _userInputBuffer.count(); i++) + userInput(_userInputBuffer.at(i).first, _userInputBuffer.at(i).second); -void Client::setConnectedToCore(QIODevice *socket, AccountId id) { - // if the socket is an orphan, the signalProxy adopts it. - // -> we don't need to care about it anymore - socket->setParent(0); - signalProxy()->addPeer(socket); - _connectedToCore = true; - setCurrentCoreAccount(id); + _userInputBuffer.clear(); } -void Client::setConnectedToInternalCore() { - _connectedToCore = true; - setCurrentCoreAccount(AccountId()); +/*** core connection stuff ***/ + +void Client::connectionStateChanged(CoreConnection::ConnectionState state) { + switch(state) { + case CoreConnection::Disconnected: + setDisconnectedFromCore(); + break; + case CoreConnection::Synchronized: + setSyncedToCore(); + break; + default: + break; + } } void Client::setSyncedToCore() { @@ -275,37 +316,75 @@ void Client::setSyncedToCore() { connect(bufferSyncer(), SIGNAL(lastSeenMsgSet(BufferId, MsgId)), _networkModel, SLOT(setLastSeenMsgId(BufferId, MsgId))); connect(bufferSyncer(), SIGNAL(bufferRemoved(BufferId)), this, SLOT(bufferRemoved(BufferId))); connect(bufferSyncer(), SIGNAL(bufferRenamed(BufferId, QString)), this, SLOT(bufferRenamed(BufferId, QString))); + connect(bufferSyncer(), SIGNAL(buffersPermanentlyMerged(BufferId, BufferId)), this, SLOT(buffersPermanentlyMerged(BufferId, BufferId))); + connect(bufferSyncer(), SIGNAL(buffersPermanentlyMerged(BufferId, BufferId)), _messageModel, SLOT(buffersPermanentlyMerged(BufferId, BufferId))); + connect(networkModel(), SIGNAL(setLastSeenMsg(BufferId, MsgId)), bufferSyncer(), SLOT(requestSetLastSeenMsg(BufferId, const MsgId &))); signalProxy()->synchronize(bufferSyncer()); // create a new BufferViewManager - _bufferViewManager = new BufferViewManager(signalProxy(), this); + Q_ASSERT(!_bufferViewManager); + _bufferViewManager = new ClientBufferViewManager(signalProxy(), this); + connect(bufferViewManager(), SIGNAL(initDone()), this, SLOT(createDefaultBufferView())); + + // create AliasManager + Q_ASSERT(!_aliasManager); + _aliasManager = new ClientAliasManager(this); + connect(aliasManager(), SIGNAL(initDone()), SLOT(sendBufferedUserInput())); + signalProxy()->synchronize(aliasManager()); + + // create NetworkConfig + Q_ASSERT(!_networkConfig); + _networkConfig = new NetworkConfig("GlobalNetworkConfig", this); + signalProxy()->synchronize(networkConfig()); + + // create IgnoreListManager + Q_ASSERT(!_ignoreListManager); + _ignoreListManager = new ClientIgnoreListManager(this); + signalProxy()->synchronize(ignoreListManager()); + + // trigger backlog request once all active bufferviews are initialized + connect(bufferViewOverlay(), SIGNAL(initDone()), this, SLOT(requestInitialBacklog())); - _syncedToCore = true; emit connected(); emit coreConnectionStateChanged(true); } -void Client::setSecuredConnection() { - emit securedConnection(); +void Client::requestInitialBacklog() { + // usually it _should_ take longer until the bufferViews are initialized, so that's what + // triggers this slot. But we have to make sure that we know all buffers yet. + // so we check the BufferSyncer and in case it wasn't initialized we wait for that instead + if(!bufferSyncer()->isInitialized()) { + connect(bufferViewOverlay(), SIGNAL(initDone()), this, SLOT(requestInitialBacklog())); + connect(bufferSyncer(), SIGNAL(initDone()), this, SLOT(requestInitialBacklog())); + return; + } + _backlogManager->requestInitialBacklog(); +} + +void Client::createDefaultBufferView() { + if(bufferViewManager()->bufferViewConfigs().isEmpty()) { + BufferViewConfig config(-1); + config.setBufferViewName(tr("All Chats")); + config.initSetBufferList(networkModel()->allBufferIdsSorted()); + bufferViewManager()->requestCreateBufferView(config.toVariantMap()); + } } void Client::disconnectFromCore() { - if(!isConnected()) + if(!coreConnection()->isConnected()) return; - signalProxy()->removeAllPeers(); + coreConnection()->disconnectFromCore(); } -void Client::disconnectedFromCore() { - _connectedToCore = false; - _syncedToCore = false; +void Client::setDisconnectedFromCore() { emit disconnected(); emit coreConnectionStateChanged(false); + backlogManager()->reset(); messageProcessor()->reset(); // Clear internal data. Hopefully nothing relies on it at this point. - setCurrentCoreAccount(0); if(_bufferSyncer) { _bufferSyncer->deleteLater(); @@ -317,6 +396,18 @@ void Client::disconnectedFromCore() { _bufferViewManager = 0; } + if(_aliasManager) { + _aliasManager->deleteLater(); + _aliasManager = 0; + } + + if(_ignoreListManager) { + _ignoreListManager->deleteLater(); + _ignoreListManager = 0; + } + // we probably don't want to save pending input for reconnect + _userInputBuffer.clear(); + _messageModel->clear(); _networkModel->clear(); @@ -330,15 +421,19 @@ void Client::disconnectedFromCore() { } Q_ASSERT(_networks.isEmpty()); - QHash::iterator idIter = _identities.begin(); + QHash::iterator idIter = _identities.begin(); while(idIter != _identities.end()) { + emit identityRemoved(idIter.key()); Identity *id = idIter.value(); - emit identityRemoved(id->id()); idIter = _identities.erase(idIter); id->deleteLater(); } Q_ASSERT(_identities.isEmpty()); + if(_networkConfig) { + _networkConfig->deleteLater(); + _networkConfig = 0; + } } /*** ***/ @@ -361,9 +456,9 @@ void Client::recvStatusMsg(QString /*net*/, QString /*msg*/) { //recvMessage(net, Message::server("", QString("[STATUS] %1").arg(msg))); } -void Client::recvMessage(const Message &msg_) { - Message msg = msg_; - messageProcessor()->process(msg); +void Client::recvMessage(const Message &msg) { + Message msg_ = msg; + messageProcessor()->process(msg_); } void Client::setBufferLastSeenMsg(BufferId id, const MsgId &msgId) { @@ -377,6 +472,24 @@ void Client::removeBuffer(BufferId id) { bufferSyncer()->requestRemoveBuffer(id); } +void Client::renameBuffer(BufferId bufferId, const QString &newName) { + if(!bufferSyncer()) + return; + bufferSyncer()->requestRenameBuffer(bufferId, newName); +} + +void Client::mergeBuffersPermanently(BufferId bufferId1, BufferId bufferId2) { + if(!bufferSyncer()) + return; + bufferSyncer()->requestMergeBuffersPermanently(bufferId1, bufferId2); +} + +void Client::purgeKnownBufferIds() { + if(!bufferSyncer()) + return; + bufferSyncer()->requestPurgeBufferIds(); +} + void Client::bufferRemoved(BufferId bufferId) { // select a sane buffer (status buffer) /* we have to manually select a buffer because otherwise inconsitent changes @@ -401,3 +514,27 @@ void Client::bufferRenamed(BufferId bufferId, const QString &newName) { networkModel()->setData(bufferIndex, newName, Qt::DisplayRole); } } + +void Client::buffersPermanentlyMerged(BufferId bufferId1, BufferId bufferId2) { + QModelIndex idx = networkModel()->bufferIndex(bufferId1); + bufferModel()->setCurrentIndex(bufferModel()->mapFromSource(idx)); + networkModel()->removeBuffer(bufferId2); +} + +void Client::logMessage(QtMsgType type, const char *msg) { + fprintf(stderr, "%s\n", msg); + fflush(stderr); + if(type == QtFatalMsg) { + Quassel::logFatalMessage(msg); + } else { + QString msgString = QString("%1\n").arg(msg); + + //Check to see if there is an instance around, else we risk recursions + //when calling instance() and creating new ones. + if (!instanceExists()) + return; + + instance()->_debugLog << msgString; + emit instance()->logUpdated(msgString); + } +}