#include <QObject>
#include "backlogsettings.h"
+#include "bufferviewoverlay.h"
#include "clientbacklogmanager.h"
-BacklogRequester::BacklogRequester(bool buffering, ClientBacklogManager *backlogManager)
+BacklogRequester::BacklogRequester(bool buffering, RequesterType requesterType, ClientBacklogManager *backlogManager)
: backlogManager(backlogManager),
_isBuffering(buffering),
+ _requesterType(requesterType),
_totalBuffers(0)
{
Q_ASSERT(backlogManager);
return !_buffersWaiting.isEmpty();
}
+QList<BufferId> BacklogRequester::allBufferIds() const {
+ QSet<BufferId> bufferIds = Client::bufferViewOverlay()->bufferIds();
+ bufferIds += Client::bufferViewOverlay()->tempRemovedBufferIds();
+ return bufferIds.toList();
+}
+
// ========================================
// FIXED BACKLOG REQUESTER
// ========================================
FixedBacklogRequester::FixedBacklogRequester(ClientBacklogManager *backlogManager)
- : BacklogRequester(true, backlogManager)
+ : BacklogRequester(true, BacklogRequester::PerBufferFixed, backlogManager)
{
BacklogSettings backlogSettings;
_backlogCount = backlogSettings.fixedBacklogAmount();
}
-void FixedBacklogRequester::requestBacklog() {
- QList<BufferId> allBuffers = allBufferIds();
- setWaitingBuffers(allBuffers);
- backlogManager->emitMessagesRequested(QObject::tr("Requesting a total of up to %1 backlog messages for %2 buffers").arg(_backlogCount * allBuffers.count()).arg(allBuffers.count()));
- foreach(BufferId bufferId, allBuffers) {
+void FixedBacklogRequester::requestBacklog(const QList<BufferId> &bufferIds) {
+ setWaitingBuffers(bufferIds);
+ backlogManager->emitMessagesRequested(QObject::tr("Requesting a total of up to %1 backlog messages for %2 buffers").arg(_backlogCount * bufferIds.count()).arg(bufferIds.count()));
+ foreach(BufferId bufferId, bufferIds) {
backlogManager->requestBacklog(bufferId, -1, -1, _backlogCount);
}
}
// GLOBAL UNREAD BACKLOG REQUESTER
// ========================================
GlobalUnreadBacklogRequester::GlobalUnreadBacklogRequester(ClientBacklogManager *backlogManager)
- : BacklogRequester(false, backlogManager)
+ : BacklogRequester(false, BacklogRequester::GlobalUnread, backlogManager)
{
BacklogSettings backlogSettings;
_limit = backlogSettings.globalUnreadBacklogLimit();
// PER BUFFER UNREAD BACKLOG REQUESTER
// ========================================
PerBufferUnreadBacklogRequester::PerBufferUnreadBacklogRequester(ClientBacklogManager *backlogManager)
- : BacklogRequester(true, backlogManager)
+ : BacklogRequester(true, BacklogRequester::PerBufferUnread, backlogManager)
{
BacklogSettings backlogSettings;
_limit = backlogSettings.perBufferUnreadBacklogLimit();
_additional = backlogSettings.perBufferUnreadBacklogAdditional();
}
-void PerBufferUnreadBacklogRequester::requestBacklog() {
- QList<BufferId> allBuffers = allBufferIds();
- setWaitingBuffers(allBuffers);
- backlogManager->emitMessagesRequested(QObject::tr("Requesting a total of up to %1 unread backlog messages for %2 buffers").arg((_limit + _additional) * allBuffers.count()).arg(allBuffers.count()));
- foreach(BufferId bufferId, allBuffers) {
+void PerBufferUnreadBacklogRequester::requestBacklog(const QList<BufferId> &bufferIds) {
+ setWaitingBuffers(bufferIds);
+ backlogManager->emitMessagesRequested(QObject::tr("Requesting a total of up to %1 unread backlog messages for %2 buffers").arg((_limit + _additional) * bufferIds.count()).arg(bufferIds.count()));
+ foreach(BufferId bufferId, bufferIds) {
backlogManager->requestBacklog(bufferId, Client::networkModel()->lastSeenMsgId(bufferId), -1, _limit, _additional);
}
}
class BacklogRequester {
public:
- enum RequesterTypes {
+ enum RequesterType {
InvalidRequester = 0,
PerBufferFixed,
PerBufferUnread,
GlobalUnread
};
- BacklogRequester(bool buffering, ClientBacklogManager *backlogManger);
+ BacklogRequester(bool buffering, RequesterType requesterType, ClientBacklogManager *backlogManger);
virtual inline ~BacklogRequester() {}
inline bool isBuffering() { return _isBuffering; }
+ inline RequesterType type() { return _requesterType; }
inline const QList<Message> &bufferedMessages() { return _bufferedMessages; }
inline int buffersWaiting() const { return _buffersWaiting.count(); }
//! returns false if it was the last missing backlogpart
bool buffer(BufferId bufferId, const MessageList &messages);
- virtual void requestBacklog() = 0;
+ virtual inline void requestBacklog() { requestBacklog(allBufferIds()); }
+ virtual void requestBacklog(const QList<BufferId> &bufferIds) = 0;
protected:
- inline QList<BufferId> allBufferIds() const { return Client::networkModel()->allBufferIds(); }
+ QList<BufferId> allBufferIds() const;
inline void setWaitingBuffers(const QList<BufferId> &buffers) { setWaitingBuffers(buffers.toSet()); }
void setWaitingBuffers(const QSet<BufferId> &buffers);
void addWaitingBuffer(BufferId buffer);
private:
bool _isBuffering;
+ RequesterType _requesterType;
MessageList _bufferedMessages;
int _totalBuffers;
QSet<BufferId> _buffersWaiting;
class FixedBacklogRequester : public BacklogRequester {
public:
FixedBacklogRequester(ClientBacklogManager *backlogManager);
- virtual void requestBacklog();
+ virtual void requestBacklog(const QList<BufferId> &bufferIds);
private:
int _backlogCount;
public:
GlobalUnreadBacklogRequester(ClientBacklogManager *backlogManager);
virtual void requestBacklog();
+ virtual void requestBacklog(const QList<BufferId> &) {}
private:
int _limit;
class PerBufferUnreadBacklogRequester : public BacklogRequester {
public:
PerBufferUnreadBacklogRequester(ClientBacklogManager *backlogManager);
- virtual void requestBacklog();
+ virtual void requestBacklog(const QList<BufferId> &bufferIds);
private:
int _limit;
QSet<BufferId> removedBuffers;
QSet<BufferId> tempRemovedBuffers;
- BufferViewConfig *config = 0;
- QSet<int>::const_iterator viewIter;
- for(viewIter = _bufferViewIds.constBegin(); viewIter != _bufferViewIds.constEnd(); viewIter++) {
- config = Client::bufferViewManager()->bufferViewConfig(*viewIter);
- if(!config)
- continue;
-
- networkIds << config->networkId();
- buffers += config->bufferList().toSet();
- tempRemovedBuffers += config->temporarilyRemovedBuffers();
-
- // in the overlay a buffer is removed it is removed from all views
- if(removedBuffers.isEmpty())
- removedBuffers = config->removedBuffers();
- else
- removedBuffers.intersect(config->removedBuffers());
-
-
- addBuffersAutomatically |= config->addNewBuffersAutomatically();
- hideInactiveBuffers &= config->hideInactiveBuffers();
- allowedBufferTypes |= config->allowedBufferTypes();
- if(minimumActivity == -1 || config->minimumActivity() < minimumActivity)
- minimumActivity = config->minimumActivity();
+ if(Client::bufferViewManager()) {
+ BufferViewConfig *config = 0;
+ QSet<int>::const_iterator viewIter;
+ for(viewIter = _bufferViewIds.constBegin(); viewIter != _bufferViewIds.constEnd(); viewIter++) {
+ config = Client::bufferViewManager()->bufferViewConfig(*viewIter);
+ if(!config)
+ continue;
+ networkIds << config->networkId();
+ buffers += config->bufferList().toSet();
+ tempRemovedBuffers += config->temporarilyRemovedBuffers();
+
+ // in the overlay a buffer is removed it is removed from all views
+ if(removedBuffers.isEmpty())
+ removedBuffers = config->removedBuffers();
+ else
+ removedBuffers.intersect(config->removedBuffers());
+
+
+ addBuffersAutomatically |= config->addNewBuffersAutomatically();
+ hideInactiveBuffers &= config->hideInactiveBuffers();
+ allowedBufferTypes |= config->allowedBufferTypes();
+ if(minimumActivity == -1 || config->minimumActivity() < minimumActivity)
+ minimumActivity = config->minimumActivity();
+ }
}
changed |= (addBuffersAutomatically != _addBuffersAutomatically);
_debugLog(&_debugLogBuffer)
{
_signalProxy->synchronize(_ircListHelper);
+ connect(this, SIGNAL(requestInitialBacklog()), _backlogManager, SLOT(requestInitialBacklog()), Qt::QueuedConnection);
}
Client::~Client() {
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(bufferSyncer(), SIGNAL(initDone()), this, SLOT(requestInitialBacklog()));
connect(networkModel(), SIGNAL(setLastSeenMsg(BufferId, MsgId)), bufferSyncer(), SLOT(requestSetLastSeenMsg(BufferId, const MsgId &)));
signalProxy()->synchronize(bufferSyncer());
// create a new BufferViewManager
Q_ASSERT(!_bufferViewManager);
_bufferViewManager = new ClientBufferViewManager(signalProxy(), this);
- connect(bufferViewManager(), SIGNAL(initDone()), this, SLOT(requestInitialBacklog()));
connect(bufferViewManager(), SIGNAL(initDone()), this, SLOT(createDefaultBufferView()));
+ connect(bufferViewManager(), SIGNAL(viewsInitialized()), this, SLOT(requestInitialBacklogBarrier()));
_syncedToCore = true;
emit connected();
emit coreConnectionStateChanged(true);
}
-void Client::requestInitialBacklog() {
- if(bufferViewManager()->isInitialized() && bufferSyncer()->isInitialized())
- Client::backlogManager()->requestInitialBacklog();
+void Client::requestInitialBacklogBarrier() {
+ // 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(bufferViewManager(), SIGNAL(viewsInitialized()), this, SLOT(requestInitialBacklogBarrier()));
+ connect(bufferSyncer(), SIGNAL(initDone()), this, SLOT(requestInitialBacklogBarrier()));
+ return;
+ }
+ emit requestInitialBacklog();
}
void Client::createDefaultBufferView() {
static inline void registerClientSyncer(ClientSyncer *syncer) { emit instance()->newClientSyncer(syncer); }
signals:
+ void requestInitialBacklog();
void requestNetworkStates();
void showConfigWizard(const QVariantMap &coredata);
void setConnectedToCore(AccountId id, QIODevice *socket = 0);
void setSyncedToCore();
- void requestInitialBacklog();
+ void requestInitialBacklogBarrier();
void createDefaultBufferView();
private:
msglist << msg;
}
+ _backlogReceived << bufferId;
+
if(isBuffering()) {
bool lastPart = !_requester->buffer(bufferId, msglist);
updateProgress(_requester->totalBuffers() - _requester->buffersWaiting(), _requester->totalBuffers());
if(lastPart) {
stopBuffering();
- reset();
}
} else {
dispatchMessages(msglist);
}
dispatchMessages(msglist);
- reset();
}
void ClientBacklogManager::requestInitialBacklog() {
}
}
-void ClientBacklogManager::stopBuffering() {
+void ClientBacklogManager::checkForBacklog(const BufferId bufferId) {
+ if(_backlogReceived.contains(bufferId))
+ return;
+
+ QList<BufferId> bufferIds;
+ bufferIds << bufferId;
+ checkForBacklog(bufferIds);
+}
+
+void ClientBacklogManager::checkForBacklog(const QList<BufferId> &bufferIds) {
Q_ASSERT(_requester);
+ switch(_requester->type()) {
+ case BacklogRequester::GlobalUnread:
+ break;
+ case BacklogRequester::PerBufferUnread:
+ case BacklogRequester::PerBufferFixed:
+ default:
+ {
+ QList<BufferId> buffers;
+ foreach(BufferId bufferId, bufferIds)
+ if(!_backlogReceived.contains(bufferId))
+ buffers << bufferId;
+ _requester->requestBacklog(buffers);
+ }
+ };
+}
+void ClientBacklogManager::stopBuffering() {
+ Q_ASSERT(_requester);
dispatchMessages(_requester->bufferedMessages(), true);
}
void ClientBacklogManager::reset() {
delete _requester;
_requester = 0;
+ _backlogReceived.clear();
}
public slots:
virtual void receiveBacklog(BufferId bufferId, MsgId first, MsgId last, int limit, int additional, QVariantList msgs);
virtual void receiveBacklogAll(MsgId first, MsgId last, int limit, int additional, QVariantList msgs);
+
void requestInitialBacklog();
+ void checkForBacklog(BufferId bufferId);
+ void checkForBacklog(const QList<BufferId> &bufferIds);
+
signals:
void messagesReceived(BufferId bufferId, int count) const;
void messagesRequested(const QString &) const;
void dispatchMessages(const MessageList &messages, bool sort = false);
BacklogRequester *_requester;
+ QSet<BufferId> _backlogReceived;
};
#endif // CLIENTBACKLOGMANAGER_H
ClientBufferViewManager::ClientBufferViewManager(SignalProxy *proxy, QObject *parent)
: BufferViewManager(proxy, parent)
{
+ connect(this, SIGNAL(initDone()), this, SLOT(waitForConfigInit()));
}
BufferViewConfig *ClientBufferViewManager::bufferViewConfigFactory(int bufferViewConfigId) {
ClientBufferViewConfig *ClientBufferViewManager::clientBufferViewConfig(int bufferViewId) const {
return static_cast<ClientBufferViewConfig *>(bufferViewConfig(bufferViewId));
}
+
+void ClientBufferViewManager::waitForConfigInit() {
+ bool initialized = true;
+ foreach(BufferViewConfig *config, bufferViewConfigs()) {
+ initialized &= config->isInitialized();
+ if(config->isInitialized())
+ continue;
+ connect(config, SIGNAL(initDone()), this, SLOT(configInitBarrier()));
+ }
+ if(initialized)
+ emit viewsInitialized();
+}
+
+void ClientBufferViewManager::configInitBarrier() {
+ BufferViewConfig *config = qobject_cast<BufferViewConfig *>(sender());
+ Q_ASSERT(config);
+ disconnect(config, SIGNAL(initDone()), this, SLOT(configInitBarrier()));
+
+ bool initialized = true;
+ foreach(BufferViewConfig *config, bufferViewConfigs()) {
+ initialized &= config->isInitialized();
+ }
+ if(initialized)
+ emit viewsInitialized();
+}
protected:
virtual BufferViewConfig *bufferViewConfigFactory(int bufferViewConfigId);
+
+signals:
+ void viewsInitialized();
+
+private slots:
+ void waitForConfigInit();
+ void configInitBarrier();
};
#endif //CLIENTBUFFERVIEWMANAGER_H