backlogrequester.cpp
buffermodel.cpp
buffersettings.cpp
+ bufferviewoverlay.cpp
client.cpp
+ clientaliasmanager.cpp
clientbacklogmanager.cpp
clientbufferviewconfig.cpp
clientbufferviewmanager.cpp
clientsettings.cpp
clientsyncer.cpp
clientuserinputhandler.cpp
+ execwrapper.cpp
irclistmodel.cpp
messagefilter.cpp
messagemodel.cpp
abstractmessageprocessor.h
abstractui.h
buffermodel.h
+ bufferviewoverlay.h
client.h
+ clientaliasmanager.h
clientbacklogmanager.h
clientbufferviewconfig.h
clientbufferviewmanager.h
clientirclisthelper.h
clientuserinputhandler.h
clientsyncer.h
+ execwrapper.h
irclistmodel.h
messagefilter.h
messagemodel.h
#include "buffersettings.h"
#include "buffersyncer.h"
#include "bufferviewconfig.h"
+ #include "bufferviewoverlay.h"
+#include "clientaliasmanager.h"
#include "clientbacklogmanager.h"
#include "clientbufferviewmanager.h"
#include "clientirclisthelper.h"
/*** Initialization/destruction ***/
+bool Client::instanceExists()
+{
+ return instanceptr;
+}
+
Client *Client::instance() {
if(!instanceptr)
instanceptr = new Client();
_networkModel(0),
_bufferModel(0),
_bufferSyncer(0),
+ _aliasManager(0),
_backlogManager(new ClientBacklogManager(this)),
_bufferViewManager(0),
+ _bufferViewOverlay(new BufferViewOverlay(this)),
_ircListHelper(new ClientIrcListHelper(this)),
- _inputHandler(new ClientUserInputHandler(this)),
+ _inputHandler(0),
_messageModel(0),
_messageProcessor(0),
_connectedToCore(false),
_debugLog(&_debugLogBuffer)
{
_signalProxy->synchronize(_ircListHelper);
+ connect(this, SIGNAL(requestInitialBacklog()), _backlogManager, SLOT(requestInitialBacklog()), Qt::QueuedConnection);
}
Client::~Client() {
_bufferModel = new BufferModel(_networkModel);
_messageModel = mainUi()->createMessageModel(this);
_messageProcessor = mainUi()->createMessageProcessor(this);
+ _inputHandler = new ClientUserInputHandler(this);
SignalProxy *p = signalProxy();
}
}
-/*** ***/
+/*** User input handling ***/
+
void Client::userInput(const BufferInfo &bufferInfo, const QString &message) {
- inputHandler()->handleUserInput(bufferInfo, 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));
+}
+
+void Client::sendBufferedUserInput() {
+ for(int i = 0; i < _userInputBuffer.count(); i++)
+ userInput(_userInputBuffer.at(i).first, _userInputBuffer.at(i).second);
+
+ _userInputBuffer.clear();
}
/*** core connection stuff ***/
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);
+ _aliasManager = new ClientAliasManager(this);
+ connect(aliasManager(), SIGNAL(initDone()), SLOT(sendBufferedUserInput()));
+ signalProxy()->synchronize(aliasManager());
+
_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() {
_bufferViewManager = 0;
}
+ if(_aliasManager) {
+ _aliasManager->deleteLater();
+ _aliasManager = 0;
+ }
+
+ // we probably don't want to save pending input for reconnect
+ _userInputBuffer.clear();
+
_messageModel->clear();
_networkModel->clear();
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);
}
class NetworkModel;
class BufferModel;
class BufferSyncer;
+ class BufferViewOverlay;
+class ClientAliasManager;
class ClientBacklogManager;
class ClientBufferViewManager;
class ClientIrcListHelper;
RemoteCore
};
+ static bool instanceExists();
static Client *instance();
static void destroy();
static void init(AbstractUi *);
static inline AbstractMessageProcessor *messageProcessor() { return instance()->_messageProcessor; }
static inline SignalProxy *signalProxy() { return instance()->_signalProxy; }
+ static inline ClientAliasManager *aliasManager() { return instance()->_aliasManager; }
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();
+
private:
Client(QObject *parent = 0);
virtual ~Client();
NetworkModel * _networkModel;
BufferModel * _bufferModel;
BufferSyncer * _bufferSyncer;
+ ClientAliasManager *_aliasManager;
ClientBacklogManager *_backlogManager;
ClientBufferViewManager *_bufferViewManager;
+ BufferViewOverlay *_bufferViewOverlay;
ClientIrcListHelper *_ircListHelper;
ClientUserInputHandler *_inputHandler;
QString _debugLogBuffer;
QTextStream _debugLog;
+ QList<QPair<BufferInfo, QString> > _userInputBuffer;
+
friend class ClientSyncer;
};
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++;
_nextDayChange = _nextDayChange.addSecs(86400);
}
+void MessageModel::insertErrorMessage(BufferInfo bufferInfo, const QString &errorString) {
+ int idx = messageCount();
+ beginInsertRows(QModelIndex(), idx, idx);
+ Message msg(bufferInfo, Message::Error, errorString);
+ if(!messagesIsEmpty())
+ msg.setMsgId(messageItemAt(idx-1)->msgId());
+ else
+ msg.setMsgId(0);
+ insertMessage__(idx, msg);
+ endInsertRows();
+}
+
void MessageModel::requestBacklog(BufferId bufferId) {
if(_messagesWaiting.contains(bufferId))
return;
#include "actioncollection.h"
#include "buffermodel.h"
#include "bufferview.h"
+ #include "bufferviewoverlay.h"
+ #include "bufferviewoverlayfilter.h"
#include "bufferwidget.h"
#include "channellistdlg.h"
#include "chatlinemodel.h"
connect(lockAct, SIGNAL(toggled(bool)), SLOT(on_actionLockLayout_toggled(bool)));
coll->addAction("ToggleSearchBar", new Action(SmallIcon("edit-find"), tr("Show &Search Bar"), coll,
- 0, 0, tr("Ctrl+F")))->setCheckable(true);
+ 0, 0, QKeySequence::Find))->setCheckable(true);
coll->addAction("ShowAwayLog", new Action(tr("Show Away Log"), coll,
this, SLOT(showAwayLog())));
coll->addAction("ToggleStatusBar", new Action(tr("Show Status &Bar"), coll,
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);