will clear activity for that buffer in other clients too.
NOTE: Activity state is not yet remembered between core restarts,
since there are still some database issues.
Client/core protocol updated, distclean mandatory.
# KDevelop Custom Project File List
-Makefile
build
build/buildconf.pri
build/contrib
src/common
src/common/bufferinfo.cpp
src/common/bufferinfo.h
+src/common/buffersyncer.cpp
+src/common/buffersyncer.h
src/common/common.pri
src/common/global.cpp
src/common/global.h
src/qtopia/ui/mainwidget.ui
src/qtopia/ui/nicklistwidget.ui
src/qtui
+src/qtui/aboutdlg.cpp
+src/qtui/aboutdlg.h
src/qtui/bufferwidget.cpp
src/qtui/bufferwidget.h
src/qtui/chatitem.cpp
src/qtui/chatwidget.h
src/qtui/configwizard.cpp
src/qtui/configwizard.h
+src/qtui/coreconfigwizard.cpp
+src/qtui/coreconfigwizard.h
src/qtui/coreconnectdlg.cpp
src/qtui/coreconnectdlg.h
src/qtui/debugconsole.cpp
src/qtui/debugconsole.h
+src/qtui/inputwidget.cpp
+src/qtui/inputwidget.h
+src/qtui/jumpkeyhandler.cpp
+src/qtui/jumpkeyhandler.h
src/qtui/mainwin.cpp
src/qtui/mainwin.h
src/qtui/nicklistwidget.cpp
src/qtui/qtuistyle.h
src/qtui/settingsdlg.cpp
src/qtui/settingsdlg.h
+src/qtui/settingspagedlg.cpp
+src/qtui/settingspagedlg.h
src/qtui/settingspages
src/qtui/settingspages/colorsettingspage.cpp
src/qtui/settingspages/colorsettingspage.h
+src/qtui/settingspages/colorsettingspage.ui
src/qtui/settingspages/createidentitydlg.ui
src/qtui/settingspages/fontssettingspage.cpp
src/qtui/settingspages/fontssettingspage.h
src/qtui/settingspages/fontssettingspage.ui
src/qtui/settingspages/generalsettingspage.cpp
src/qtui/settingspages/generalsettingspage.h
+src/qtui/settingspages/generalsettingspage.ui
src/qtui/settingspages/identitiessettingspage.cpp
src/qtui/settingspages/identitiessettingspage.h
src/qtui/settingspages/identitiessettingspage.ui
+src/qtui/settingspages/networkeditdlg.ui
src/qtui/settingspages/networkssettingspage.cpp
src/qtui/settingspages/networkssettingspage.h
src/qtui/settingspages/networkssettingspage.ui
+src/qtui/settingspages/nickeditdlg.ui
src/qtui/settingspages/saveidentitiesdlg.ui
+src/qtui/settingspages/servereditdlg.ui
src/qtui/settingspages/settingspages.pri
src/qtui/topicwidget.cpp
src/qtui/topicwidget.h
src/qtui/ui/nicklistwidget.ui
src/qtui/ui/settingsdlg.ui
src/qtui/ui/topicwidget.ui
+src/qtui/verticaldock.cpp
+src/qtui/verticaldock.h
src/uisupport
+src/uisupport/action.cpp
+src/uisupport/action.h
+src/uisupport/actioncollection.cpp
+src/uisupport/actioncollection.h
src/uisupport/bufferview.cpp
src/uisupport/bufferview.h
src/uisupport/bufferviewfilter.cpp
src/uisupport/inputline.h
src/uisupport/nickview.cpp
src/uisupport/nickview.h
+src/uisupport/nickviewfilter.cpp
+src/uisupport/nickviewfilter.h
src/uisupport/settingspage.cpp
src/uisupport/settingspage.h
src/uisupport/tabcompleter.cpp
#include "buffer.h"
+#include "buffersyncer.h"
#include "client.h"
+#include "networkmodel.h"
+#include "quasselui.h"
#include "util.h"
Buffer::Buffer(BufferInfo bufferid, QObject *parent)
: QObject(parent),
- _bufferInfo(bufferid)
+ _bufferInfo(bufferid),
+ _isVisible(false),
+ _activityLevel(NoActivity)
{
+
}
BufferInfo Buffer::bufferInfo() const {
}
void Buffer::appendMsg(const Message &msg) {
+ updateActivityLevel(msg);
AbstractUiMsg *m = Client::layoutMsg(msg);
layoutedMsgs.append(m);
emit msgAppended(m);
}
void Buffer::prependMsg(const Message &msg) {
+ updateActivityLevel(msg);
layoutQueue.append(msg);
}
return layoutQueue.count();
}
+void Buffer::setVisible(bool visible) {
+ _isVisible = visible;
+ setActivityLevel(NoActivity);
+ if(!layoutedMsgs.count()) return;
+ setLastSeen(layoutedMsgs.last()->timestamp());
+}
+
+void Buffer::setLastSeen(const QDateTime &seen) {
+ if(seen.isValid() && seen > lastSeen()) { //qDebug() << "setting:" << bufferInfo().bufferName() << seen;
+ _lastSeen = seen;
+ Client::bufferSyncer()->requestSetLastSeen(bufferInfo().bufferId(), seen);
+ setActivityLevel(NoActivity);
+ }
+}
+
+void Buffer::setActivityLevel(ActivityLevel level) {
+ _activityLevel = level;
+ if(bufferInfo().bufferId() > 0) Client::networkModel()->setBufferActivity(bufferInfo(), level);
+}
+
+void Buffer::updateActivityLevel(const Message &msg) {
+ if(isVisible()) return;
+ if(lastSeen().isValid() && lastSeen() >= msg.timestamp()) return;
+
+ ActivityLevel level = activityLevel() | OtherActivity;
+ if(msg.type() == Message::Plain || msg.type() == Message::Notice) level |= NewMessage;
+ if(msg.flags() & Message::Highlight) level |= Highlight;
+
+ if(level != activityLevel()) setActivityLevel(level);
+}
#ifndef _BUFFER_H_
#define _BUFFER_H_
+#include <QDateTime>
+
class AbstractUiMsg;
class IrcChannel;
class NickModel;
#include "message.h"
#include "bufferinfo.h"
-//!\brief Encapsulates the contents of a single channel, query or server status context.
-/** A Buffer maintains a list of existing nicks and their status.
+/// Encapsulates the contents of a single channel, query or server status context.
+/**
*/
class Buffer : public QObject {
Q_OBJECT
public:
+ enum Activity {
+ NoActivity = 0x00,
+ OtherActivity = 0x01,
+ NewMessage = 0x02,
+ Highlight = 0x40
+ };
+ Q_DECLARE_FLAGS(ActivityLevel, Activity)
+
Buffer(BufferInfo, QObject *parent = 0);
BufferInfo bufferInfo() const;
-
QList<AbstractUiMsg *> contents() const;
-
+ inline bool isVisible() const { return _isVisible; }
+ inline QDateTime lastSeen() const { return _lastSeen; }
+ inline ActivityLevel activityLevel() const { return _activityLevel; }
+
signals:
void msgAppended(AbstractUiMsg *);
void msgPrepended(AbstractUiMsg *);
void appendMsg(const Message &);
void prependMsg(const Message &);
bool layoutMsg();
+ void setVisible(bool visible);
+ void setLastSeen(const QDateTime &);
+ void setActivityLevel(ActivityLevel level);
private:
BufferInfo _bufferInfo;
+ bool _isVisible;
+ QDateTime _lastSeen;
+ ActivityLevel _activityLevel;
QList<Message> layoutQueue;
QList<AbstractUiMsg *> layoutedMsgs;
+ void updateActivityLevel(const Message &msg);
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(Buffer::ActivityLevel)
+
#endif
// initialize the Property Mapper
_propertyMapper.setModel(this);
_selectionModelSynchronizer.addRegularSelectionModel(_propertyMapper.selectionModel());
- connect(_propertyMapper.selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)),
- this, SLOT(currentChanged(QModelIndex, QModelIndex)));
}
BufferModel::~BufferModel() {
QModelIndex BufferModel::currentIndex() {
return propertyMapper()->selectionModel()->currentIndex();
}
-
-void BufferModel::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) {
- Q_UNUSED(current);
- setData(current, QDateTime::currentDateTime(), NetworkModel::LastSeenRole);
- setData(previous, QDateTime::currentDateTime(), NetworkModel::LastSeenRole);
- setData(previous, qVariantFromValue((int)BufferItem::NoActivity), NetworkModel::BufferActivityRole);
-}
QModelIndex currentIndex();
-private slots:
- void currentChanged(const QModelIndex ¤t, const QModelIndex &previous);
-
private:
SelectionModelSynchronizer _selectionModelSynchronizer;
ModelPropertyMapper _propertyMapper;
#include "client.h"
#include "bufferinfo.h"
+#include "buffersyncer.h"
#include "global.h"
#include "identity.h"
#include "ircchannel.h"
mainUi(0),
_networkModel(0),
_bufferModel(0),
+ _bufferSyncer(0),
_connectedToCore(false),
_syncedToCore(false)
{
return buff;
}
-Buffer *Client::monitorBuffer() {
- return instance()->_monitorBuffer;
-}
-
-
-NetworkModel *Client::networkModel() {
- return instance()->_networkModel;
-}
-
-BufferModel *Client::bufferModel() {
- return instance()->_bufferModel;
-}
-
-SignalProxy *Client::signalProxy() {
- return instance()->_signalProxy;
-}
-
bool Client::isConnected() {
return instance()->_connectedToCore;
}
}
void Client::setSyncedToCore() {
+ // create buffersyncer
+ Q_ASSERT(!_bufferSyncer);
+ _bufferSyncer = new BufferSyncer(this);
+ connect(bufferSyncer(), SIGNAL(lastSeenSet(BufferId, const QDateTime &)), this, SLOT(updateLastSeen(BufferId, const QDateTime &)));
+ signalProxy()->synchronize(bufferSyncer());
+
_syncedToCore = true;
emit connected();
emit coreConnectionStateChanged(true);
emit coreConnectionStateChanged(false);
// Clear internal data. Hopefully nothing relies on it at this point.
+ _bufferSyncer->deleteLater();
+ _bufferSyncer = 0;
_networkModel->clear();
+ QHash<BufferId, Buffer *>::iterator bufferIter = _buffers.begin();
+ while(bufferIter != _buffers.end()) {
+ Buffer *buffer = bufferIter.value();
+ disconnect(buffer, SIGNAL(destroyed()), this, 0);
+ bufferIter = _buffers.erase(bufferIter);
+ buffer->deleteLater();
+ }
+ Q_ASSERT(_buffers.isEmpty());
+
QHash<NetworkId, Network*>::iterator netIter = _networks.begin();
while(netIter != _networks.end()) {
Network *net = netIter.value();
}
Q_ASSERT(_networks.isEmpty());
- QHash<BufferId, Buffer *>::iterator bufferIter = _buffers.begin();
- while(bufferIter != _buffers.end()) {
- Buffer *buffer = bufferIter.value();
- disconnect(buffer, SIGNAL(destroyed()), this, 0);
- bufferIter = _buffers.erase(bufferIter);
- buffer->deleteLater();
- }
- Q_ASSERT(_buffers.isEmpty());
-
QHash<IdentityId, Identity*>::iterator idIter = _identities.begin();
while(idIter != _identities.end()) {
Identity *id = idIter.value();
} else {
b = buffer(msg.bufferInfo());
}
-
+
checkForHighlight(msg);
b->appendMsg(msg);
- networkModel()->updateBufferActivity(msg);
-
+ //bufferModel()->updateBufferActivity(msg);
+
if(msg.type() == Message::Plain || msg.type() == Message::Notice || msg.type() == Message::Action) {
const Network *net = network(msg.bufferInfo().networkId());
QString networkName = net != 0
Message mmsg = Message(msg.timestamp(), msg.bufferInfo(), msg.type(), msg.text(), sender, msg.flags());
monitorBuffer()->appendMsg(mmsg);
}
-
}
void Client::recvStatusMsg(QString /*net*/, QString /*msg*/) {
Message msg = v.value<Message>();
checkForHighlight(msg);
b->prependMsg(msg);
- networkModel()->updateBufferActivity(msg);
+ //networkModel()->updateBufferActivity(msg);
if(!layoutQueue.contains(b)) layoutQueue.append(b);
}
if(layoutQueue.count() && !layoutTimer->isActive()) layoutTimer->start();
return instance()->mainUi->layoutMsg(msg);
}
-void Client::checkForHighlight(Message &msg) const {
+void Client::checkForHighlight(Message &msg) {
const Network *net = network(msg.bufferInfo().networkId());
if(net && !net->myNick().isEmpty()) {
QRegExp nickRegExp("^(.*\\W)?" + QRegExp::escape(net->myNick()) + "(\\W.*)?$");
msg.setFlags(msg.flags() | Message::Highlight);
}
}
+
+void Client::updateLastSeen(BufferId id, const QDateTime &lastSeen) {
+ Buffer *b = buffer(id);
+ if(!b) {
+ qWarning() << "Client::updateLastSeen(): Unknown buffer" << id;
+ return;
+ }
+ b->setLastSeen(lastSeen);
+}
+
+void Client::setBufferLastSeen(BufferId id, const QDateTime &lastSeen) {
+ if(!bufferSyncer()) return;
+ bufferSyncer()->requestSetLastSeen(id, lastSeen);
+}
+
+
#include <QPointer>
#include "buffer.h" // needed for activity lvl
+
class BufferInfo;
class Message;
class AbstractUiMsg;
class NetworkModel;
class BufferModel;
+class BufferSyncer;
class IrcUser;
class IrcChannel;
class SignalProxy;
static QList<Buffer *> buffers();
static Buffer *buffer(BufferId bufferUid);
static Buffer *buffer(BufferInfo);
- static Buffer *monitorBuffer();
+ static inline Buffer *monitorBuffer() { return instance()->_monitorBuffer; }
static QList<NetworkId> networkIds();
static const Network * network(NetworkId);
static void updateNetwork(const NetworkInfo &info);
static void removeNetwork(NetworkId id);
- static NetworkModel *networkModel();
- static BufferModel *bufferModel();
- static SignalProxy *signalProxy();
+ static inline NetworkModel *networkModel() { return instance()->_networkModel; }
+ static inline BufferModel *bufferModel() { return instance()->_bufferModel; }
+ static inline SignalProxy *signalProxy() { return instance()->_signalProxy; }
+ static inline BufferSyncer *bufferSyncer() { return instance()->_bufferSyncer; }
static AccountId currentCoreAccount();
enum ClientMode { LocalCore, RemoteCore };
- void checkForHighlight(Message &msg) const;
-
+ static void checkForHighlight(Message &msg);
+ static void setBufferLastSeen(BufferId id, const QDateTime &seen); // this is synced to core and other clients
+
signals:
void sendInput(BufferInfo, QString message);
void showBuffer(Buffer *);
void recvStatusMsg(QString network, QString message);
void recvBacklogData(BufferInfo, QVariantList, bool);
void updateBufferInfo(BufferInfo);
+ void updateLastSeen(BufferId id, const QDateTime &lastSeen);
void layoutMsg();
static QPointer<Client> instanceptr;
QPointer<QIODevice> socket;
- QPointer<SignalProxy> _signalProxy;
- QPointer<AbstractUi> mainUi;
- QPointer<NetworkModel> _networkModel;
- QPointer<BufferModel> _bufferModel;
+
+ SignalProxy * _signalProxy;
+ AbstractUi * mainUi;
+ NetworkModel * _networkModel;
+ BufferModel * _bufferModel;
+ BufferSyncer * _bufferSyncer;
ClientMode clientMode;
// Core has accepted our version info and sent its own. Let's see if we accept it as well...
if(msg["CoreBuild"].toUInt() < Global::coreBuildNeeded) {
emit connectionError(tr("<b>The Quassel Core you are trying to connect to is too old!</b><br>"
- "Need at least a Core Version %1 (Build >= %2) to connect.").arg(Global::quasselVersion).arg(Global::quasselBuild));
+ "Need at least a Core Version %1 (Build >= %2) to connect.").arg(Global::quasselVersion).arg(Global::coreBuildNeeded));
disconnectFromCore();
return;
}
BufferItem::BufferItem(BufferInfo bufferInfo, AbstractTreeItem *parent)
: PropertyMapItem(QStringList() << "bufferName" << "topic" << "nickCount", parent),
_bufferInfo(bufferInfo),
- _activity(NoActivity)
+ _activity(Buffer::NoActivity)
{
Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
if(bufferType() == BufferInfo::QueryBuffer)
flags |= Qt::ItemIsDropEnabled;
setFlags(flags);
-
- _lastSeen = BufferSettings(bufferInfo.bufferId()).lastSeen();
}
const BufferInfo &BufferItem::bufferInfo() const {
return qobject_cast<NetworkItem *>(parent())->isActive();
}
-BufferItem::ActivityLevel BufferItem::activity() const {
- return _activity;
-}
-
-bool BufferItem::setActivity(const ActivityLevel &level) {
+bool BufferItem::setActivityLevel(Buffer::ActivityLevel level) {
_activity = level;
emit dataChanged();
return true;
}
-void BufferItem::updateActivity(const ActivityLevel &level) {
- ActivityLevel oldActivity = _activity;
+void BufferItem::updateActivityLevel(Buffer::ActivityLevel level) {
+ Buffer::ActivityLevel oldActivity = _activity;
_activity |= level;
if(oldActivity != _activity)
emit dataChanged();
case NetworkModel::ItemActiveRole:
return isActive();
case NetworkModel::BufferActivityRole:
- return qVariantFromValue((int)activity());
+ return (int)activityLevel();
default:
return PropertyMapItem::data(column, role);
}
bool BufferItem::setData(int column, const QVariant &value, int role) {
switch(role) {
case NetworkModel::BufferActivityRole:
- return setActivity((ActivityLevel)value.toInt());
- case NetworkModel::LastSeenRole:
- return setLastSeen();
+ return setActivityLevel((Buffer::ActivityLevel)value.toInt());
default:
return PropertyMapItem::setData(column, value, role);
}
addUserToCategory(ircUser);
}
+/*
void BufferItem::setLastMsgInsert(QDateTime msgDate) {
if(msgDate.isValid() && msgDate > _lastMsgInsert)
_lastMsgInsert = msgDate;
}
-
+*/
+/*
+// FIXME emit dataChanged()
bool BufferItem::setLastSeen() {
if(_lastSeen > _lastMsgInsert)
return false;
QDateTime BufferItem::lastSeen() {
return _lastSeen;
}
-
+*/
/*****************************************
* Network Items
*****************************************/
emit dataChanged(itemindex, itemindex);
}
+/*
void NetworkModel::updateBufferActivity(const Message &msg) {
BufferItem *buff = bufferItem(msg.bufferInfo());
Q_ASSERT(buff);
bufferItem(msg.bufferInfo())->updateActivity(level);
}
+*/
+
+void NetworkModel::setBufferActivity(const BufferInfo &info, Buffer::ActivityLevel level) {
+ BufferItem *buff = bufferItem(info);
+ Q_ASSERT(buff);
+
+ buff->setActivityLevel(level);
+}
const Network *NetworkModel::networkByIndex(const QModelIndex &index) const {
QVariant netVariant = index.data(NetworkIdRole);
QString bufferName() const;
QString topic() const;
int nickCount() const;
-
+
bool isStatusBuffer() const;
BufferInfo::Type bufferType() const;
bool isActive() const;
-
- enum Activity {
- NoActivity = 0x00,
- OtherActivity = 0x01,
- NewMessage = 0x02,
- Highlight = 0x40
- };
- Q_DECLARE_FLAGS(ActivityLevel, Activity)
- ActivityLevel activity() const;
- bool setActivity(const ActivityLevel &level);
- void updateActivity(const ActivityLevel &level);
+ inline Buffer::ActivityLevel activityLevel() const { return _activity; }
+ bool setActivityLevel(Buffer::ActivityLevel level);
+ void updateActivityLevel(Buffer::ActivityLevel level);
void setLastMsgInsert(QDateTime msgDate);
bool setLastSeen();
void addUserToCategory(IrcUser *ircUser);
void removeUserFromCategory(IrcUser *ircUser);
void userModeChanged(IrcUser *ircUser);
-
+
private slots:
void ircChannelDestroyed();
void ircUserDestroyed();
-
+
private:
BufferInfo _bufferInfo;
- ActivityLevel _activity;
- QDateTime _lastMsgInsert;
- QDateTime _lastSeen;
+ Buffer::ActivityLevel _activity;
QPointer<IrcChannel> _ircChannel;
};
-Q_DECLARE_OPERATORS_FOR_FLAGS(BufferItem::ActivityLevel)
+
/*****************************************
* Network Items
BufferIdRole,
NetworkIdRole,
BufferInfoRole,
- ItemTypeRole,
- LastSeenRole
+ ItemTypeRole
};
enum itemTypes {
UserCategoryItemType,
IrcUserItemType
};
-
+
NetworkModel(QObject *parent = 0);
static QList<QVariant> defaultHeader();
const Network *networkByIndex(const QModelIndex &index) const;
+ Buffer::ActivityLevel bufferActivity(const BufferInfo &buffer) const;
+
public slots:
void bufferUpdated(BufferInfo bufferInfo);
- void updateBufferActivity(const Message &msg);
+ void setBufferActivity(const BufferInfo &buffer, Buffer::ActivityLevel activity);
void networkRemoved(const NetworkId &networkId);
private:
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005-08 by the Quassel IRC Team *
+ * 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 "buffersyncer.h"
+
+BufferSyncer::BufferSyncer(QObject *parent) : SyncableObject(parent) {
+
+
+}
+
+
+QDateTime BufferSyncer::lastSeen(BufferId buffer) const {
+ if(_lastSeen.contains(buffer)) return _lastSeen[buffer];
+ return QDateTime();
+}
+
+bool BufferSyncer::setLastSeen(BufferId buffer, const QDateTime &time) {
+ if(_lastSeen[buffer] < time) {
+ _lastSeen[buffer] = time;
+ emit lastSeenSet(buffer, time);
+ return true;
+ }
+ return false;
+}
+
+QVariantList BufferSyncer::initLastSeen() const {
+ QVariantList list;
+ foreach(BufferId id, _lastSeen.keys()) {
+ list << QVariant::fromValue<BufferId>(id) << _lastSeen[id];
+ }
+ return list;
+}
+
+void BufferSyncer::initSetLastSeen(const QVariantList &list) {
+ _lastSeen.clear();
+ Q_ASSERT(list.count() % 2 == 0);
+ for(int i = 0; i < list.count(); i += 2) {
+ setLastSeen(list[i].value<BufferId>(), list[i+1].toDateTime());
+ }
+}
+
+void BufferSyncer::requestSetLastSeen(BufferId buffer, const QDateTime &time) {
+ if(setLastSeen(buffer, time)) emit setLastSeenRequested(buffer, time);
+}
+
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005-08 by the Quassel IRC Team *
+ * 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 BUFFERSYNCER_H_
+#define BUFFERSYNCER_H_
+
+#include <QDateTime>
+
+#include "syncableobject.h"
+#include "types.h"
+
+class BufferSyncer : public SyncableObject {
+ Q_OBJECT
+
+ public:
+ explicit BufferSyncer(QObject *parent);
+
+ QDateTime lastSeen(BufferId buffer) const;
+
+ public slots:
+ QVariantList initLastSeen() const;
+ void initSetLastSeen(const QVariantList &);
+
+ void requestSetLastSeen(BufferId buffer, const QDateTime &time);
+
+ signals:
+ void lastSeenSet(BufferId buffer, const QDateTime &time);
+ void setLastSeenRequested(BufferId buffer, const QDateTime &time);
+
+ private slots:
+ bool setLastSeen(BufferId buffer, const QDateTime &time);
+
+ private:
+ QMap<BufferId, QDateTime> _lastSeen;
+};
+
+#endif
-DEPMOD =
+DEPMOD =
QT_MOD = network
-SRCS += bufferinfo.cpp global.cpp identity.cpp logger.cpp message.cpp settings.cpp signalproxy.cpp syncableobject.cpp \
+SRCS += bufferinfo.cpp buffersyncer.cpp global.cpp identity.cpp logger.cpp message.cpp settings.cpp signalproxy.cpp syncableobject.cpp \
util.cpp network.cpp ircuser.cpp ircchannel.cpp
-HDRS += bufferinfo.h global.h identity.h logger.h message.h settings.h signalproxy.h syncableobject.h \
+HDRS += bufferinfo.h buffersyncer.h global.h identity.h logger.h message.h settings.h signalproxy.h syncableobject.h \
util.h network.h ircuser.h ircchannel.h types.h
case Message::Error:
s = tr("%De*"); t = tr("%De%1").arg(txt); break;
case Message::Join:
- s = tr("%Dj-->"); t = tr("%Dj%DN%DU%1%DU%DN %DH(%2@%3)%DH has joined %DC%DU%4%DU%DC").arg(nick, user, host, bufferName); break;
+ s = tr("%Dj-->"); t = tr("%Dj%DN%1%DN %DH(%2@%3)%DH has joined %DC%4%DC").arg(nick, user, host, bufferName); break;
case Message::Part:
- s = tr("%Dp<--"); t = tr("%Dp%DN%DU%1%DU%DN %DH(%2@%3)%DH has left %DC%DU%4%DU%DC").arg(nick, user, host, bufferName);
+ s = tr("%Dp<--"); t = tr("%Dp%DN%1%DN %DH(%2@%3)%DH has left %DC%4%DC").arg(nick, user, host, bufferName);
if(!txt.isEmpty()) t = QString("%1 (%2)").arg(t).arg(txt);
break;
case Message::Quit:
QString victim = txt.section(" ", 0, 0);
//if(victim == ui.ownNick->currentText()) victim = tr("you");
QString kickmsg = txt.section(" ", 1);
- t = tr("%Dk%DN%DU%1%DU%DN has kicked %DN%DU%2%DU%DN from %DC%DU%3%DU%DC").arg(nick).arg(victim).arg(bufferName);
+ t = tr("%Dk%DN%1%DN has kicked %DN%2%DN from %DC%3%DC").arg(nick).arg(victim).arg(bufferName);
if(!kickmsg.isEmpty()) t = QString("%1 (%2)").arg(t).arg(kickmsg);
}
break;
case Message::Nick:
s = tr("%Dr<->");
if(nick == text()) t = tr("%DrYou are now known as %DN%1%DN").arg(txt);
- else t = tr("%Dr%DN%1%DN is now known as %DN%DU%2%DU%DN").arg(nick, txt);
+ else t = tr("%Dr%DN%1%DN is now known as %DN%2%DN").arg(nick, txt);
break;
case Message::Mode:
s = tr("%Dm***");
if(nick.isEmpty()) t = tr("%DmUser mode: %DM%1%DM").arg(text());
- else t = tr("%DmMode %DM%1%DM by %DN%DU%2%DU%DN").arg(txt, nick);
+ else t = tr("%DmMode %DM%1%DM by %DN%2%DN").arg(txt, nick);
break;
case Message::Action:
s = tr("%Da-*-");
- t = tr("%Da%DN%DU%1%DU%DN %2").arg(nick).arg(txt);
+ t = tr("%Da%DN%1%DN %2").arg(nick).arg(txt);
break;
default:
s = tr("%De%1").arg(sender());
if(proxy()->proxyMode() == SignalProxy::Client) emit connectRequested(); // on the client this triggers calling this slot on the core
else {
if(connectionState() != Disconnected) {
- qWarning() << "Requesting connect while not being disconnected!";
+ qWarning() << "Requesting connect while already being connected!";
return;
}
emit connectRequested(networkId()); // and this is for CoreSession :)
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
+#include <QtScript>
+
#include "core.h"
#include "coresession.h"
#include "networkconnection.h"
#include "signalproxy.h"
+#include "buffersyncer.h"
#include "storage.h"
#include "network.h"
#include "util.h"
#include "coreusersettings.h"
-#include <QtScript>
-
CoreSession::CoreSession(UserId uid, bool restoreState, QObject *parent) : QObject(parent),
_user(uid),
_signalProxy(new SignalProxy(SignalProxy::Server, 0, this)),
+ _bufferSyncer(new BufferSyncer(this)),
scriptEngine(new QScriptEngine(this))
{
loadSettings();
initScriptEngine();
+ // init BufferSyncer
+ //QHash<BufferId, QDateTime> lastSeenHash = Core::bufferLastSeenDates(user());
+ //foreach(BufferId id, lastSeenHash.keys()) _bufferSyncer->requestSetLastSeen(id, lastSeenHash[id]);
+ // FIXME connect(_bufferSyncer, SIGNAL(lastSeenSet(BufferId, const QDateTime &)), this, SLOT(storeBufferLastSeen(BufferId, const QDateTime &)));
+ p->synchronize(_bufferSyncer);
+
// Restore session state
if(restoreState) restoreSessionState();
// FIXME
// connection should only go away on explicit /part, and handle reconnections etcpp internally otherwise
- Q_ASSERT(_connections.contains(networkid));
- _connections.take(networkid)->deleteLater();
+ //Q_ASSERT(_connections.contains(networkid));
+ if(_connections.contains(networkid)) _connections.take(networkid)->deleteLater();
}
// FIXME switch to BufferId
return v;
}
+void CoreSession::storeBufferLastSeen(BufferId buffer, const QDateTime &lastSeen) {
+ Core::setBufferLastSeen(user(), buffer, lastSeen);
+}
+
void CoreSession::sendBacklog(BufferInfo id, QVariant v1, QVariant v2) {
QList<QVariant> log;
QList<Message> msglist;
qWarning() << "Update request for unknown network received!";
return;
}
- _networks[info.networkId]->setNetworkInfo(info);
+ _networks[info.networkId]->setNetworkInfo(info); qDebug() << "unlim" << info.unlimitedReconnectRetries << _networks[info.networkId]->unlimitedReconnectRetries();
Core::updateNetwork(user(), info);
}
#include "message.h"
+class BufferSyncer;
class Identity;
class NetworkConnection;
class Network;
*/
void updateBufferInfo(UserId user, const BufferInfo &bufferInfo);
+ void storeBufferLastSeen(BufferId buffer, const QDateTime &lastSeen);
+
void scriptRequest(QString script);
private:
QHash<NetworkId, Network *> _networksToRemove;
QHash<IdentityId, Identity *> _identities;
+ BufferSyncer *_bufferSyncer;
+
QScriptEngine *scriptEngine;
};
}
void NetworkConnection::disconnectFromIrc() {
- socket.disconnectFromHost();
+ if(socket.state() < QAbstractSocket::ConnectedState) {
+ setConnectionState(Network::Disconnected);
+ socketDisconnected();
+ } else socket.disconnectFromHost();
}
void NetworkConnection::socketHasData() {
BufferWidget::BufferWidget(QWidget *parent)
: QWidget(parent),
_bufferModel(0),
- _selectionModel(0)
+ _selectionModel(0),
+ _currentBuffer(0)
{
ui.setupUi(this);
}
if(!_chatWidgets.contains(bufferId))
return;
+ if(Client::buffer(bufferId)) Client::buffer(bufferId)->setVisible(false);
ChatWidget *chatWidget = _chatWidgets.take(bufferId);
ui.stackedWidget->removeWidget(chatWidget);
chatWidget->deleteLater();
variant = current.data(NetworkModel::BufferIdRole);
if(!variant.isValid())
return;
-
- setCurrentBuffer(qVariantValue<BufferId>(variant));
+ setCurrentBuffer(variant.value<BufferId>());
}
void BufferWidget::setCurrentBuffer(BufferId bufferId) {
- ChatWidget *chatWidget;
+ ChatWidget *chatWidget = 0;
+ Buffer *buf = Client::buffer(bufferId);
+ if(!buf) {
+ qWarning() << "BufferWidget::setBuffer(BufferId): Can't show unknown Buffer:" << bufferId;
+ return;
+ }
+ Buffer *prevBuffer = Client::buffer(currentBuffer());
+ if(prevBuffer) prevBuffer->setVisible(false);
if(_chatWidgets.contains(bufferId)) {
chatWidget = _chatWidgets[bufferId];
} else {
- Buffer *buf = Client::buffer(bufferId);
- if(!buf) {
- qWarning() << "BufferWidget::setBuffer(BufferId): Can't show unknown Buffer:" << bufferId;
- return;
- }
chatWidget = new ChatWidget(this);
chatWidget->init(bufferId);
QList<ChatLine *> lines;
ui.stackedWidget->addWidget(chatWidget);
chatWidget->setFocusProxy(this);
}
+ _currentBuffer = bufferId;
ui.stackedWidget->setCurrentWidget(chatWidget);
+ buf->setVisible(true);
setFocus();
}
inline QItemSelectionModel *selectionModel() const { return _selectionModel; }
void setSelectionModel(QItemSelectionModel *selectionModel);
+
+ inline BufferId currentBuffer() const { return _currentBuffer; }
protected slots:
// virtual void closeEditor(QWidget *editor, QAbstractItemDelegate::EndEditHint hint);
QPointer<BufferModel> _bufferModel;
QPointer<QItemSelectionModel> _selectionModel;
+
+ BufferId _currentBuffer;
};
#endif
systray = new QSystemTrayIcon(this);
systray->setIcon(QIcon(":/icons/quassel-icon.png"));
- QString toolTip("left click to minimize the quassel client to tray");
+ QString toolTip("Left click to minimize the Quassel Client to tray");
systray->setToolTip(toolTip);
systrayMenu = new QMenu(this);
a->setText(net->networkName());
if(net->connectionState() == Network::Initialized) {
a->setIcon(QIcon(":/16x16/actions/network-connect"));
- a->setEnabled(true);
+ //a->setEnabled(true);
} else if(net->connectionState() == Network::Disconnected) {
a->setIcon(QIcon(":/16x16/actions/network-disconnect"));
- a->setEnabled(true);
+ //a->setEnabled(true);
} else {
a->setIcon(QIcon(":/16x16/actions/gear"));
- a->setEnabled(false);
+ //a->setEnabled(false);
}
return;
}
if(currentId != 0) saveToNetworkInfo(networkInfos[currentId]);
//ui.identityList->removeItem(ui.identityList->findData(id.toInt()));
foreach(NetworkInfo info, networkInfos.values()) {
- qDebug() << info.networkName << info.networkId << info.identity;
+ //qDebug() << info.networkName << info.networkId << info.identity;
if(info.identity == id) {
if(info.networkId == currentId) ui.identityList->setCurrentIndex(0);
info.identity = 1; // set to default
if(id == currentId) displayNetwork(0);
NetworkInfo info = networkInfos.take(id);
QList<QListWidgetItem *> items = ui.networkList->findItems(info.networkName, Qt::MatchExactly);
- if(items.count()) {
- Q_ASSERT(items[0]->data(Qt::UserRole).value<NetworkId>() == id);
- delete ui.networkList->takeItem(ui.networkList->row(items[0]));
+ foreach(QListWidgetItem *item, items) {
+ if(item->data(Qt::UserRole).value<NetworkId>() == id)
+ delete ui.networkList->takeItem(ui.networkList->row(item));
}
setWidgetStates();
widgetHasChanged();
if(!index.data(NetworkModel::ItemActiveRole).toBool())
return inactiveActivity.value<QColor>();
- BufferItem::ActivityLevel activity = (BufferItem::ActivityLevel)index.data(NetworkModel::BufferActivityRole).toInt();
+ Buffer::ActivityLevel activity = (Buffer::ActivityLevel)index.data(NetworkModel::BufferActivityRole).toInt();
- if(activity & BufferItem::Highlight)
+ if(activity & Buffer::Highlight)
return highlightActivity.value<QColor>();
- if(activity & BufferItem::NewMessage)
+ if(activity & Buffer::NewMessage)
return newMessageActivity.value<QColor>();
- if(activity & BufferItem::OtherActivity)
+ if(activity & Buffer::OtherActivity)
return otherActivity.value<QColor>();
return noActivity.value<QColor>();
// Default format
QTextCharFormat def;
def.setForeground(QBrush("#000000"));
- def.setFont(QFont("Courier", 10));
+ //def.setFont(QFont("Courier", 10));
+ def.font().setStyleHint(QFont::TypeWriter);
_defaultFormats = QVector<QTextCharFormat>(NumFormatTypes, def);
_customFormats = QVector<QTextCharFormat>(NumFormatTypes, QTextFormat().toCharFormat());
{ using namespace Global;
quasselVersion = "0.2.0-pre";
- quasselDate = "2008-02-14";
- quasselBuild = 523;
+ quasselDate = "2008-02-18";
+ quasselBuild = 526;
//! Minimum client build number the core needs
- clientBuildNeeded = 519;
+ clientBuildNeeded = 526;
clientVersionNeeded = quasselVersion;
//! Minimum core build number the client needs
- coreBuildNeeded = 519;
+ coreBuildNeeded = 526;
coreVersionNeeded = quasselVersion;
}