mirror of
https://github.com/crystalidea/qt6windows7.git
synced 2025-07-04 16:25:27 +08:00
qt 6.5.1 original
This commit is contained in:
20
tests/auto/gui/text/qtextmarkdownwriter/CMakeLists.txt
Normal file
20
tests/auto/gui/text/qtextmarkdownwriter/CMakeLists.txt
Normal file
@ -0,0 +1,20 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## tst_qtextmarkdownwriter Test:
|
||||
#####################################################################
|
||||
|
||||
# Collect test data
|
||||
list(APPEND test_data "data/example.md")
|
||||
list(APPEND test_data "data/blockquotes.md")
|
||||
|
||||
qt_internal_add_test(tst_qtextmarkdownwriter
|
||||
SOURCES
|
||||
tst_qtextmarkdownwriter.cpp
|
||||
LIBRARIES
|
||||
Qt::CorePrivate
|
||||
Qt::Gui
|
||||
Qt::GuiPrivate
|
||||
TESTDATA ${test_data}
|
||||
)
|
62
tests/auto/gui/text/qtextmarkdownwriter/data/blockquotes.md
Normal file
62
tests/auto/gui/text/qtextmarkdownwriter/data/blockquotes.md
Normal file
@ -0,0 +1,62 @@
|
||||
In 1958, Mahatma Gandhi was quoted as follows:
|
||||
|
||||
> The Earth provides enough to satisfy every man's need but not for every man's
|
||||
> greed.
|
||||
|
||||
In [The CommonMark Specification](https://spec.commonmark.org/0.29/) John
|
||||
MacFarlane writes:
|
||||
|
||||
> What distinguishes Markdown from many other lightweight markup syntaxes,
|
||||
> which are often easier to write, is its readability. As Gruber writes:
|
||||
|
||||
> > The overriding design goal for Markdown's formatting syntax is to make it
|
||||
> > as readable as possible. The idea is that a Markdown-formatted document should
|
||||
> > be publishable as-is, as plain text, without looking like it's been marked up
|
||||
> > with tags or formatting instructions. (
|
||||
> > <http://daringfireball.net/projects/markdown/> )
|
||||
|
||||
> The point can be illustrated by comparing a sample of AsciiDoc with an
|
||||
> equivalent sample of Markdown. Here is a sample of AsciiDoc from the AsciiDoc
|
||||
> manual:
|
||||
|
||||
> ```AsciiDoc
|
||||
> 1. List item one.
|
||||
> +
|
||||
> List item one continued with a second paragraph followed by an
|
||||
> Indented block.
|
||||
> +
|
||||
> .................
|
||||
> $ ls *.sh
|
||||
> $ mv *.sh ~/tmp
|
||||
> .................
|
||||
> +
|
||||
> List item continued with a third paragraph.
|
||||
>
|
||||
> 2. List item two continued with an open block.
|
||||
> ...
|
||||
> ```
|
||||
The quotation includes an embedded quotation and a code quotation and ends with
|
||||
an ellipsis due to being incomplete.
|
||||
|
||||
Now let's have an indented code block:
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("# hello markdown\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
and end with a fenced code block:
|
||||
|
||||
~~~pseudocode
|
||||
#include <something.h>
|
||||
#include <else.h>
|
||||
|
||||
a block {
|
||||
a statement;
|
||||
another statement;
|
||||
}
|
||||
~~~
|
||||
|
96
tests/auto/gui/text/qtextmarkdownwriter/data/example.md
Normal file
96
tests/auto/gui/text/qtextmarkdownwriter/data/example.md
Normal file
@ -0,0 +1,96 @@
|
||||
# QTextEdit
|
||||
|
||||
The QTextEdit widget is an advanced editor that supports formatted rich text.
|
||||
It can be used to display HTML and other rich document formats. Internally,
|
||||
QTextEdit uses the QTextDocument class to describe both the high-level
|
||||
structure of each document and the low-level formatting of paragraphs.
|
||||
|
||||
If you are viewing this document in the textedit example, you can edit this
|
||||
document to explore Qt's rich text editing features. We have included some
|
||||
comments in each of the following sections to encourage you to experiment.
|
||||
|
||||
## Font and Paragraph Styles
|
||||
|
||||
QTextEdit supports **bold**, *italic*, _underline_ and ~~strikethrough~~ font
|
||||
styles, and can display multicolored text. Font families such as Times New
|
||||
Roman and `Courier` can also be used directly. *If you place the cursor in a
|
||||
region of styled text, the controls in the tool bars will change to reflect the
|
||||
current style.*
|
||||
|
||||
Paragraphs can be formatted so that the text is left-aligned, right-aligned,
|
||||
centered, or fully justified.
|
||||
|
||||
*Try changing the alignment of some text and resize the editor to see how the
|
||||
text layout changes.*
|
||||
|
||||
## Lists
|
||||
|
||||
Different kinds of lists can be included in rich text documents. Standard
|
||||
bullet lists can be nested, using different symbols for each level of the list:
|
||||
|
||||
- Disc symbols are typically used for top-level list items.
|
||||
* Circle symbols can be used to distinguish between items in lower-level
|
||||
lists.
|
||||
+ Square symbols provide a reasonable alternative to discs and circles.
|
||||
|
||||
Ordered lists can be created that can be used for tables of contents. Different
|
||||
characters can be used to enumerate items, and we can use both Roman and Arabic
|
||||
numerals in the same list structure:
|
||||
|
||||
1. Introduction
|
||||
2. Qt Tools
|
||||
1) Qt Assistant
|
||||
2) Qt Designer
|
||||
1. Form Editor
|
||||
2. Component Architecture
|
||||
3) Qt Linguist
|
||||
|
||||
The list will automatically be renumbered if you add or remove items. *Try
|
||||
adding new sections to the above list or removing existing item to see the
|
||||
numbers change.*
|
||||
|
||||
## Images
|
||||
|
||||
Inline images are treated like ordinary ranges of characters in the text
|
||||
editor, so they flow with the surrounding text. Images can also be selected in
|
||||
the same way as text, making it easy to cut, copy, and paste them.
|
||||
|
||||
 *Try to select this image by clicking and dragging
|
||||
over it with the mouse, or use the text cursor to select it by holding down
|
||||
Shift and using the arrow keys. You can then cut or copy it, and paste it into
|
||||
different parts of this document.*
|
||||
|
||||
## Tables
|
||||
|
||||
QTextEdit can arrange and format tables, supporting features such as row and
|
||||
column spans, text formatting within cells, and size constraints for columns.
|
||||
|
||||
|
||||
| |Development Tools |Programming Techniques |Graphical User Interfaces|
|
||||
|-------------|------------------------------------|---------------------------|-------------------------|
|
||||
|9:00 - 11:00 |Introduction to Qt |||
|
||||
|11:00 - 13:00|Using qmake |Object-oriented Programming|Layouts in Qt |
|
||||
|13:00 - 15:00|Qt Designer Tutorial |Extreme Programming |Writing Custom Styles |
|
||||
|15:00 - 17:00|Qt Linguist and Internationalization|Test-Driven Development | |
|
||||
|
||||
*Try adding text to the cells in the table and experiment with the alignment of
|
||||
the paragraphs.*
|
||||
|
||||
## Hyperlinks
|
||||
|
||||
QTextEdit is designed to support hyperlinks between documents, and this feature
|
||||
is used extensively in
|
||||
[Qt Assistant](http://doc.qt.io/qt-5/qtassistant-index.html). Hyperlinks are
|
||||
automatically created when an HTML file is imported into an editor. Since the
|
||||
rich text framework supports hyperlinks natively, they can also be created
|
||||
programmatically.
|
||||
|
||||
## Undo and Redo
|
||||
|
||||
Full support for undo and redo operations is built into QTextEdit and the
|
||||
underlying rich text framework. Operations on a document can be packaged
|
||||
together to make editing a more comfortable experience for the user.
|
||||
|
||||
*Try making changes to this document and press `Ctrl+Z` to undo them. You can
|
||||
always recover the original contents of the document.*
|
||||
|
@ -0,0 +1,12 @@
|
||||
# heading 1
|
||||
|
||||
- list item 1
|
||||
- list item 2
|
||||
|
||||
## heading 2
|
||||
|
||||
1) list item 1
|
||||
2) list item 2
|
||||
|
||||
the end paragraph
|
||||
|
28
tests/auto/gui/text/qtextmarkdownwriter/data/links.md
Normal file
28
tests/auto/gui/text/qtextmarkdownwriter/data/links.md
Normal file
@ -0,0 +1,28 @@
|
||||
A series of links.
|
||||
|
||||
[link](/uri)
|
||||
|
||||
[link]()
|
||||
|
||||
[link](/uri "title")
|
||||
|
||||
[link](/uri "àbcdè")
|
||||
|
||||
[link](/uri "title title \" title title")
|
||||
|
||||
[link](/url "title \""")
|
||||
|
||||
[link](/url "title
|
||||
title
|
||||
title title
|
||||
\"title\" title \"
|
||||
title")
|
||||
|
||||
* [link](/url "title")
|
||||
* [link](/url)
|
||||
* [link](/url "title
|
||||
title title")
|
||||
* nonlink
|
||||
|
||||
Qt has the <https://qt.io> site
|
||||
|
@ -0,0 +1,31 @@
|
||||
- something happens in the debugger like this:
|
||||
|
||||
```
|
||||
1 QQuickEventPoint::setGrabberItem qquickevents.cpp 869 0x7ffff7a963f2
|
||||
2 QQuickItem::grabMouse qquickitem.cpp 7599 0x7ffff7abea29
|
||||
3 QQuickWindowPrivate::deliverMatchingPointsToItem qquickwindow.cpp 2738 0x7ffff7aea34c
|
||||
4 QQuickWindowPrivate::deliverPressOrReleaseEvent qquickwindow.cpp 2692 0x7ffff7ae9e57
|
||||
5 QQuickWindowPrivate::deliverMouseEvent qquickwindow.cpp 1911 0x7ffff7ae561b
|
||||
6 QQuickWindowPrivate::deliverPointerEvent qquickwindow.cpp 2454 0x7ffff7ae888c
|
||||
7 QQuickWindowPrivate::handleMouseEvent qquickwindow.cpp 2282 0x7ffff7ae7f1a
|
||||
8 QQuickWindow::mousePressEvent qquickwindow.cpp 2249 0x7ffff7ae7bf5
|
||||
9 QQuickView::mousePressEvent qquickview.cpp 626 0x7ffff7bd6bad
|
||||
10 QWindow::event qwindow.cpp 2258 0x7ffff70b2c54
|
||||
```
|
||||
and then I want to explain something about it.
|
||||
|
||||
- something I tried to fix it:
|
||||
|
||||
```c++
|
||||
item->ungrab();
|
||||
```
|
||||
- still didn't fix it, expecting a breakthrough any day now
|
||||
- some sort of miracle
|
||||
- profit!
|
||||
- Alternatively we can have a non-indented fenced code block under a list item:
|
||||
|
||||
```qml
|
||||
import QtQuick
|
||||
Text { text: "hello world" }
|
||||
```
|
||||
- but that means the code block is not part of the list item.
|
13
tests/auto/gui/text/qtextmarkdownwriter/data/wordWrap.md
Normal file
13
tests/auto/gui/text/qtextmarkdownwriter/data/wordWrap.md
Normal file
@ -0,0 +1,13 @@
|
||||
[The CommonMark Specification](https://spec.commonmark.org/0.29/) is the
|
||||
conservative formal specification of the Markdown format, while
|
||||
[GitHub Flavored Markdown](https://guides.github.com/features/mastering-markdown/#GitHub-flavored-markdown)
|
||||
adds extra features such as task lists and tables.
|
||||
|
||||
Qt owes thanks to the authors of the [MD4C parser](https://github.com/mity/md4c)
|
||||
for making markdown import possible. The QTextMarkdownWriter class does not
|
||||
have such dependencies, and also has not yet been tested as extensively, so we
|
||||
do not yet guarantee that we are able to rewrite every Markdown document that
|
||||
you are able to read and display with Text or QTextEdit. But you are free to
|
||||
write [bugs](https://bugreports.qt.io) about any troublesome cases that you
|
||||
encounter.
|
||||
|
@ -0,0 +1,533 @@
|
||||
// Copyright (C) 2019 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include <QTest>
|
||||
#include <QTextDocument>
|
||||
#include <QTextCursor>
|
||||
#include <QTextBlock>
|
||||
#include <QTextList>
|
||||
#include <QTextTable>
|
||||
#include <QBuffer>
|
||||
#include <QDebug>
|
||||
#include <QFontInfo>
|
||||
#include <QLoggingCategory>
|
||||
|
||||
#include <private/qtextmarkdownwriter_p.h>
|
||||
|
||||
Q_LOGGING_CATEGORY(lcTests, "qt.text.tests")
|
||||
|
||||
// #define DEBUG_WRITE_OUTPUT
|
||||
|
||||
class tst_QTextMarkdownWriter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public slots:
|
||||
void init();
|
||||
void cleanup();
|
||||
|
||||
private slots:
|
||||
void testWriteParagraph_data();
|
||||
void testWriteParagraph();
|
||||
void testWriteList();
|
||||
void testWriteEmptyList();
|
||||
void testWriteCheckboxListItemEndingWithCode();
|
||||
void testWriteNestedBulletLists_data();
|
||||
void testWriteNestedBulletLists();
|
||||
void testWriteNestedNumericLists();
|
||||
void testWriteTable();
|
||||
void rewriteDocument_data();
|
||||
void rewriteDocument();
|
||||
void fromHtml_data();
|
||||
void fromHtml();
|
||||
|
||||
private:
|
||||
bool isMainFontFixed();
|
||||
bool isFixedFontProportional();
|
||||
QString documentToUnixMarkdown();
|
||||
|
||||
private:
|
||||
QTextDocument *document;
|
||||
};
|
||||
|
||||
void tst_QTextMarkdownWriter::init()
|
||||
{
|
||||
document = new QTextDocument();
|
||||
}
|
||||
|
||||
void tst_QTextMarkdownWriter::cleanup()
|
||||
{
|
||||
delete document;
|
||||
}
|
||||
|
||||
bool tst_QTextMarkdownWriter::isMainFontFixed()
|
||||
{
|
||||
bool ret = QFontInfo(QGuiApplication::font()).fixedPitch();
|
||||
if (ret) {
|
||||
qCWarning(lcTests) << "QFontDatabase::GeneralFont is monospaced: markdown writing is likely to use too many backticks"
|
||||
<< QFontDatabase::systemFont(QFontDatabase::GeneralFont);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool tst_QTextMarkdownWriter::isFixedFontProportional()
|
||||
{
|
||||
bool ret = !QFontInfo(QFontDatabase::systemFont(QFontDatabase::FixedFont)).fixedPitch();
|
||||
if (ret) {
|
||||
qCWarning(lcTests) << "QFontDatabase::FixedFont is NOT monospaced: markdown writing is likely to use too few backticks"
|
||||
<< QFontDatabase::systemFont(QFontDatabase::FixedFont);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString tst_QTextMarkdownWriter::documentToUnixMarkdown()
|
||||
{
|
||||
QString ret;
|
||||
QTextStream ts(&ret, QIODevice::WriteOnly);
|
||||
QTextMarkdownWriter writer(ts, QTextDocument::MarkdownDialectGitHub);
|
||||
writer.writeAll(document);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void tst_QTextMarkdownWriter::testWriteParagraph_data()
|
||||
{
|
||||
QTest::addColumn<QString>("input");
|
||||
QTest::addColumn<QString>("expectedOutput");
|
||||
|
||||
QTest::newRow("empty") << "" <<
|
||||
"";
|
||||
QTest::newRow("spaces") << "foobar word" <<
|
||||
"foobar word\n\n";
|
||||
QTest::newRow("starting spaces") << " starting spaces" <<
|
||||
" starting spaces\n\n";
|
||||
QTest::newRow("trailing spaces") << "trailing spaces " <<
|
||||
"trailing spaces \n\n";
|
||||
QTest::newRow("tab") << "word\ttab x" <<
|
||||
"word\ttab x\n\n";
|
||||
QTest::newRow("tab2") << "word\t\ttab\tx" <<
|
||||
"word\t\ttab\tx\n\n";
|
||||
QTest::newRow("misc") << "foobar word\ttab x" <<
|
||||
"foobar word\ttab x\n\n";
|
||||
QTest::newRow("misc2") << "\t \tFoo" <<
|
||||
"\t \tFoo\n\n";
|
||||
}
|
||||
|
||||
void tst_QTextMarkdownWriter::testWriteParagraph()
|
||||
{
|
||||
QFETCH(QString, input);
|
||||
QFETCH(QString, expectedOutput);
|
||||
|
||||
QTextCursor cursor(document);
|
||||
cursor.insertText(input);
|
||||
|
||||
const QString output = documentToUnixMarkdown();
|
||||
if (output != expectedOutput && isMainFontFixed())
|
||||
QEXPECT_FAIL("", "fixed-pitch main font (QTBUG-103484)", Continue);
|
||||
QCOMPARE(output, expectedOutput);
|
||||
}
|
||||
|
||||
void tst_QTextMarkdownWriter::testWriteList()
|
||||
{
|
||||
QTextCursor cursor(document);
|
||||
QTextList *list = cursor.createList(QTextListFormat::ListDisc);
|
||||
cursor.insertText("ListItem 1");
|
||||
list->add(cursor.block());
|
||||
cursor.insertBlock();
|
||||
cursor.insertText("ListItem 2");
|
||||
list->add(cursor.block());
|
||||
|
||||
const QString output = documentToUnixMarkdown();
|
||||
const QString expected = QString::fromLatin1("- ListItem 1\n- ListItem 2\n");
|
||||
if (output != expected && isMainFontFixed())
|
||||
QEXPECT_FAIL("", "fixed-pitch main font (QTBUG-103484)", Continue);
|
||||
QCOMPARE(output, expected);
|
||||
}
|
||||
|
||||
void tst_QTextMarkdownWriter::testWriteEmptyList()
|
||||
{
|
||||
QTextCursor cursor(document);
|
||||
cursor.createList(QTextListFormat::ListDisc);
|
||||
|
||||
QCOMPARE(documentToUnixMarkdown(), QString::fromLatin1("- \n"));
|
||||
}
|
||||
|
||||
void tst_QTextMarkdownWriter::testWriteCheckboxListItemEndingWithCode()
|
||||
{
|
||||
QTextCursor cursor(document);
|
||||
QTextList *list = cursor.createList(QTextListFormat::ListDisc);
|
||||
cursor.insertText("Image.originalSize property (not necessary; PdfDocument.pagePointSize() substitutes)");
|
||||
list->add(cursor.block());
|
||||
{
|
||||
auto fmt = cursor.block().blockFormat();
|
||||
fmt.setMarker(QTextBlockFormat::MarkerType::Unchecked);
|
||||
cursor.setBlockFormat(fmt);
|
||||
}
|
||||
cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::MoveAnchor, 2);
|
||||
cursor.movePosition(QTextCursor::Left, QTextCursor::MoveAnchor);
|
||||
cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor, 4);
|
||||
QCOMPARE(cursor.selectedText(), QString::fromLatin1("PdfDocument.pagePointSize()"));
|
||||
auto fmt = cursor.charFormat();
|
||||
fmt.setFontFixedPitch(true);
|
||||
cursor.setCharFormat(fmt);
|
||||
cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::MoveAnchor, 5);
|
||||
cursor.movePosition(QTextCursor::Left, QTextCursor::MoveAnchor);
|
||||
cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor, 4);
|
||||
QCOMPARE(cursor.selectedText(), QString::fromLatin1("Image.originalSize"));
|
||||
cursor.setCharFormat(fmt);
|
||||
|
||||
const QString output = documentToUnixMarkdown();
|
||||
const QString expected = QString::fromLatin1(
|
||||
"- [ ] `Image.originalSize` property (not necessary; `PdfDocument.pagePointSize()`\n substitutes)\n");
|
||||
if (output != expected && isMainFontFixed())
|
||||
QEXPECT_FAIL("", "fixed-pitch main font (QTBUG-103484)", Continue);
|
||||
QCOMPARE(output, expected);
|
||||
}
|
||||
|
||||
void tst_QTextMarkdownWriter::testWriteNestedBulletLists_data()
|
||||
{
|
||||
QTest::addColumn<bool>("checkbox");
|
||||
QTest::addColumn<bool>("checked");
|
||||
QTest::addColumn<bool>("continuationLine");
|
||||
QTest::addColumn<bool>("continuationParagraph");
|
||||
QTest::addColumn<QString>("expectedOutput");
|
||||
|
||||
QTest::newRow("plain bullets") << false << false << false << false <<
|
||||
"- ListItem 1\n * ListItem 2\n + ListItem 3\n- ListItem 4\n * ListItem 5\n";
|
||||
QTest::newRow("bullets with continuation lines") << false << false << true << false <<
|
||||
"- ListItem 1\n * ListItem 2\n + ListItem 3 with text that won't fit on one line and thus needs a\n continuation\n- ListItem 4\n * ListItem 5 with text that won't fit on one line and thus needs a\n continuation\n";
|
||||
QTest::newRow("bullets with continuation paragraphs") << false << false << false << true <<
|
||||
"- ListItem 1\n\n * ListItem 2\n + ListItem 3\n\n continuation\n\n- ListItem 4\n\n * ListItem 5\n\n continuation\n\n";
|
||||
QTest::newRow("unchecked") << true << false << false << false <<
|
||||
"- [ ] ListItem 1\n * [ ] ListItem 2\n + [ ] ListItem 3\n- [ ] ListItem 4\n * [ ] ListItem 5\n";
|
||||
QTest::newRow("checked") << true << true << false << false <<
|
||||
"- [x] ListItem 1\n * [x] ListItem 2\n + [x] ListItem 3\n- [x] ListItem 4\n * [x] ListItem 5\n";
|
||||
QTest::newRow("checked with continuation lines") << true << true << true << false <<
|
||||
"- [x] ListItem 1\n * [x] ListItem 2\n + [x] ListItem 3 with text that won't fit on one line and thus needs a\n continuation\n- [x] ListItem 4\n * [x] ListItem 5 with text that won't fit on one line and thus needs a\n continuation\n";
|
||||
QTest::newRow("checked with continuation paragraphs") << true << true << false << true <<
|
||||
"- [x] ListItem 1\n\n * [x] ListItem 2\n + [x] ListItem 3\n\n continuation\n\n- [x] ListItem 4\n\n * [x] ListItem 5\n\n continuation\n\n";
|
||||
}
|
||||
|
||||
void tst_QTextMarkdownWriter::testWriteNestedBulletLists()
|
||||
{
|
||||
QFETCH(bool, checkbox);
|
||||
QFETCH(bool, checked);
|
||||
QFETCH(bool, continuationParagraph);
|
||||
QFETCH(bool, continuationLine);
|
||||
QFETCH(QString, expectedOutput);
|
||||
|
||||
QTextCursor cursor(document);
|
||||
QTextBlockFormat blockFmt = cursor.blockFormat();
|
||||
if (checkbox) {
|
||||
blockFmt.setMarker(checked ? QTextBlockFormat::MarkerType::Checked : QTextBlockFormat::MarkerType::Unchecked);
|
||||
cursor.setBlockFormat(blockFmt);
|
||||
}
|
||||
|
||||
QTextList *list1 = cursor.createList(QTextListFormat::ListDisc);
|
||||
cursor.insertText("ListItem 1");
|
||||
list1->add(cursor.block());
|
||||
|
||||
QTextListFormat fmt2;
|
||||
fmt2.setStyle(QTextListFormat::ListCircle);
|
||||
fmt2.setIndent(2);
|
||||
QTextList *list2 = cursor.insertList(fmt2);
|
||||
cursor.insertText("ListItem 2");
|
||||
|
||||
QTextListFormat fmt3;
|
||||
fmt3.setStyle(QTextListFormat::ListSquare);
|
||||
fmt3.setIndent(3);
|
||||
cursor.insertList(fmt3);
|
||||
cursor.insertText(continuationLine ?
|
||||
"ListItem 3 with text that won't fit on one line and thus needs a continuation" :
|
||||
"ListItem 3");
|
||||
if (continuationParagraph) {
|
||||
QTextBlockFormat blockFmt;
|
||||
blockFmt.setIndent(2);
|
||||
cursor.insertBlock(blockFmt);
|
||||
cursor.insertText("continuation");
|
||||
}
|
||||
|
||||
cursor.insertBlock(blockFmt);
|
||||
cursor.insertText("ListItem 4");
|
||||
list1->add(cursor.block());
|
||||
|
||||
cursor.insertBlock();
|
||||
cursor.insertText(continuationLine ?
|
||||
"ListItem 5 with text that won't fit on one line and thus needs a continuation" :
|
||||
"ListItem 5");
|
||||
list2->add(cursor.block());
|
||||
if (continuationParagraph) {
|
||||
QTextBlockFormat blockFmt;
|
||||
blockFmt.setIndent(2);
|
||||
cursor.insertBlock(blockFmt);
|
||||
cursor.insertText("continuation");
|
||||
}
|
||||
|
||||
const QString output = documentToUnixMarkdown();
|
||||
#ifdef DEBUG_WRITE_OUTPUT
|
||||
{
|
||||
QFile out("/tmp/" + QLatin1String(QTest::currentDataTag()) + ".md");
|
||||
out.open(QFile::WriteOnly);
|
||||
out.write(output.toUtf8());
|
||||
out.close();
|
||||
}
|
||||
#endif
|
||||
if (output != expectedOutput && isMainFontFixed())
|
||||
QEXPECT_FAIL("", "fixed-pitch main font (QTBUG-103484)", Continue);
|
||||
QCOMPARE(output, expectedOutput);
|
||||
}
|
||||
|
||||
void tst_QTextMarkdownWriter::testWriteNestedNumericLists()
|
||||
{
|
||||
QTextCursor cursor(document);
|
||||
|
||||
QTextList *list1 = cursor.createList(QTextListFormat::ListDecimal);
|
||||
cursor.insertText("ListItem 1");
|
||||
list1->add(cursor.block());
|
||||
|
||||
QTextListFormat fmt2;
|
||||
fmt2.setStyle(QTextListFormat::ListLowerAlpha);
|
||||
fmt2.setNumberSuffix(QLatin1String(")"));
|
||||
fmt2.setIndent(2);
|
||||
QTextList *list2 = cursor.insertList(fmt2);
|
||||
cursor.insertText("ListItem 2");
|
||||
|
||||
QTextListFormat fmt3;
|
||||
fmt3.setStyle(QTextListFormat::ListDecimal);
|
||||
fmt3.setIndent(3);
|
||||
cursor.insertList(fmt3);
|
||||
cursor.insertText("ListItem 3");
|
||||
|
||||
cursor.insertBlock();
|
||||
cursor.insertText("ListItem 4");
|
||||
list1->add(cursor.block());
|
||||
|
||||
cursor.insertBlock();
|
||||
cursor.insertText("ListItem 5");
|
||||
list2->add(cursor.block());
|
||||
|
||||
const QString output = documentToUnixMarkdown();
|
||||
// There's no QTextList API to set the starting number so we hard-coded all lists to start at 1 (QTBUG-65384)
|
||||
const QString expected = QString::fromLatin1(
|
||||
"1. ListItem 1\n 1) ListItem 2\n 1. ListItem 3\n2. ListItem 4\n 2) ListItem 5\n");
|
||||
if (output != expected && isMainFontFixed())
|
||||
QEXPECT_FAIL("", "fixed-pitch main font (QTBUG-103484)", Continue);
|
||||
QCOMPARE(output, expected);
|
||||
}
|
||||
|
||||
void tst_QTextMarkdownWriter::testWriteTable()
|
||||
{
|
||||
QTextCursor cursor(document);
|
||||
QTextTable * table = cursor.insertTable(4, 3);
|
||||
cursor = table->cellAt(0, 0).firstCursorPosition();
|
||||
// valid Markdown tables need headers, but QTextTable doesn't make that distinction
|
||||
// so QTextMarkdownWriter assumes the first row of any table is a header
|
||||
cursor.insertText("one");
|
||||
cursor.movePosition(QTextCursor::NextCell);
|
||||
cursor.insertText("two");
|
||||
cursor.movePosition(QTextCursor::NextCell);
|
||||
cursor.insertText("three");
|
||||
cursor.movePosition(QTextCursor::NextCell);
|
||||
|
||||
cursor.insertText("alice");
|
||||
cursor.movePosition(QTextCursor::NextCell);
|
||||
cursor.insertText("bob");
|
||||
cursor.movePosition(QTextCursor::NextCell);
|
||||
cursor.insertText("carl");
|
||||
cursor.movePosition(QTextCursor::NextCell);
|
||||
|
||||
cursor.insertText("dennis");
|
||||
cursor.movePosition(QTextCursor::NextCell);
|
||||
cursor.insertText("eric");
|
||||
cursor.movePosition(QTextCursor::NextCell);
|
||||
cursor.insertText("fiona");
|
||||
cursor.movePosition(QTextCursor::NextCell);
|
||||
|
||||
cursor.insertText("gina");
|
||||
/*
|
||||
|one |two |three|
|
||||
|------|----|-----|
|
||||
|alice |bob |carl |
|
||||
|dennis|eric|fiona|
|
||||
|gina | | |
|
||||
*/
|
||||
|
||||
QString md = documentToUnixMarkdown();
|
||||
|
||||
#ifdef DEBUG_WRITE_OUTPUT
|
||||
{
|
||||
QFile out("/tmp/table.md");
|
||||
out.open(QFile::WriteOnly);
|
||||
out.write(md.toUtf8());
|
||||
out.close();
|
||||
}
|
||||
#endif
|
||||
|
||||
QString expected = QString::fromLatin1(
|
||||
"\n|one |two |three|\n|------|----|-----|\n|alice |bob |carl |\n|dennis|eric|fiona|\n|gina | | |\n\n");
|
||||
if (md != expected && isMainFontFixed())
|
||||
QEXPECT_FAIL("", "fixed-pitch main font (QTBUG-103484)", Continue);
|
||||
QCOMPARE(md, expected);
|
||||
|
||||
// create table with merged cells
|
||||
document->clear();
|
||||
cursor = QTextCursor(document);
|
||||
table = cursor.insertTable(3, 3);
|
||||
table->mergeCells(0, 0, 1, 2);
|
||||
table->mergeCells(1, 1, 1, 2);
|
||||
cursor = table->cellAt(0, 0).firstCursorPosition();
|
||||
cursor.insertText("a");
|
||||
cursor.movePosition(QTextCursor::NextCell);
|
||||
cursor.insertText("b");
|
||||
cursor.movePosition(QTextCursor::NextCell);
|
||||
cursor.insertText("c");
|
||||
cursor.movePosition(QTextCursor::NextCell);
|
||||
cursor.insertText("d");
|
||||
cursor.movePosition(QTextCursor::NextCell);
|
||||
cursor.insertText("e");
|
||||
cursor.movePosition(QTextCursor::NextCell);
|
||||
cursor.insertText("f");
|
||||
/*
|
||||
+---+-+
|
||||
|a |b|
|
||||
+---+-+
|
||||
|c| d|
|
||||
+-+-+-+
|
||||
|e|f| |
|
||||
+-+-+-+
|
||||
|
||||
generates
|
||||
|
||||
|a ||b|
|
||||
|-|-|-|
|
||||
|c|d ||
|
||||
|e|f| |
|
||||
|
||||
*/
|
||||
|
||||
md = documentToUnixMarkdown();
|
||||
|
||||
#ifdef DEBUG_WRITE_OUTPUT
|
||||
{
|
||||
QFile out("/tmp/table-merged-cells.md");
|
||||
out.open(QFile::WriteOnly);
|
||||
out.write(md.toUtf8());
|
||||
out.close();
|
||||
}
|
||||
#endif
|
||||
|
||||
expected = QString::fromLatin1("\n|a ||b|\n|-|-|-|\n|c|d ||\n|e|f| |\n\n");
|
||||
if (md != expected && isMainFontFixed())
|
||||
QEXPECT_FAIL("", "fixed-pitch main font (QTBUG-103484)", Continue);
|
||||
QCOMPARE(md, expected);
|
||||
}
|
||||
|
||||
void tst_QTextMarkdownWriter::rewriteDocument_data()
|
||||
{
|
||||
QTest::addColumn<QString>("inputFile");
|
||||
|
||||
QTest::newRow("block quotes") << "blockquotes.md";
|
||||
QTest::newRow("example") << "example.md";
|
||||
QTest::newRow("list items after headings") << "headingsAndLists.md";
|
||||
QTest::newRow("word wrap") << "wordWrap.md";
|
||||
QTest::newRow("links") << "links.md";
|
||||
QTest::newRow("lists and code blocks") << "listsAndCodeBlocks.md";
|
||||
}
|
||||
|
||||
void tst_QTextMarkdownWriter::rewriteDocument()
|
||||
{
|
||||
QFETCH(QString, inputFile);
|
||||
QTextDocument doc;
|
||||
QFile f(QFINDTESTDATA("data/" + inputFile));
|
||||
QVERIFY(f.open(QFile::ReadOnly | QIODevice::Text));
|
||||
QString orig = QString::fromUtf8(f.readAll());
|
||||
f.close();
|
||||
doc.setMarkdown(orig);
|
||||
QString md = doc.toMarkdown();
|
||||
|
||||
#ifdef DEBUG_WRITE_OUTPUT
|
||||
QFile out("/tmp/rewrite-" + inputFile);
|
||||
out.open(QFile::WriteOnly);
|
||||
out.write(md.toUtf8());
|
||||
out.close();
|
||||
#endif
|
||||
|
||||
if (md != orig && isMainFontFixed())
|
||||
QEXPECT_FAIL("", "fixed-pitch main font (QTBUG-103484)", Continue);
|
||||
QCOMPARE(md, orig);
|
||||
}
|
||||
|
||||
void tst_QTextMarkdownWriter::fromHtml_data()
|
||||
{
|
||||
QTest::addColumn<QString>("input");
|
||||
QTest::addColumn<QString>("expectedOutput");
|
||||
|
||||
QTest::newRow("long URL") <<
|
||||
"<span style=\"font-style:italic;\">https://www.example.com/dir/subdir/subsubdir/subsubsubdir/subsubsubsubdir/subsubsubsubsubdir/</span>" <<
|
||||
"*https://www.example.com/dir/subdir/subsubdir/subsubsubdir/subsubsubsubdir/subsubsubsubsubdir/*\n\n";
|
||||
QTest::newRow("non-emphasis inline asterisk") << "3 * 4" << "3 * 4\n\n";
|
||||
QTest::newRow("arithmetic") << "(2 * a * x + b)^2 = b^2 - 4 * a * c" << "(2 * a * x + b)^2 = b^2 - 4 * a * c\n\n";
|
||||
QTest::newRow("escaped asterisk after newline") <<
|
||||
"The first sentence of this paragraph holds 80 characters, then there's a star. * This is wrapped, but is <em>not</em> a bullet point." <<
|
||||
"The first sentence of this paragraph holds 80 characters, then there's a star.\n\\* This is wrapped, but is *not* a bullet point.\n\n";
|
||||
QTest::newRow("escaped plus after newline") <<
|
||||
"The first sentence of this paragraph holds 80 characters, then there's a plus. + This is wrapped, but is <em>not</em> a bullet point." <<
|
||||
"The first sentence of this paragraph holds 80 characters, then there's a plus.\n\\+ This is wrapped, but is *not* a bullet point.\n\n";
|
||||
QTest::newRow("escaped hyphen after newline") <<
|
||||
"The first sentence of this paragraph holds 80 characters, then there's a minus. - This is wrapped, but is <em>not</em> a bullet point." <<
|
||||
"The first sentence of this paragraph holds 80 characters, then there's a minus.\n\\- This is wrapped, but is *not* a bullet point.\n\n";
|
||||
QTest::newRow("list items with indented continuations") <<
|
||||
"<ul><li>bullet<p>continuation paragraph</p></li><li>another bullet<br/>continuation line</li></ul>" <<
|
||||
"- bullet\n\n continuation paragraph\n\n- another bullet\n continuation line\n";
|
||||
QTest::newRow("nested list items with continuations") <<
|
||||
"<ul><li>bullet<p>continuation paragraph</p></li><li>another bullet<br/>continuation line</li><ul><li>bullet<p>continuation paragraph</p></li><li>another bullet<br/>continuation line</li></ul></ul>" <<
|
||||
"- bullet\n\n continuation paragraph\n\n- another bullet\n continuation line\n\n - bullet\n\n continuation paragraph\n\n - another bullet\n continuation line\n";
|
||||
QTest::newRow("nested ordered list items with continuations") <<
|
||||
"<ol><li>item<p>continuation paragraph</p></li><li>another item<br/>continuation line</li><ol><li>item<p>continuation paragraph</p></li><li>another item<br/>continuation line</li></ol><li>another</li><li>another</li></ol>" <<
|
||||
"1. item\n\n continuation paragraph\n\n2. another item\n continuation line\n\n 1. item\n\n continuation paragraph\n\n 2. another item\n continuation line\n\n3. another\n4. another\n";
|
||||
QTest::newRow("thematic break") <<
|
||||
"something<hr/>something else" <<
|
||||
"something\n\n- - -\nsomething else\n\n";
|
||||
QTest::newRow("block quote") <<
|
||||
"<p>In 1958, Mahatma Gandhi was quoted as follows:</p><blockquote>The Earth provides enough to satisfy every man's need but not for every man's greed.</blockquote>" <<
|
||||
"In 1958, Mahatma Gandhi was quoted as follows:\n\n> The Earth provides enough to satisfy every man's need but not for every man's\n> greed.\n\n";
|
||||
QTest::newRow("image") <<
|
||||
"<img src=\"/url\" alt=\"foo\" title=\"title\"/>" <<
|
||||
"\n\n";
|
||||
QTest::newRow("code") <<
|
||||
"<pre class=\"language-pseudocode\">\n#include \"foo.h\"\n\nblock {\n statement();\n}\n\n</pre>" <<
|
||||
"```pseudocode\n#include \"foo.h\"\n\nblock {\n statement();\n}\n\n```\n\n";
|
||||
// TODO
|
||||
// QTest::newRow("escaped number and paren after double newline") <<
|
||||
// "<p>(The first sentence of this paragraph is a line, the next paragraph has a number</p>13) but that's not part of an ordered list" <<
|
||||
// "(The first sentence of this paragraph is a line, the next paragraph has a number\n\n13\\) but that's not part of an ordered list\n\n";
|
||||
QTest::newRow("preformats with embedded backticks") <<
|
||||
"<pre>none `one` ``two``</pre>plain<pre>```three``` ````four````</pre>plain" <<
|
||||
"```\nnone `one` ``two``\n\n```\nplain\n\n```\n```three``` ````four````\n\n```\nplain\n\n";
|
||||
QTest::newRow("list items with and without checkboxes") <<
|
||||
"<ul><li>bullet</li><li class=\"unchecked\">unchecked item</li><li class=\"checked\">checked item</li></ul>" <<
|
||||
"- bullet\n- [ ] unchecked item\n- [x] checked item\n";
|
||||
}
|
||||
|
||||
void tst_QTextMarkdownWriter::fromHtml()
|
||||
{
|
||||
QFETCH(QString, input);
|
||||
QFETCH(QString, expectedOutput);
|
||||
|
||||
document->setHtml(input);
|
||||
QString output = documentToUnixMarkdown();
|
||||
|
||||
#ifdef DEBUG_WRITE_OUTPUT
|
||||
{
|
||||
QFile out("/tmp/" + QLatin1String(QTest::currentDataTag()) + ".md");
|
||||
out.open(QFile::WriteOnly);
|
||||
out.write(output.toUtf8());
|
||||
out.close();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (output != expectedOutput && (isMainFontFixed() || isFixedFontProportional()))
|
||||
QEXPECT_FAIL("", "fixed main font or proportional fixed font (QTBUG-103484)", Continue);
|
||||
QCOMPARE(output, expectedOutput);
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QTextMarkdownWriter)
|
||||
#include "tst_qtextmarkdownwriter.moc"
|
Reference in New Issue
Block a user