From ebc1ff03428b0461645b4cf416bc1dc7da1b2791 Mon Sep 17 00:00:00 2001 From: Dexter Gaon-Shatford Date: Fri, 8 Apr 2022 14:08:15 -0400 Subject: [PATCH] FIX(client): resolve list tags, etc. polluting log As reported in #4491, #4986 and #5430, since the changes to the chat in the 1.4.x release, some tags would "pollute" the rest of the log, i.e. cause future log entries to be contained within them. The source of the issue seems to be that the `insertBlock` method of `QTextCursor` appears to correspond to the `

` HTML tag. The `

` tag may only contain inline elements, but `QTextEdit` will not fail outright when inserting block-level elements and will instead attempt to correct the invalid input which results in the behaviour reported in the above issues (as far as I can tell). My proposed solution is to use the `insertFrame` method for all messages. Fixes #4491 (cherry picked from commit ae097d6354d99325093dd5a12cb8632e2ba20edf) --- src/mumble/Log.cpp | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/mumble/Log.cpp b/src/mumble/Log.cpp index c653dc93f9d..fbcca30903b 100644 --- a/src/mumble/Log.cpp +++ b/src/mumble/Log.cpp @@ -616,9 +616,7 @@ QString Log::validHtml(const QString &html, QTextCursor *tc) { } if (tc) { - QTextCursor tcNew(&qtd); - tcNew.movePosition(QTextCursor::End, QTextCursor::KeepAnchor); - tc->insertFragment(tcNew.selection()); + tc->insertHtml(qtd.toHtml()); return QString(); } else { return qtd.toHtml(); @@ -649,11 +647,6 @@ void Log::log(MsgType mt, const QString &console, const QString &terse, bool own // the setting might change in that time). const int msgMargin = Global::get().s.iChatMessageMargins; - QTextBlockFormat format = tc.blockFormat(); - format.setTopMargin(msgMargin); - format.setBottomMargin(msgMargin); - tc.setBlockFormat(format); - LogTextBrowser *tlog = Global::get().mw->qteLog; const int oldscrollvalue = tlog->getLogScroll(); const bool scroll = (oldscrollvalue == tlog->getLogScrollMaximum()); @@ -672,24 +665,25 @@ void Log::log(MsgType mt, const QString &console, const QString &terse, bool own QString fixedNLPlain = plain.replace(QLatin1String("\r\n"), QLatin1String("\n")).replace(QLatin1String("\r"), QLatin1String("\n")); + QTextFrameFormat qttf; + // `insertFrame` causes a blank line to precede the inserted frame. + // This is remedied by setting a negative top margin of equal height. + static int lineSpacing = QFontMetrics(tc.currentFrame()->format().toCharFormat().font()).lineSpacing(); + qttf.setTopMargin(-lineSpacing); + qttf.setBottomMargin(msgMargin); + if (fixedNLPlain.contains(QRegExp(QLatin1String("\\n[ \\t]*$")))) { // If the message ends with one or more blank lines (or lines only containing whitespace) // paint a border around the message to make clear that it contains invisible parts. // The beginning of the message is clear anyway (the date and potentially the "To XY" part) // so we don't have to care about that. - QTextFrameFormat qttf; qttf.setBorder(1); qttf.setPadding(2); - qttf.setMargin(msgMargin); qttf.setBorderStyle(QTextFrameFormat::BorderStyle_Dashed); - tc.insertFrame(qttf); - } else if (!tc.block().text().isEmpty()) { - // Only insert a block if the current block is not empty. It may be empty because - // it is the default block of an empty document. Another cause might be that apparently - // a new empty block is automatically inserted after a frame. - tc.insertBlock(); } + tc.insertFrame(qttf); + const QString timeString = dt.time().toString(QLatin1String(Global::get().s.bLog24HourClock ? "HH:mm:ss" : "hh:mm:ss AP")); tc.insertHtml(Log::msgColor(QString::fromLatin1("[%1] ").arg(timeString.toHtmlEscaped()), Log::Time));