X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fclient%2Fclient.cpp;h=b1e2f119e12c02ee2dcdd94efd2221d61098ebc9;hp=7bbbefe7203e8d23940e252caae9d28da9e4147f;hb=1a45f16a9734820fba42fe1db3f38dd1eee49df6;hpb=1cb02004ee5973b89368bd84f234d4652794690d diff --git a/src/client/client.cpp b/src/client/client.cpp index 7bbbefe7..b1e2f119 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2005-2015 by the Quassel Project * + * Copyright (C) 2005-2018 by the Quassel Project * * devel@quassel-irc.org * * * * This program is free software; you can redistribute it and/or modify * @@ -38,6 +38,7 @@ #include "clientuserinputhandler.h" #include "coreaccountmodel.h" #include "coreconnection.h" +#include "dccconfig.h" #include "ircchannel.h" #include "ircuser.h" #include "message.h" @@ -47,91 +48,49 @@ #include "networkmodel.h" #include "quassel.h" #include "signalproxy.h" +#include "transfermodel.h" #include "util.h" +#include "clientauthhandler.h" #include #include -QPointer Client::instanceptr = 0; -Quassel::Features Client::_coreFeatures = 0; - -/*** Initialization/destruction ***/ - -bool Client::instanceExists() -{ - return instanceptr; -} - - -Client *Client::instance() -{ - if (!instanceptr) - instanceptr = new Client(); - return instanceptr; -} - - -void Client::destroy() -{ - if (instanceptr) { - delete instanceptr->mainUi(); - instanceptr->deleteLater(); - instanceptr = 0; - } -} - - -void Client::init(AbstractUi *ui) -{ - instance()->_mainUi = ui; - instance()->init(); -} - - -Client::Client(QObject *parent) - : QObject(parent), +Client::Client(std::unique_ptr ui, QObject *parent) + : QObject(parent), Singleton(this), _signalProxy(new SignalProxy(SignalProxy::Client, this)), - _mainUi(0), - _networkModel(0), - _bufferModel(0), + _mainUi(std::move(ui)), + _networkModel(new NetworkModel(this)), + _bufferModel(new BufferModel(_networkModel)), _bufferSyncer(0), _aliasManager(0), _backlogManager(new ClientBacklogManager(this)), _bufferViewManager(0), _bufferViewOverlay(new BufferViewOverlay(this)), + _coreInfo(new CoreInfo(this)), + _dccConfig(0), _ircListHelper(new ClientIrcListHelper(this)), - _inputHandler(0), + _inputHandler(new ClientUserInputHandler(this)), _networkConfig(0), _ignoreListManager(0), + _highlightRuleManager(0), _transferManager(0), - _messageModel(0), - _messageProcessor(0), + _transferModel(new TransferModel(this)), + _messageModel(_mainUi->createMessageModel(this)), + _messageProcessor(_mainUi->createMessageProcessor(this)), _coreAccountModel(new CoreAccountModel(this)), _coreConnection(new CoreConnection(this)), - _connected(false), - _debugLog(&_debugLogBuffer) -{ - _signalProxy->synchronize(_ircListHelper); -} - - -Client::~Client() + _connected(false) { - disconnectFromCore(); -} - - -void Client::init() -{ - _networkModel = new NetworkModel(this); + //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(this, SIGNAL(networkRemoved(NetworkId)), - _networkModel, SLOT(networkRemoved(NetworkId))); + connect(this, SIGNAL(networkRemoved(NetworkId)), _networkModel, SLOT(networkRemoved(NetworkId))); + connect(this, SIGNAL(networkRemoved(NetworkId)), _messageProcessor, SLOT(networkRemoved(NetworkId))); - _bufferModel = new BufferModel(_networkModel); - _messageModel = mainUi()->createMessageModel(this); - _messageProcessor = mainUi()->createMessageProcessor(this); - _inputHandler = new ClientUserInputHandler(this); + connect(backlogManager(), SIGNAL(messagesReceived(BufferId, int)), _messageModel, SLOT(messagesReceived(BufferId, int))); + connect(coreConnection(), SIGNAL(stateChanged(CoreConnection::ConnectionState)), SLOT(connectionStateChanged(CoreConnection::ConnectionState))); SignalProxy *p = signalProxy(); @@ -152,33 +111,36 @@ void Client::init() p->attachSlot(SIGNAL(networkCreated(NetworkId)), this, SLOT(coreNetworkCreated(NetworkId))); p->attachSlot(SIGNAL(networkRemoved(NetworkId)), this, SLOT(coreNetworkRemoved(NetworkId))); - //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())); + p->attachSignal(this, SIGNAL(requestPasswordChange(PeerPtr,QString,QString,QString)), SIGNAL(changePassword(PeerPtr,QString,QString,QString))); + p->attachSlot(SIGNAL(passwordChanged(PeerPtr,bool)), this, SLOT(corePasswordChanged(PeerPtr,bool))); + + p->attachSignal(this, SIGNAL(requestKickClient(int)), SIGNAL(kickClient(int))); + p->attachSlot(SIGNAL(disconnectFromCore()), this, SLOT(disconnectFromCore())); - // attach backlog manager p->synchronize(backlogManager()); - connect(backlogManager(), SIGNAL(messagesReceived(BufferId, int)), _messageModel, SLOT(messagesReceived(BufferId, int))); + p->synchronize(coreInfo()); + p->synchronize(_ircListHelper); coreAccountModel()->load(); - - connect(coreConnection(), SIGNAL(stateChanged(CoreConnection::ConnectionState)), SLOT(connectionStateChanged(CoreConnection::ConnectionState))); coreConnection()->init(); } -/*** public static methods ***/ +Client::~Client() +{ + disconnectFromCore(); +} + AbstractUi *Client::mainUi() { - return instance()->_mainUi; + return instance()->_mainUi.get(); } -void Client::setCoreFeatures(Quassel::Features features) +bool Client::isCoreFeatureEnabled(Quassel::Feature feature) { - _coreFeatures = features; + return coreConnection()->peer() ? coreConnection()->peer()->hasFeature(feature) : false; } @@ -194,6 +156,22 @@ bool Client::internalCore() } +void Client::onDbUpgradeInProgress(bool inProgress) +{ + emit dbUpgradeInProgress(inProgress); +} + + +void Client::onExitRequested(int exitCode, const QString &reason) +{ + if (!reason.isEmpty()) { + qCritical() << reason; + emit exitRequested(reason); + } + QCoreApplication::exit(exitCode); +} + + /*** Network handling ***/ QList Client::networkIds() @@ -382,60 +360,111 @@ void Client::setSyncedToCore() connect(bufferSyncer(), SIGNAL(buffersPermanentlyMerged(BufferId, BufferId)), this, SLOT(buffersPermanentlyMerged(BufferId, BufferId))); connect(bufferSyncer(), SIGNAL(buffersPermanentlyMerged(BufferId, BufferId)), _messageModel, SLOT(buffersPermanentlyMerged(BufferId, BufferId))); connect(bufferSyncer(), SIGNAL(bufferMarkedAsRead(BufferId)), SIGNAL(bufferMarkedAsRead(BufferId))); + connect(bufferSyncer(), SIGNAL(bufferActivityChanged(BufferId, const Message::Types)), _networkModel, SLOT(bufferActivityChanged(BufferId, const Message::Types))); + connect(bufferSyncer(), SIGNAL(highlightCountChanged(BufferId, int)), _networkModel, SLOT(highlightCountChanged(BufferId, int))); connect(networkModel(), SIGNAL(requestSetLastSeenMsg(BufferId, MsgId)), bufferSyncer(), SLOT(requestSetLastSeenMsg(BufferId, const MsgId &))); - signalProxy()->synchronize(bufferSyncer()); + + SignalProxy *p = signalProxy(); + p->synchronize(bufferSyncer()); // create a new BufferViewManager Q_ASSERT(!_bufferViewManager); - _bufferViewManager = new ClientBufferViewManager(signalProxy(), this); + _bufferViewManager = new ClientBufferViewManager(p, this); connect(_bufferViewManager, SIGNAL(initDone()), _bufferViewOverlay, SLOT(restore())); // create AliasManager Q_ASSERT(!_aliasManager); _aliasManager = new ClientAliasManager(this); connect(aliasManager(), SIGNAL(initDone()), SLOT(sendBufferedUserInput())); - signalProxy()->synchronize(aliasManager()); + p->synchronize(aliasManager()); // create NetworkConfig Q_ASSERT(!_networkConfig); _networkConfig = new NetworkConfig("GlobalNetworkConfig", this); - signalProxy()->synchronize(networkConfig()); + p->synchronize(networkConfig()); // create IgnoreListManager Q_ASSERT(!_ignoreListManager); _ignoreListManager = new ClientIgnoreListManager(this); - signalProxy()->synchronize(ignoreListManager()); + p->synchronize(ignoreListManager()); + // create Core-Side HighlightRuleManager + Q_ASSERT(!_highlightRuleManager); + _highlightRuleManager = new HighlightRuleManager(this); + p->synchronize(highlightRuleManager()); + // Listen to network removed events + connect(this, SIGNAL(networkRemoved(NetworkId)), + _highlightRuleManager, SLOT(networkRemoved(NetworkId))); + +/* not ready yet + // create TransferManager and DccConfig if core supports them + Q_ASSERT(!_dccConfig); Q_ASSERT(!_transferManager); - _transferManager = new ClientTransferManager(this); - signalProxy()->synchronize(transferManager()); + if (isCoreFeatureEnabled(Quassel::Feature::DccFileTransfer)) { + _dccConfig = new DccConfig(this); + p->synchronize(dccConfig()); + _transferManager = new ClientTransferManager(this); + _transferModel->setManager(_transferManager); + p->synchronize(transferManager()); + } +*/ // trigger backlog request once all active bufferviews are initialized - connect(bufferViewOverlay(), SIGNAL(initDone()), this, SLOT(requestInitialBacklog())); + connect(bufferViewOverlay(), SIGNAL(initDone()), this, SLOT(finishConnectionInitialization())); _connected = true; emit connected(); emit coreConnectionStateChanged(true); } - -void Client::requestInitialBacklog() +void Client::finishConnectionInitialization() { // 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()) { - disconnect(bufferViewOverlay(), SIGNAL(initDone()), this, SLOT(requestInitialBacklog())); - connect(bufferSyncer(), SIGNAL(initDone()), this, SLOT(requestInitialBacklog())); + disconnect(bufferViewOverlay(), SIGNAL(initDone()), this, SLOT(finishConnectionInitialization())); + connect(bufferSyncer(), SIGNAL(initDone()), this, SLOT(finishConnectionInitialization())); return; } - disconnect(bufferViewOverlay(), SIGNAL(initDone()), this, SLOT(requestInitialBacklog())); - disconnect(bufferSyncer(), SIGNAL(initDone()), this, SLOT(requestInitialBacklog())); + disconnect(bufferViewOverlay(), SIGNAL(initDone()), this, SLOT(finishConnectionInitialization())); + disconnect(bufferSyncer(), SIGNAL(initDone()), this, SLOT(finishConnectionInitialization())); + + requestInitialBacklog(); + if (isCoreFeatureEnabled(Quassel::Feature::BufferActivitySync)) { + bufferSyncer()->markActivitiesChanged(); + bufferSyncer()->markHighlightCountsChanged(); + } +} + +void Client::requestInitialBacklog() +{ _backlogManager->requestInitialBacklog(); } +void Client::requestLegacyCoreInfo() +{ + // On older cores, the CoreInfo object was only synchronized on demand. Synchronize now if + // needed. + if (isConnected() && !isCoreFeatureEnabled(Quassel::Feature::SyncedCoreInfo)) { + // Delete the existing core info object (it will always exist as client is single-threaded) + _coreInfo->deleteLater(); + // No need to set to null when creating new one immediately after + + // Create a fresh, unsynchronized CoreInfo object, emulating legacy behavior of CoreInfo not + // persisting + _coreInfo = new CoreInfo(this); + // Synchronize the new object + signalProxy()->synchronize(_coreInfo); + + // Let others know signal handlers have been reset + emit coreInfoResynchronized(); + } +} + + void Client::disconnectFromCore() { if (!coreConnection()->isConnected()) @@ -448,7 +477,6 @@ void Client::disconnectFromCore() void Client::setDisconnectedFromCore() { _connected = false; - _coreFeatures = 0; emit disconnected(); emit coreConnectionStateChanged(false); @@ -463,6 +491,8 @@ void Client::setDisconnectedFromCore() _bufferSyncer = 0; } + _coreInfo->reset(); + if (_bufferViewManager) { _bufferViewManager->deleteLater(); _bufferViewManager = 0; @@ -480,9 +510,20 @@ void Client::setDisconnectedFromCore() _ignoreListManager = 0; } + if (_highlightRuleManager) { + _highlightRuleManager->deleteLater(); + _highlightRuleManager = nullptr; + } + if (_transferManager) { + _transferModel->setManager(nullptr); _transferManager->deleteLater(); - _transferManager = 0; + _transferManager = nullptr; + } + + if (_dccConfig) { + _dccConfig->deleteLater(); + _dccConfig = nullptr; } // we probably don't want to save pending input for reconnect @@ -529,7 +570,7 @@ void Client::networkDestroyed() break; } else { - netIter++; + ++netIter; } } } @@ -646,46 +687,29 @@ void Client::markBufferAsRead(BufferId id) } -#if QT_VERSION < 0x050000 -void Client::logMessage(QtMsgType type, const char *msg) +void Client::refreshLegacyCoreInfo() { - fprintf(stderr, "%s\n", msg); - fflush(stderr); - if (type == QtFatalMsg) { - Quassel::logFatalMessage(msg); - } - else { - QString msgString = QString("%1\n").arg(msg); + instance()->requestLegacyCoreInfo(); +} - //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); - } +void Client::changePassword(const QString &oldPassword, const QString &newPassword) { + CoreAccount account = currentCoreAccount(); + account.setPassword(newPassword); + coreAccountModel()->createOrUpdateAccount(account); + emit instance()->requestPasswordChange(nullptr, account.user(), oldPassword, newPassword); } -#else -void Client::logMessage(QtMsgType type, const QMessageLogContext &context, const QString &msg) -{ - Q_UNUSED(context); - fprintf(stderr, "%s\n", msg.toLocal8Bit().constData()); - fflush(stderr); - if (type == QtFatalMsg) { - Quassel::logFatalMessage(msg.toLocal8Bit().constData()); - } - 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; +void Client::kickClient(int peerId) +{ + emit instance()->requestKickClient(peerId); +} - instance()->_debugLog << msgString; - emit instance()->logUpdated(msgString); - } + +void Client::corePasswordChanged(PeerPtr, bool success) +{ + if (success) + coreAccountModel()->save(); + emit passwordChanged(success); } -#endif