diff --git a/src/libcalamares/utils/String.cpp b/src/libcalamares/utils/String.cpp index 0c7bf8fb5..02b41f1c0 100644 --- a/src/libcalamares/utils/String.cpp +++ b/src/libcalamares/utils/String.cpp @@ -175,7 +175,36 @@ truncateMultiLine( const QString& string, CalamaresUtils::LinesStartEnd lines, C } } - return front + back; + if ( front.length() + back.length() <= chars.total ) + { + return front + back; + } + + // We need to cut off some bits, preserving whether there are + // newlines present at the end of the string. Go case-by-case: + if ( !front.isEmpty() && back.isEmpty() ) + { + // Truncate towards the front + bool needsNewline = front.endsWith( NEWLINE ); + front.truncate( chars.total ); + if ( !front.endsWith( NEWLINE ) && needsNewline ) + { + front.append( NEWLINE ); + } + return front; + } + if ( front.isEmpty() && !back.isEmpty() ) + { + // Truncate towards the tail + return back.right( chars.total ); + } + // Both are non-empty, so nibble away at both of them + front.truncate( chars.total / 2 ); + if ( !front.endsWith( NEWLINE ) ) + { + front.append( NEWLINE ); + } + return front + back.right( chars.total / 2 ); } diff --git a/src/libcalamares/utils/Tests.cpp b/src/libcalamares/utils/Tests.cpp index 3992fe78a..d8abd9c5f 100644 --- a/src/libcalamares/utils/Tests.cpp +++ b/src/libcalamares/utils/Tests.cpp @@ -597,6 +597,8 @@ and the translations updated.)" ); QVERIFY( !longString.endsWith( NEWLINE ) ); QCOMPARE( longString.count( NEWLINE ), 2 ); QVERIFY( longString.length() > insufficientLength ); + // Even the first line must be more than the insufficientLength + QVERIFY( longString.indexOf( NEWLINE ) > insufficientLength ); // Grab first line, untruncated { @@ -626,11 +628,51 @@ and the translations updated.)" ); QVERIFY( longString.endsWith( s ) ); QVERIFY( !s.endsWith( NEWLINE ) ); QVERIFY( s.endsWith( "updated." ) ); - cDebug() << "Result-line" << Logger::Quote << s; QCOMPARE( s.count( NEWLINE ), 1 ); // Because last line doesn't end with a newline QVERIFY( s.startsWith( "displayed in " ) ); } + // First line, truncated + { + auto s = truncateMultiLine( longString, LinesStartEnd { 1, 0 }, CharCount { insufficientLength } ); + cDebug() << "Result-line" << Logger::Quote << s; + QVERIFY( s.length() > 1 ); + QVERIFY( s.endsWith( NEWLINE ) ); + QVERIFY( s.startsWith( "Some " ) ); + // Because the first line has a newline, the truncated version does too, + // but that makes it one longer than requested. + QCOMPARE( s.length(), insufficientLength + 1 ); + QVERIFY( longString.startsWith( s.left( insufficientLength ) ) ); + } + + // Last line, truncated; this line is quite short + { + const int quiteShort = 8; + QVERIFY( longString.lastIndexOf( NEWLINE ) < longString.length() - quiteShort ); + + auto s = truncateMultiLine( longString, LinesStartEnd { 0, 1 }, CharCount { quiteShort } ); + cDebug() << "Result-line" << Logger::Quote << s; + QVERIFY( s.length() > 1 ); + QVERIFY( !s.endsWith( NEWLINE ) ); // Because the original doesn't either + QVERIFY( s.startsWith( "upda" ) ); + QCOMPARE( s.length(), quiteShort ); // No extra newlines + QVERIFY( longString.endsWith( s ) ); + } + + // First and last, but both truncated + { + const int quiteShort = 16; + QVERIFY( longString.indexOf( NEWLINE ) > quiteShort ); + QVERIFY( longString.lastIndexOf( NEWLINE ) < longString.length() - quiteShort ); + + auto s = truncateMultiLine( longString, LinesStartEnd { 1, 1 }, CharCount { quiteShort } ); + cDebug() << "Result-line" << Logger::Quote << s; + QVERIFY( s.length() > 1 ); + QVERIFY( !s.endsWith( NEWLINE ) ); // Because the original doesn't either + QVERIFY( s.startsWith( "Some " ) ); + QVERIFY( s.endsWith( "updated." ) ); + QCOMPARE( s.length(), quiteShort + 1 ); // Newline between front and back part + } }