mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-08 04:44:13 +02:00
Keep the DXF text lines of master for texts that do not wrap
layoutLines() trimmed the trailing spaces of every line and kept
non-breaking spaces, which the DXF export used to write as plain spaces
(toPlainText()). A DXF R10 file has no code page, so a reader assuming
Windows-1252 could show them as 'Â '. Now a paragraph that does not
wrap gives exactly its line of toPlainText().split('\n') again
(trailing spaces and tabs kept, non-breaking spaces as plain spaces,
<br> as a line break). In a paragraph that wraps, every line loses its
trailing spaces, so spaces that wrap to a line of their own give an
empty line: not written, but it keeps the spacing of the next lines.
Test: tst_textlines compares with toPlainText() for trailing spaces,
tabs, non-breaking spaces, <br> and paragraphs, and checks wrapped
lines (fails before).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+26
-7
@@ -29,6 +29,11 @@ namespace TextLines
|
||||
@return the lines of document as they are laid out: a paragraph
|
||||
wrapped to the width of the text gives several lines. For the
|
||||
exports that write a text line by line (DXF).
|
||||
A paragraph that is not wrapped gives exactly its line of
|
||||
toPlainText().split('\n'), as these exports wrote before: trailing
|
||||
spaces are kept, and non-breaking spaces become plain spaces. In a
|
||||
wrapped paragraph, the lines lose their trailing spaces (the one a
|
||||
line was broken at, and a line made only of spaces becomes empty).
|
||||
*/
|
||||
inline QStringList layoutLines(const QTextDocument *document)
|
||||
{
|
||||
@@ -39,18 +44,32 @@ namespace TextLines
|
||||
{
|
||||
const QString text = block.text();
|
||||
const QTextLayout *layout = block.layout();
|
||||
if (!layout || layout->lineCount() == 0) {
|
||||
lines << text;
|
||||
const int count = layout ? layout->lineCount() : 0;
|
||||
if (count == 0) {
|
||||
lines << QString(text).replace(QChar::Nbsp, QLatin1Char(' '));
|
||||
continue;
|
||||
}
|
||||
for (int i = 0 ; i < layout->lineCount() ; ++i)
|
||||
|
||||
//Wrapped: a line ends without a line break typed by the user
|
||||
bool wrapped = false;
|
||||
for (int i = 0 ; i < count - 1 ; ++i) {
|
||||
const QTextLine line = layout->lineAt(i);
|
||||
const int end = line.textStart() + line.textLength();
|
||||
if (end == 0 || text.at(end - 1) != QChar::LineSeparator)
|
||||
wrapped = true;
|
||||
}
|
||||
|
||||
for (int i = 0 ; i < count ; ++i)
|
||||
{
|
||||
const QTextLine line = layout->lineAt(i);
|
||||
QString part = text.mid(line.textStart(), line.textLength());
|
||||
//The space the line was broken at, or a line separator
|
||||
while (!part.isEmpty() && part.back().isSpace())
|
||||
part.chop(1);
|
||||
lines << part;
|
||||
if (part.endsWith(QChar::LineSeparator))
|
||||
part.chop(1); //A line break typed by the user (Shift+Enter)
|
||||
if (wrapped) {
|
||||
while (!part.isEmpty() && part.back().isSpace())
|
||||
part.chop(1);
|
||||
}
|
||||
lines << part.replace(QChar::Nbsp, QLatin1Char(' '));
|
||||
}
|
||||
}
|
||||
return lines;
|
||||
|
||||
@@ -34,6 +34,32 @@ private slots:
|
||||
QStringList({QStringLiteral("Motor protection"), QStringLiteral("switch Q12")}));
|
||||
}
|
||||
|
||||
// A text without a width gives exactly the lines the DXF export wrote
|
||||
// before, toPlainText().split('\n'): trailing spaces and tabs kept,
|
||||
// non-breaking spaces as plain spaces, <br> as a line break.
|
||||
void unwrappedTextIsUnchanged_data()
|
||||
{
|
||||
QTest::addColumn<QString>("html");
|
||||
QTest::newRow("trailing spaces") << QStringLiteral("K1 \nswitch\t");
|
||||
QTest::newRow("non-breaking spaces") << QStringLiteral("<p>K1 24V DC</p>");
|
||||
QTest::newRow("line break") << QStringLiteral("<p>Wiper to 6<br>contacts</p>");
|
||||
QTest::newRow("paragraphs") << QStringLiteral("<p>relais voyant </p><p> preventa</p>");
|
||||
QTest::newRow("empty") << QString();
|
||||
}
|
||||
|
||||
void unwrappedTextIsUnchanged()
|
||||
{
|
||||
QFETCH(QString, html);
|
||||
QTextDocument document;
|
||||
if (Qt::mightBeRichText(html))
|
||||
document.setHtml(html);
|
||||
else
|
||||
document.setPlainText(html);
|
||||
|
||||
QCOMPARE(TextLines::layoutLines(&document),
|
||||
document.toPlainText().split(QLatin1Char('\n')));
|
||||
}
|
||||
|
||||
// A text wrapped to its width gives one line per drawn line, without
|
||||
// the space the line was broken at.
|
||||
void wrappedTextGivesTheDrawnLines()
|
||||
@@ -48,6 +74,41 @@ private slots:
|
||||
QStringList({QStringLiteral("Motor"), QStringLiteral("protection"),
|
||||
QStringLiteral("switch"), QStringLiteral("Q12")}));
|
||||
}
|
||||
|
||||
// A wrapped paragraph has no trailing spaces left, even on its last
|
||||
// line: tabs and spaces that wrap to a line of their own (as in the
|
||||
// affuteuse_250h example) give an empty line, which is not written but
|
||||
// still keeps the line spacing.
|
||||
void wrappedTextHasNoTrailingSpaces()
|
||||
{
|
||||
QTextDocument document(QStringLiteral("\tMotor\t\t "));
|
||||
QTextOption option = document.defaultTextOption();
|
||||
option.setWrapMode(QTextOption::WordWrap);
|
||||
document.setDefaultTextOption(option);
|
||||
document.setTextWidth(80);
|
||||
|
||||
const QStringList lines = TextLines::layoutLines(&document);
|
||||
QVERIFY(lines.size() > 1);
|
||||
QVERIFY(lines.contains(QStringLiteral("Motor")));
|
||||
for (const QString &line : lines)
|
||||
QVERIFY2(line.isEmpty() || !line.back().isSpace(), qPrintable(line));
|
||||
}
|
||||
|
||||
// Non-breaking spaces also become plain spaces in a wrapped text.
|
||||
void wrappedTextHasPlainSpaces()
|
||||
{
|
||||
QTextDocument document;
|
||||
document.setHtml(QStringLiteral("<p>K1 24V and more words</p>"));
|
||||
QTextOption option = document.defaultTextOption();
|
||||
option.setWrapMode(QTextOption::WordWrap);
|
||||
document.setDefaultTextOption(option);
|
||||
document.setTextWidth(1);
|
||||
|
||||
const QStringList lines = TextLines::layoutLines(&document);
|
||||
QCOMPARE(lines.first(), QStringLiteral("K1 24V"));
|
||||
for (const QString &line : lines)
|
||||
QVERIFY(!line.contains(QChar::Nbsp));
|
||||
}
|
||||
};
|
||||
|
||||
QTEST_MAIN(tst_textlines)
|
||||
|
||||
Reference in New Issue
Block a user