From 541013790cdbd0c32d81debf8f42ac6b5183a4aa Mon Sep 17 00:00:00 2001 From: Manuel Nickschas Date: Thu, 8 Oct 2009 10:54:11 +0200 Subject: [PATCH] Untie the marker line from lastSeenMsg We now handle the marker line position independently from lastSeenMsg in the backend. This will allow for setting the marker line manually in the future, for people who don't want the automatic mark-as-read thingy. Currently, it's still set on buffer change, and the behavior should be the same as before. Note that this needs an updated core to work correctly, and will be disabled (= forced auto) else. --- src/client/client.cpp | 11 +++-- src/client/client.h | 1 + src/client/networkmodel.cpp | 40 ++++++++++++++--- src/client/networkmodel.h | 14 +++--- src/common/buffersyncer.cpp | 52 +++++++++++++++++++---- src/common/buffersyncer.h | 16 ++++++- src/core/corebuffersyncer.cpp | 23 +++++++--- src/core/corebuffersyncer.h | 4 +- src/qtui/chatitem.cpp | 9 ++++ src/qtui/chatitem.h | 9 +--- src/qtui/chatline.cpp | 2 +- src/qtui/chatviewsearchcontroller.cpp | 1 + src/uisupport/abstractbuffercontainer.cpp | 10 ++--- src/uisupport/abstractbuffercontainer.h | 2 + 14 files changed, 151 insertions(+), 43 deletions(-) diff --git a/src/client/client.cpp b/src/client/client.cpp index 30c11009..07b3c265 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -316,6 +316,7 @@ void Client::setSyncedToCore() { Q_ASSERT(!_bufferSyncer); _bufferSyncer = new BufferSyncer(this); connect(bufferSyncer(), SIGNAL(lastSeenMsgSet(BufferId, MsgId)), _networkModel, SLOT(setLastSeenMsgId(BufferId, MsgId))); + connect(bufferSyncer(), SIGNAL(markerLineSet(BufferId,MsgId)), _networkModel, SLOT(setMarkerLineMsgId(BufferId,MsgId))); connect(bufferSyncer(), SIGNAL(bufferRemoved(BufferId)), this, SLOT(bufferRemoved(BufferId))); connect(bufferSyncer(), SIGNAL(bufferRenamed(BufferId, QString)), this, SLOT(bufferRenamed(BufferId, QString))); connect(bufferSyncer(), SIGNAL(buffersPermanentlyMerged(BufferId, BufferId)), this, SLOT(buffersPermanentlyMerged(BufferId, BufferId))); @@ -468,9 +469,13 @@ void Client::recvMessage(const Message &msg) { } void Client::setBufferLastSeenMsg(BufferId id, const MsgId &msgId) { - if(!bufferSyncer()) - return; - bufferSyncer()->requestSetLastSeenMsg(id, msgId); + if(bufferSyncer()) + bufferSyncer()->requestSetLastSeenMsg(id, msgId); +} + +void Client::setBufferMarkerLine(BufferId id, const MsgId &msgId) { + if(bufferSyncer()) + bufferSyncer()->requestSetMarkerLine(id, msgId); } void Client::removeBuffer(BufferId id) { diff --git a/src/client/client.h b/src/client/client.h index 53dc7864..e401f463 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -127,6 +127,7 @@ public: static void userInput(const BufferInfo &bufferInfo, const QString &message); static void setBufferLastSeenMsg(BufferId id, const MsgId &msgId); // this is synced to core and other clients + static void setBufferMarkerLine(BufferId id, const MsgId &msgId); // this is synced to core and other clients static void removeBuffer(BufferId id); static void renameBuffer(BufferId bufferId, const QString &newName); static void mergeBuffersPermanently(BufferId bufferId1, BufferId bufferId2); diff --git a/src/client/networkmodel.cpp b/src/client/networkmodel.cpp index 1c365a44..6bc96f80 100644 --- a/src/client/networkmodel.cpp +++ b/src/client/networkmodel.cpp @@ -68,6 +68,7 @@ QVariant NetworkItem::data(int column, int role) const { } } +// FIXME shouldn't we check the bufferItemCache here? BufferItem *NetworkItem::findBufferItem(BufferId bufferId) { BufferItem *bufferItem = 0; @@ -231,8 +232,13 @@ void BufferItem::setActivityLevel(BufferInfo::ActivityLevel level) { void BufferItem::clearActivityLevel() { _activity = BufferInfo::NoActivity; - _lastSeenMarkerMsgId = _lastSeenMsgId; _firstUnreadMsgId = MsgId(); + + // FIXME remove with core proto v11 + if(!Client::coreFeatures() & Quassel::SynchronizedMarkerLine) { + _markerLineMsgId = _lastSeenMsgId; + } + emit dataChanged(); } @@ -286,6 +292,8 @@ QVariant BufferItem::data(int column, int role) const { return (int)activityLevel(); case NetworkModel::BufferFirstUnreadMsgIdRole: return qVariantFromValue(firstUnreadMsgId()); + case NetworkModel::MarkerLineMsgIdRole: + return qVariantFromValue(markerLineMsgId()); default: return PropertyMapItem::data(column, role); } @@ -307,14 +315,23 @@ void BufferItem::setBufferName(const QString &name) { emit dataChanged(0); } -void BufferItem::setLastSeenMsgId(const MsgId &msgId) { +void BufferItem::setLastSeenMsgId(MsgId msgId) { _lastSeenMsgId = msgId; - if(!isCurrentBuffer()) { - _lastSeenMarkerMsgId = msgId; + + // FIXME remove with core protocol v11 + if(!Client::coreFeatures() & Quassel::SynchronizedMarkerLine) { + if(!isCurrentBuffer()) + _markerLineMsgId = msgId; } + setActivityLevel(BufferInfo::NoActivity); } +void BufferItem::setMarkerLineMsgId(MsgId msgId) { + _markerLineMsgId = msgId; + emit dataChanged(); +} + bool BufferItem::isCurrentBuffer() const { return _bufferInfo.bufferId() == Client::bufferModel()->currentIndex().data(NetworkModel::BufferIdRole).value(); } @@ -979,13 +996,14 @@ MsgId NetworkModel::lastSeenMsgId(BufferId bufferId) const { return _bufferItemCache[bufferId]->lastSeenMsgId(); } -MsgId NetworkModel::lastSeenMarkerMsgId(BufferId bufferId) const { +MsgId NetworkModel::markerLineMsgId(BufferId bufferId) const { if(!_bufferItemCache.contains(bufferId)) return MsgId(); - return _bufferItemCache[bufferId]->lastSeenMarkerMsgId(); + return _bufferItemCache[bufferId]->markerLineMsgId(); } +// FIXME we always seem to use this (expensive) non-const version MsgId NetworkModel::lastSeenMsgId(const BufferId &bufferId) { BufferItem *bufferItem = findBufferItem(bufferId); if(!bufferItem) { @@ -1006,6 +1024,16 @@ void NetworkModel::setLastSeenMsgId(const BufferId &bufferId, const MsgId &msgId bufferItem->setLastSeenMsgId(msgId); } +void NetworkModel::setMarkerLineMsgId(const BufferId &bufferId, const MsgId &msgId) { + BufferItem *bufferItem = findBufferItem(bufferId); + if(!bufferItem) { + qDebug() << "NetworkModel::setMarkerLineMsgId(): buffer is unknown:" << bufferId; + Client::purgeKnownBufferIds(); + return; + } + bufferItem->setMarkerLineMsgId(msgId); +} + void NetworkModel::updateBufferActivity(Message &msg) { int redirectionTarget = 0; switch(msg.type()) { diff --git a/src/client/networkmodel.h b/src/client/networkmodel.h index 09f9ece3..52b49eb0 100644 --- a/src/client/networkmodel.h +++ b/src/client/networkmodel.h @@ -105,9 +105,11 @@ public: virtual inline bool isActive() const { return qobject_cast(parent())->isActive(); } - inline const MsgId &lastSeenMsgId() const { return _lastSeenMsgId; } - inline const MsgId &lastSeenMarkerMsgId() const { return _lastSeenMarkerMsgId; } - void setLastSeenMsgId(const MsgId &msgId); + inline MsgId lastSeenMsgId() const { return _lastSeenMsgId; } + inline MsgId markerLineMsgId() const { return _markerLineMsgId; } + void setLastSeenMsgId(MsgId msgId); + void setMarkerLineMsgId(MsgId msgId); + inline BufferInfo::ActivityLevel activityLevel() const { return _activity; } void setActivityLevel(BufferInfo::ActivityLevel level); void clearActivityLevel(); @@ -125,7 +127,7 @@ private: BufferInfo _bufferInfo; BufferInfo::ActivityLevel _activity; MsgId _lastSeenMsgId; - MsgId _lastSeenMarkerMsgId; + MsgId _markerLineMsgId; MsgId _firstUnreadMsgId; }; @@ -275,6 +277,7 @@ public: IrcUserRole, IrcChannelRole, BufferFirstUnreadMsgIdRole, + MarkerLineMsgIdRole, }; enum ItemType { @@ -317,7 +320,7 @@ public: BufferInfo::Type bufferType(BufferId bufferId) const; BufferInfo bufferInfo(BufferId bufferId) const; MsgId lastSeenMsgId(BufferId bufferId) const; - MsgId lastSeenMarkerMsgId(BufferId bufferId) const; + MsgId markerLineMsgId(BufferId bufferId) const; NetworkId networkId(BufferId bufferId) const; QString networkName(BufferId bufferId) const; @@ -330,6 +333,7 @@ public slots: void removeBuffer(BufferId bufferId); MsgId lastSeenMsgId(const BufferId &bufferId); void setLastSeenMsgId(const BufferId &bufferId, const MsgId &msgId); + void setMarkerLineMsgId(const BufferId &bufferId, const MsgId &msgId); void setBufferActivity(const BufferId &bufferId, BufferInfo::ActivityLevel activity); void clearBufferActivity(const BufferId &bufferId); void updateBufferActivity(Message &msg); diff --git a/src/common/buffersyncer.cpp b/src/common/buffersyncer.cpp index 82fe0da0..4987429a 100644 --- a/src/common/buffersyncer.cpp +++ b/src/common/buffersyncer.cpp @@ -26,16 +26,15 @@ BufferSyncer::BufferSyncer(QObject *parent) { } -BufferSyncer::BufferSyncer(const QHash &lastSeenMsg, QObject *parent) +BufferSyncer::BufferSyncer(const QHash &lastSeenMsg, const QHash &markerLines, QObject *parent) : SyncableObject(parent), - _lastSeenMsg(lastSeenMsg) + _lastSeenMsg(lastSeenMsg), + _markerLines(markerLines) { } MsgId BufferSyncer::lastSeenMsg(BufferId buffer) const { - if(_lastSeenMsg.contains(buffer)) - return _lastSeenMsg[buffer]; - return MsgId(); + return _lastSeenMsg.value(buffer, MsgId()); } bool BufferSyncer::setLastSeenMsg(BufferId buffer, const MsgId &msgId) { @@ -52,13 +51,27 @@ bool BufferSyncer::setLastSeenMsg(BufferId buffer, const MsgId &msgId) { return false; } +MsgId BufferSyncer::markerLine(BufferId buffer) const { + return _markerLines.value(buffer, MsgId()); +} + +bool BufferSyncer::setMarkerLine(BufferId buffer, const MsgId &msgId) { + if(!msgId.isValid()) + return false; + + _markerLines[buffer] = msgId; + SYNC(ARG(buffer), ARG(msgId)) + emit markerLineSet(buffer, msgId); + return true; +} + QVariantList BufferSyncer::initLastSeenMsg() const { QVariantList list; QHash::const_iterator iter = _lastSeenMsg.constBegin(); while(iter != _lastSeenMsg.constEnd()) { list << QVariant::fromValue(iter.key()) - << QVariant::fromValue(iter.value()); - iter++; + << QVariant::fromValue(iter.value()); + ++iter; } return list; } @@ -67,13 +80,34 @@ void BufferSyncer::initSetLastSeenMsg(const QVariantList &list) { _lastSeenMsg.clear(); Q_ASSERT(list.count() % 2 == 0); for(int i = 0; i < list.count(); i += 2) { - setLastSeenMsg(list[i].value(), list[i+1].value()); + setLastSeenMsg(list.at(i).value(), list.at(i+1).value()); + } +} + +QVariantList BufferSyncer::initMarkerLines() const { + QVariantList list; + QHash::const_iterator iter = _markerLines.constBegin(); + while(iter != _markerLines.constEnd()) { + list << QVariant::fromValue(iter.key()) + << QVariant::fromValue(iter.value()); + ++iter; + } + return list; +} + +void BufferSyncer::initSetMarkerLines(const QVariantList &list) { + _markerLines.clear(); + Q_ASSERT(list.count() % 2 == 0); + for(int i = 0; i < list.count(); i += 2) { + setMarkerLine(list.at(i).value(), list.at(i+1).value()); } } void BufferSyncer::removeBuffer(BufferId buffer) { if(_lastSeenMsg.contains(buffer)) _lastSeenMsg.remove(buffer); + if(_markerLines.contains(buffer)) + _markerLines.remove(buffer); SYNC(ARG(buffer)) emit bufferRemoved(buffer); } @@ -81,6 +115,8 @@ void BufferSyncer::removeBuffer(BufferId buffer) { void BufferSyncer::mergeBuffersPermanently(BufferId buffer1, BufferId buffer2) { if(_lastSeenMsg.contains(buffer2)) _lastSeenMsg.remove(buffer2); + if(_markerLines.contains(buffer2)) + _markerLines.remove(buffer2); SYNC(ARG(buffer1), ARG(buffer2)) emit buffersPermanentlyMerged(buffer1, buffer2); } diff --git a/src/common/buffersyncer.h b/src/common/buffersyncer.h index 48931896..55198288 100644 --- a/src/common/buffersyncer.h +++ b/src/common/buffersyncer.h @@ -30,17 +30,22 @@ class BufferSyncer : public SyncableObject { public: explicit BufferSyncer(QObject *parent); - explicit BufferSyncer(const QHash &lastSeenMsg, QObject *parent); + explicit BufferSyncer(const QHash &lastSeenMsg, const QHash &markerLines, QObject *parent); inline virtual const QMetaObject *syncMetaObject() const { return &staticMetaObject; } MsgId lastSeenMsg(BufferId buffer) const; + MsgId markerLine(BufferId buffer) const; public slots: QVariantList initLastSeenMsg() const; void initSetLastSeenMsg(const QVariantList &); + QVariantList initMarkerLines() const; + void initSetMarkerLines(const QVariantList &); + virtual inline void requestSetLastSeenMsg(BufferId buffer, const MsgId &msgId) { REQUEST(ARG(buffer), ARG(msgId)) } + virtual inline void requestSetMarkerLine(BufferId buffer, const MsgId &msgId) { REQUEST(ARG(buffer), ARG(msgId)) } virtual inline void requestRemoveBuffer(BufferId buffer) { REQUEST(ARG(buffer)) } virtual void removeBuffer(BufferId buffer); @@ -55,16 +60,23 @@ public slots: signals: void lastSeenMsgSet(BufferId buffer, const MsgId &msgId); + void markerLineSet(BufferId buffer, const MsgId &msgId); void bufferRemoved(BufferId buffer); void bufferRenamed(BufferId buffer, QString newName); void buffersPermanentlyMerged(BufferId buffer1, BufferId buffer2); protected slots: bool setLastSeenMsg(BufferId buffer, const MsgId &msgId); - QList bufferIds() const { return _lastSeenMsg.keys(); } + bool setMarkerLine(BufferId buffer, const MsgId &msgId); + +protected: + inline QList lastSeenBufferIds() const { return _lastSeenMsg.keys(); } + inline QList markerLineBufferIds() const { return _markerLines.keys(); } + inline QHash markerLines() const { return _markerLines; } private: QHash _lastSeenMsg; + QHash _markerLines; }; #endif diff --git a/src/core/corebuffersyncer.cpp b/src/core/corebuffersyncer.cpp index 37ff255f..55c28b26 100644 --- a/src/core/corebuffersyncer.cpp +++ b/src/core/corebuffersyncer.cpp @@ -32,7 +32,7 @@ public: INIT_SYNCABLE_OBJECT(CoreBufferSyncer) CoreBufferSyncer::CoreBufferSyncer(CoreSession *parent) - : BufferSyncer(Core::bufferLastSeenMsgIds(parent->user()), parent), + : BufferSyncer(Core::bufferLastSeenMsgIds(parent->user()), Core::bufferMarkerLineMsgIds(parent->user()), parent), _coreSession(parent), _purgeBuffers(false) { @@ -40,18 +40,31 @@ CoreBufferSyncer::CoreBufferSyncer(CoreSession *parent) void CoreBufferSyncer::requestSetLastSeenMsg(BufferId buffer, const MsgId &msgId) { if(setLastSeenMsg(buffer, msgId)) - dirtyBuffers << buffer; + dirtyLastSeenBuffers << buffer; +} + +void CoreBufferSyncer::requestSetMarkerLine(BufferId buffer, const MsgId &msgId) { + if(setMarkerLine(buffer, msgId)) + dirtyMarkerLineBuffers << buffer; } void CoreBufferSyncer::storeDirtyIds() { UserId userId = _coreSession->user(); MsgId msgId; - foreach(BufferId bufferId, dirtyBuffers) { + foreach(BufferId bufferId, dirtyLastSeenBuffers) { msgId = lastSeenMsg(bufferId); if(msgId.isValid()) Core::setBufferLastSeenMsg(userId, bufferId, msgId); } - dirtyBuffers.clear(); + + foreach(BufferId bufferId, dirtyMarkerLineBuffers) { + msgId = markerLine(bufferId); + if(msgId.isValid()) + Core::setBufferMarkerLineMsg(userId, bufferId, msgId); + } + + dirtyLastSeenBuffers.clear(); + dirtyMarkerLineBuffers.clear(); } void CoreBufferSyncer::removeBuffer(BufferId bufferId) { @@ -140,7 +153,7 @@ void CoreBufferSyncer::purgeBufferIds() { actualBuffers << bufferInfo.bufferId(); } - QList storedIds = bufferIds(); + QSet storedIds = lastSeenBufferIds().toSet() + markerLineBufferIds().toSet(); foreach(BufferId bufferId, storedIds) { if(!actualBuffers.contains(bufferId)) { BufferSyncer::removeBuffer(bufferId); diff --git a/src/core/corebuffersyncer.h b/src/core/corebuffersyncer.h index f567735a..89694bf6 100644 --- a/src/core/corebuffersyncer.h +++ b/src/core/corebuffersyncer.h @@ -34,6 +34,7 @@ public: public slots: virtual void requestSetLastSeenMsg(BufferId buffer, const MsgId &msgId); + virtual void requestSetMarkerLine(BufferId buffer, const MsgId &msgId); virtual inline void requestRemoveBuffer(BufferId buffer) { removeBuffer(buffer); } virtual void removeBuffer(BufferId bufferId); @@ -55,7 +56,8 @@ private: CoreSession *_coreSession; bool _purgeBuffers; - QSet dirtyBuffers; + QSet dirtyLastSeenBuffers; + QSet dirtyMarkerLineBuffers; void purgeBufferIds(); }; diff --git a/src/qtui/chatitem.cpp b/src/qtui/chatitem.cpp index c40fd34b..6add4465 100644 --- a/src/qtui/chatitem.cpp +++ b/src/qtui/chatitem.cpp @@ -31,6 +31,7 @@ #include "buffermodel.h" #include "bufferview.h" #include "chatitem.h" +#include "chatline.h" #include "chatlinemodel.h" #include "contextmenuactionprovider.h" #include "iconloader.h" @@ -49,6 +50,14 @@ ChatItem::ChatItem(const qreal &width, const qreal &height, const QPointF &pos, setPos(pos); } +const QAbstractItemModel *ChatItem::model() const { + return static_cast(parentItem())->model(); +} + +int ChatItem::row() const { + return static_cast(parentItem())->row(); +} + QVariant ChatItem::data(int role) const { QModelIndex index = model()->index(row(), column()); if(!index.isValid()) { diff --git a/src/qtui/chatitem.h b/src/qtui/chatitem.h index 3d5ad2ff..36fb1c1e 100644 --- a/src/qtui/chatitem.h +++ b/src/qtui/chatitem.h @@ -38,8 +38,8 @@ protected: ChatItem(const qreal &width, const qreal &height, const QPointF &pos, QGraphicsItem *parent); public: - inline const QAbstractItemModel *model() const; - inline int row() const; + const QAbstractItemModel *model() const; + int row() const; virtual ChatLineModel::ColumnType column() const = 0; inline ChatScene *chatScene() const { return qobject_cast(scene()); } @@ -268,9 +268,4 @@ private: /*************************************************************************************************/ -// Avoid circular include deps -#include "chatline.h" -const QAbstractItemModel *ChatItem::model() const { return static_cast(parentItem())->model(); } -int ChatItem::row() const { return static_cast(parentItem())->row(); } - #endif diff --git a/src/qtui/chatline.cpp b/src/qtui/chatline.cpp index c1c98da6..38e78c69 100644 --- a/src/qtui/chatline.cpp +++ b/src/qtui/chatline.cpp @@ -184,7 +184,7 @@ void ChatLine::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, // don't show the marker if we wrote that new line if(!(flags & Message::Self)) { BufferId bufferId = BufferId(chatScene()->idString().toInt()); - MsgId lastSeenMsgId = Client::networkModel()->lastSeenMarkerMsgId(bufferId); + MsgId lastSeenMsgId = Client::networkModel()->markerLineMsgId(bufferId); if(lastSeenMsgId < myMsgId && lastSeenMsgId >= prevMsgId) { QLinearGradient gradient(0, 0, 0, contentsItem().fontMetrics()->lineSpacing()); gradient.setColorAt(0, QtUi::style()->brush(UiStyle::MarkerLine).color()); // FIXME: Use full (gradient?) brush instead of just the color diff --git a/src/qtui/chatviewsearchcontroller.cpp b/src/qtui/chatviewsearchcontroller.cpp index c732486d..add7478b 100644 --- a/src/qtui/chatviewsearchcontroller.cpp +++ b/src/qtui/chatviewsearchcontroller.cpp @@ -24,6 +24,7 @@ #include #include "chatitem.h" +#include "chatline.h" #include "chatlinemodel.h" #include "chatscene.h" #include "messagemodel.h" diff --git a/src/uisupport/abstractbuffercontainer.cpp b/src/uisupport/abstractbuffercontainer.cpp index 7be93f0d..8fa43513 100644 --- a/src/uisupport/abstractbuffercontainer.cpp +++ b/src/uisupport/abstractbuffercontainer.cpp @@ -79,7 +79,10 @@ void AbstractBufferContainer::currentChanged(const QModelIndex ¤t, const Q void AbstractBufferContainer::setCurrentBuffer(BufferId bufferId) { BufferId prevBufferId = currentBuffer(); if(prevBufferId.isValid() && _chatViews.contains(prevBufferId)) { - Client::setBufferLastSeenMsg(prevBufferId, _chatViews[prevBufferId]->lastMsgId()); + MsgId msgId = _chatViews.value(prevBufferId)->lastMsgId(); + Client::setBufferLastSeenMsg(prevBufferId, msgId); + if(autoSetMarkerLine()) + Client::setBufferMarkerLine(prevBufferId, msgId); } if(!bufferId.isValid()) { @@ -94,10 +97,7 @@ void AbstractBufferContainer::setCurrentBuffer(BufferId bufferId) { _currentBuffer = bufferId; showChatView(bufferId); Client::networkModel()->clearBufferActivity(bufferId); + Client::setBufferLastSeenMsg(bufferId, _chatViews[bufferId]->lastMsgId()); Client::backlogManager()->checkForBacklog(bufferId); setFocus(); - - if(bufferId.isValid() && _chatViews.contains(bufferId)) { - Client::setBufferLastSeenMsg(bufferId, _chatViews[bufferId]->lastMsgId()); - } } diff --git a/src/uisupport/abstractbuffercontainer.h b/src/uisupport/abstractbuffercontainer.h index bf583333..84ab2807 100644 --- a/src/uisupport/abstractbuffercontainer.h +++ b/src/uisupport/abstractbuffercontainer.h @@ -52,6 +52,8 @@ protected: */ virtual void removeChatView(BufferId) = 0; + virtual inline bool autoSetMarkerLine() const { return true; } + protected slots: virtual void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); virtual void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); -- 2.20.1