From: Manuel Nickschas Date: Mon, 18 Feb 2008 00:33:29 +0000 (+0000) Subject: Buffer activity levels are now synced between clients, meaning that seeing a buffer... X-Git-Tag: 0.2.0-alpha1~54 X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=commitdiff_plain;h=8010224cf5bfe5685dc2cf535e8dc1ec19c4c364 Buffer activity levels are now synced between clients, meaning that seeing a buffer in one client 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. --- diff --git a/Quassel.kdevelop.filelist b/Quassel.kdevelop.filelist index b74b8086..9d3b4b2b 100644 --- a/Quassel.kdevelop.filelist +++ b/Quassel.kdevelop.filelist @@ -1,5 +1,4 @@ # KDevelop Custom Project File List -Makefile build build/buildconf.pri build/contrib @@ -53,6 +52,8 @@ src/client/treemodel.h 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 @@ -139,6 +140,8 @@ src/qtopia/ui/editcoreacctdlg.ui 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 @@ -155,10 +158,16 @@ src/qtui/chatwidget.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 @@ -172,22 +181,29 @@ src/qtui/qtuistyle.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 @@ -201,7 +217,13 @@ src/qtui/ui/mainwin.ui 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 @@ -212,6 +234,8 @@ src/uisupport/inputline.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 diff --git a/src/client/buffer.cpp b/src/client/buffer.cpp index a316ae15..54bd81a1 100644 --- a/src/client/buffer.cpp +++ b/src/client/buffer.cpp @@ -21,14 +21,20 @@ #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 { @@ -41,12 +47,14 @@ QList Buffer::contents() 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); } @@ -59,3 +67,33 @@ bool Buffer::layoutMsg() { 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); +} diff --git a/src/client/buffer.h b/src/client/buffer.h index 9bf4b783..def01bdd 100644 --- a/src/client/buffer.h +++ b/src/client/buffer.h @@ -21,6 +21,8 @@ #ifndef _BUFFER_H_ #define _BUFFER_H_ +#include + class AbstractUiMsg; class IrcChannel; class NickModel; @@ -30,19 +32,29 @@ struct BufferState; #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 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 *); @@ -52,13 +64,22 @@ public slots: 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 layoutQueue; QList layoutedMsgs; + void updateActivityLevel(const Message &msg); }; +Q_DECLARE_OPERATORS_FOR_FLAGS(Buffer::ActivityLevel) + #endif diff --git a/src/client/buffermodel.cpp b/src/client/buffermodel.cpp index 4b78ea95..e0f80ed1 100644 --- a/src/client/buffermodel.cpp +++ b/src/client/buffermodel.cpp @@ -35,8 +35,6 @@ BufferModel::BufferModel(NetworkModel *parent) // 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() { @@ -72,10 +70,3 @@ void BufferModel::mapProperty(int column, int role, QObject *target, const QByte 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); -} diff --git a/src/client/buffermodel.h b/src/client/buffermodel.h index 80f1ec0a..2d6f4b47 100644 --- a/src/client/buffermodel.h +++ b/src/client/buffermodel.h @@ -51,9 +51,6 @@ public: QModelIndex currentIndex(); -private slots: - void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); - private: SelectionModelSynchronizer _selectionModelSynchronizer; ModelPropertyMapper _propertyMapper; diff --git a/src/client/client.cpp b/src/client/client.cpp index 4d716ed0..a2473b17 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -21,6 +21,7 @@ #include "client.h" #include "bufferinfo.h" +#include "buffersyncer.h" #include "global.h" #include "identity.h" #include "ircchannel.h" @@ -61,6 +62,7 @@ Client::Client(QObject *parent) mainUi(0), _networkModel(0), _bufferModel(0), + _bufferSyncer(0), _connectedToCore(false), _syncedToCore(false) { @@ -164,23 +166,6 @@ Buffer *Client::buffer(BufferInfo bufferInfo) { 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; } @@ -295,6 +280,12 @@ void Client::setConnectedToCore(QIODevice *sock, AccountId id) { } 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); @@ -312,8 +303,19 @@ void Client::disconnectFromCore() { emit coreConnectionStateChanged(false); // Clear internal data. Hopefully nothing relies on it at this point. + _bufferSyncer->deleteLater(); + _bufferSyncer = 0; _networkModel->clear(); + QHash::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::iterator netIter = _networks.begin(); while(netIter != _networks.end()) { Network *net = netIter.value(); @@ -324,15 +326,6 @@ void Client::disconnectFromCore() { } Q_ASSERT(_networks.isEmpty()); - QHash::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::iterator idIter = _identities.begin(); while(idIter != _identities.end()) { Identity *id = idIter.value(); @@ -394,11 +387,11 @@ void Client::recvMessage(const Message &message) { } 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 @@ -408,7 +401,6 @@ void Client::recvMessage(const Message &message) { Message mmsg = Message(msg.timestamp(), msg.bufferInfo(), msg.type(), msg.text(), sender, msg.flags()); monitorBuffer()->appendMsg(mmsg); } - } void Client::recvStatusMsg(QString /*net*/, QString /*msg*/) { @@ -421,7 +413,7 @@ void Client::recvBacklogData(BufferInfo id, QVariantList msgs, bool /*done*/) { Message msg = v.value(); 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(); @@ -442,7 +434,7 @@ AbstractUiMsg *Client::layoutMsg(const Message &msg) { 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.*)?$"); @@ -450,3 +442,19 @@ void Client::checkForHighlight(Message &msg) const { 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); +} + + diff --git a/src/client/client.h b/src/client/client.h index c1463e59..feb9f16f 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -27,6 +27,7 @@ #include #include "buffer.h" // needed for activity lvl + class BufferInfo; class Message; @@ -38,6 +39,7 @@ class AbstractUi; class AbstractUiMsg; class NetworkModel; class BufferModel; +class BufferSyncer; class IrcUser; class IrcChannel; class SignalProxy; @@ -58,7 +60,7 @@ public: static QList buffers(); static Buffer *buffer(BufferId bufferUid); static Buffer *buffer(BufferInfo); - static Buffer *monitorBuffer(); + static inline Buffer *monitorBuffer() { return instance()->_monitorBuffer; } static QList networkIds(); static const Network * network(NetworkId); @@ -88,9 +90,10 @@ public: 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(); @@ -103,8 +106,9 @@ public: 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 *); @@ -163,6 +167,7 @@ private slots: void recvStatusMsg(QString network, QString message); void recvBacklogData(BufferInfo, QVariantList, bool); void updateBufferInfo(BufferInfo); + void updateLastSeen(BufferId id, const QDateTime &lastSeen); void layoutMsg(); @@ -188,10 +193,12 @@ private: static QPointer instanceptr; QPointer socket; - QPointer _signalProxy; - QPointer mainUi; - QPointer _networkModel; - QPointer _bufferModel; + + SignalProxy * _signalProxy; + AbstractUi * mainUi; + NetworkModel * _networkModel; + BufferModel * _bufferModel; + BufferSyncer * _bufferSyncer; ClientMode clientMode; diff --git a/src/client/clientsyncer.cpp b/src/client/clientsyncer.cpp index 29b4973d..601bff03 100644 --- a/src/client/clientsyncer.cpp +++ b/src/client/clientsyncer.cpp @@ -172,7 +172,7 @@ void ClientSyncer::clientInitAck(const QVariantMap &msg) { // 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("The Quassel Core you are trying to connect to is too old!
" - "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; } diff --git a/src/client/networkmodel.cpp b/src/client/networkmodel.cpp index 00604471..be13afd5 100644 --- a/src/client/networkmodel.cpp +++ b/src/client/networkmodel.cpp @@ -37,14 +37,12 @@ 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 { @@ -70,18 +68,14 @@ bool BufferItem::isActive() const { return qobject_cast(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(); @@ -102,7 +96,7 @@ QVariant BufferItem::data(int column, int role) const { case NetworkModel::ItemActiveRole: return isActive(); case NetworkModel::BufferActivityRole: - return qVariantFromValue((int)activity()); + return (int)activityLevel(); default: return PropertyMapItem::data(column, role); } @@ -111,9 +105,7 @@ QVariant BufferItem::data(int column, int role) const { 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); } @@ -271,11 +263,14 @@ void BufferItem::userModeChanged(IrcUser *ircUser) { 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; @@ -288,7 +283,7 @@ bool BufferItem::setLastSeen() { QDateTime BufferItem::lastSeen() { return _lastSeen; } - +*/ /***************************************** * Network Items *****************************************/ @@ -743,6 +738,7 @@ void NetworkModel::bufferUpdated(BufferInfo bufferInfo) { emit dataChanged(itemindex, itemindex); } +/* void NetworkModel::updateBufferActivity(const Message &msg) { BufferItem *buff = bufferItem(msg.bufferInfo()); Q_ASSERT(buff); @@ -761,6 +757,14 @@ void NetworkModel::updateBufferActivity(const Message &msg) { 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); diff --git a/src/client/networkmodel.h b/src/client/networkmodel.h index 8c36233f..961c1ca3 100644 --- a/src/client/networkmodel.h +++ b/src/client/networkmodel.h @@ -62,23 +62,15 @@ public: 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(); @@ -92,20 +84,18 @@ public slots: 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; }; -Q_DECLARE_OPERATORS_FOR_FLAGS(BufferItem::ActivityLevel) + /***************************************** * Network Items @@ -215,8 +205,7 @@ public: BufferIdRole, NetworkIdRole, BufferInfoRole, - ItemTypeRole, - LastSeenRole + ItemTypeRole }; enum itemTypes { @@ -225,7 +214,7 @@ public: UserCategoryItemType, IrcUserItemType }; - + NetworkModel(QObject *parent = 0); static QList defaultHeader(); @@ -244,9 +233,11 @@ public: 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: diff --git a/src/common/buffersyncer.cpp b/src/common/buffersyncer.cpp new file mode 100644 index 00000000..cf16d8d3 --- /dev/null +++ b/src/common/buffersyncer.cpp @@ -0,0 +1,62 @@ +/*************************************************************************** + * 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(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(), list[i+1].toDateTime()); + } +} + +void BufferSyncer::requestSetLastSeen(BufferId buffer, const QDateTime &time) { + if(setLastSeen(buffer, time)) emit setLastSeenRequested(buffer, time); +} + diff --git a/src/common/buffersyncer.h b/src/common/buffersyncer.h new file mode 100644 index 00000000..785c2be4 --- /dev/null +++ b/src/common/buffersyncer.h @@ -0,0 +1,54 @@ +/*************************************************************************** + * 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 + +#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 _lastSeen; +}; + +#endif diff --git a/src/common/common.pri b/src/common/common.pri index 0555aee9..98e9a3ea 100644 --- a/src/common/common.pri +++ b/src/common/common.pri @@ -1,6 +1,6 @@ -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 diff --git a/src/common/message.cpp b/src/common/message.cpp index 4a6ba919..91e1f493 100644 --- a/src/common/message.cpp +++ b/src/common/message.cpp @@ -112,9 +112,9 @@ void Message::format() { 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: @@ -126,23 +126,23 @@ void Message::format() { 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()); diff --git a/src/common/network.cpp b/src/common/network.cpp index 3162bd4c..b565a78e 100644 --- a/src/common/network.cpp +++ b/src/common/network.cpp @@ -725,7 +725,7 @@ void Network::requestConnect() const { 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 :) diff --git a/src/core/coresession.cpp b/src/core/coresession.cpp index d39498ab..22ed2121 100644 --- a/src/core/coresession.cpp +++ b/src/core/coresession.cpp @@ -18,11 +18,14 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ +#include + #include "core.h" #include "coresession.h" #include "networkconnection.h" #include "signalproxy.h" +#include "buffersyncer.h" #include "storage.h" #include "network.h" @@ -33,11 +36,10 @@ #include "util.h" #include "coreusersettings.h" -#include - 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)) { @@ -67,6 +69,12 @@ CoreSession::CoreSession(UserId uid, bool restoreState, QObject *parent) : QObje loadSettings(); initScriptEngine(); + // init BufferSyncer + //QHash 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(); @@ -268,8 +276,8 @@ void CoreSession::networkDisconnected(NetworkId networkid) { // 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 @@ -333,6 +341,10 @@ QVariant CoreSession::sessionState() { 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 log; QList msglist; @@ -436,7 +448,7 @@ void CoreSession::updateNetwork(const NetworkInfo &info) { 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); } diff --git a/src/core/coresession.h b/src/core/coresession.h index 51c14a72..640ea99b 100644 --- a/src/core/coresession.h +++ b/src/core/coresession.h @@ -26,6 +26,7 @@ #include "message.h" +class BufferSyncer; class Identity; class NetworkConnection; class Network; @@ -146,6 +147,8 @@ private slots: */ void updateBufferInfo(UserId user, const BufferInfo &bufferInfo); + void storeBufferLastSeen(BufferId buffer, const QDateTime &lastSeen); + void scriptRequest(QString script); private: @@ -160,6 +163,8 @@ private: QHash _networksToRemove; QHash _identities; + BufferSyncer *_bufferSyncer; + QScriptEngine *scriptEngine; }; diff --git a/src/core/networkconnection.cpp b/src/core/networkconnection.cpp index 381e99d2..6ac715c8 100644 --- a/src/core/networkconnection.cpp +++ b/src/core/networkconnection.cpp @@ -204,7 +204,10 @@ QVariant NetworkConnection::state() const { } void NetworkConnection::disconnectFromIrc() { - socket.disconnectFromHost(); + if(socket.state() < QAbstractSocket::ConnectedState) { + setConnectionState(Network::Disconnected); + socketDisconnected(); + } else socket.disconnectFromHost(); } void NetworkConnection::socketHasData() { diff --git a/src/qtui/bufferwidget.cpp b/src/qtui/bufferwidget.cpp index 99a2f308..8831a28e 100644 --- a/src/qtui/bufferwidget.cpp +++ b/src/qtui/bufferwidget.cpp @@ -31,7 +31,8 @@ BufferWidget::BufferWidget(QWidget *parent) : QWidget(parent), _bufferModel(0), - _selectionModel(0) + _selectionModel(0), + _currentBuffer(0) { ui.setupUi(this); } @@ -95,6 +96,7 @@ void BufferWidget::removeBuffer(BufferId bufferId) { 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(); @@ -107,20 +109,21 @@ void BufferWidget::currentChanged(const QModelIndex ¤t, const QModelIndex variant = current.data(NetworkModel::BufferIdRole); if(!variant.isValid()) return; - - setCurrentBuffer(qVariantValue(variant)); + setCurrentBuffer(variant.value()); } 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 lines; @@ -135,7 +138,9 @@ void BufferWidget::setCurrentBuffer(BufferId bufferId) { ui.stackedWidget->addWidget(chatWidget); chatWidget->setFocusProxy(this); } + _currentBuffer = bufferId; ui.stackedWidget->setCurrentWidget(chatWidget); + buf->setVisible(true); setFocus(); } diff --git a/src/qtui/bufferwidget.h b/src/qtui/bufferwidget.h index b9235f95..e484a187 100644 --- a/src/qtui/bufferwidget.h +++ b/src/qtui/bufferwidget.h @@ -49,6 +49,8 @@ public: 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); @@ -70,6 +72,8 @@ private: QPointer _bufferModel; QPointer _selectionModel; + + BufferId _currentBuffer; }; #endif diff --git a/src/qtui/mainwin.cpp b/src/qtui/mainwin.cpp index 1b738041..5b430870 100644 --- a/src/qtui/mainwin.cpp +++ b/src/qtui/mainwin.cpp @@ -267,7 +267,7 @@ void MainWin::setupSystray() { 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); @@ -430,13 +430,13 @@ void MainWin::clientNetworkUpdated() { 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; } diff --git a/src/qtui/settingspages/networkssettingspage.cpp b/src/qtui/settingspages/networkssettingspage.cpp index 88980f69..65301f0f 100644 --- a/src/qtui/settingspages/networkssettingspage.cpp +++ b/src/qtui/settingspages/networkssettingspage.cpp @@ -282,7 +282,7 @@ void NetworksSettingsPage::clientIdentityRemoved(IdentityId id) { 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 @@ -327,9 +327,9 @@ void NetworksSettingsPage::clientNetworkRemoved(NetworkId id) { if(id == currentId) displayNetwork(0); NetworkInfo info = networkInfos.take(id); QList items = ui.networkList->findItems(info.networkName, Qt::MatchExactly); - if(items.count()) { - Q_ASSERT(items[0]->data(Qt::UserRole).value() == id); - delete ui.networkList->takeItem(ui.networkList->row(items[0])); + foreach(QListWidgetItem *item, items) { + if(item->data(Qt::UserRole).value() == id) + delete ui.networkList->takeItem(ui.networkList->row(item)); } setWidgetStates(); widgetHasChanged(); diff --git a/src/uisupport/bufferviewfilter.cpp b/src/uisupport/bufferviewfilter.cpp index 22b51413..bae2522d 100644 --- a/src/uisupport/bufferviewfilter.cpp +++ b/src/uisupport/bufferviewfilter.cpp @@ -173,13 +173,13 @@ QVariant BufferViewFilter::foreground(const QModelIndex &index) const { if(!index.data(NetworkModel::ItemActiveRole).toBool()) return inactiveActivity.value(); - 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(); - if(activity & BufferItem::NewMessage) + if(activity & Buffer::NewMessage) return newMessageActivity.value(); - if(activity & BufferItem::OtherActivity) + if(activity & Buffer::OtherActivity) return otherActivity.value(); return noActivity.value(); diff --git a/src/uisupport/uistyle.cpp b/src/uisupport/uistyle.cpp index ec7364ee..8c62b373 100644 --- a/src/uisupport/uistyle.cpp +++ b/src/uisupport/uistyle.cpp @@ -25,7 +25,8 @@ UiStyle::UiStyle(const QString &settingsKey) : _settingsKey(settingsKey) { // 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(NumFormatTypes, def); _customFormats = QVector(NumFormatTypes, QTextFormat().toCharFormat()); diff --git a/version.inc b/version.inc index 7d1679aa..bbc453f9 100644 --- a/version.inc +++ b/version.inc @@ -4,15 +4,15 @@ { 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; }