[network/ruqola] src/widgets/room/delegate/messagelistlayout: Give the unread-messages line vertical padding

Till Adam <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit 404ac54788df3da3a9f5de0ab55875c4f907a325 by Till Adam.
Committed on 27/07/2026 at 18:32.
Pushed by tilladam into branch 'master'.

Give the unread-messages line vertical padding

The standalone unread-messages separator (drawn when the last-seen position falls between two messages of the same day) was pinned to the very top edge of the following message's cell and reserved no vertical space. The line therefore hugged the top of that message — author line and avatar sat immediately below it — while the gap above came only from the previous message's spacing, so the separator looked lopsided.

Reserve a band the height of one text line for the separator and centre the line within it, mirroring how a date header occupies the top of a row. In the Normal layout the author line is anchored to the cell top rather than to `usableRect`, so the existing date-header compensation (which shifts the baseline, sender rect and avatar down) is generalised to cover the unread line as well; Cozy and Compact already derive the baseline from `usableRect` and need only the reserved band.

Fixes the lopsided placement in all three view modes (Normal / Cozy / Compact).

M  +5    -1    src/widgets/room/delegate/messagelistlayout/messagelistcompactlayout.cpp
M  +5    -1    src/widgets/room/delegate/messagelistlayout/messagelistcozylayout.cpp
M  +19   -12   src/widgets/room/delegate/messagelistlayout/messagelistnormallayout.cpp

https://invent.kde.org/network/ruqola/-/commit/404ac54788df3da3a9f5de0ab55875c4f907a325

diff --git a/src/widgets/room/delegate/messagelistlayout/messagelistcompactlayout.cpp b/src/widgets/room/delegate/messagelistlayout/messagelistcompactlayout.cpp
index f553033026..fe0b2ba48c 100644
--- a/src/widgets/room/delegate/messagelistlayout/messagelistcompactlayout.cpp
+++ b/src/widgets/room/delegate/messagelistlayout/messagelistcompactlayout.cpp
@@ -50,7 +50,11 @@ MessageListLayoutBase::Layout MessageListCompactLayout::doLayout(const QStyleOpt
     if (index.data(MessagesModel::DateDiffersFromPrevious).toBool()) {
         usableRect.setTop(usableRect.top() + option.fontMetrics.height());
     } else if (displayLastSeenMessage) {
-        layout.displayLastSeenMessageY = usableRect.top();
+        // Reserve a band for the unread-messages line and center it, so the line
+        // gets symmetric padding instead of hugging the top of the next message.
+        const int lastSeenLineHeight = option.fontMetrics.height();
+        layout.displayLastSeenMessageY = usableRect.top() + lastSeenLineHeight / 2;
+        usableRect.setTop(usableRect.top() + lastSeenLineHeight);
     }
 
     layout.usableRect = usableRect; // Just for the top, for now. The left will move later on.
diff --git a/src/widgets/room/delegate/messagelistlayout/messagelistcozylayout.cpp b/src/widgets/room/delegate/messagelistlayout/messagelistcozylayout.cpp
index 5a28715337..5b5df12695 100644
--- a/src/widgets/room/delegate/messagelistlayout/messagelistcozylayout.cpp
+++ b/src/widgets/room/delegate/messagelistlayout/messagelistcozylayout.cpp
@@ -49,7 +49,11 @@ MessageListLayoutBase::Layout MessageListCozyLayout::doLayout(const QStyleOption
     if (index.data(MessagesModel::DateDiffersFromPrevious).toBool()) {
         usableRect.setTop(usableRect.top() + option.fontMetrics.height());
     } else if (displayLastSeenMessage) {
-        layout.displayLastSeenMessageY = usableRect.top();
+        // Reserve a band for the unread-messages line and center it, so the line
+        // gets symmetric padding instead of hugging the top of the next message.
+        const int lastSeenLineHeight = option.fontMetrics.height();
+        layout.displayLastSeenMessageY = usableRect.top() + lastSeenLineHeight / 2;
+        usableRect.setTop(usableRect.top() + lastSeenLineHeight);
     }
 
     layout.usableRect = usableRect; // Just for the top, for now. The left will move later on.
diff --git a/src/widgets/room/delegate/messagelistlayout/messagelistnormallayout.cpp b/src/widgets/room/delegate/messagelistlayout/messagelistnormallayout.cpp
index 3a076b7799..983bc9eb2f 100644
--- a/src/widgets/room/delegate/messagelistlayout/messagelistnormallayout.cpp
+++ b/src/widgets/room/delegate/messagelistlayout/messagelistnormallayout.cpp
@@ -48,11 +48,19 @@ MessageListLayoutBase::Layout MessageListNormalLayout::doLayout(const QStyleOpti
 
     QRect usableRect = option.rect;
     const bool displayLastSeenMessage = index.data(MessagesModel::DisplayLastSeenMessage).toBool();
-    if (index.data(MessagesModel::DateDiffersFromPrevious).toBool()) {
-        usableRect.setTop(usableRect.top() + option.fontMetrics.height());
+    const bool dateDiffersFromPrevious = index.data(MessagesModel::DateDiffersFromPrevious).toBool();
+    // A date header and a standalone unread-messages line each occupy a band at the top of
+    // the row. Reserve it here; the author line is shifted down by the same amount below.
+    int topBandHeight = 0;
+    if (dateDiffersFromPrevious) {
+        topBandHeight = option.fontMetrics.height();
     } else if (displayLastSeenMessage) {
-        layout.displayLastSeenMessageY = usableRect.top();
+        topBandHeight = option.fontMetrics.height();
+        // Center the line in its band so it gets symmetric padding instead of hugging the
+        // top of the next message.
+        layout.displayLastSeenMessageY = usableRect.top() + topBandHeight / 2;
     }
+    usableRect.setTop(usableRect.top() + topBandHeight);
 
     layout.usableRect = usableRect; // Just for the top, for now. The left will move later on.
     usableRect.setTop(usableRect.top() + senderAscent); // FIXME position.
@@ -140,16 +148,15 @@ MessageListLayoutBase::Layout MessageListNormalLayout::doLayout(const QStyleOpti
     // Align top of sender rect so it matches the baseline of the richtext
     layout.senderRect =
         QRectF(senderX, layout.baseLine - senderAscent, senderTextSize.width(), (layout.sameSenderAsPreviousMessage ? 0 : senderTextSize.height()));
-    if (index.data(MessagesModel::DateDiffersFromPrevious).toBool()) {
-        // A date header occupies the row's top line (drawn by drawDate), and usableRect
-        // already pushed the message text down by that line's height. Shift the whole
-        // author line — the name baseline, its rect, and therefore the avatar — down by
-        // the same height, so a date row is exactly a regular new-sender row plus one
-        // header line. (Replaces an "- 4" fudge that moved only the baseline, leaving the
+    if (topBandHeight > 0) {
+        // A date header (drawn by drawDate) or a standalone unread-messages line occupies the
+        // row's top band, and usableRect already pushed the message text down by that band's
+        // height. Shift the whole author line — the name baseline, its rect, and therefore the
+        // avatar — down by the same height, so such a row is exactly a regular new-sender row
+        // plus the top band. (Replaces an "- 4" fudge that moved only the baseline, leaving the
         // author line looser above its text than a normal new-sender row.)
-        const int headerHeight = option.fontMetrics.height();
-        layout.baseLine += headerHeight;
-        layout.senderRect.moveTop(layout.senderRect.top() + headerHeight);
+        layout.baseLine += topBandHeight;
+        layout.senderRect.moveTop(layout.senderRect.top() + topBandHeight);
     }
     // Align top of avatar with top of sender rect
     const double senderRectY{layout.senderRect.y()};
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.