From dbb9579566f3accd8aa5fe61db9692991117afd3 Mon Sep 17 00:00:00 2001
From: Shawn Rutledge blah blah
with another one (but
hopefully the application has an action to insert one manually)
- a heading is more likely to be followed by a paragraph, or perhaps
a smaller heading; another heading at the same level is unlikely.
We need to reset the char format, not only the block format, because
the large font and heavy font weight are stored there.
- when adding to a todo list, hitting enter at the end of the last task,
let's assume the next task is not yet done, so it will be unchecked
by default (else, why are you writing a todo list at all)
To achieve that, we need to customize the formats and call the
insertBlock() overload that takes them. The no-argument insertBlock()
will continue to preserve the formats, because it's an old API that is
used for much more than interactive editing.
Additionally, word processors tend to let you end a list (for example)
by hitting enter twice. In that case, you stay in the same paragraph
that you created the first time you hit enter, but now the formats are
reset to default, so that you can go on typing an ordinary paragraph,
rather than having to mouse up to the toolbar to select the paragraph
style in a combobox, or something like that. So we now do that: reset
both block and char formats after you hit enter on a blank line; but if
you then hit enter again, after the block format has been reset, then
you will get the actual blank line (empty block) inserted.
[ChangeLog][QtWidgets][QTextEdit] Hitting enter at the end of a line
with a special block format (horizontal rule, heading, checklist item)
now makes some "smart" adjustments to avoid retaining properties that
are unlikely to be continued on the next line. Hitting enter twice now
resets block and char formats to default.
Fixes: QTBUG-48815
Task-number: QTBUG-80473
Fixes: QTBUG-97459
Change-Id: I3dfdd5b4c0d9ffb4673acc861cb7b5c22291df25
Reviewed-by: Eskil Abrahamsen Blomfeldt
automatically
+ // - the next paragraph after a heading should be a normal paragraph
+ // - remove the bottom margin from the last list item before appending
+ // - the next checklist item after a checked item should be unchecked
+ auto blockFmt = cursor.blockFormat();
+ auto charFmt = cursor.charFormat();
+ blockFmt.clearProperty(QTextFormat::BlockTrailingHorizontalRulerWidth);
+ if (blockFmt.hasProperty(QTextFormat::HeadingLevel)) {
+ blockFmt.clearProperty(QTextFormat::HeadingLevel);
+ charFmt = QTextCharFormat();
+ }
+ if (cursor.currentList()) {
+ auto existingFmt = cursor.blockFormat();
+ existingFmt.clearProperty(QTextBlockFormat::BlockBottomMargin);
+ cursor.setBlockFormat(existingFmt);
+ if (blockFmt.marker() == QTextBlockFormat::MarkerType::Checked)
+ blockFmt.setMarker(QTextBlockFormat::MarkerType::Unchecked);
+ }
+
+ // After a blank line, reset block and char formats. I.e. you can end a list,
+ // block quote, etc. by hitting enter twice, and get back to normal paragraph style.
+ if (cursor.block().text().isEmpty() &&
+ !cursor.blockFormat().hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth) &&
+ !cursor.blockFormat().hasProperty(QTextFormat::BlockCodeLanguage)) {
+ blockFmt = QTextBlockFormat();
+ const bool blockFmtChanged = (cursor.blockFormat() != blockFmt);
+ charFmt = QTextCharFormat();
+ cursor.setBlockFormat(blockFmt);
+ cursor.setCharFormat(charFmt);
+ // If the user hit enter twice just to get back to default format,
+ // don't actually insert a new block. But if the user then hits enter
+ // yet again, the block format will not change, so we will insert a block.
+ // This is what many word processors do.
+ if (blockFmtChanged)
+ return;
+ }
+
+ cursor.insertBlock(blockFmt, charFmt);
+}
+
void QWidgetTextControlPrivate::append(const QString &text, Qt::TextFormat format)
{
QTextCursor tmp(doc);
diff --git a/src/widgets/widgets/qwidgettextcontrol_p_p.h b/src/widgets/widgets/qwidgettextcontrol_p_p.h
index a7a19e748d0..c94f859e6f6 100644
--- a/src/widgets/widgets/qwidgettextcontrol_p_p.h
+++ b/src/widgets/widgets/qwidgettextcontrol_p_p.h
@@ -179,6 +179,7 @@ public:
bool isPreediting() const;
void commitPreedit();
+ void insertParagraphSeparator();
void append(const QString &text, Qt::TextFormat format = Qt::AutoText);
QTextDocument *doc;
diff --git a/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp b/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp
index 8d5716c1292..9126b874724 100644
--- a/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp
+++ b/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp
@@ -58,6 +58,8 @@
#include "../../../shared/platforminputcontext.h"
#include
" << 1
+ << pmap{{QTextFormat::BlockBottomMargin, {}}} << pmap{}
+ << pmap{{QTextFormat::BlockBottomMargin, 12}} << pmap{};
+ QTest::newRow("double enter after list: default format") << "
" << 2
+ << pmap{{QTextFormat::BlockBottomMargin, {}}} << pmap{}
+ << pmap{} << pmap{};
+ QTest::newRow("continue block quote") << "I'll be back
" << 1
+ << pmap{{QTextFormat::BlockLeftMargin, 40}} << pmap{}
+ << pmap{{QTextFormat::BlockLeftMargin, 40}} << pmap{};
+ QTest::newRow("double enter after block quote") << "I'll be back
" << 2
+ << pmap{{QTextFormat::BlockLeftMargin, 40}} << pmap{}
+ << pmap{{QTextFormat::BlockLeftMargin, {}}} << pmap{};
+ QTest::newRow("bottom margin after bullet list") << "
" << 1
+ << pmap{{QTextFormat::BlockBottomMargin, {}}} << pmap{}
+ << pmap{{QTextFormat::BlockBottomMargin, 12}} << pmap{};
+ QTest::newRow("paragraph after heading") << "so big!
" << 1
+ << pmap{{QTextFormat::HeadingLevel, 1}} << pmap{}
+ << pmap{{QTextFormat::HeadingLevel, {}}} << pmap{};
+ QTest::newRow("paragraph after hrule") << "