qt 6.5.1 original

This commit is contained in:
kleuter
2023-10-29 23:33:08 +01:00
parent 71d22ab6b0
commit 85d238dfda
21202 changed files with 5499099 additions and 0 deletions

View 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}
)

View 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;
}
~~~

View 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.
![image](images/logo32.png) *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.*

View File

@ -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

View 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 \"&quot;")
[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

View File

@ -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.

View 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.

View File

@ -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\"/>" <<
"![foo](/url \"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"