Store highlight status per buffer coreside
authorJanne Koschinski <janne@kuschku.de>
Tue, 8 May 2018 18:36:25 +0000 (13:36 -0500)
committerManuel Nickschas <sputnick@quassel-irc.org>
Wed, 23 May 2018 22:33:28 +0000 (00:33 +0200)
- Add highlightCount to buffersyncer, same as with buffer activities
- If this value is increased, it is synced with clients, and they add
  it to the buffer status, showing it in orange
- This allows you to see highlights even if they are not loaded in
  initial backlog, but only core-side highlights.

Closes GH-333.

27 files changed:
src/client/client.cpp
src/client/networkmodel.cpp
src/client/networkmodel.h
src/common/buffersyncer.cpp
src/common/buffersyncer.h
src/core/SQL/PostgreSQL/migrate_write_buffer.sql
src/core/SQL/PostgreSQL/select_buffer_highlightcount.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/select_buffer_highlightcounts.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/setup_050_buffer.sql
src/core/SQL/PostgreSQL/update_buffer_highlightcount.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/version/26/upgrade_000_alter_buffer_add_highlightcount.sql [new file with mode: 0644]
src/core/SQL/SQLite/migrate_read_buffer.sql
src/core/SQL/SQLite/select_buffer_highlightcount.sql [new file with mode: 0644]
src/core/SQL/SQLite/select_buffer_highlightcounts.sql [new file with mode: 0644]
src/core/SQL/SQLite/setup_030_buffer.sql
src/core/SQL/SQLite/update_buffer_highlightcount.sql [new file with mode: 0644]
src/core/SQL/SQLite/version/28/upgrade_000_alter_buffer_add_highlightcount.sql [new file with mode: 0644]
src/core/abstractsqlstorage.h
src/core/core.h
src/core/corebuffersyncer.cpp
src/core/corebuffersyncer.h
src/core/postgresqlstorage.cpp
src/core/postgresqlstorage.h
src/core/sql.qrc
src/core/sqlitestorage.cpp
src/core/sqlitestorage.h
src/core/storage.h

index 5805887..f8627d0 100644 (file)
@@ -394,6 +394,7 @@ void Client::setSyncedToCore()
     connect(bufferSyncer(), SIGNAL(buffersPermanentlyMerged(BufferId, BufferId)), _messageModel, SLOT(buffersPermanentlyMerged(BufferId, BufferId)));
     connect(bufferSyncer(), SIGNAL(bufferMarkedAsRead(BufferId)), SIGNAL(bufferMarkedAsRead(BufferId)));
     connect(bufferSyncer(), SIGNAL(bufferActivityChanged(BufferId, const Message::Types)), _networkModel, SLOT(bufferActivityChanged(BufferId, const Message::Types)));
     connect(bufferSyncer(), SIGNAL(buffersPermanentlyMerged(BufferId, BufferId)), _messageModel, SLOT(buffersPermanentlyMerged(BufferId, BufferId)));
     connect(bufferSyncer(), SIGNAL(bufferMarkedAsRead(BufferId)), SIGNAL(bufferMarkedAsRead(BufferId)));
     connect(bufferSyncer(), SIGNAL(bufferActivityChanged(BufferId, const Message::Types)), _networkModel, SLOT(bufferActivityChanged(BufferId, const Message::Types)));
+    connect(bufferSyncer(), SIGNAL(highlightCountChanged(BufferId, int)), _networkModel, SLOT(highlightCountChanged(BufferId, int)));
     connect(networkModel(), SIGNAL(requestSetLastSeenMsg(BufferId, MsgId)), bufferSyncer(), SLOT(requestSetLastSeenMsg(BufferId, const MsgId &)));
 
     SignalProxy *p = signalProxy();
     connect(networkModel(), SIGNAL(requestSetLastSeenMsg(BufferId, MsgId)), bufferSyncer(), SLOT(requestSetLastSeenMsg(BufferId, const MsgId &)));
 
     SignalProxy *p = signalProxy();
@@ -460,8 +461,10 @@ void Client::finishConnectionInitialization()
     disconnect(bufferSyncer(), SIGNAL(initDone()), this, SLOT(finishConnectionInitialization()));
 
     requestInitialBacklog();
     disconnect(bufferSyncer(), SIGNAL(initDone()), this, SLOT(finishConnectionInitialization()));
 
     requestInitialBacklog();
-    if (isCoreFeatureEnabled(Quassel::Feature::BufferActivitySync))
+    if (isCoreFeatureEnabled(Quassel::Feature::BufferActivitySync)) {
         bufferSyncer()->markActivitiesChanged();
         bufferSyncer()->markActivitiesChanged();
+        bufferSyncer()->markHighlightCountsChanged();
+    }
 }
 
 
 }
 
 
index 77aeccc..8214966 100644 (file)
@@ -147,8 +147,12 @@ BufferItem *NetworkItem::bufferItem(const BufferInfo &bufferInfo)
     }
 
     BufferSyncer *bufferSyncer = Client::bufferSyncer();
     }
 
     BufferSyncer *bufferSyncer = Client::bufferSyncer();
-    if (bufferSyncer)
-        bufferItem->addActivity(bufferSyncer->activity(bufferItem->bufferId()), false);
+    if (bufferSyncer) {
+        bufferItem->addActivity(
+                bufferSyncer->activity(bufferItem->bufferId()),
+                bufferSyncer->highlightCount(bufferItem->bufferId()) > 0
+        );
+    }
 
     return bufferItem;
 }
 
     return bufferItem;
 }
@@ -1757,3 +1761,12 @@ void NetworkModel::bufferActivityChanged(BufferId bufferId, const Message::Types
     auto activityVisibleTypesIntersection = activity & visibleTypes;
     _bufferItem->setActivity(activityVisibleTypesIntersection, false);
 }
     auto activityVisibleTypesIntersection = activity & visibleTypes;
     _bufferItem->setActivity(activityVisibleTypesIntersection, false);
 }
+
+void NetworkModel::highlightCountChanged(BufferId bufferId, int count) {
+    auto _bufferItem = findBufferItem(bufferId);
+    if (!_bufferItem) {
+        qDebug() << "NetworkModel::highlightCountChanged(): buffer is unknown:" << bufferId;
+        return;
+    }
+    _bufferItem->addActivity(Message::Types{}, count > 0);
+}
index cc06938..6b68191 100644 (file)
@@ -386,6 +386,7 @@ public slots:
     void updateBufferActivity(Message &msg);
     void networkRemoved(const NetworkId &networkId);
     void bufferActivityChanged(BufferId, Message::Types);
     void updateBufferActivity(Message &msg);
     void networkRemoved(const NetworkId &networkId);
     void bufferActivityChanged(BufferId, Message::Types);
+    void highlightCountChanged(BufferId, int);
 
 signals:
     void requestSetLastSeenMsg(BufferId buffer, MsgId msg);
 
 signals:
     void requestSetLastSeenMsg(BufferId buffer, MsgId msg);
index 7198a46..3f437d9 100644 (file)
@@ -27,11 +27,17 @@ BufferSyncer::BufferSyncer(QObject *parent)
 }
 
 
 }
 
 
-BufferSyncer::BufferSyncer(const QHash<BufferId, MsgId> &lastSeenMsg, const QHash<BufferId, MsgId> &markerLines, const QHash<BufferId, Message::Types> &activities, QObject *parent)
-    : SyncableObject(parent),
+BufferSyncer::BufferSyncer(
+        const QHash<BufferId, MsgId> &lastSeenMsg,
+        const QHash<BufferId, MsgId> &markerLines,
+        const QHash<BufferId, Message::Types> &activities,
+        const QHash<BufferId, int> &highlightCounts,
+        QObject *parent
+) : SyncableObject(parent),
     _lastSeenMsg(lastSeenMsg),
     _markerLines(markerLines),
     _lastSeenMsg(lastSeenMsg),
     _markerLines(markerLines),
-    _bufferActivities(activities)
+    _bufferActivities(activities),
+    _highlightCounts(highlightCounts)
 {
 }
 
 {
 }
 
@@ -162,6 +168,8 @@ void BufferSyncer::removeBuffer(BufferId buffer)
         _markerLines.remove(buffer);
     if (_bufferActivities.contains(buffer))
         _bufferActivities.remove(buffer);
         _markerLines.remove(buffer);
     if (_bufferActivities.contains(buffer))
         _bufferActivities.remove(buffer);
+    if (_highlightCounts.contains(buffer))
+        _highlightCounts.remove(buffer);
     SYNC(ARG(buffer))
     emit bufferRemoved(buffer);
 }
     SYNC(ARG(buffer))
     emit bufferRemoved(buffer);
 }
@@ -175,6 +183,31 @@ void BufferSyncer::mergeBuffersPermanently(BufferId buffer1, BufferId buffer2)
         _markerLines.remove(buffer2);
     if (_bufferActivities.contains(buffer2))
         _bufferActivities.remove(buffer2);
         _markerLines.remove(buffer2);
     if (_bufferActivities.contains(buffer2))
         _bufferActivities.remove(buffer2);
+    if (_highlightCounts.contains(buffer2))
+        _highlightCounts.remove(buffer2);
     SYNC(ARG(buffer1), ARG(buffer2))
     emit buffersPermanentlyMerged(buffer1, buffer2);
 }
     SYNC(ARG(buffer1), ARG(buffer2))
     emit buffersPermanentlyMerged(buffer1, buffer2);
 }
+
+int BufferSyncer::highlightCount(BufferId buffer) const {
+    return _highlightCounts.value(buffer, 0);
+}
+
+QVariantList BufferSyncer::initHighlightCounts() const {
+    QVariantList list;
+    auto iter = _highlightCounts.constBegin();
+    while (iter != _highlightCounts.constEnd()) {
+        list << QVariant::fromValue<BufferId>(iter.key())
+             << QVariant::fromValue<int>((int) iter.value());
+        ++iter;
+    }
+    return list;
+}
+
+void BufferSyncer::initSetHighlightCounts(const QVariantList &list) {
+    _highlightCounts.clear();
+    Q_ASSERT(list.count() % 2 == 0);
+    for (int i = 0; i < list.count(); i += 2) {
+        setHighlightCount(list.at(i).value<BufferId>(), list.at(i+1).value<int>());
+    }
+}
index 3dc706e..9ca0c01 100644 (file)
@@ -32,13 +32,14 @@ class BufferSyncer : public SyncableObject
 
 public:
     explicit BufferSyncer(QObject *parent);
 
 public:
     explicit BufferSyncer(QObject *parent);
-    explicit BufferSyncer(const QHash<BufferId, MsgId> &lastSeenMsg, const QHash<BufferId, MsgId> &markerLines, const QHash<BufferId, Message::Types> &activities, QObject *parent);
+    explicit BufferSyncer(const QHash<BufferId, MsgId> &lastSeenMsg, const QHash<BufferId, MsgId> &markerLines, const QHash<BufferId, Message::Types> &activities, const QHash<BufferId, int> &highlightCounts, QObject *parent);
 
     inline virtual const QMetaObject *syncMetaObject() const { return &staticMetaObject; }
 
     MsgId lastSeenMsg(BufferId buffer) const;
     MsgId markerLine(BufferId buffer) const;
     Message::Types activity(BufferId buffer) const;
 
     inline virtual const QMetaObject *syncMetaObject() const { return &staticMetaObject; }
 
     MsgId lastSeenMsg(BufferId buffer) const;
     MsgId markerLine(BufferId buffer) const;
     Message::Types activity(BufferId buffer) const;
+    int highlightCount(BufferId buffer) const;
 
     void markActivitiesChanged() {
         for (auto buffer : _bufferActivities.keys()) {
 
     void markActivitiesChanged() {
         for (auto buffer : _bufferActivities.keys()) {
@@ -46,6 +47,12 @@ public:
         }
     }
 
         }
     }
 
+    void markHighlightCountsChanged() {
+        for (auto buffer : _highlightCounts.keys()) {
+            emit highlightCountChanged(buffer, highlightCount(buffer));
+        }
+    }
+
 public slots:
     QVariantList initLastSeenMsg() const;
     void initSetLastSeenMsg(const QVariantList &);
 public slots:
     QVariantList initLastSeenMsg() const;
     void initSetLastSeenMsg(const QVariantList &);
@@ -56,6 +63,9 @@ public slots:
     QVariantList initActivities() const;
     void initSetActivities(const QVariantList &);
 
     QVariantList initActivities() const;
     void initSetActivities(const QVariantList &);
 
+    QVariantList initHighlightCounts() const;
+    void initSetHighlightCounts(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)) setMarkerLine(buffer, msgId); }
 
     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)) setMarkerLine(buffer, msgId); }
 
@@ -66,6 +76,12 @@ public slots:
         emit bufferActivityChanged(buffer, flags);
     }
 
         emit bufferActivityChanged(buffer, flags);
     }
 
+    virtual inline void setHighlightCount(BufferId buffer, int count) {
+        SYNC(ARG(buffer), ARG(count));
+        _highlightCounts[buffer] = count;
+        emit highlightCountChanged(buffer, count);
+    }
+
     virtual inline void requestRemoveBuffer(BufferId buffer) { REQUEST(ARG(buffer)) }
     virtual void removeBuffer(BufferId buffer);
 
     virtual inline void requestRemoveBuffer(BufferId buffer) { REQUEST(ARG(buffer)) }
     virtual void removeBuffer(BufferId buffer);
 
@@ -88,6 +104,7 @@ signals:
     void buffersPermanentlyMerged(BufferId buffer1, BufferId buffer2);
     void bufferMarkedAsRead(BufferId buffer);
     void bufferActivityChanged(BufferId, Message::Types);
     void buffersPermanentlyMerged(BufferId buffer1, BufferId buffer2);
     void bufferMarkedAsRead(BufferId buffer);
     void bufferActivityChanged(BufferId, Message::Types);
+    void highlightCountChanged(BufferId, int);
 
 protected slots:
     bool setLastSeenMsg(BufferId buffer, const MsgId &msgId);
 
 protected slots:
     bool setLastSeenMsg(BufferId buffer, const MsgId &msgId);
@@ -102,6 +119,7 @@ private:
     QHash<BufferId, MsgId> _lastSeenMsg;
     QHash<BufferId, MsgId> _markerLines;
     QHash<BufferId, Message::Types> _bufferActivities;
     QHash<BufferId, MsgId> _lastSeenMsg;
     QHash<BufferId, MsgId> _markerLines;
     QHash<BufferId, Message::Types> _bufferActivities;
+    QHash<BufferId, int> _highlightCounts;
 };
 
 
 };
 
 
index 3ae6cf4..e87a736 100644 (file)
@@ -1,2 +1,2 @@
-INSERT INTO buffer (bufferid, userid, groupid, networkid, buffername, buffercname, buffertype, lastmsgid, lastseenmsgid, markerlinemsgid, bufferactivity, key, joined, cipher)
-VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+INSERT INTO buffer (bufferid, userid, groupid, networkid, buffername, buffercname, buffertype, lastmsgid, lastseenmsgid, markerlinemsgid, bufferactivity, highlightcount, key, joined, cipher)
+VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
diff --git a/src/core/SQL/PostgreSQL/select_buffer_highlightcount.sql b/src/core/SQL/PostgreSQL/select_buffer_highlightcount.sql
new file mode 100644 (file)
index 0000000..33058f8
--- /dev/null
@@ -0,0 +1,7 @@
+SELECT COALESCE(t.sum,0)
+FROM
+  (SELECT COUNT(*) AS sum FROM backlog
+   WHERE bufferid = :bufferid
+     AND flags & 2 != 0
+     AND flags & 1 = 0
+     AND messageid > :lastseenmsgid) t;
diff --git a/src/core/SQL/PostgreSQL/select_buffer_highlightcounts.sql b/src/core/SQL/PostgreSQL/select_buffer_highlightcounts.sql
new file mode 100644 (file)
index 0000000..b5b7688
--- /dev/null
@@ -0,0 +1,3 @@
+SELECT bufferid, highlightcount
+FROM buffer
+WHERE userid = :userid
index 0d92f43..5b73c88 100644 (file)
@@ -10,6 +10,7 @@ create TABLE buffer (
        lastseenmsgid integer NOT NULL DEFAULT 0,
        markerlinemsgid integer NOT NULL DEFAULT 0,
        bufferactivity integer NOT NULL DEFAULT 0,
        lastseenmsgid integer NOT NULL DEFAULT 0,
        markerlinemsgid integer NOT NULL DEFAULT 0,
        bufferactivity integer NOT NULL DEFAULT 0,
+       highlightcount integer NOT NULL DEFAULT 0,
        key varchar(128),
        joined boolean NOT NULL DEFAULT FALSE, -- BOOL
        cipher TEXT,
        key varchar(128),
        joined boolean NOT NULL DEFAULT FALSE, -- BOOL
        cipher TEXT,
diff --git a/src/core/SQL/PostgreSQL/update_buffer_highlightcount.sql b/src/core/SQL/PostgreSQL/update_buffer_highlightcount.sql
new file mode 100644 (file)
index 0000000..9619fd3
--- /dev/null
@@ -0,0 +1,3 @@
+UPDATE buffer
+SET highlightcount = :highlightcount
+WHERE userid = :userid AND bufferid = :bufferid
diff --git a/src/core/SQL/PostgreSQL/version/26/upgrade_000_alter_buffer_add_highlightcount.sql b/src/core/SQL/PostgreSQL/version/26/upgrade_000_alter_buffer_add_highlightcount.sql
new file mode 100644 (file)
index 0000000..4ea3d99
--- /dev/null
@@ -0,0 +1,2 @@
+ALTER TABLE buffer
+ADD COLUMN highlightcount integer NOT NULL DEFAULT 0
index da20e39..515e2c8 100644 (file)
@@ -1,2 +1,2 @@
-SELECT bufferid, userid, groupid, networkid, buffername, buffercname, buffertype, lastmsgid, lastseenmsgid, markerlinemsgid, bufferactivity, key, joined, cipher
+SELECT bufferid, userid, groupid, networkid, buffername, buffercname, buffertype, lastmsgid, lastseenmsgid, markerlinemsgid, bufferactivity, highlightcount, key, joined, cipher
 FROM buffer
 FROM buffer
diff --git a/src/core/SQL/SQLite/select_buffer_highlightcount.sql b/src/core/SQL/SQLite/select_buffer_highlightcount.sql
new file mode 100644 (file)
index 0000000..33058f8
--- /dev/null
@@ -0,0 +1,7 @@
+SELECT COALESCE(t.sum,0)
+FROM
+  (SELECT COUNT(*) AS sum FROM backlog
+   WHERE bufferid = :bufferid
+     AND flags & 2 != 0
+     AND flags & 1 = 0
+     AND messageid > :lastseenmsgid) t;
diff --git a/src/core/SQL/SQLite/select_buffer_highlightcounts.sql b/src/core/SQL/SQLite/select_buffer_highlightcounts.sql
new file mode 100644 (file)
index 0000000..b5b7688
--- /dev/null
@@ -0,0 +1,3 @@
+SELECT bufferid, highlightcount
+FROM buffer
+WHERE userid = :userid
index 5781c24..7e29531 100644 (file)
@@ -10,6 +10,7 @@ CREATE TABLE buffer (
        lastseenmsgid INTEGER NOT NULL DEFAULT 0,
        markerlinemsgid INTEGER NOT NULL DEFAULT 0,
        bufferactivity INTEGER NOT NULL DEFAULT 0,
        lastseenmsgid INTEGER NOT NULL DEFAULT 0,
        markerlinemsgid INTEGER NOT NULL DEFAULT 0,
        bufferactivity INTEGER NOT NULL DEFAULT 0,
+       highlightcount INTEGER NOT NULL DEFAULT 0,
        key TEXT,
        joined INTEGER NOT NULL DEFAULT 0, -- BOOL
        cipher TEXT,
        key TEXT,
        joined INTEGER NOT NULL DEFAULT 0, -- BOOL
        cipher TEXT,
diff --git a/src/core/SQL/SQLite/update_buffer_highlightcount.sql b/src/core/SQL/SQLite/update_buffer_highlightcount.sql
new file mode 100644 (file)
index 0000000..9619fd3
--- /dev/null
@@ -0,0 +1,3 @@
+UPDATE buffer
+SET highlightcount = :highlightcount
+WHERE userid = :userid AND bufferid = :bufferid
diff --git a/src/core/SQL/SQLite/version/28/upgrade_000_alter_buffer_add_highlightcount.sql b/src/core/SQL/SQLite/version/28/upgrade_000_alter_buffer_add_highlightcount.sql
new file mode 100644 (file)
index 0000000..4ea3d99
--- /dev/null
@@ -0,0 +1,2 @@
+ALTER TABLE buffer
+ADD COLUMN highlightcount integer NOT NULL DEFAULT 0
index c554d9a..2a59fbf 100644 (file)
@@ -234,6 +234,7 @@ public:
         int lastseenmsgid;
         int markerlinemsgid;
         int bufferactivity;
         int lastseenmsgid;
         int markerlinemsgid;
         int bufferactivity;
+        int highlightcount;
         QString key;
         bool joined;
         QString cipher;
         QString key;
         bool joined;
         QString cipher;
index 98e2612..640ba18 100644 (file)
@@ -606,6 +606,39 @@ public:
         return instance()->_storage->bufferActivity(bufferId, lastSeenMsgId);
     }
 
         return instance()->_storage->bufferActivity(bufferId, lastSeenMsgId);
     }
 
+    //! Update the highlight count for a Buffer
+    /** This Method is used to make the highlight count state of a Buffer persistent
+     *  \note This method is threadsafe.
+     *
+     * \param user      The Owner of that Buffer
+     * \param bufferId  The buffer id
+     * \param MsgId     The Message id where the marker line should be placed
+     */
+    static inline void setHighlightCount(UserId user, BufferId bufferId, int highlightCount) {
+        return instance()->_storage->setHighlightCount(user, bufferId, highlightCount);
+    }
+
+
+    //! Get a Hash of all highlight count states
+    /** This Method is called when the Quassel Core is started to restore the highlight count
+     *  \note This method is threadsafe.
+     *
+     * \param user      The Owner of the buffers
+     */
+    static inline QHash<BufferId, int> highlightCounts(UserId user) {
+        return instance()->_storage->highlightCounts(user);
+    }
+    //! Get the highlight count states for a buffer
+    /** This method is used to load the highlight count of a buffer when its last seen message changes.
+     *  \note This method is threadsafe.
+     *
+     * \param bufferId The buffer
+     * \param lastSeenMsgId     The last seen message
+     */
+    static inline int highlightCount(BufferId bufferId, MsgId lastSeenMsgId) {
+        return instance()->_storage->highlightCount(bufferId, lastSeenMsgId);
+    }
+
     static inline QDateTime startTime() { return instance()->_startTime; }
     static inline bool isConfigured() { return instance()->_configured; }
     static bool sslSupported();
     static inline QDateTime startTime() { return instance()->_startTime; }
     static inline bool isConfigured() { return instance()->_configured; }
     static bool sslSupported();
index 175606b..0548326 100644 (file)
@@ -34,11 +34,12 @@ public:
 
 INIT_SYNCABLE_OBJECT(CoreBufferSyncer)
 CoreBufferSyncer::CoreBufferSyncer(CoreSession *parent)
 
 INIT_SYNCABLE_OBJECT(CoreBufferSyncer)
 CoreBufferSyncer::CoreBufferSyncer(CoreSession *parent)
-    : BufferSyncer(Core::bufferLastSeenMsgIds(parent->user()), Core::bufferMarkerLineMsgIds(parent->user()), Core::bufferActivities(parent->user()), parent),
+    : BufferSyncer(Core::bufferLastSeenMsgIds(parent->user()), Core::bufferMarkerLineMsgIds(parent->user()), Core::bufferActivities(parent->user()), Core::highlightCounts(parent->user()), parent),
     _coreSession(parent),
     _purgeBuffers(false)
 {
     connect(parent, SIGNAL(displayMsg(Message)), SLOT(addBufferActivity(Message)));
     _coreSession(parent),
     _purgeBuffers(false)
 {
     connect(parent, SIGNAL(displayMsg(Message)), SLOT(addBufferActivity(Message)));
+    connect(parent, SIGNAL(displayMsg(Message)), SLOT(addCoreHighlight(Message)));
 }
 
 
 }
 
 
@@ -46,7 +47,11 @@ void CoreBufferSyncer::requestSetLastSeenMsg(BufferId buffer, const MsgId &msgId
 {
     if (setLastSeenMsg(buffer, msgId)) {
         int activity = Core::bufferActivity(buffer, msgId);
 {
     if (setLastSeenMsg(buffer, msgId)) {
         int activity = Core::bufferActivity(buffer, msgId);
+        int highlightCount = Core::highlightCount(buffer, msgId);
+
         setBufferActivity(buffer, activity);
         setBufferActivity(buffer, activity);
+        setHighlightCount(buffer, highlightCount);
+
         dirtyLastSeenBuffers << buffer;
     }
 }
         dirtyLastSeenBuffers << buffer;
     }
 }
@@ -79,9 +84,14 @@ void CoreBufferSyncer::storeDirtyIds()
         Core::setBufferActivity(userId, bufferId, activity(bufferId));
     }
 
         Core::setBufferActivity(userId, bufferId, activity(bufferId));
     }
 
+    foreach(BufferId bufferId, dirtyHighlights) {
+        Core::setHighlightCount(userId, bufferId, highlightCount(bufferId));
+    }
+
     dirtyLastSeenBuffers.clear();
     dirtyMarkerLineBuffers.clear();
     dirtyActivities.clear();
     dirtyLastSeenBuffers.clear();
     dirtyMarkerLineBuffers.clear();
     dirtyActivities.clear();
+    dirtyHighlights.clear();
 }
 
 
 }
 
 
@@ -195,3 +205,8 @@ void CoreBufferSyncer::setBufferActivity(BufferId buffer, int activity) {
     BufferSyncer::setBufferActivity(buffer, activity);
     dirtyActivities << buffer;
 }
     BufferSyncer::setBufferActivity(buffer, activity);
     dirtyActivities << buffer;
 }
+
+void CoreBufferSyncer::setHighlightCount(BufferId buffer, int highlightCount) {
+    BufferSyncer::setHighlightCount(buffer, highlightCount);
+    dirtyHighlights << buffer;
+}
index 6aeaa6d..dd33f06 100644 (file)
@@ -47,8 +47,17 @@ public slots:
         }
     }
 
         }
     }
 
+    void addCoreHighlight(const Message &message) {
+        auto oldHighlightCount = highlightCount(message.bufferId());
+        if (message.flags().testFlag(Message::Flag::Highlight) && !message.flags().testFlag(Message::Flag::Self)) {
+            setHighlightCount(message.bufferId(), oldHighlightCount + 1);
+        }
+    }
+
     void setBufferActivity(BufferId buffer, int activity) override;
 
     void setBufferActivity(BufferId buffer, int activity) override;
 
+    void setHighlightCount(BufferId buffer, int highlightCount) override;
+
     inline void requestRenameBuffer(BufferId buffer, QString newName) override { renameBuffer(buffer, newName); }
     void renameBuffer(BufferId buffer, QString newName) override;
 
     inline void requestRenameBuffer(BufferId buffer, QString newName) override { renameBuffer(buffer, newName); }
     void renameBuffer(BufferId buffer, QString newName) override;
 
@@ -60,6 +69,7 @@ public slots:
     inline void requestMarkBufferAsRead(BufferId buffer) override {
         int activity = Message::Types();
         setBufferActivity(buffer, activity);
     inline void requestMarkBufferAsRead(BufferId buffer) override {
         int activity = Message::Types();
         setBufferActivity(buffer, activity);
+        setHighlightCount(buffer, 0);
         markBufferAsRead(buffer);
     }
 
         markBufferAsRead(buffer);
     }
 
@@ -75,6 +85,7 @@ private:
     QSet<BufferId> dirtyLastSeenBuffers;
     QSet<BufferId> dirtyMarkerLineBuffers;
     QSet<BufferId> dirtyActivities;
     QSet<BufferId> dirtyLastSeenBuffers;
     QSet<BufferId> dirtyMarkerLineBuffers;
     QSet<BufferId> dirtyActivities;
+    QSet<BufferId> dirtyHighlights;
 
     void purgeBufferIds();
 };
 
     void purgeBufferIds();
 };
index b64592d..7377149 100644 (file)
@@ -1478,6 +1478,61 @@ void PostgreSqlStorage::setBufferCipher(UserId user, const NetworkId &networkId,
     watchQuery(query);
 }
 
     watchQuery(query);
 }
 
+
+void PostgreSqlStorage::setHighlightCount(UserId user, BufferId bufferId, int highlightcount)
+{
+    QSqlQuery query(logDb());
+    query.prepare(queryString("update_buffer_highlightcount"));
+
+    query.bindValue(":userid", user.toInt());
+    query.bindValue(":bufferid", bufferId.toInt());
+    query.bindValue(":highlightcount", highlightcount);
+    safeExec(query);
+    watchQuery(query);
+}
+
+QHash<BufferId, int> PostgreSqlStorage::highlightCounts(UserId user)
+{
+    QHash<BufferId, int> highlightCountHash;
+
+    QSqlDatabase db = logDb();
+    if (!beginReadOnlyTransaction(db)) {
+        qWarning() << "PostgreSqlStorage::highlightCounts(): cannot start read only transaction!";
+        qWarning() << " -" << qPrintable(db.lastError().text());
+        return highlightCountHash;
+    }
+
+    QSqlQuery query(db);
+    query.prepare(queryString("select_buffer_highlightcounts"));
+    query.bindValue(":userid", user.toInt());
+    safeExec(query);
+    if (!watchQuery(query)) {
+        db.rollback();
+        return highlightCountHash;
+    }
+
+    while (query.next()) {
+        highlightCountHash[query.value(0).toInt()] = query.value(1).toInt();
+    }
+
+    db.commit();
+    return highlightCountHash;
+}
+
+int PostgreSqlStorage::highlightCount(BufferId bufferId, MsgId lastSeenMsgId)
+{
+    QSqlQuery query(logDb());
+    query.prepare(queryString("select_buffer_highlightcount"));
+    query.bindValue(":bufferid", bufferId.toInt());
+    query.bindValue(":lastseenmsgid", lastSeenMsgId.toInt());
+    safeExec(query);
+    watchQuery(query);
+    int result = int(0);
+    if (query.first())
+        result = query.value(0).toInt();
+    return result;
+}
+
 bool PostgreSqlStorage::logMessage(Message &msg)
 {
     QSqlDatabase db = logDb();
 bool PostgreSqlStorage::logMessage(Message &msg)
 {
     QSqlDatabase db = logDb();
@@ -2102,9 +2157,10 @@ bool PostgreSqlMigrationWriter::writeMo(const BufferMO &buffer)
     bindValue(8, buffer.lastseenmsgid);
     bindValue(9, buffer.markerlinemsgid);
     bindValue(10, buffer.bufferactivity);
     bindValue(8, buffer.lastseenmsgid);
     bindValue(9, buffer.markerlinemsgid);
     bindValue(10, buffer.bufferactivity);
-    bindValue(11, buffer.key);
-    bindValue(12, buffer.joined);
-    bindValue(13, buffer.cipher);
+    bindValue(11, buffer.highlightcount);
+    bindValue(12, buffer.key);
+    bindValue(13, buffer.joined);
+    bindValue(14, buffer.cipher);
     return exec();
 }
 
     return exec();
 }
 
index 3146581..5322a09 100644 (file)
@@ -98,6 +98,9 @@ public slots:
     void setBufferActivity(UserId id, BufferId bufferId, Message::Types type) override;
     QHash<BufferId, Message::Types> bufferActivities(UserId id) override;
     Message::Types bufferActivity(BufferId bufferId, MsgId lastSeenMsgId) override;
     void setBufferActivity(UserId id, BufferId bufferId, Message::Types type) override;
     QHash<BufferId, Message::Types> bufferActivities(UserId id) override;
     Message::Types bufferActivity(BufferId bufferId, MsgId lastSeenMsgId) override;
+    void setHighlightCount(UserId id, BufferId bufferId, int count) override;
+    QHash<BufferId, int> highlightCounts(UserId id) override;
+    int highlightCount(BufferId bufferId, MsgId lastSeenMsgId) override;
     QHash<QString, QByteArray> bufferCiphers(UserId user, const NetworkId &networkId) override;
     void setBufferCipher(UserId user, const NetworkId &networkId, const QString &bufferName, const QByteArray &cipher) override;
 
     QHash<QString, QByteArray> bufferCiphers(UserId user, const NetworkId &networkId) override;
     void setBufferCipher(UserId user, const NetworkId &networkId, const QString &bufferName, const QByteArray &cipher) override;
 
index 60ef637..b8fc95e 100644 (file)
@@ -40,6 +40,8 @@
     <file>./SQL/PostgreSQL/select_buffer_bufferactivity.sql</file>
     <file>./SQL/PostgreSQL/select_buffer_by_id.sql</file>
     <file>./SQL/PostgreSQL/select_buffer_ciphers.sql</file>
     <file>./SQL/PostgreSQL/select_buffer_bufferactivity.sql</file>
     <file>./SQL/PostgreSQL/select_buffer_by_id.sql</file>
     <file>./SQL/PostgreSQL/select_buffer_ciphers.sql</file>
+    <file>./SQL/PostgreSQL/select_buffer_highlightcount.sql</file>
+    <file>./SQL/PostgreSQL/select_buffer_highlightcounts.sql</file>
     <file>./SQL/PostgreSQL/select_buffer_lastseen_messages.sql</file>
     <file>./SQL/PostgreSQL/select_buffer_markerlinemsgids.sql</file>
     <file>./SQL/PostgreSQL/select_buffers.sql</file>
     <file>./SQL/PostgreSQL/select_buffer_lastseen_messages.sql</file>
     <file>./SQL/PostgreSQL/select_buffer_markerlinemsgids.sql</file>
     <file>./SQL/PostgreSQL/select_buffers.sql</file>
@@ -82,6 +84,7 @@
     <file>./SQL/PostgreSQL/update_backlog_bufferid.sql</file>
     <file>./SQL/PostgreSQL/update_buffer_bufferactivity.sql</file>
     <file>./SQL/PostgreSQL/update_buffer_cipher.sql</file>
     <file>./SQL/PostgreSQL/update_backlog_bufferid.sql</file>
     <file>./SQL/PostgreSQL/update_buffer_bufferactivity.sql</file>
     <file>./SQL/PostgreSQL/update_buffer_cipher.sql</file>
+    <file>./SQL/PostgreSQL/update_buffer_highlightcount.sql</file>
     <file>./SQL/PostgreSQL/update_buffer_lastseen.sql</file>
     <file>./SQL/PostgreSQL/update_buffer_markerlinemsgid.sql</file>
     <file>./SQL/PostgreSQL/update_buffer_name.sql</file>
     <file>./SQL/PostgreSQL/update_buffer_lastseen.sql</file>
     <file>./SQL/PostgreSQL/update_buffer_markerlinemsgid.sql</file>
     <file>./SQL/PostgreSQL/update_buffer_name.sql</file>
     <file>./SQL/PostgreSQL/version/23/upgrade_000_create_senderprefixes.sql</file>
     <file>./SQL/PostgreSQL/version/24/upgrade_000_alter_buffer_add_bufferactivity.sql</file>
     <file>./SQL/PostgreSQL/version/25/upgrade_000_alter_buffer_add_cipher.sql</file>
     <file>./SQL/PostgreSQL/version/23/upgrade_000_create_senderprefixes.sql</file>
     <file>./SQL/PostgreSQL/version/24/upgrade_000_alter_buffer_add_bufferactivity.sql</file>
     <file>./SQL/PostgreSQL/version/25/upgrade_000_alter_buffer_add_cipher.sql</file>
+    <file>./SQL/PostgreSQL/version/26/upgrade_000_alter_buffer_add_highlightcount.sql</file>
     <file>./SQL/SQLite/delete_backlog_by_uid.sql</file>
     <file>./SQL/SQLite/delete_backlog_for_buffer.sql</file>
     <file>./SQL/SQLite/delete_backlog_for_network.sql</file>
     <file>./SQL/SQLite/delete_backlog_by_uid.sql</file>
     <file>./SQL/SQLite/delete_backlog_for_buffer.sql</file>
     <file>./SQL/SQLite/delete_backlog_for_network.sql</file>
     <file>./SQL/SQLite/select_buffer_bufferactivity.sql</file>
     <file>./SQL/SQLite/select_buffer_by_id.sql</file>
     <file>./SQL/SQLite/select_buffer_ciphers.sql</file>
     <file>./SQL/SQLite/select_buffer_bufferactivity.sql</file>
     <file>./SQL/SQLite/select_buffer_by_id.sql</file>
     <file>./SQL/SQLite/select_buffer_ciphers.sql</file>
+    <file>./SQL/SQLite/select_buffer_highlightcount.sql</file>
+    <file>./SQL/SQLite/select_buffer_highlightcounts.sql</file>
     <file>./SQL/SQLite/select_buffer_lastseen_messages.sql</file>
     <file>./SQL/SQLite/select_buffer_markerlinemsgids.sql</file>
     <file>./SQL/SQLite/select_buffers.sql</file>
     <file>./SQL/SQLite/select_buffer_lastseen_messages.sql</file>
     <file>./SQL/SQLite/select_buffer_markerlinemsgids.sql</file>
     <file>./SQL/SQLite/select_buffers.sql</file>
     <file>./SQL/SQLite/update_backlog_bufferid.sql</file>
     <file>./SQL/SQLite/update_buffer_bufferactivity.sql</file>
     <file>./SQL/SQLite/update_buffer_cipher.sql</file>
     <file>./SQL/SQLite/update_backlog_bufferid.sql</file>
     <file>./SQL/SQLite/update_buffer_bufferactivity.sql</file>
     <file>./SQL/SQLite/update_buffer_cipher.sql</file>
+    <file>./SQL/SQLite/update_buffer_highlightcount.sql</file>
     <file>./SQL/SQLite/update_buffer_lastseen.sql</file>
     <file>./SQL/SQLite/update_buffer_markerlinemsgid.sql</file>
     <file>./SQL/SQLite/update_buffer_name.sql</file>
     <file>./SQL/SQLite/update_buffer_lastseen.sql</file>
     <file>./SQL/SQLite/update_buffer_markerlinemsgid.sql</file>
     <file>./SQL/SQLite/update_buffer_name.sql</file>
     <file>./SQL/SQLite/version/25/upgrade_000_alter_buffer_add_bufferactivity.sql</file>
     <file>./SQL/SQLite/version/26/upgrade_000_create_buffer_idx.sql</file>
     <file>./SQL/SQLite/version/27/upgrade_000_alter_buffer_add_cipher.sql</file>
     <file>./SQL/SQLite/version/25/upgrade_000_alter_buffer_add_bufferactivity.sql</file>
     <file>./SQL/SQLite/version/26/upgrade_000_create_buffer_idx.sql</file>
     <file>./SQL/SQLite/version/27/upgrade_000_alter_buffer_add_cipher.sql</file>
+    <file>./SQL/SQLite/version/28/upgrade_000_alter_buffer_add_highlightcount.sql</file>
 </qresource>
 </RCC>
 </qresource>
 </RCC>
index 6333882..d71dd3c 100644 (file)
@@ -1620,6 +1620,79 @@ void SqliteStorage::setBufferCipher(UserId user, const NetworkId &networkId, con
     unlock();
 }
 
     unlock();
 }
 
+void SqliteStorage::setHighlightCount(UserId user, BufferId bufferId, int count)
+{
+    QSqlDatabase db = logDb();
+    db.transaction();
+
+    {
+        QSqlQuery query(db);
+        query.prepare(queryString("update_buffer_highlightcount"));
+        query.bindValue(":userid", user.toInt());
+        query.bindValue(":bufferid", bufferId.toInt());
+        query.bindValue(":highlightcount", count);
+
+        lockForWrite();
+        safeExec(query);
+        watchQuery(query);
+    }
+    db.commit();
+    unlock();
+}
+
+
+QHash<BufferId, int> SqliteStorage::highlightCounts(UserId user)
+{
+    QHash<BufferId, int> highlightCountHash;
+
+    QSqlDatabase db = logDb();
+    db.transaction();
+
+    bool error = false;
+    {
+        QSqlQuery query(db);
+        query.prepare(queryString("select_buffer_highlightcounts"));
+        query.bindValue(":userid", user.toInt());
+
+        lockForRead();
+        safeExec(query);
+        error = !watchQuery(query);
+        if (!error) {
+            while (query.next()) {
+                highlightCountHash[query.value(0).toInt()] = query.value(1).toInt();
+            }
+        }
+    }
+
+    db.commit();
+    unlock();
+    return highlightCountHash;
+}
+
+
+int SqliteStorage::highlightCount(BufferId bufferId, MsgId lastSeenMsgId)
+{
+    QSqlDatabase db = logDb();
+    db.transaction();
+
+    int result = 0;
+    {
+        QSqlQuery query(db);
+        query.prepare(queryString("select_buffer_highlightcount"));
+        query.bindValue(":bufferid", bufferId.toInt());
+        query.bindValue(":lastseenmsgid", lastSeenMsgId.toInt());
+
+        lockForRead();
+        safeExec(query);
+        if (query.first())
+            result = query.value(0).toInt();
+    }
+
+    db.commit();
+    unlock();
+    return result;
+}
+
 bool SqliteStorage::logMessage(Message &msg)
 {
     QSqlDatabase db = logDb();
 bool SqliteStorage::logMessage(Message &msg)
 {
     QSqlDatabase db = logDb();
@@ -2116,9 +2189,10 @@ bool SqliteMigrationReader::readMo(BufferMO &buffer)
     buffer.lastseenmsgid = value(8).toInt();
     buffer.markerlinemsgid = value(9).toInt();
     buffer.bufferactivity = value(10).toInt();
     buffer.lastseenmsgid = value(8).toInt();
     buffer.markerlinemsgid = value(9).toInt();
     buffer.bufferactivity = value(10).toInt();
-    buffer.key = value(11).toString();
-    buffer.joined = value(12).toInt() == 1 ? true : false;
-    buffer.cipher = value(13).toString();
+    buffer.highlightcount = value(11).toInt();
+    buffer.key = value(12).toString();
+    buffer.joined = value(13).toInt() == 1 ? true : false;
+    buffer.cipher = value(14).toString();
     return true;
 }
 
     return true;
 }
 
index aa0dad1..367c644 100644 (file)
@@ -99,6 +99,9 @@ public slots:
     void setBufferActivity(UserId id, BufferId bufferId, Message::Types type) override;
     QHash<BufferId, Message::Types> bufferActivities(UserId id) override;
     Message::Types bufferActivity(BufferId bufferId, MsgId lastSeenMsgId) override;
     void setBufferActivity(UserId id, BufferId bufferId, Message::Types type) override;
     QHash<BufferId, Message::Types> bufferActivities(UserId id) override;
     Message::Types bufferActivity(BufferId bufferId, MsgId lastSeenMsgId) override;
+    void setHighlightCount(UserId id, BufferId bufferId, int count) override;
+    QHash<BufferId, int> highlightCounts(UserId id) override;
+    int highlightCount(BufferId bufferId, MsgId lastSeenMsgId) override;
     QHash<QString, QByteArray> bufferCiphers(UserId user, const NetworkId &networkId) override;
     void setBufferCipher(UserId user, const NetworkId &networkId, const QString &bufferName, const QByteArray &cipher) override;
 
     QHash<QString, QByteArray> bufferCiphers(UserId user, const NetworkId &networkId) override;
     void setBufferCipher(UserId user, const NetworkId &networkId, const QString &bufferName, const QByteArray &cipher) override;
 
index 49f2df8..d22372e 100644 (file)
@@ -430,6 +430,33 @@ public slots:
      */
     virtual void setBufferCipher(UserId user, const NetworkId &networkId, const QString &bufferName, const QByteArray &cipher) = 0;
 
      */
     virtual void setBufferCipher(UserId user, const NetworkId &networkId, const QString &bufferName, const QByteArray &cipher) = 0;
 
+    //! Update the highlight count for a Buffer
+    /** This Method is used to make the activity state of a Buffer persistent
+     *  \note This method is threadsafe.
+     *
+     * \param user      The Owner of that Buffer
+     * \param bufferId  The buffer id
+     * \param MsgId     The Message id where the marker line should be placed
+     */
+    virtual void setHighlightCount(UserId id, BufferId bufferId, int count) = 0;
+
+    //! Get a Hash of all highlight count states
+    /** This Method is called when the Quassel Core is started to restore the HighlightCounts
+     *  \note This method is threadsafe.
+     *
+     * \param user      The Owner of the buffers
+     */
+    virtual QHash<BufferId, int> highlightCounts(UserId id) = 0;
+
+    //! Get the highlight count states for a buffer
+    /** This method is used to load the activity state of a buffer when its last seen message changes.
+     *  \note This method is threadsafe.
+     *
+     * \param bufferId The buffer
+     * \param lastSeenMsgId     The last seen message
+     */
+    virtual int highlightCount(BufferId bufferId, MsgId lastSeenMsgId) = 0;
+
     /* Message handling */
 
     //! Store a Message in the storage backend and set its unique Id.
     /* Message handling */
 
     //! Store a Message in the storage backend and set its unique Id.