[network/ruqola] src/widgets/room: Remeasure message rows when their height changes

Laurent Montel <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit 6268a0e336ae1ef585fc5428670c270f68ebeefe by Laurent Montel, on behalf of Till Adam.
Committed on 28/07/2026 at 11:54.
Pushed by tilladam into branch 'master'.

Remeasure message rows when their height changes

The message list reacted to two height-changing events with a bare repaint
and no relayout, so rows kept the stale heights held in the delegate's
per-message size-hint cache:

- Marking a room read (Room::lastSeenChanged) removes the "unread messages"
  marker, which had reserved a band of vertical space at the top of the row
  it preceded; the row then stayed tall with the band left as dead space.
- Switching message style (Compact/Normal/Cozy) recreates the layout and
  clears the size-hint cache in switchMessageLayout(), but the previous
  style's row geometry lingered until an unrelated event forced a relayout.

Give lastSeenChanged its own slot that clears the stale size hints and
schedules a relayout, and add the relayout to slotUpdateView() (the
style-switch path already clears the cache). Row heights now update as soon
as they change.

M  +21   -2    src/widgets/room/messagelistview.cpp
M  +1    -0    src/widgets/room/messagelistview.h

https://invent.kde.org/network/ruqola/-/commit/6268a0e336ae1ef585fc5428670c270f68ebeefe

diff --git a/src/widgets/room/messagelistview.cpp b/src/widgets/room/messagelistview.cpp
index e04bb10064..824b0f7bb3 100644
--- a/src/widgets/room/messagelistview.cpp
+++ b/src/widgets/room/messagelistview.cpp
@@ -140,18 +140,37 @@ void MessageListView::paintEvent(QPaintEvent *e)
 
 void MessageListView::slotUpdateView()
 {
+    // A message-style switch (Compact/Normal/Cozy) recreates the layout and clears the delegate's
+    // size-hint cache in switchMessageLayout(), but without a relayout the view keeps the previous
+    // style's row geometry until an unrelated event (scroll/resize/new message) triggers one.
+    // Remeasure here so the switch takes effect immediately. (A colour-scheme refresh also arrives
+    // via this slot and harmlessly relayouts.)
+    scheduleDelayedItemsLayout();
     viewport()->update();
 }
 
+void MessageListView::slotLastSeenChanged()
+{
+    // The "unread messages" marker reserves a band of vertical space at the top of the row it
+    // precedes, and that extra height is baked into the delegate's per-message size-hint cache
+    // (keyed by message id only). When the room is marked read the marker disappears
+    // (DisplayLastSeenMessage flips to false), but a plain repaint would keep the cached row
+    // height and leave the band as dead space — the row stays tall. Drop the now-stale sizes and
+    // relayout so the affected row shrinks back. Mark-as-read is infrequent, so clearing the
+    // whole cache (rather than hunting the single boundary row) is a fine trade-off.
+    mMessageListDelegate->clearSizeHintCache();
+    scheduleDelayedItemsLayout();
+}
+
 void MessageListView::setRoom(Room *room)
 {
     if (mRoom) {
-        disconnect(mRoom, &Room::lastSeenChanged, this, &MessageListView::slotUpdateView);
+        disconnect(mRoom, &Room::lastSeenChanged, this, &MessageListView::slotLastSeenChanged);
         mMessageListDelegate->clearSelection();
     }
     mRoom = room;
     if (mRoom) {
-        connect(mRoom, &Room::lastSeenChanged, this, &MessageListView::slotUpdateView);
+        connect(mRoom, &Room::lastSeenChanged, this, &MessageListView::slotLastSeenChanged);
     }
 }
 
diff --git a/src/widgets/room/messagelistview.h b/src/widgets/room/messagelistview.h
index 59a3b0acdb..28fe3b4198 100644
--- a/src/widgets/room/messagelistview.h
+++ b/src/widgets/room/messagelistview.h
@@ -94,6 +94,7 @@ private:
     [[nodiscard]] LIBRUQOLAWIDGETS_NO_EXPORT QString generatePermalink(const QString &messageId) const;
     LIBRUQOLAWIDGETS_NO_EXPORT void slotShowUserInfo(const QString &userName);
     LIBRUQOLAWIDGETS_NO_EXPORT void slotUpdateView();
+    LIBRUQOLAWIDGETS_NO_EXPORT void slotLastSeenChanged();
     LIBRUQOLAWIDGETS_NO_EXPORT void slotTranslate(const QString &from, const QString &to, const QPersistentModelIndex &modelIndex);
     LIBRUQOLAWIDGETS_NO_EXPORT void slotTextToSpeech(const QModelIndex &index);
     LIBRUQOLAWIDGETS_NO_EXPORT void addDebugMenu(QMenu &menu, const QModelIndex &index);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.