backlogrequester.cpp
buffermodel.cpp
buffersettings.cpp
+ bufferviewoverlay.cpp
client.cpp
clientaliasmanager.cpp
clientbacklogmanager.cpp
abstractmessageprocessor.h
abstractui.h
buffermodel.h
+ bufferviewoverlay.h
client.h
clientaliasmanager.h
clientbacklogmanager.h
#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();
}
+BufferIdList 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 BufferIdList &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 BufferIdList &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 void requestBacklog(const BufferIdList &bufferIds) = 0;
+ virtual inline void requestBacklog() { requestBacklog(allBufferIds()); }
protected:
- inline QList<BufferId> allBufferIds() const { return Client::networkModel()->allBufferIds(); }
+ BufferIdList 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 BufferIdList &bufferIds);
private:
int _backlogCount;
public:
GlobalUnreadBacklogRequester(ClientBacklogManager *backlogManager);
virtual void requestBacklog();
+ virtual void requestBacklog(const BufferIdList &) {}
private:
int _limit;
class PerBufferUnreadBacklogRequester : public BacklogRequester {
public:
PerBufferUnreadBacklogRequester(ClientBacklogManager *backlogManager);
- virtual void requestBacklog();
+ virtual void requestBacklog(const BufferIdList &bufferIds);
private:
int _limit;
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005-08 by the Quassel Project *
+ * 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 "bufferviewoverlay.h"
+
+#include <QEvent>
+
+#include "bufferviewconfig.h"
+#include "client.h"
+#include "clientbufferviewmanager.h"
+#include "networkmodel.h"
+
+const int BufferViewOverlay::_updateEventId = QEvent::registerEventType();
+
+BufferViewOverlay::BufferViewOverlay(QObject *parent)
+ : QObject(parent),
+ _aboutToUpdate(false),
+ _addBuffersAutomatically(false),
+ _hideInactiveBuffers(false),
+ _allowedBufferTypes(0),
+ _minimumActivity(0)
+{
+}
+
+void BufferViewOverlay::addView(int viewId) {
+ if(_bufferViewIds.contains(viewId))
+ return;
+
+ BufferViewConfig *config = Client::bufferViewManager()->bufferViewConfig(viewId);
+ if(!config) {
+ qDebug() << "BufferViewOverlay::addView(): no such buffer view:" << viewId;
+ return;
+ }
+
+ _bufferViewIds << viewId;
+ if(config->isInitialized()) {
+ viewInitialized(config);
+ } else {
+ disconnect(config, SIGNAL(initDone()), this, SLOT(viewInitialized()));
+ connect(config, SIGNAL(initDone()), this, SLOT(viewInitialized()));
+ }
+}
+
+void BufferViewOverlay::removeView(int viewId) {
+ if(!_bufferViewIds.contains(viewId))
+ return;
+
+ _bufferViewIds.remove(viewId);
+ BufferViewConfig *config = qobject_cast<BufferViewConfig *>(sender());
+ if(config)
+ disconnect(config, 0, this, 0);
+ update();
+}
+
+void BufferViewOverlay::viewInitialized(BufferViewConfig *config) {
+ if(!config) {
+ qWarning() << "BufferViewOverlay::viewInitialized() received invalid view!";
+ return;
+ }
+ disconnect(config, SIGNAL(initDone()), this, SLOT(viewInitialized()));
+
+ connect(config, SIGNAL(networkIdSet(const NetworkId &)), this, SLOT(update()));
+ connect(config, SIGNAL(addNewBuffersAutomaticallySet(bool)), this, SLOT(update()));
+ connect(config, SIGNAL(sortAlphabeticallySet(bool)), this, SLOT(update()));
+ connect(config, SIGNAL(hideInactiveBuffersSet(bool)), this, SLOT(update()));
+ connect(config, SIGNAL(allowedBufferTypesSet(int)), this, SLOT(update()));
+ connect(config, SIGNAL(minimumActivitySet(int)), this, SLOT(update()));
+ connect(config, SIGNAL(bufferListSet()), this, SLOT(update()));
+ connect(config, SIGNAL(bufferAdded(const BufferId &, int)), this, SLOT(update()));
+ connect(config, SIGNAL(bufferRemoved(const BufferId &)), this, SLOT(update()));
+ connect(config, SIGNAL(bufferPermanentlyRemoved(const BufferId &)), this, SLOT(update()));
+
+ // check if the view was removed in the meantime...
+ if(_bufferViewIds.contains(config->bufferViewId()))
+ update();
+}
+
+void BufferViewOverlay::viewInitialized() {
+ BufferViewConfig *config = qobject_cast<BufferViewConfig *>(sender());
+ Q_ASSERT(config);
+
+ viewInitialized(config);
+}
+
+void BufferViewOverlay::update() {
+ if(_aboutToUpdate) {
+ return;
+ }
+ _aboutToUpdate = true;
+ QCoreApplication::postEvent(this, new QEvent((QEvent::Type)_updateEventId));
+}
+
+void BufferViewOverlay::updateHelper() {
+ bool changed = false;
+
+ bool addBuffersAutomatically = false;
+ bool hideInactiveBuffers = true;
+ int allowedBufferTypes = 0;
+ int minimumActivity = -1;
+ QSet<NetworkId> networkIds;
+ QSet<BufferId> buffers;
+ QSet<BufferId> removedBuffers;
+ QSet<BufferId> tempRemovedBuffers;
+
+ 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();
+ if(config->networkId().isValid()) {
+ NetworkId networkId = config->networkId();
+ // we have to filter out all the buffers that don't belong to this net... :/
+ QSet<BufferId> bufferIds;
+ foreach(BufferId bufferId, config->bufferList()) {
+ if(Client::networkModel()->networkId(bufferId) == networkId)
+ bufferIds << bufferId;
+ }
+ buffers += bufferIds;
+
+ bufferIds.clear();
+ foreach(BufferId bufferId, config->temporarilyRemovedBuffers()) {
+ if(Client::networkModel()->networkId(bufferId) == networkId)
+ bufferIds << bufferId;
+ }
+ tempRemovedBuffers += bufferIds;
+ } else {
+ 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);
+ changed |= (hideInactiveBuffers != _hideInactiveBuffers);
+ changed |= (allowedBufferTypes != _allowedBufferTypes);
+ changed |= (minimumActivity != _minimumActivity);
+ changed |= (networkIds != _networkIds);
+ changed |= (buffers != _buffers);
+ changed |= (removedBuffers != _removedBuffers);
+ changed |= (tempRemovedBuffers != _tempRemovedBuffers);
+
+ _addBuffersAutomatically = addBuffersAutomatically;
+ _hideInactiveBuffers = hideInactiveBuffers;
+ _allowedBufferTypes = allowedBufferTypes;
+ _minimumActivity = minimumActivity;
+ _networkIds = networkIds;
+ _buffers = buffers;
+ _removedBuffers = removedBuffers;
+ _tempRemovedBuffers = tempRemovedBuffers;
+
+ if(changed)
+ emit hasChanged();
+}
+
+void BufferViewOverlay::customEvent(QEvent *event) {
+ if(event->type() == _updateEventId) {
+ updateHelper();
+ _aboutToUpdate = false;
+ }
+}
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005-08 by the Quassel Project *
+ * 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 BUFFERVIEWOVERLAY_H
+#define BUFFERVIEWOVERLAY_H
+
+#include <QObject>
+
+#include "types.h"
+
+class BufferViewConfig;
+class ClientBufferViewConfig;
+
+class BufferViewOverlay : public QObject {
+ Q_OBJECT
+
+public:
+ BufferViewOverlay(QObject *parent = 0);
+
+ inline bool allNetworks() const { return _networkIds.contains(NetworkId()); }
+
+ inline const QSet<NetworkId> &networkIds() const { return _networkIds; }
+ inline const QSet<BufferId> &bufferIds() const { return _buffers; }
+ inline const QSet<BufferId> &removedBufferIds() const { return _removedBuffers; }
+ inline const QSet<BufferId> &tempRemovedBufferIds() const { return _tempRemovedBuffers; }
+
+ inline bool addBuffersAutomatically() const { return _addBuffersAutomatically; }
+ inline bool hideInactiveBuffers() const { return _hideInactiveBuffers; }
+ inline int allowedBufferTypes() const { return _allowedBufferTypes; }
+ inline int minimumActivity() const { return _minimumActivity; }
+
+public slots:
+ void addView(int viewId);
+ void removeView(int viewId);
+
+ // updates propagated from the actual views
+ void update();
+
+signals:
+ void hasChanged();
+
+protected:
+ virtual void customEvent(QEvent *event);
+
+private slots:
+ void viewInitialized();
+ void viewInitialized(BufferViewConfig *config);
+
+private:
+ void updateHelper();
+ bool _aboutToUpdate;
+
+ QSet<int> _bufferViewIds;
+
+ QSet<NetworkId> _networkIds;
+
+ bool _addBuffersAutomatically;
+ bool _hideInactiveBuffers;
+ int _allowedBufferTypes;
+ int _minimumActivity;
+
+ QSet<BufferId> _buffers;
+ QSet<BufferId> _removedBuffers;
+ QSet<BufferId> _tempRemovedBuffers;
+
+ static const int _updateEventId;
+};
+
+#endif //BUFFERVIEWOVERLAY_H
#include "buffersettings.h"
#include "buffersyncer.h"
#include "bufferviewconfig.h"
+#include "bufferviewoverlay.h"
#include "clientaliasmanager.h"
#include "clientbacklogmanager.h"
#include "clientbufferviewmanager.h"
_aliasManager(0),
_backlogManager(new ClientBacklogManager(this)),
_bufferViewManager(0),
+ _bufferViewOverlay(new BufferViewOverlay(this)),
_ircListHelper(new ClientIrcListHelper(this)),
_inputHandler(0),
_messageModel(0),
_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()));
// create AliasManager
Q_ASSERT(!_aliasManager);
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() {
class NetworkModel;
class BufferModel;
class BufferSyncer;
+class BufferViewOverlay;
class ClientAliasManager;
class ClientBacklogManager;
class ClientBufferViewManager;
static inline ClientBacklogManager *backlogManager() { return instance()->_backlogManager; }
static inline ClientIrcListHelper *ircListHelper() { return instance()->_ircListHelper; }
static inline ClientBufferViewManager *bufferViewManager() { return instance()->_bufferViewManager; }
+ static inline BufferViewOverlay *bufferViewOverlay() { return instance()->_bufferViewOverlay; }
static inline ClientUserInputHandler *inputHandler() { return instance()->_inputHandler; }
static AccountId currentCoreAccount();
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();
void sendBufferedUserInput();
ClientAliasManager *_aliasManager;
ClientBacklogManager *_backlogManager;
ClientBufferViewManager *_bufferViewManager;
+ BufferViewOverlay *_bufferViewOverlay;
ClientIrcListHelper *_ircListHelper;
ClientUserInputHandler *_inputHandler;
updateProgress(_requester->totalBuffers() - _requester->buffersWaiting(), _requester->totalBuffers());
if(lastPart) {
stopBuffering();
- reset();
}
} else {
dispatchMessages(msglist);
}
dispatchMessages(msglist);
- reset();
}
void ClientBacklogManager::requestInitialBacklog() {
}
}
-void ClientBacklogManager::stopBuffering() {
+BufferIdList ClientBacklogManager::filterNewBufferIds(const BufferIdList &bufferIds) {
+ BufferIdList newBuffers;
+ foreach(BufferId bufferId, bufferIds) {
+ if(!_buffersRequested.contains(bufferId))
+ newBuffers << bufferId;
+ }
+ _buffersRequested += bufferIds.toSet();
+ return newBuffers;
+}
+
+void ClientBacklogManager::checkForBacklog(const QList<BufferId> &bufferIds) {
Q_ASSERT(_requester);
+ switch(_requester->type()) {
+ case BacklogRequester::GlobalUnread:
+ break;
+ case BacklogRequester::PerBufferUnread:
+ case BacklogRequester::PerBufferFixed:
+ default:
+ {
+ BufferIdList buffers = filterNewBufferIds(bufferIds);
+ if(!buffers.isEmpty())
+ _requester->requestBacklog(buffers);
+ }
+ };
+}
+void ClientBacklogManager::stopBuffering() {
+ Q_ASSERT(_requester);
dispatchMessages(_requester->bufferedMessages(), true);
}
void ClientBacklogManager::reset() {
delete _requester;
_requester = 0;
+ _buffersRequested.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 BufferIdList &bufferIds);
+
signals:
void messagesReceived(BufferId bufferId, int count) const;
void messagesRequested(const QString &) const;
private:
bool isBuffering();
void stopBuffering();
+ BufferIdList filterNewBufferIds(const BufferIdList &bufferIds);
void dispatchMessages(const MessageList &messages, bool sort = false);
BacklogRequester *_requester;
+ QSet<BufferId> _buffersRequested;
};
+// inlines
+inline void ClientBacklogManager::checkForBacklog(BufferId bufferId) {
+ checkForBacklog(BufferIdList() << bufferId);
+}
+
#endif // CLIENTBACKLOGMANAGER_H
#include "clientbufferviewmanager.h"
+#include "bufferviewoverlay.h"
#include "clientbufferviewconfig.h"
ClientBufferViewManager::ClientBufferViewManager(SignalProxy *proxy, QObject *parent)
: BufferViewManager(proxy, parent)
{
+ connect(this, SIGNAL(initDone()), this, SLOT(waitForConfigInit()));
}
BufferViewConfig *ClientBufferViewManager::bufferViewConfigFactory(int bufferViewConfigId) {
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();
+}
#define CLIENTBUFFERVIEWMANAGER_H
#include "bufferviewmanager.h"
+
class ClientBufferViewConfig;
+class BufferViewOverlay;
class ClientBufferViewManager : public BufferViewManager {
Q_OBJECT
protected:
virtual BufferViewConfig *bufferViewConfigFactory(int bufferViewConfigId);
+
+signals:
+ void viewsInitialized();
+
+private slots:
+ void waitForConfigInit();
+ void configInitBarrier();
};
#endif //CLIENTBUFFERVIEWMANAGER_H
while(iter != msglist.constBegin()) {
iter--;
- if(!fastForward && (*iter).msgId() < minId)
+ if(!fastForward && (*iter).msgId() <= minId)
break;
processedMsgs++;
}
} else {
while(iter != msglist.constEnd()) {
- if(!fastForward && (*iter).msgId() < minId)
+ if(!fastForward && (*iter).msgId() <= minId)
break;
processedMsgs++;
Q_DECLARE_METATYPE(IdentityId)
Q_DECLARE_METATYPE(AccountId)
+// a few typedefs
+typedef QList<MsgId> MsgIdList;
+typedef QList<BufferId> BufferIdList;
+
//! Base class for exceptions.
struct Exception {
Exception(QString msg = "Unknown Exception") : _msg(msg) {};
protected:
QString _msg;
-
};
#endif
#include "actioncollection.h"
#include "buffermodel.h"
#include "bufferview.h"
+#include "bufferviewoverlay.h"
+#include "bufferviewoverlayfilter.h"
#include "bufferwidget.h"
#include "channellistdlg.h"
#include "chatlinemodel.h"
qApp, SLOT(aboutQt())));
coll->addAction("DebugNetworkModel", new Action(SmallIcon("tools-report-bug"), tr("Debug &NetworkModel"), coll,
this, SLOT(on_actionDebugNetworkModel_triggered())));
+ coll->addAction("DebugBufferViewOverlay", new Action(SmallIcon("tools-report-bug"), tr("Debug &BufferViewOverlay"), coll,
+ this, SLOT(on_actionDebugBufferViewOverlay_triggered())));
coll->addAction("DebugMessageModel", new Action(SmallIcon("tools-report-bug"), tr("Debug &MessageModel"), coll,
this, SLOT(on_actionDebugMessageModel_triggered())));
coll->addAction("DebugLog", new Action(SmallIcon("tools-report-bug"), tr("Debug &Log"), coll,
_helpMenu->addSeparator();
_helpDebugMenu = _helpMenu->addMenu(SmallIcon("tools-report-bug"), tr("Debug"));
_helpDebugMenu->addAction(coll->action("DebugNetworkModel"));
+ _helpDebugMenu->addAction(coll->action("DebugBufferViewOverlay"));
_helpDebugMenu->addAction(coll->action("DebugMessageModel"));
_helpDebugMenu->addAction(coll->action("DebugLog"));
}
addDockWidget(Qt::LeftDockWidgetArea, dock);
_bufferViewsMenu->addAction(dock->toggleViewAction());
+ connect(dock->toggleViewAction(), SIGNAL(toggled(bool)), this, SLOT(bufferViewToggled(bool)));
_bufferViews.append(dock);
}
}
}
+void MainWin::bufferViewToggled(bool enabled) {
+ QAction *action = qobject_cast<QAction *>(sender());
+ Q_ASSERT(action);
+ BufferViewDock *dock = qobject_cast<BufferViewDock *>(action->parent());
+ Q_ASSERT(dock);
+ if(enabled) {
+ Client::bufferViewOverlay()->addView(dock->bufferViewId());
+ BufferViewConfig *config = dock->config();
+ if(config && config->isInitialized()) {
+ BufferIdList buffers;
+ if(config->networkId().isValid()) {
+ foreach(BufferId bufferId, config->bufferList()) {
+ if(Client::networkModel()->networkId(bufferId) == config->networkId())
+ buffers << bufferId;
+ }
+ foreach(BufferId bufferId, config->temporarilyRemovedBuffers().toList()) {
+ if(Client::networkModel()->networkId(bufferId) == config->networkId())
+ buffers << bufferId;
+ }
+ } else {
+ buffers = BufferIdList::fromSet(config->bufferList().toSet() + config->temporarilyRemovedBuffers());
+ }
+ Client::backlogManager()->checkForBacklog(buffers);
+ }
+ } else {
+ Client::bufferViewOverlay()->removeView(dock->bufferViewId());
+ }
+}
+
BufferView *MainWin::allBuffersView() const {
// "All Buffers" is always the first dock created
if(_bufferViews.count() > 0)
view->show();
}
+void MainWin::on_actionDebugBufferViewOverlay_triggered() {
+ QTreeView *view = new QTreeView;
+ view->setAttribute(Qt::WA_DeleteOnClose);
+ view->setWindowTitle("Debug BufferViewOverlay View");
+ BufferViewOverlayFilter *filter = new BufferViewOverlayFilter(Client::bufferModel(), Client::bufferViewOverlay());
+ filter->setParent(view);
+ view->setModel(filter);
+ view->setColumnWidth(0, 250);
+ view->setColumnWidth(1, 250);
+ view->setColumnWidth(2, 80);
+ view->resize(610, 300);
+ view->show();
+}
+
void MainWin::on_actionDebugMessageModel_triggered() {
QTableView *view = new QTableView(0);
DebugMessageModelFilter *filter = new DebugMessageModelFilter(view);
void on_actionConfigureViews_triggered();
void on_actionLockLayout_toggled(bool lock);
void on_actionDebugNetworkModel_triggered();
+ void on_actionDebugBufferViewOverlay_triggered();
void on_actionDebugMessageModel_triggered();
void on_actionDebugLog_triggered();
void loadLayout();
void saveLayout();
+ void bufferViewToggled(bool enabled);
+
signals:
void connectToCore(const QVariantMap &connInfo);
void disconnectFromCore();
actioncollection.cpp
bufferview.cpp
bufferviewfilter.cpp
+ bufferviewoverlayfilter.cpp
clearablelineedit.cpp
clickablelabel.cpp
colorbutton.cpp
actioncollection.h
bufferview.h
bufferviewfilter.h
+ bufferviewoverlayfilter.h
clearablelineedit.h
clickablelabel.h
colorbutton.h
#include "abstractbuffercontainer.h"
#include "client.h"
+#include "clientbacklogmanager.h"
#include "networkmodel.h"
AbstractBufferContainer::AbstractBufferContainer(QWidget *parent)
_currentBuffer = bufferId;
showChatView(bufferId);
Client::networkModel()->clearBufferActivity(bufferId);
+ Client::backlogManager()->checkForBacklog(bufferId);
setFocus();
}
setWindowTitle(newName);
toggleViewAction()->setText(newName);
}
+
+int BufferViewDock::bufferViewId() const {
+ BufferView *view = bufferView();
+ if(!view)
+ return 0;
+
+ if(view->config())
+ return view->config()->bufferViewId();
+ else
+ return 0;
+}
+
+BufferViewConfig *BufferViewDock::config() const {
+ BufferView *view = bufferView();
+ if(!view)
+ return 0;
+ else
+ return view->config();
+}
public:
BufferViewDock(BufferViewConfig *config, QWidget *parent);
+ int bufferViewId() const;
+ BufferViewConfig *config() const;
inline BufferView *bufferView() const { return qobject_cast<BufferView *>(widget()); }
public slots:
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005-09 by the Quassel Project *
+ * 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 "bufferviewoverlayfilter.h"
+
+#include "bufferviewoverlay.h"
+#include "networkmodel.h"
+#include "types.h"
+
+BufferViewOverlayFilter::BufferViewOverlayFilter(QAbstractItemModel *model, BufferViewOverlay *overlay)
+ : QSortFilterProxyModel(model),
+ _overlay(0)
+{
+ setOverlay(overlay);
+ setSourceModel(model);
+
+ setDynamicSortFilter(true);
+}
+
+void BufferViewOverlayFilter::setOverlay(BufferViewOverlay *overlay) {
+ if(_overlay == overlay)
+ return;
+
+ if(_overlay) {
+ disconnect(_overlay, 0, this, 0);
+ }
+
+ _overlay = overlay;
+
+ if(!overlay) {
+ invalidate();
+ return;
+ }
+
+ connect(overlay, SIGNAL(destroyed()), this, SLOT(overlayDestroyed()));
+ connect(overlay, SIGNAL(hasChanged()), this, SLOT(invalidate()));
+ invalidate();
+}
+
+void BufferViewOverlayFilter::overlayDestroyed() {
+ setOverlay(0);
+}
+
+bool BufferViewOverlayFilter::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const {
+ if(!_overlay)
+ return false;
+
+ QModelIndex source_bufferIndex = sourceModel()->index(source_row, 0, source_parent);
+
+ if(!source_bufferIndex.isValid()) {
+ qWarning() << "filterAcceptsRow has been called with an invalid Child";
+ return false;
+ }
+
+ NetworkId networkId = sourceModel()->data(source_bufferIndex, NetworkModel::NetworkIdRole).value<NetworkId>();
+ if(!_overlay->networkIds().contains(networkId) && ! _overlay->allNetworks())
+ return false;
+
+ int activityLevel = sourceModel()->data(source_bufferIndex, NetworkModel::BufferActivityRole).toInt();
+ if(_overlay->minimumActivity() > activityLevel)
+ return false;
+
+ bool isActive = sourceModel()->data(source_bufferIndex, NetworkModel::ItemActiveRole).toBool();
+ if(_overlay->hideInactiveBuffers() && !isActive && activityLevel <= BufferInfo::OtherActivity)
+ return false;
+
+ int bufferType = sourceModel()->data(source_bufferIndex, NetworkModel::BufferTypeRole).toInt();
+ if(!(_overlay->allowedBufferTypes() & bufferType))
+ return false;
+
+ BufferId bufferId = sourceModel()->data(source_bufferIndex, NetworkModel::BufferIdRole).value<BufferId>();
+ Q_ASSERT(bufferId.isValid());
+
+ if(_overlay->bufferIds().contains(bufferId))
+ return true;
+
+ if(_overlay->tempRemovedBufferIds().contains(bufferId))
+ return activityLevel > BufferInfo::OtherActivity;
+
+ if(_overlay->removedBufferIds().contains(bufferId))
+ return false;
+
+ // the buffer is not known to us
+ return _overlay->addBuffersAutomatically();
+}
+
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005-09 by the Quassel Project *
+ * 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 BUFFERVIEWOVERLAYFILTER_H_
+#define BUFFERVIEWOVERLAYFILTER_H_
+
+#include <QSortFilterProxyModel>
+
+#include "types.h"
+
+class BufferViewOverlay;
+
+class BufferViewOverlayFilter : public QSortFilterProxyModel {
+ Q_OBJECT
+
+public:
+ BufferViewOverlayFilter(QAbstractItemModel *model, BufferViewOverlay *overlay = 0);
+
+ void setOverlay(BufferViewOverlay *overlay);
+
+protected:
+ bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
+
+private slots:
+ void overlayDestroyed();
+
+private:
+ BufferViewOverlay *_overlay;
+};
+
+#endif // BUFFERVIEWOVERLAYFILTER_H_