[network/ruqola] src/widgets/room/delegate: Don't assert on link-preview card geometry while painting

Laurent Montel <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit 3ffe51ca54eb41be495de0ef3a667654c952236a by Laurent Montel, on behalf of Till Adam.
Committed on 27/07/2026 at 05:23.
Pushed by mlaurent into branch 'master'.

Don't assert on link-preview card geometry while painting

draw() re-runs layoutPreview() with the rect width the delegate allocated from
sizeHint(), and asserted that the recomputed contentWidth equalled that width.
That round-trip goes through QTextDocument::idealWidth(), which is not perfectly
stable across text widths, so for some descriptions the recomputed width differs
by a pixel and the assert aborts the whole application while painting the
message list.

Drop the assert and draw the card background at the allocated rect rather than
the recomputed contentWidth, so a pixel of drift is harmless (the card stays
within its slot) instead of fatal. The internal content still uses the
recomputed, self-consistent layout.

M  +8    -9    src/widgets/room/delegate/messagedelegatehelperurlpreview.cpp
M  +2    -2    src/widgets/room/delegate/messagedelegatehelperurlpreview.h

https://invent.kde.org/network/ruqola/-/commit/3ffe51ca54eb41be495de0ef3a667654c952236a

diff --git a/src/widgets/room/delegate/messagedelegatehelperurlpreview.cpp b/src/widgets/room/delegate/messagedelegatehelperurlpreview.cpp
index 64590683f9..f57330df5c 100644
--- a/src/widgets/room/delegate/messagedelegatehelperurlpreview.cpp
+++ b/src/widgets/room/delegate/messagedelegatehelperurlpreview.cpp
@@ -54,22 +54,21 @@ void MessageDelegateHelperUrlPreview::draw(const MessageUrl &messageUrl,
                                            const QStyleOptionViewItem &option) const
 {
     const PreviewLayout layout = layoutPreview(messageUrl, option, previewRect.width(), previewRect.height());
-    // The card geometry must round-trip: re-entering layoutPreview() here with the
-    // rect width the delegate got from sizeHint() has to reproduce the same docWidth
-    // (see the contentWidth computation in layoutPreview()). If this fires, that
-    // invariant broke and the text/thumbnail/toggle will be misplaced.
-    Q_ASSERT(previewRect.width() == layout.contentWidth);
 
     // A subtle rounded background sets the preview apart as embedded, secondary
     // content (the job the old "Link Preview" label did, without the chrome).
     // Colours come from the palette so it themes itself for light and dark.
+    // The card fills the rect the delegate allocated from sizeHint(), not the freshly
+    // recomputed contentWidth: re-running layoutPreview() here can differ by a pixel
+    // (QTextDocument::idealWidth() is not perfectly stable across text widths), so using
+    // the allocated rect keeps the card within its slot instead of aborting on that drift.
     painter->save();
     painter->setRenderHint(QPainter::Antialiasing, true);
     QColor borderColor = option.palette.color(QPalette::WindowText);
     borderColor.setAlpha(30);
     painter->setPen(borderColor);
     painter->setBrush(option.palette.color(QPalette::AlternateBase));
-    const QRectF cardRect(previewRect.x() + 0.5, previewRect.y() + PreviewTopGap + 0.5, layout.contentWidth - 1, layout.contentHeight - PreviewTopGap - 1);
+    const QRectF cardRect(previewRect.x() + 0.5, previewRect.y() + PreviewTopGap + 0.5, previewRect.width() - 1, previewRect.height() - PreviewTopGap - 1);
     painter->drawRoundedRect(cardRect, PreviewCornerRadius, PreviewCornerRadius);
     painter->restore();
 
@@ -160,9 +159,9 @@ MessageDelegateHelperUrlPreview::PreviewLayout MessageDelegateHelperUrlPreview::
     layout.docWidth = qMax(0, urlsPreviewWidth - 2 * PreviewPadding - leftReserve - rightReserve);
     layout.descriptionSize = documentTypeForIndexSize(convertMessageUrlToDocumentDescriptionInfo(messageUrl, layout.docWidth));
 
-    // contentWidth adds the padding and reserves back onto docWidth, so it is the
-    // exact inverse of the docWidth computation above (see the round-trip assert in
-    // draw()).
+    // contentWidth adds the padding and reserves back onto docWidth, so it is the exact
+    // inverse of the docWidth computation above. sizeHint() reports it as the slot width;
+    // draw() then works from the slot rect it is handed rather than re-deriving it.
     const int innerWidth = leftReserve + layout.descriptionSize.width() + rightReserve;
     const int innerHeight = qMax(qMax(thumbLogical.height(), layout.descriptionSize.height()), iconSize);
     layout.contentWidth = innerWidth + 2 * PreviewPadding;
diff --git a/src/widgets/room/delegate/messagedelegatehelperurlpreview.h b/src/widgets/room/delegate/messagedelegatehelperurlpreview.h
index 5ffebb62b4..23c692cfcd 100644
--- a/src/widgets/room/delegate/messagedelegatehelperurlpreview.h
+++ b/src/widgets/room/delegate/messagedelegatehelperurlpreview.h
@@ -48,8 +48,8 @@ private:
         // Logical-pixel geometry of the compact card. textLeftOffset is where the
         // description document starts (to the right of the thumbnail); docWidth is
         // the text width it is laid out at; contentWidth/Height is the whole card.
-        // The layout round-trips between sizeHint() and draw() (see the assert in
-        // draw()).
+        // sizeHint() reports contentWidth/Height as the slot size; draw() re-derives the
+        // rest from the rect it is handed, which is that slot (see draw()).
         int textLeftOffset = 0;
         int docWidth = 0;
         int contentWidth = 0;
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.