tests/auto/qtextdocumentfragment/tst_qtextdocumentfragment.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the test suite of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 
       
    43 #include <QtTest/QtTest>
       
    44 
       
    45 
       
    46 #include <qtextdocument.h>
       
    47 #include <qtextdocumentfragment.h>
       
    48 #include <qtexttable.h>
       
    49 #include <qtextlist.h>
       
    50 #include <qdebug.h>
       
    51 #include <private/qtextdocument_p.h>
       
    52 
       
    53 
       
    54 #include <qtextcursor.h>
       
    55 
       
    56 QT_FORWARD_DECLARE_CLASS(QTextDocument)
       
    57 
       
    58 //TESTED_CLASS=
       
    59 //TESTED_FILES=gui/text/qtextdocumentfragment.h gui/text/qtextdocumentfragment.cpp gui/text/qtexthtmlparser.cpp gui/text/qtexthtmlparser_p.h
       
    60 
       
    61 class tst_QTextDocumentFragment : public QObject
       
    62 {
       
    63     Q_OBJECT
       
    64 
       
    65 public:
       
    66     tst_QTextDocumentFragment();
       
    67     ~tst_QTextDocumentFragment();
       
    68 
       
    69 public slots:
       
    70     void init();
       
    71     void cleanup();
       
    72 private slots:
       
    73     void listCopying();
       
    74     void listZeroCopying();
       
    75     void listCopying2();
       
    76     void tableCopying();
       
    77     void tableCopyingWithColSpans();
       
    78     void tableColSpanAndWidth();
       
    79     void tableImport();
       
    80     void tableImport2();
       
    81     void tableImport3();
       
    82     void tableImport4();
       
    83     void tableImport5();
       
    84     void textCopy();
       
    85     void copyWholeDocument();
       
    86     void title();
       
    87     void html_listIndents1();
       
    88     void html_listIndents2();
       
    89     void html_listIndents3();
       
    90     void html_listIndents4();
       
    91     void html_listIndents5();
       
    92     void html_listIndents6();
       
    93     void blockCharFormat();
       
    94     void blockCharFormatCopied();
       
    95     void initialBlock();
       
    96     void clone();
       
    97     void dontRemoveInitialBlockIfItHoldsObjectIndexedCharFormat();
       
    98     void dosLineFeed();
       
    99     void unorderedListEnumeration();
       
   100     void resetHasBlockAfterClosedBlockTags();
       
   101     void ignoreStyleTags();
       
   102     void hrefAnchor();
       
   103     void namedAnchorFragments();
       
   104     void namedAnchorFragments2();
       
   105     void namedAnchorFragments3();
       
   106     void dontInheritAlignmentInTables();
       
   107     void cellBlockCount();
       
   108     void cellBlockCount2();
       
   109     void emptyTable();
       
   110     void emptyTable2();
       
   111     void emptyTable3();
       
   112     void doubleRowClose();
       
   113     void mayNotHaveChildren();
       
   114     void inheritAlignment();
       
   115     void dontEmitEmptyNodeWhenEmptyTagIsFollowedByCloseTag();
       
   116     void toPlainText();
       
   117     void copyTableRow();
       
   118     void copyTableColumn();
       
   119     void copySubTable();
       
   120     void html_textDecoration();
       
   121     void html_infiniteLoop();
       
   122     void html_blockIndent();
       
   123     void html_listIndent();
       
   124     void html_whitespace();
       
   125     void html_whitespace_data();
       
   126     void html_qt3Whitespace();
       
   127     void html_qt3WhitespaceWithFragments();
       
   128     void html_qt3WhitespaceAfterTags();
       
   129     void html_listStart1();
       
   130     void html_listStart2();
       
   131     void html_cssMargin();
       
   132     void html_hexEntities();
       
   133     void html_decEntities();
       
   134     void html_thCentered();
       
   135     void orderedListNumbering();
       
   136     void html_blockAfterList();
       
   137     void html_subAndSuperScript();
       
   138     void html_cssColors();
       
   139     void obeyFragmentMarkersInImport();
       
   140     void whitespaceWithFragmentMarkers();
       
   141     void html_emptyParapgraphs1();
       
   142     void html_emptyParapgraphs2();
       
   143     void html_emptyParagraphs3();
       
   144     void html_emptyParagraphs4();
       
   145     void html_font();
       
   146     void html_fontSize();
       
   147     void html_fontSizeAdjustment();
       
   148     void html_cssFontSize();
       
   149     void html_cssShorthandFont();
       
   150     void html_bodyBgColor();
       
   151     void html_qtBgColor();
       
   152     void html_blockLevelDiv();
       
   153     void html_spanNesting();
       
   154     void html_nestedLists();
       
   155     void noSpecialCharactersInPlainText();
       
   156     void html_doNotInheritBackground();
       
   157     void html_inheritBackgroundToInlineElements();
       
   158     void html_doNotInheritBackgroundFromBlockElements();
       
   159     void html_nobr();
       
   160     void fromPlainText();
       
   161     void fromPlainText2();
       
   162     void html_closingImageTag();
       
   163     void html_emptyDocument();
       
   164     void html_closingTag();
       
   165     void html_anchorAroundImage();
       
   166     void html_floatBorder();
       
   167     void html_frameImport();
       
   168     void html_frameImport2();
       
   169     void html_dontAddMarginsAcrossTableCells();
       
   170     void html_dontMergeCenterBlocks();
       
   171     void html_tableCellBgColor();
       
   172     void html_tableCellBgColor2();
       
   173     void html_cellSkip();
       
   174     void nonZeroMarginOnImport();
       
   175     void html_charFormatPropertiesUnset();
       
   176     void html_headings();
       
   177     void html_quotedFontFamily();
       
   178     void html_spanBackgroundColor();
       
   179     void defaultFont();
       
   180     void html_brokenTitle_data();
       
   181     void html_brokenTitle();
       
   182     void html_blockVsInline();
       
   183     void html_tbody();
       
   184     void html_nestedTables();
       
   185     void html_rowSpans();
       
   186     void html_rowSpans2();
       
   187     void html_implicitParagraphs();
       
   188     void html_missingCloseTag();
       
   189     void html_anchorColor();
       
   190     void html_lastParagraphClosing();
       
   191     void html_tableHeaderBodyFootParent();
       
   192     void html_columnWidths();
       
   193     void html_bodyBackground();
       
   194     void html_tableCellBackground();
       
   195     void css_bodyBackground();
       
   196     void css_tableCellBackground();
       
   197     void css_fontWeight();
       
   198     void css_float();
       
   199     void css_textIndent();
       
   200     void css_inline();
       
   201     void css_external();
       
   202     void css_import();
       
   203     void css_selectors_data();
       
   204     void css_selectors();
       
   205     void css_nodeNameCaseInsensitivity();
       
   206     void css_textUnderlineStyle_data();
       
   207     void css_textUnderlineStyle();
       
   208     void css_textUnderlineStyleAndDecoration();
       
   209     void css_listStyleType();
       
   210     void css_linkPseudo();
       
   211     void css_pageBreaks();
       
   212     void css_cellPaddings();
       
   213     void universalSelectors_data();
       
   214     void universalSelectors();
       
   215     void screenMedia();
       
   216     void htmlResourceLoading();
       
   217     void someCaseInsensitiveAttributeValues();
       
   218     void backgroundImage();
       
   219     void dontMergePreAndNonPre();
       
   220     void leftMarginInsideHtml();
       
   221     void html_margins();
       
   222     void newlineInsidePreShouldBecomeNewParagraph();
       
   223     void invalidColspan();
       
   224     void html_brokenTableWithJustTr();
       
   225     void html_brokenTableWithJustTd();
       
   226     void html_preNewlineHandling_data();
       
   227     void html_preNewlineHandling();
       
   228     void html_br();
       
   229     void html_dl();
       
   230     void html_tableStrangeNewline();
       
   231     void html_tableStrangeNewline2();
       
   232     void html_tableStrangeNewline3();
       
   233     void html_caption();
       
   234     void html_windowsEntities();
       
   235     void html_eatenText();
       
   236     void html_hr();
       
   237     void html_hrMargins();
       
   238     void html_blockQuoteMargins();
       
   239     void html_definitionListMargins();
       
   240     void html_listMargins();
       
   241     void html_titleAttribute();
       
   242     void html_compressDivs();
       
   243     void completeToPlainText();
       
   244     void copyContents();
       
   245     void html_textAfterHr();
       
   246     void blockTagClosing();
       
   247     void isEmpty();
       
   248     void html_alignmentInheritance();
       
   249     void html_ignoreEmptyDivs();
       
   250     void html_dontInheritAlignmentForFloatingImages();
       
   251     void html_verticalImageAlignment();
       
   252     void html_verticalCellAlignment();
       
   253     void html_borderColor();
       
   254     void html_borderStyle();
       
   255     void html_borderWidth();
       
   256     void html_userState();
       
   257     void html_rootFrameProperties();
       
   258     void html_alignmentPropertySet();
       
   259     void html_appendList();
       
   260     void html_appendList2();
       
   261     void html_qt3RichtextWhitespaceMode();
       
   262     void html_brAfterHr();
       
   263     void html_unclosedHead();
       
   264     void html_entities();
       
   265     void html_entities_data();
       
   266     void html_ignore_script();
       
   267     void html_directionWithHtml();
       
   268     void html_directionWithRichText();
       
   269     void html_metaInBody();
       
   270     void html_importImageWithoutAspectRatio();
       
   271     void html_fromFirefox();
       
   272 
       
   273 private:
       
   274     inline void setHtml(const QString &html)
       
   275     // don't take the shortcut in QTextDocument::setHtml
       
   276     { doc->clear(); QTextCursor(doc).insertFragment(QTextDocumentFragment::fromHtml(html)); }
       
   277 
       
   278     inline void appendHtml(const QString &html)
       
   279     {
       
   280         QTextCursor cursor(doc);
       
   281         cursor.movePosition(QTextCursor::End);
       
   282         cursor.insertHtml(html);
       
   283     }
       
   284 
       
   285     QTextDocument *doc;
       
   286     QTextCursor cursor;
       
   287 };
       
   288 
       
   289 tst_QTextDocumentFragment::tst_QTextDocumentFragment()
       
   290 {
       
   291     QImage img(16, 16, QImage::Format_ARGB32_Premultiplied);
       
   292     img.save("foo.png");
       
   293 }
       
   294 
       
   295 tst_QTextDocumentFragment::~tst_QTextDocumentFragment()
       
   296 {
       
   297     QFile::remove(QLatin1String("foo.png"));
       
   298 }
       
   299 
       
   300 void tst_QTextDocumentFragment::init()
       
   301 {
       
   302     doc = new QTextDocument;
       
   303     cursor = QTextCursor(doc);
       
   304 }
       
   305 
       
   306 void tst_QTextDocumentFragment::cleanup()
       
   307 {
       
   308     cursor = QTextCursor();
       
   309     delete doc;
       
   310     doc = 0;
       
   311 }
       
   312 
       
   313 #include <private/qtextdocument_p.h>
       
   314 #include <qdebug.h>
       
   315 static void dumpTable(const QTextDocumentPrivate *pt)
       
   316 {
       
   317     qDebug() << "---dump----";
       
   318     qDebug() << "all text:" << pt->buffer();
       
   319     for (QTextDocumentPrivate::FragmentIterator it = pt->begin();
       
   320          !it.atEnd(); ++it) {
       
   321         qDebug() << "Fragment at text position" << it.position() << "; stringPosition" << it.value()->stringPosition << "; size" << it.value()->size_array[0] << "format :" << it.value()->format << "frag: " << it.n;
       
   322         qDebug() << "    text:" << pt->buffer().mid(it.value()->stringPosition, it.value()->size_array[0]);
       
   323     }
       
   324     qDebug() << "----begin block dump----";
       
   325     for (QTextBlock it = pt->blocksBegin(); it.isValid(); it = it.next())
       
   326         qDebug() << "block at" << it.position() << "with length" << it.length() << "block alignment" << it.blockFormat().alignment();
       
   327     qDebug() << "---dump----";
       
   328 }
       
   329 static void dumpTable(QTextDocument *doc) { dumpTable(doc->docHandle()); }
       
   330 
       
   331 void tst_QTextDocumentFragment::listCopying()
       
   332 {
       
   333     cursor.insertList(QTextListFormat::ListDecimal);
       
   334 
       
   335     QTextFormat originalBlockFormat = cursor.blockFormat();
       
   336     QVERIFY(originalBlockFormat.objectIndex() != -1);
       
   337     int originalListItemIdx = cursor.blockFormat().objectIndex();
       
   338 
       
   339     cursor.insertText("Hello World");
       
   340 
       
   341     QTextDocumentFragment fragment(doc);
       
   342 
       
   343     cursor.insertFragment(fragment);
       
   344 
       
   345     QVERIFY(cursor.currentList());
       
   346     QVERIFY(cursor.blockFormat() != originalBlockFormat);
       
   347     QVERIFY(cursor.blockFormat().objectIndex() != originalListItemIdx);
       
   348 }
       
   349 
       
   350 void tst_QTextDocumentFragment::listZeroCopying()
       
   351 {
       
   352     // same testcase as above but using the zero-copying
       
   353 
       
   354     cursor.insertList(QTextListFormat::ListDecimal);
       
   355 
       
   356     QTextFormat originalBlockFormat = cursor.blockFormat();
       
   357     int originalListItemIdx = cursor.blockFormat().objectIndex();
       
   358 
       
   359     cursor.insertText("Hello World");
       
   360 
       
   361     QTextDocumentFragment fragment(doc);
       
   362     cursor.insertFragment(fragment);
       
   363 
       
   364     QVERIFY(cursor.currentList());
       
   365     QVERIFY(cursor.blockFormat() != originalBlockFormat);
       
   366     QVERIFY(cursor.blockFormat().objectIndex() != originalListItemIdx);
       
   367 }
       
   368 
       
   369 void tst_QTextDocumentFragment::listCopying2()
       
   370 {
       
   371     cursor.insertList(QTextListFormat::ListDecimal);
       
   372     cursor.insertText("Hello World");
       
   373 
       
   374     cursor.insertList(QTextListFormat::ListDisc);
       
   375     cursor.insertText("Hello World");
       
   376 
       
   377     QTextDocumentFragment fragment(doc);
       
   378 
       
   379     cursor.insertFragment(fragment);
       
   380 
       
   381     cursor.movePosition(QTextCursor::Start);
       
   382     int listItemCount = 0;
       
   383     do {
       
   384 	if (cursor.currentList())
       
   385 	    listItemCount++;
       
   386     } while (cursor.movePosition(QTextCursor::NextBlock));
       
   387 
       
   388     QCOMPARE(listItemCount, 4);
       
   389 
       
   390     // we call this here because it used to cause a failing assertion in the
       
   391     // list manager.
       
   392     doc->undo();
       
   393 }
       
   394 
       
   395 void tst_QTextDocumentFragment::tableCopying()
       
   396 {
       
   397     // this tests both, the fragment to use the direction insertion instead of using the
       
   398     // cursor, which might adjuts its position when inserting a table step by step, as well
       
   399     // as the pasiveness of the tablemanager.
       
   400     QTextDocumentFragment fragment;
       
   401     {
       
   402 	QTextDocument doc;
       
   403 	QTextCursor cursor(&doc);
       
   404 
       
   405 	QTextTableFormat fmt;
       
   406 	QTextTable *table = cursor.insertTable(2, 2, fmt);
       
   407 
       
   408 	table->cellAt(0, 0).firstCursorPosition().insertText("First Cell");
       
   409 	table->cellAt(0, 1).firstCursorPosition().insertText("Second Cell");
       
   410 	table->cellAt(1, 0).firstCursorPosition().insertText("Third Cell");
       
   411 	table->cellAt(1, 1).firstCursorPosition().insertText("Fourth Cell");
       
   412 
       
   413 	fragment = QTextDocumentFragment(&doc);
       
   414     }
       
   415     {
       
   416 	QTextDocument doc;
       
   417 	QTextCursor cursor(&doc);
       
   418 
       
   419 	cursor.insertText("FooBar");
       
   420 	cursor.insertBlock();
       
   421 	cursor.movePosition(QTextCursor::Left);
       
   422 
       
   423 	cursor.insertFragment(fragment);
       
   424 	cursor.movePosition(QTextCursor::Start);
       
   425 	cursor.movePosition(QTextCursor::NextBlock);
       
   426 
       
   427 	QTextTable *table = cursor.currentTable();
       
   428 	QVERIFY(table);
       
   429 	QCOMPARE(table->rows(), 2);
       
   430 	QCOMPARE(table->columns(), 2);
       
   431     }
       
   432 }
       
   433 
       
   434 void tst_QTextDocumentFragment::tableCopyingWithColSpans()
       
   435 {
       
   436     const char html[] = ""
       
   437 "<table border>"
       
   438 "  <tr>"
       
   439 "    <td>First Cell"
       
   440 "    <td>Second Cell"
       
   441 "  </tr>"
       
   442 "  <tr>"
       
   443 "    <td colspan=\"2\">Third Cell"
       
   444 "  </tr>"
       
   445 "  <tr>"
       
   446 "    <td>Fourth Cell"
       
   447 "    <td>Fifth Cell"
       
   448 "  </tr>"
       
   449 "</table>";
       
   450     setHtml(html);
       
   451 
       
   452     cursor.movePosition(QTextCursor::Start);
       
   453     cursor.movePosition(QTextCursor::NextBlock);
       
   454     QTextTable *table = cursor.currentTable();
       
   455     QVERIFY(table);
       
   456     QVERIFY(table->columns() == 2 && table->rows() == 3);
       
   457 
       
   458     cursor = table->cellAt(2, 0).lastCursorPosition();
       
   459     cursor.setPosition(table->cellAt(0, 0).firstPosition(), QTextCursor::KeepAnchor);
       
   460     QVERIFY(cursor.hasComplexSelection());
       
   461 
       
   462     int firstRow = 0, numRows = 0, firstCol = 0, numCols = 0;
       
   463     cursor.selectedTableCells(&firstRow, &numRows, &firstCol, &numCols);
       
   464     QCOMPARE(firstRow, 0);
       
   465     QCOMPARE(numRows, 3);
       
   466     QCOMPARE(firstCol, 0);
       
   467     QCOMPARE(numCols, 1);
       
   468 
       
   469     QTextDocumentFragment frag = cursor.selection();
       
   470     cleanup();
       
   471     init();
       
   472     cursor.insertFragment(frag);
       
   473 
       
   474     cursor.movePosition(QTextCursor::Start);
       
   475     cursor.movePosition(QTextCursor::NextBlock);
       
   476     table = cursor.currentTable();
       
   477     QVERIFY(table);
       
   478     QVERIFY(table->columns() == 1 && table->rows() == 3);
       
   479 }
       
   480 
       
   481 void tst_QTextDocumentFragment::tableColSpanAndWidth()
       
   482 {
       
   483     const char html[] = ""
       
   484 "<table border=\"0\">"
       
   485 "  <tr>"
       
   486 "    <td colspan=\"4\" width=\"400\">First Cell</td>"
       
   487 "  </tr>"
       
   488 "</table>";
       
   489     setHtml(html);
       
   490 
       
   491     cursor.movePosition(QTextCursor::Start);
       
   492     cursor.movePosition(QTextCursor::NextBlock);
       
   493     QTextTable *table = cursor.currentTable();
       
   494     QVERIFY(table);
       
   495     QVERIFY(table->columns() == 4 && table->rows() == 1);
       
   496     // make sure its approx 400 and not a multiple due to the colspan
       
   497     QVERIFY(doc->size().width()> 398.);
       
   498     QVERIFY(doc->size().width() < 420.);
       
   499 }
       
   500 
       
   501 void tst_QTextDocumentFragment::tableImport()
       
   502 {
       
   503     // used to cause a failing assertion, as HTMLImporter::closeTag was
       
   504     // called twice with the last node.
       
   505     QTextDocumentFragment fragment = QTextDocumentFragment::fromHtml(QString::fromLatin1("<table><tr><td>Hey</td><td>Blah"));
       
   506     QVERIFY(!fragment.isEmpty());
       
   507 }
       
   508 
       
   509 void tst_QTextDocumentFragment::tableImport2()
       
   510 {
       
   511     {
       
   512 	const char html[] = ""
       
   513 	    "<table>"
       
   514 	    "<tr><td>First Cell</td><td>Second Cell</td></tr>"
       
   515 	    "<tr><td>Third Cell</td><td>Fourth Cell</td></tr>"
       
   516 	    "</table>";
       
   517 
       
   518 	QTextDocument doc;
       
   519 	QTextCursor cursor(&doc);
       
   520 	cursor.insertFragment(QTextDocumentFragment::fromHtml(QByteArray::fromRawData(html, sizeof(html) / sizeof(html[0]))));
       
   521 
       
   522 	cursor.movePosition(QTextCursor::Start);
       
   523 	cursor.movePosition(QTextCursor::NextBlock);
       
   524 	QTextTable *table = cursor.currentTable();
       
   525 	QVERIFY(table);
       
   526 	QCOMPARE(table->columns(), 2);
       
   527 	QCOMPARE(table->rows(), 2);
       
   528     }
       
   529     {
       
   530 	const char html[] = ""
       
   531 	    "<table>"
       
   532 	    "<tr><td>First Cell</td><td>Second Cell</td></tr>"
       
   533 	    "<tr><td>Third Cell</td><td>"
       
   534 	    "                           <table>"
       
   535 	    "                           <tr><td>First Nested Cell</td><td>Second Nested Cell</td></tr>"
       
   536 	    "                           <tr><td>Third Nested Cell</td><td>Fourth Nested Cell</td></tr>"
       
   537 	    "                           <tr><td>Fifth Nested Cell</td><td>Sixth Nested Cell</td></tr>"
       
   538 	    "                           </table></td></tr>"
       
   539 	    "</table>";
       
   540 
       
   541 	QTextDocument doc;
       
   542 	QTextCursor cursor(&doc);
       
   543 	cursor.insertFragment(QTextDocumentFragment::fromHtml(QByteArray::fromRawData(html, sizeof(html) / sizeof(html[0]))));
       
   544 
       
   545 	cursor.movePosition(QTextCursor::Start);
       
   546 	cursor.movePosition(QTextCursor::NextBlock);
       
   547 	QTextTable *table = cursor.currentTable();
       
   548 	QVERIFY(table);
       
   549 	QCOMPARE(table->columns(), 2);
       
   550 	QCOMPARE(table->rows(), 2);
       
   551 
       
   552         /*
       
   553 	QTextCursor fourthCell = table->cellAt(1, 1).firstCursorPosition();
       
   554 	fourthCell.movePosition(QTextCursor::NextBlock);
       
   555 	table = fourthCell.currentTable();
       
   556 	QVERIFY(table);
       
   557 	QVERIFY(table != cursor.currentTable());
       
   558 	QCOMPARE(table->columns(), 2);
       
   559 	QCOMPARE(table->rows(), 3);
       
   560         */
       
   561     }
       
   562     {
       
   563 	const char buggyHtml[] = ""
       
   564 	    "<table>"
       
   565 	    "<tr><td>First Cell<td>Second Cell"
       
   566 	    "<tr><td>Third Cell<td>Fourth Cell"
       
   567 	    "</table>";
       
   568 
       
   569 	QTextDocument doc;
       
   570 	QTextCursor cursor(&doc);
       
   571 	cursor.insertFragment(QTextDocumentFragment::fromHtml(QByteArray::fromRawData(buggyHtml, sizeof(buggyHtml) / sizeof(buggyHtml[0]))));
       
   572 
       
   573 	cursor.movePosition(QTextCursor::Start);
       
   574 	cursor.movePosition(QTextCursor::NextBlock);
       
   575 	QTextTable *table = cursor.currentTable();
       
   576 	QVERIFY(table);
       
   577 	QCOMPARE(table->columns(), 2);
       
   578 	QCOMPARE(table->rows(), 2);
       
   579     }
       
   580     {
       
   581 	const char buggyHtml[] = ""
       
   582 	    "<table>"
       
   583 	    "<tr><th>First Cell<th>Second Cell"
       
   584 	    "<tr><td>Third Cell<td>Fourth Cell"
       
   585 	    "</table>";
       
   586 
       
   587 	QTextDocument doc;
       
   588 	QTextCursor cursor(&doc);
       
   589 	cursor.insertFragment(QTextDocumentFragment::fromHtml(QByteArray::fromRawData(buggyHtml, sizeof(buggyHtml) / sizeof(buggyHtml[0]))));
       
   590 
       
   591 	cursor.movePosition(QTextCursor::Start);
       
   592 	cursor.movePosition(QTextCursor::NextBlock);
       
   593 	QTextTable *table = cursor.currentTable();
       
   594 	QVERIFY(table);
       
   595 	QCOMPARE(table->columns(), 2);
       
   596 	QCOMPARE(table->rows(), 2);
       
   597     }
       
   598 
       
   599 }
       
   600 
       
   601 void tst_QTextDocumentFragment::tableImport3()
       
   602 {
       
   603     // ### would be better to have tree tests for QTextHtmlParser
       
   604     // make sure the p is a child of the td. If not the following td
       
   605     // ends up outside the table, causing an assertion
       
   606     const char html[] = "<table><tr><td><p></p></td><td></td></tr></table>";
       
   607     QTextDocumentFragment fragment = QTextDocumentFragment::fromHtml(QString::fromLatin1(html));
       
   608     QVERIFY(!fragment.isEmpty());
       
   609 }
       
   610 
       
   611 void tst_QTextDocumentFragment::tableImport4()
       
   612 {
       
   613     const char html[] = "<table>"
       
   614         "<tr><td>blah</td></tr>"
       
   615         "<tr><td>blah</td><td>blah</td></tr>"
       
   616         "</table>";
       
   617     cursor.insertFragment(QTextDocumentFragment::fromHtml(QString::fromLatin1(html)));
       
   618     cursor.movePosition(QTextCursor::Start);
       
   619     cursor.movePosition(QTextCursor::NextBlock);
       
   620     QVERIFY(cursor.currentTable());
       
   621     QCOMPARE(cursor.currentTable()->columns(), 2);
       
   622 }
       
   623 
       
   624 void tst_QTextDocumentFragment::tableImport5()
       
   625 {
       
   626     const char html[] = "<table>"
       
   627         "<tr>"
       
   628         " <td>Foo</td>"
       
   629         " <td>Bar</td>"
       
   630         " <td>Bleh</td>"
       
   631         "  <td>Blub</td>"
       
   632         "</tr>"
       
   633         "<tr>"
       
   634         "  <td>Ahh</td>"
       
   635         "  <td colspan=5>Gah</td>"
       
   636         "</tr>"
       
   637         "</table>";
       
   638 
       
   639     cursor.insertFragment(QTextDocumentFragment::fromHtml(QString::fromLatin1(html)));
       
   640     cursor.movePosition(QTextCursor::Start);
       
   641     cursor.movePosition(QTextCursor::NextBlock);
       
   642     QVERIFY(cursor.currentTable());
       
   643     QCOMPARE(cursor.currentTable()->rows(), 2);
       
   644     QCOMPARE(cursor.currentTable()->columns(), 6);
       
   645 }
       
   646 
       
   647 void tst_QTextDocumentFragment::textCopy()
       
   648 {
       
   649     /* this test used to cause failing assertions in QTextDocumentFragment */
       
   650     /* copy&paste 'lo\bwor' */
       
   651     cursor.insertText("Hello");
       
   652     cursor.insertBlock();
       
   653     cursor.insertText("World");
       
   654 
       
   655     cursor.movePosition(QTextCursor::Start);
       
   656     cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::MoveAnchor, 3);
       
   657     cursor.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor);
       
   658     cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, 3);
       
   659 
       
   660     QTextDocumentFragment fragment(cursor);
       
   661     QVERIFY(!fragment.isEmpty());
       
   662     cursor.insertFragment(fragment);
       
   663 }
       
   664 
       
   665 void tst_QTextDocumentFragment::copyWholeDocument()
       
   666 {
       
   667     // used to cause the famous currentBlock.position() == pos + 1 failing assertion
       
   668     cursor.insertText("\nHey\nBlah\n");
       
   669     cursor.movePosition(QTextCursor::Start);
       
   670     cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
       
   671 
       
   672     QTextFrameFormat fmt = doc->rootFrame()->frameFormat();
       
   673     fmt.setBackground(Qt::blue);
       
   674     doc->rootFrame()->setFrameFormat(fmt);
       
   675 
       
   676     QTextDocumentFragment fragment(cursor);
       
   677     QVERIFY(true); // good if we reach this point :)
       
   678 
       
   679     cleanup();
       
   680     init();
       
   681 
       
   682     fmt.setBackground(Qt::red);
       
   683     doc->rootFrame()->setFrameFormat(fmt);
       
   684 
       
   685     cursor.insertFragment(fragment);
       
   686 
       
   687     QVERIFY(doc->rootFrame()->frameFormat().background().color() == Qt::red);
       
   688 }
       
   689 
       
   690 void tst_QTextDocumentFragment::title()
       
   691 {
       
   692     doc->setHtml(QString::fromLatin1("<html><head><title>Test</title></head><body>Blah</body></html>"));
       
   693     QCOMPARE(doc->metaInformation(QTextDocument::DocumentTitle), QString::fromLatin1("Test"));
       
   694 }
       
   695 
       
   696 void tst_QTextDocumentFragment::html_listIndents1()
       
   697 {
       
   698     const char html[] = "<ul><li>Hey</li><li>Hah</li></ul>";
       
   699     setHtml(QString::fromLatin1(html));
       
   700     cursor.movePosition(QTextCursor::Start);
       
   701     cursor.movePosition(QTextCursor::NextBlock);
       
   702     QTextList *list = cursor.currentList();
       
   703     QVERIFY(list);
       
   704     QCOMPARE(list->format().indent(), 1);
       
   705     QCOMPARE(cursor.block().blockFormat().indent(), 0);
       
   706 }
       
   707 
       
   708 void tst_QTextDocumentFragment::html_listIndents2()
       
   709 {
       
   710     const char html[] = "<ul><li>Hey<p>Hah</ul>";
       
   711     setHtml(QString::fromLatin1(html));
       
   712     cursor.movePosition(QTextCursor::Start);
       
   713     QTextList *list = cursor.currentList();
       
   714     QVERIFY(list);
       
   715     QCOMPARE(list->format().indent(), 1);
       
   716     QCOMPARE(cursor.block().blockFormat().indent(), 0);
       
   717 
       
   718     cursor.movePosition(QTextCursor::NextBlock);
       
   719     QCOMPARE(cursor.block().blockFormat().indent(), 1);
       
   720 }
       
   721 
       
   722 void tst_QTextDocumentFragment::html_listIndents3()
       
   723 {
       
   724     const char html[] = "<ul><li><p>Hah</ul>";
       
   725     setHtml(QString::fromLatin1(html));
       
   726     cursor.movePosition(QTextCursor::Start);
       
   727     QTextList *list = cursor.currentList();
       
   728     QVERIFY(list);
       
   729     QCOMPARE(list->format().indent(), 1);
       
   730     QCOMPARE(cursor.block().blockFormat().indent(), 0);
       
   731 }
       
   732 
       
   733 void tst_QTextDocumentFragment::html_listIndents4()
       
   734 {
       
   735     const char html[] = "<ul><li>Foo</ul><p>This should not have the same indent as Foo";
       
   736     setHtml(QString::fromLatin1(html));
       
   737     cursor.movePosition(QTextCursor::Start);
       
   738     QTextList *list = cursor.currentList();
       
   739     QVERIFY(list);
       
   740     QCOMPARE(list->format().indent(), 1);
       
   741 
       
   742     cursor.movePosition(QTextCursor::NextBlock);
       
   743     QVERIFY(!cursor.currentList());
       
   744     QCOMPARE(cursor.blockFormat().indent(), 0);
       
   745 }
       
   746 
       
   747 void tst_QTextDocumentFragment::html_listIndents5()
       
   748 {
       
   749     const char html[] = "<ul><li>Foo<p><li>Bar</li></ul>";
       
   750     setHtml(QString::fromLatin1(html));
       
   751     cursor.movePosition(QTextCursor::Start);
       
   752     QTextList *list = cursor.currentList();
       
   753     QVERIFY(list);
       
   754     QCOMPARE(list->format().indent(), 1);
       
   755 
       
   756     cursor.movePosition(QTextCursor::NextBlock);
       
   757     QVERIFY(cursor.currentList() == list);
       
   758     QCOMPARE(cursor.blockFormat().indent(), 0);
       
   759 }
       
   760 
       
   761 void tst_QTextDocumentFragment::html_listIndents6()
       
   762 {
       
   763     const char html[] = "<ul><li>Outer List<div class=\"testclass\"><ul><li>Nested Item 1</li></ul></div></li></ul>";
       
   764     setHtml(QString::fromLatin1(html));
       
   765     cursor.movePosition(QTextCursor::Start);
       
   766     QTextList *list = cursor.currentList();
       
   767     QVERIFY(list);
       
   768     QCOMPARE(list->format().indent(), 1);
       
   769 
       
   770     cursor.movePosition(QTextCursor::NextBlock);
       
   771     QVERIFY(cursor.currentList() != list);
       
   772     list = cursor.currentList();
       
   773     QVERIFY(list);
       
   774     QCOMPARE(list->format().indent(), 2);
       
   775 
       
   776     QCOMPARE(cursor.blockFormat().indent(), 0);
       
   777 }
       
   778 
       
   779 void tst_QTextDocumentFragment::blockCharFormat()
       
   780 {
       
   781     const char html[] = "<p style=\"font-style:italic\"><span style=\"font-style:normal\">Test</span></p>";
       
   782     setHtml(QString::fromLatin1(html));
       
   783     QVERIFY(doc->begin().charFormat().fontItalic());
       
   784 }
       
   785 
       
   786 void tst_QTextDocumentFragment::blockCharFormatCopied()
       
   787 {
       
   788     QTextCharFormat fmt;
       
   789     fmt.setForeground(Qt::green);
       
   790     cursor.setBlockCharFormat(fmt);
       
   791     cursor.insertText("Test", QTextCharFormat());
       
   792     QTextDocumentFragment frag(doc);
       
   793     cleanup();
       
   794     init();
       
   795     cursor.insertFragment(frag);
       
   796     QVERIFY(cursor.blockCharFormat() == fmt);
       
   797 }
       
   798 
       
   799 void tst_QTextDocumentFragment::initialBlock()
       
   800 {
       
   801     const char html[] = "<p>Test</p>";
       
   802     setHtml(QString::fromLatin1(html));
       
   803     QCOMPARE(doc->blockCount(), 1);
       
   804 }
       
   805 
       
   806 void tst_QTextDocumentFragment::clone()
       
   807 {
       
   808     QTextBlockFormat mod;
       
   809     mod.setAlignment(Qt::AlignCenter);
       
   810     cursor.mergeBlockFormat(mod);
       
   811     cursor.insertText("Blah");
       
   812     QVERIFY(cursor.blockFormat().alignment() == Qt::AlignCenter);
       
   813     QTextDocumentFragment frag(doc);
       
   814     cleanup();
       
   815     init();
       
   816     cursor.insertFragment(frag);
       
   817     cursor.movePosition(QTextCursor::Start);
       
   818     QVERIFY(cursor.blockFormat().alignment() == Qt::AlignCenter);
       
   819 }
       
   820 
       
   821 void tst_QTextDocumentFragment::dontRemoveInitialBlockIfItHoldsObjectIndexedCharFormat()
       
   822 {
       
   823     const char html[] = "<table><tr><td>cell one<td>cell two</tr><tr><td>cell three<td>cell four</tr></table>";
       
   824     QVERIFY(doc->begin().charFormat().objectIndex() == -1);
       
   825     setHtml(QString::fromLatin1(html));
       
   826     int cnt = 0;
       
   827 
       
   828     int objectIndexOfLast = -1;
       
   829     for (QTextBlock blk = doc->begin(); blk.isValid(); blk = blk.next()) {
       
   830         ++cnt;
       
   831         objectIndexOfLast = blk.charFormat().objectIndex();
       
   832     }
       
   833     //   beginning of frame for first cell
       
   834     // + beginning of frame for second cell
       
   835     // + beginning of frame for third cell
       
   836     // + beginning of frame for fourth cell
       
   837     // + end of frame
       
   838     // + initial block
       
   839     // ==> 6
       
   840     QCOMPARE(cnt, 6);
       
   841     QVERIFY(objectIndexOfLast != -1);
       
   842     QVERIFY(doc->begin().next().charFormat().objectIndex() != -1);
       
   843 }
       
   844 
       
   845 void tst_QTextDocumentFragment::dosLineFeed()
       
   846 {
       
   847     const char html[] = "<pre>Test\r\n</pre>Bar";
       
   848     setHtml(QString::fromLatin1(html));
       
   849     QVERIFY(!doc->toPlainText().contains('\r'));
       
   850     QCOMPARE(doc->toPlainText(), QString("Test\nBar"));
       
   851 }
       
   852 
       
   853 void tst_QTextDocumentFragment::unorderedListEnumeration()
       
   854 {
       
   855     const char html[] = "<ul><ul><ul><li>Blah</li></ul></ul>";
       
   856     setHtml(QString::fromLatin1(html));
       
   857     cursor.movePosition(QTextCursor::End);
       
   858     QVERIFY(cursor.currentList());
       
   859     QVERIFY(cursor.currentList()->format().style() == QTextListFormat::ListCircle);
       
   860 
       
   861     const char html2[] = "<ul><ul><ul type=disc><li>Blah</li></ul></ul>";
       
   862     setHtml(QString::fromLatin1(html2));
       
   863     cursor.movePosition(QTextCursor::End);
       
   864     QVERIFY(cursor.currentList());
       
   865     QVERIFY(cursor.currentList()->format().style() == QTextListFormat::ListDisc);
       
   866 
       
   867 }
       
   868 
       
   869 void tst_QTextDocumentFragment::resetHasBlockAfterClosedBlockTags()
       
   870 {
       
   871     // when closing tags we have to make sure hasBlock in import() gets resetted
       
   872     const char html[] = "<body><table><tr><td><td><p></table><p></body>";
       
   873     setHtml(QString::fromLatin1(html));
       
   874     QVERIFY(!doc->isEmpty());
       
   875 }
       
   876 
       
   877 void tst_QTextDocumentFragment::ignoreStyleTags()
       
   878 {
       
   879     const char html[] = "<body><style>Blah</style>Hello</body>";
       
   880     setHtml(QString::fromLatin1(html));
       
   881     QCOMPARE(doc->toPlainText(), QString("Hello"));
       
   882 }
       
   883 
       
   884 void tst_QTextDocumentFragment::hrefAnchor()
       
   885 {
       
   886     {
       
   887         const char html[] = "<a href=\"test\">blah</a>";
       
   888         setHtml(QString::fromLatin1(html));
       
   889         QVERIFY(doc->begin().begin().fragment().charFormat().isAnchor());
       
   890         QCOMPARE(doc->begin().begin().fragment().charFormat().anchorHref(), QString::fromAscii("test"));
       
   891         QVERIFY(doc->begin().begin().fragment().charFormat().fontUnderline() == true);
       
   892     }
       
   893 
       
   894     {
       
   895         // only hyperlinks should have special formatting
       
   896         const char html[] = "<a>blah</a>";
       
   897         setHtml(QString::fromLatin1(html));
       
   898         QVERIFY(doc->begin().begin().fragment().charFormat().isAnchor());
       
   899         QVERIFY(doc->begin().begin().fragment().charFormat().fontUnderline() == false);
       
   900     }
       
   901 }
       
   902 
       
   903 void tst_QTextDocumentFragment::namedAnchorFragments()
       
   904 {
       
   905     // named anchors should be 'invisible', but the fragment right after it should
       
   906     // hold the attribute
       
   907     const char html[] = "a<a name=\"test\" />blah";
       
   908     setHtml(QString::fromLatin1(html));
       
   909 
       
   910     QTextBlock firstBlock = doc->begin();
       
   911     QVERIFY(firstBlock.isValid());
       
   912 
       
   913     QTextBlock::Iterator it = firstBlock.begin();
       
   914     QVERIFY(!it.atEnd());
       
   915 
       
   916     // the 'a'
       
   917     QVERIFY(it.fragment().isValid());
       
   918     QCOMPARE(it.fragment().text(), QString::fromAscii("a"));
       
   919     QVERIFY(it.fragment().charFormat().isAnchor() == false);
       
   920 
       
   921     // the 'b' of 'blah' as separate fragment with the anchor attribute
       
   922     ++it;
       
   923     QVERIFY(it.fragment().isValid());
       
   924     QCOMPARE(it.fragment().text(), QString::fromAscii("b"));
       
   925     QVERIFY(it.fragment().charFormat().isAnchor());
       
   926 
       
   927     // the 'lah' of 'blah' as remainder
       
   928     ++it;
       
   929     QVERIFY(it.fragment().isValid());
       
   930     QVERIFY(it.fragment().text().startsWith("lah"));
       
   931     QVERIFY(it.fragment().charFormat().isAnchor() == false);
       
   932 }
       
   933 
       
   934 void tst_QTextDocumentFragment::namedAnchorFragments2()
       
   935 {
       
   936     const char html[] = "<p>    <a name=\"foo\"> Hello";
       
   937     setHtml(QString::fromLatin1(html));
       
   938 
       
   939     QCOMPARE(doc->toPlainText(), QString("Hello"));
       
   940 
       
   941     QTextBlock::Iterator it = doc->begin().begin();
       
   942     QVERIFY(!it.atEnd());
       
   943 
       
   944     QCOMPARE(it.fragment().text(), QString::fromAscii("H"));
       
   945     QVERIFY(it.fragment().charFormat().isAnchor());
       
   946 
       
   947     ++it;
       
   948 
       
   949     QCOMPARE(it.fragment().text(), QString::fromAscii("ello"));
       
   950     QVERIFY(!it.fragment().charFormat().isAnchor());
       
   951 }
       
   952 
       
   953 void tst_QTextDocumentFragment::namedAnchorFragments3()
       
   954 {
       
   955     setHtml("<a name=\"target\" /><a name=\"target2\"/><span>Text</span>");
       
   956 
       
   957     QCOMPARE(doc->toPlainText(), QString("Text"));
       
   958 
       
   959     QTextBlock::Iterator it = doc->begin().begin();
       
   960     QVERIFY(!it.atEnd());
       
   961 
       
   962     QCOMPARE(it.fragment().text(), QString::fromAscii("T"));
       
   963     QVERIFY(it.fragment().charFormat().isAnchor());
       
   964     QCOMPARE(it.fragment().charFormat().anchorName(), QString("target"));
       
   965     QStringList targets; targets << "target" << "target2";
       
   966     QCOMPARE(it.fragment().charFormat().anchorNames(), targets);
       
   967 
       
   968     ++it;
       
   969 
       
   970     QCOMPARE(it.fragment().text(), QString::fromAscii("ext"));
       
   971     QVERIFY(!it.fragment().charFormat().isAnchor());
       
   972 }
       
   973 
       
   974 void tst_QTextDocumentFragment::dontInheritAlignmentInTables()
       
   975 {
       
   976     const char html[] = "<table align=center><tr><td>Hey</td></tr></table>";
       
   977     setHtml(QString::fromLatin1(html));
       
   978 
       
   979     cursor.movePosition(QTextCursor::Start);
       
   980     cursor.movePosition(QTextCursor::NextBlock);
       
   981     QVERIFY(cursor.currentTable());
       
   982     QVERIFY(cursor.currentTable()->cellAt(0, 0).isValid());
       
   983     QVERIFY(cursor.currentTable()->cellAt(0, 0).firstCursorPosition().block().next().blockFormat().alignment() != Qt::AlignHCenter);
       
   984 }
       
   985 
       
   986 void tst_QTextDocumentFragment::cellBlockCount()
       
   987 {
       
   988     const char html[] = "<table><tr><td>Hey</td></tr></table>";
       
   989     setHtml(QString::fromLatin1(html));
       
   990 
       
   991     cursor.movePosition(QTextCursor::Start);
       
   992     cursor.movePosition(QTextCursor::NextBlock);
       
   993     QVERIFY(cursor.currentTable());
       
   994 
       
   995     QTextTableCell cell = cursor.currentTable()->cellAt(0, 0);
       
   996     QVERIFY(cell.isValid());
       
   997 
       
   998     int blockCount = 0;
       
   999     for (QTextFrame::iterator it = cell.begin(); !it.atEnd(); ++it) {
       
  1000         QVERIFY(it.currentFrame() == 0);
       
  1001         QVERIFY(it.currentBlock().isValid());
       
  1002         ++blockCount;
       
  1003     }
       
  1004     QCOMPARE(blockCount, 1);
       
  1005 }
       
  1006 
       
  1007 void tst_QTextDocumentFragment::cellBlockCount2()
       
  1008 {
       
  1009     const char html[] = "<table><tr><td><p>Hey</p></td></tr></table>";
       
  1010     setHtml(QString::fromLatin1(html));
       
  1011 
       
  1012     cursor.movePosition(QTextCursor::Start);
       
  1013     cursor.movePosition(QTextCursor::NextBlock);
       
  1014     QVERIFY(cursor.currentTable());
       
  1015 
       
  1016     QTextTableCell cell = cursor.currentTable()->cellAt(0, 0);
       
  1017     QVERIFY(cell.isValid());
       
  1018 
       
  1019     int blockCount = 0;
       
  1020     for (QTextFrame::iterator it = cell.begin(); !it.atEnd(); ++it) {
       
  1021         QVERIFY(it.currentFrame() == 0);
       
  1022         QVERIFY(it.currentBlock().isValid());
       
  1023         ++blockCount;
       
  1024     }
       
  1025     QCOMPARE(blockCount, 1);
       
  1026 }
       
  1027 
       
  1028 void tst_QTextDocumentFragment::emptyTable()
       
  1029 {
       
  1030     const char html[] = "<table></table>";
       
  1031     setHtml(QString::fromLatin1(html));
       
  1032     QVERIFY(true); // don't crash with a failing assertion
       
  1033 }
       
  1034 
       
  1035 void tst_QTextDocumentFragment::emptyTable2()
       
  1036 {
       
  1037     const char html[] = "<table></td></tr></table><p>blah</p>";
       
  1038     setHtml(QString::fromLatin1(html));
       
  1039     QVERIFY(true); // don't crash with a failing assertion
       
  1040 }
       
  1041 
       
  1042 void tst_QTextDocumentFragment::emptyTable3()
       
  1043 {
       
  1044     const char html[] = "<table><tr><td><table></table></td><td>Foobar</td></tr></table>";
       
  1045     setHtml(QString::fromLatin1(html));
       
  1046 
       
  1047     cursor.movePosition(QTextCursor::Start);
       
  1048     cursor.movePosition(QTextCursor::NextBlock);
       
  1049     QTextTable *table = cursor.currentTable();
       
  1050     QVERIFY(table);
       
  1051     QCOMPARE(table->rows(), 1);
       
  1052     QCOMPARE(table->columns(), 2);
       
  1053     QTextTableCell cell = table->cellAt(0, 0);
       
  1054     QVERIFY(cell.isValid());
       
  1055     QVERIFY(cell.firstPosition() == cell.lastPosition());
       
  1056     cell = table->cellAt(0, 1);
       
  1057     QTextCursor cursor = cell.firstCursorPosition();
       
  1058     cursor.setPosition(cell.lastPosition(), QTextCursor::KeepAnchor);
       
  1059     QCOMPARE(cursor.selectedText(), QString("Foobar"));
       
  1060 }
       
  1061 
       
  1062 void tst_QTextDocumentFragment::doubleRowClose()
       
  1063 {
       
  1064     const char html[] = "<table><tr><td>Blah</td></tr></tr><tr><td>Hm</td></tr></table>";
       
  1065     setHtml(QString::fromLatin1(html));
       
  1066     QVERIFY(true); // don't crash with a failing assertion
       
  1067 }
       
  1068 
       
  1069 void tst_QTextDocumentFragment::mayNotHaveChildren()
       
  1070 {
       
  1071     // make sure the Hey does not end up as tag text for the img tag
       
  1072     const char html[] = "<img />Hey";
       
  1073     setHtml(QString::fromLatin1(html));
       
  1074     QCOMPARE(doc->toPlainText().mid(1), QString::fromAscii("Hey"));
       
  1075 }
       
  1076 
       
  1077 void tst_QTextDocumentFragment::inheritAlignment()
       
  1078 {
       
  1079     // make sure attributes from the body tag get inherited
       
  1080     const char html[] = "<body align=right><p>Hey";
       
  1081     setHtml(QString::fromLatin1(html));
       
  1082     // html alignment is absolute
       
  1083     QVERIFY(doc->begin().blockFormat().alignment() == Qt::Alignment(Qt::AlignRight|Qt::AlignAbsolute));
       
  1084 }
       
  1085 
       
  1086 void tst_QTextDocumentFragment::dontEmitEmptyNodeWhenEmptyTagIsFollowedByCloseTag()
       
  1087 {
       
  1088     // make sure the Hey does not end up as tag text for the img tag
       
  1089     const char html[] = "<body align=right><p align=left>Blah<img></img><p>Hey";
       
  1090     setHtml(QString::fromLatin1(html));
       
  1091     QVERIFY(doc->begin().blockFormat().alignment() == Qt::Alignment(Qt::AlignLeft|Qt::AlignAbsolute));
       
  1092     QVERIFY(doc->begin().next().blockFormat().alignment() == Qt::Alignment(Qt::AlignRight|Qt::AlignAbsolute));
       
  1093 }
       
  1094 
       
  1095 void tst_QTextDocumentFragment::toPlainText()
       
  1096 {
       
  1097     QString input = "Hello\nWorld";
       
  1098     input += QChar::ParagraphSeparator;
       
  1099     input += "Blah";
       
  1100     doc->setPlainText(input);
       
  1101     QCOMPARE(doc->blockCount(), 3);
       
  1102 }
       
  1103 
       
  1104 void tst_QTextDocumentFragment::copyTableRow()
       
  1105 {
       
  1106     QTextDocumentFragment frag;
       
  1107     {
       
  1108         QTextTable *table = cursor.insertTable(2, 2);
       
  1109         table->cellAt(0, 0).firstCursorPosition().insertText("Blah");
       
  1110         table->cellAt(0, 1).firstCursorPosition().insertText("Foo");
       
  1111         table->cellAt(1, 0).firstCursorPosition().insertText("Bar");
       
  1112         table->cellAt(1, 1).firstCursorPosition().insertText("Hah");
       
  1113 
       
  1114         // select second row
       
  1115         cursor = table->cellAt(1, 1).firstCursorPosition();
       
  1116         cursor.movePosition(QTextCursor::PreviousBlock, QTextCursor::KeepAnchor);
       
  1117 
       
  1118         QCOMPARE(table->cellAt(cursor.position()).row(), 1);
       
  1119         QCOMPARE(table->cellAt(cursor.position()).column(), 0);
       
  1120         QCOMPARE(table->cellAt(cursor.anchor()).row(), 1);
       
  1121         QCOMPARE(table->cellAt(cursor.anchor()).column(), 1);
       
  1122 
       
  1123         frag = QTextDocumentFragment(cursor);
       
  1124     }
       
  1125     {
       
  1126         QTextDocument doc2;
       
  1127         cursor = QTextCursor(&doc2);
       
  1128         cursor.insertFragment(frag);
       
  1129 
       
  1130         cursor.movePosition(QTextCursor::Start);
       
  1131         cursor.movePosition(QTextCursor::NextBlock);
       
  1132         QTextTable *table = cursor.currentTable();
       
  1133 
       
  1134         QVERIFY(table);
       
  1135         QCOMPARE(table->columns(), 2);
       
  1136         QCOMPARE(table->rows(), 1);
       
  1137 
       
  1138         QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("Bar"));
       
  1139         QCOMPARE(table->cellAt(0, 1).firstCursorPosition().block().text(), QString("Hah"));
       
  1140     }
       
  1141 }
       
  1142 
       
  1143 void tst_QTextDocumentFragment::copyTableColumn()
       
  1144 {
       
  1145     QTextDocumentFragment frag;
       
  1146     {
       
  1147         QTextTable *table = cursor.insertTable(2, 2);
       
  1148         table->cellAt(0, 0).firstCursorPosition().insertText("Blah");
       
  1149         table->cellAt(0, 1).firstCursorPosition().insertText("Foo");
       
  1150         table->cellAt(1, 0).firstCursorPosition().insertText("Bar");
       
  1151         table->cellAt(1, 1).firstCursorPosition().insertText("Hah");
       
  1152 
       
  1153         // select second column
       
  1154         cursor = table->cellAt(0, 1).firstCursorPosition();
       
  1155         cursor.movePosition(QTextCursor::Down, QTextCursor::KeepAnchor);
       
  1156 
       
  1157         QCOMPARE(table->cellAt(cursor.anchor()).row(), 0);
       
  1158         QCOMPARE(table->cellAt(cursor.anchor()).column(), 1);
       
  1159         QCOMPARE(table->cellAt(cursor.position()).row(), 1);
       
  1160         QCOMPARE(table->cellAt(cursor.position()).column(), 1);
       
  1161 
       
  1162         frag = QTextDocumentFragment(cursor);
       
  1163     }
       
  1164     {
       
  1165         QTextDocument doc2;
       
  1166         cursor = QTextCursor(&doc2);
       
  1167         cursor.insertFragment(frag);
       
  1168 
       
  1169         cursor.movePosition(QTextCursor::Start);
       
  1170         cursor.movePosition(QTextCursor::NextBlock);
       
  1171         QTextTable *table = cursor.currentTable();
       
  1172 
       
  1173         QVERIFY(table);
       
  1174         QCOMPARE(table->columns(), 1);
       
  1175         QCOMPARE(table->rows(), 2);
       
  1176 
       
  1177         QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("Foo"));
       
  1178         QCOMPARE(table->cellAt(1, 0).firstCursorPosition().block().text(), QString("Hah"));
       
  1179     }
       
  1180 }
       
  1181 
       
  1182 void tst_QTextDocumentFragment::copySubTable()
       
  1183 {
       
  1184     QTextDocumentFragment frag;
       
  1185     {
       
  1186         QTextTableFormat fmt;
       
  1187         QVector<QTextLength> constraints;
       
  1188         constraints << QTextLength(QTextLength::PercentageLength, 16);
       
  1189         constraints << QTextLength(QTextLength::PercentageLength, 28);
       
  1190         constraints << QTextLength(QTextLength::PercentageLength, 28);
       
  1191         constraints << QTextLength(QTextLength::PercentageLength, 28);
       
  1192         fmt.setColumnWidthConstraints(constraints);
       
  1193 
       
  1194         QTextTable *table = cursor.insertTable(4, 4, fmt);
       
  1195         for (int row = 0; row < 4; ++row)
       
  1196             for (int col = 0; col < 4; ++col)
       
  1197                 table->cellAt(row, col).firstCursorPosition().insertText(QString("%1/%2").arg(row).arg(col));
       
  1198 
       
  1199         QCOMPARE(table->format().columnWidthConstraints().count(), table->columns());
       
  1200 
       
  1201         // select 2x2 subtable
       
  1202         cursor = table->cellAt(1, 1).firstCursorPosition();
       
  1203         cursor.movePosition(QTextCursor::Down, QTextCursor::KeepAnchor);
       
  1204         cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor);
       
  1205 
       
  1206         QCOMPARE(table->cellAt(cursor.anchor()).row(), 1);
       
  1207         QCOMPARE(table->cellAt(cursor.anchor()).column(), 1);
       
  1208         QCOMPARE(table->cellAt(cursor.position()).row(), 2);
       
  1209         QCOMPARE(table->cellAt(cursor.position()).column(), 2);
       
  1210 
       
  1211         frag = QTextDocumentFragment(cursor);
       
  1212     }
       
  1213     {
       
  1214         QTextDocument doc2;
       
  1215         cursor = QTextCursor(&doc2);
       
  1216         cursor.insertFragment(frag);
       
  1217 
       
  1218         cursor.movePosition(QTextCursor::Start);
       
  1219         cursor.movePosition(QTextCursor::NextBlock);
       
  1220         QTextTable *table = cursor.currentTable();
       
  1221 
       
  1222         QVERIFY(table);
       
  1223         QVERIFY(table->format().columnWidthConstraints().isEmpty());
       
  1224         QCOMPARE(table->columns(), 2);
       
  1225         QCOMPARE(table->rows(), 2);
       
  1226 
       
  1227         QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("1/1"));
       
  1228         QCOMPARE(table->cellAt(0, 1).firstCursorPosition().block().text(), QString("1/2"));
       
  1229         QCOMPARE(table->cellAt(1, 0).firstCursorPosition().block().text(), QString("2/1"));
       
  1230         QCOMPARE(table->cellAt(1, 1).firstCursorPosition().block().text(), QString("2/2"));
       
  1231     }
       
  1232 }
       
  1233 
       
  1234 void tst_QTextDocumentFragment::html_textDecoration()
       
  1235 {
       
  1236     const char html[] = "<span style='text-decoration: overline line-through underline'>Blah</span>";
       
  1237     cursor.insertFragment(QTextDocumentFragment::fromHtml(QByteArray::fromRawData(html, sizeof(html) / sizeof(html[0]))));
       
  1238 
       
  1239     cursor.movePosition(QTextCursor::Start);
       
  1240     cursor.movePosition(QTextCursor::NextCharacter);
       
  1241     QVERIFY(cursor.charFormat().fontUnderline());
       
  1242     QVERIFY(cursor.charFormat().fontOverline());
       
  1243     QVERIFY(cursor.charFormat().fontStrikeOut());
       
  1244 }
       
  1245 
       
  1246 void tst_QTextDocumentFragment::html_infiniteLoop()
       
  1247 {
       
  1248     {
       
  1249         // used to cause an infinite loop due to the lack of a space after the
       
  1250         // tag name
       
  1251         const char html[] = "<ahref=\"argl\">Link</a>";
       
  1252         cursor.insertFragment(QTextDocumentFragment::fromHtml(html));
       
  1253         QVERIFY(true);
       
  1254     }
       
  1255 
       
  1256     {
       
  1257         const char html[] = "<a href=\"\"a<";
       
  1258         cursor.insertFragment(QTextDocumentFragment::fromHtml(html));
       
  1259         QVERIFY(true);
       
  1260     }
       
  1261 }
       
  1262 
       
  1263 void tst_QTextDocumentFragment::html_blockIndent()
       
  1264 {
       
  1265     const char html[] = "<p style=\"-qt-block-indent:3;\">Test</p>";
       
  1266     cursor.insertFragment(QTextDocumentFragment::fromHtml(html));
       
  1267     QCOMPARE(cursor.blockFormat().indent(), 3);
       
  1268 }
       
  1269 
       
  1270 void tst_QTextDocumentFragment::html_listIndent()
       
  1271 {
       
  1272     const char html[] = "<ul style=\"-qt-list-indent:4;\"><li>Blah</ul>";
       
  1273     cursor.insertFragment(QTextDocumentFragment::fromHtml(html));
       
  1274     QVERIFY(cursor.currentList());
       
  1275     QCOMPARE(cursor.currentList()->format().indent(), 4);
       
  1276 }
       
  1277 
       
  1278 void tst_QTextDocumentFragment::html_whitespace_data()
       
  1279 {
       
  1280     QTest::addColumn<QString>("html");
       
  1281     QTest::addColumn<QString>("expectedPlainText");
       
  1282 
       
  1283     QTest::newRow("1") << QString("<span>This is some test</span><span> with spaces between words</span>")
       
  1284                        << QString("This is some test with spaces between words");
       
  1285 
       
  1286     QTest::newRow("2") << QString("<span>  </span><span>nowhitespacehereplease</span>")
       
  1287                        << QString::fromLatin1("nowhitespacehereplease");
       
  1288 
       
  1289     QTest::newRow("3") << QString("<span style=\"white-space: pre;\">  white  space  here  </span>")
       
  1290                        << QString::fromLatin1("  white  space  here  ");
       
  1291 
       
  1292     QTest::newRow("4") << QString("<span style=\"white-space: pre-wrap;\">  white  space  here  </span>")
       
  1293                        << QString::fromLatin1("  white  space  here  ");
       
  1294 
       
  1295     QTest::newRow("5") << QString("<a href=\"One.html\">One</a> <a href=\"Two.html\">Two</a> <b>Three</b>\n"
       
  1296                                   "<b>Four</b>")
       
  1297                        << QString::fromLatin1("One Two Three Four");
       
  1298 
       
  1299     QTest::newRow("6") << QString("<p>Testing:     <b><i><u>BoldItalic</u></i></b> <i>Italic</i></p>")
       
  1300                        << QString("Testing: BoldItalic Italic");
       
  1301 
       
  1302     QTest::newRow("7") << QString("<table><tr><td>Blah</td></tr></table> <table border><tr><td>Foo</td></tr></table>")
       
  1303                        << QString("\nBlah\n\nFoo\n");
       
  1304 
       
  1305     QTest::newRow("8") << QString("<table><tr><td><i>Blah</i></td></tr></table> <i>Blub</i>")
       
  1306                        << QString("\nBlah\nBlub");
       
  1307 
       
  1308     QTest::newRow("task116492") << QString("<p>a<font=\"Times\"> b </font>c</p>")
       
  1309                                 << QString("a b c");
       
  1310 
       
  1311     QTest::newRow("task121653") << QString("abc<b> def</b>")
       
  1312                                 << QString("abc def");
       
  1313 
       
  1314     QTest::newRow("task122650") << QString("<p>Foo</p>    Bar")
       
  1315                                 << QString("Foo\nBar");
       
  1316 
       
  1317     QTest::newRow("task122650-2") << QString("<p>Foo</p>  <p>  Bar")
       
  1318                                   << QString("Foo \nBar");
       
  1319 
       
  1320     QTest::newRow("task122650-3") << QString("<html>Before<pre>\nTest</pre>")
       
  1321                                   << QString("Before\nTest");
       
  1322 
       
  1323     QTest::newRow("br-with-whitespace") << QString("Foo<br>\nBlah")
       
  1324                                         << QString("Foo\nBlah");
       
  1325 
       
  1326     QTest::newRow("collapse-p-with-newline") << QString("Foo<p>\n<p>\n<p>\n<p>\n<p>\n<p>\nBar")
       
  1327             << QString("Foo\nBar");
       
  1328 
       
  1329     QTest::newRow("table") << QString("<table><tr><td>Blah</td></tr></table>\nTest")
       
  1330                            << QString("\nBlah\nTest");
       
  1331 
       
  1332     QTest::newRow("table2") << QString("<table><tr><td><pre>\nTest\n</pre></td>\n </tr></table>")
       
  1333                             << QString("\nTest\n");
       
  1334 
       
  1335     QTest::newRow("table3") << QString("<table><tr><td><pre>\nTest\n</pre> \n \n </td></tr></table>")
       
  1336                             << QString("\nTest \n");
       
  1337 }
       
  1338 
       
  1339 void tst_QTextDocumentFragment::html_whitespace()
       
  1340 {
       
  1341     QFETCH(QString, html);
       
  1342     QFETCH(QString, expectedPlainText);
       
  1343 
       
  1344     setHtml(html);
       
  1345 
       
  1346     QCOMPARE(doc->toPlainText(), expectedPlainText);
       
  1347 }
       
  1348 
       
  1349 void tst_QTextDocumentFragment::html_qt3Whitespace()
       
  1350 {
       
  1351     QString text = "This     text       has         some   whitespace"
       
  1352                    "\n and \nnewlines that \n should be ignored\n\n";
       
  1353     const QString html = QString("<html><head><meta name=\"qrichtext\" content=\"1\" /></head><body>")
       
  1354                          + text
       
  1355                          + QString("</body></html>");
       
  1356 
       
  1357     cursor.insertFragment(QTextDocumentFragment::fromHtml(html));
       
  1358 
       
  1359     text.remove(QChar::fromLatin1('\n'));
       
  1360 
       
  1361     QCOMPARE(doc->toPlainText(), text);
       
  1362 }
       
  1363 
       
  1364 void tst_QTextDocumentFragment::html_qt3WhitespaceWithFragments()
       
  1365 {
       
  1366     QString text = "This     text       has         some   whitespace"
       
  1367                    "\n and \nnewlines that \n should be ignored\n\n";
       
  1368     const QString html = QString("<html><head><meta name=\"qrichtext\" content=\"1\" /></head><body>"
       
  1369                                  "blah blah<!--StartFragment--><span>")
       
  1370                          + text
       
  1371                          + QString("</span><!--EndFragment--></body></html>");
       
  1372 
       
  1373     cursor.insertFragment(QTextDocumentFragment::fromHtml(html));
       
  1374 
       
  1375     text.remove(QChar::fromLatin1('\n'));
       
  1376 
       
  1377     QCOMPARE(doc->toPlainText(), text);
       
  1378 }
       
  1379 
       
  1380 void tst_QTextDocumentFragment::html_qt3WhitespaceAfterTags()
       
  1381 {
       
  1382     QString text = "    This     text       has         some   whitespace   ";
       
  1383     const QString html = QString("<html><head><meta name=\"qrichtext\" content=\"1\" /></head><body><span>")
       
  1384                          + text
       
  1385                          + QString("</span></body></html>");
       
  1386 
       
  1387     cursor.insertFragment(QTextDocumentFragment::fromHtml(html));
       
  1388 
       
  1389     QCOMPARE(doc->toPlainText(), text);
       
  1390 }
       
  1391 
       
  1392 void tst_QTextDocumentFragment::html_listStart1()
       
  1393 {
       
  1394     // don't create a block for the <ul> element, even if there's some whitespace between
       
  1395     // it and the <li>
       
  1396     const char html[] = "<ul>        <li>list item</li><ul>";
       
  1397     cursor.insertFragment(QTextDocumentFragment::fromHtml(QByteArray::fromRawData(html, sizeof(html) / sizeof(html[0]))));
       
  1398 
       
  1399     QCOMPARE(doc->blockCount(), 1);
       
  1400 }
       
  1401 
       
  1402 void tst_QTextDocumentFragment::html_listStart2()
       
  1403 {
       
  1404     // unlike with html_listStart1 we want a block showing the 'buggy' text here
       
  1405     const char html[] = "<ul>buggy, but text should appear<li>list item</li><ul>";
       
  1406     cursor.insertFragment(QTextDocumentFragment::fromHtml(QByteArray::fromRawData(html, sizeof(html) / sizeof(html[0]))));
       
  1407 
       
  1408     QCOMPARE(doc->blockCount(), 2);
       
  1409 }
       
  1410 
       
  1411 void tst_QTextDocumentFragment::html_cssMargin()
       
  1412 {
       
  1413     const char html[] = "<p style=\"margin-top: 1px; margin-bottom: 2px; margin-left: 3px; margin-right: 4px\">Test</p>";
       
  1414     cursor.insertFragment(QTextDocumentFragment::fromHtml(html));
       
  1415     const QTextBlockFormat fmt = cursor.blockFormat();
       
  1416     QCOMPARE(fmt.topMargin(), qreal(1));
       
  1417     QCOMPARE(fmt.bottomMargin(), qreal(2));
       
  1418     QCOMPARE(fmt.leftMargin(), qreal(3));
       
  1419     QCOMPARE(fmt.rightMargin(), qreal(4));
       
  1420 }
       
  1421 
       
  1422 void tst_QTextDocumentFragment::html_hexEntities()
       
  1423 {
       
  1424     const char html[] = "&#x00040;";
       
  1425     cursor.insertFragment(QTextDocumentFragment::fromHtml(html));
       
  1426     QCOMPARE(doc->begin().begin().fragment().text(), QString("@"));
       
  1427 }
       
  1428 
       
  1429 void tst_QTextDocumentFragment::html_decEntities()
       
  1430 {
       
  1431     const char html[] = "&#64;";
       
  1432     cursor.insertFragment(QTextDocumentFragment::fromHtml(html));
       
  1433     QCOMPARE(doc->begin().begin().fragment().text(), QString("@"));
       
  1434 }
       
  1435 
       
  1436 void tst_QTextDocumentFragment::html_thCentered()
       
  1437 {
       
  1438     const char html[] = "<table><tr><th>This should be centered</th></tr></table>";
       
  1439     cursor.insertFragment(QTextDocumentFragment::fromHtml(html));
       
  1440 
       
  1441     cursor.movePosition(QTextCursor::PreviousBlock);
       
  1442     QTextTable *table = cursor.currentTable();
       
  1443     QVERIFY(table);
       
  1444 
       
  1445     QVERIFY(table->cellAt(0, 0).begin().currentBlock().blockFormat().alignment() == Qt::AlignCenter);
       
  1446 }
       
  1447 
       
  1448 void tst_QTextDocumentFragment::orderedListNumbering()
       
  1449 {
       
  1450     // Supporter issue 45941 - make sure _two_ separate lists
       
  1451     // are imported, which have their own numbering
       
  1452     const char html[] = "<html><body>"
       
  1453                         "<ol><li>elem 1</li></ol>"
       
  1454                         "<ol><li>elem 1</li></ol>"
       
  1455                         "</body></html>";
       
  1456 
       
  1457     cursor.insertFragment(QTextDocumentFragment::fromHtml(html));
       
  1458 
       
  1459     int numberOfLists = 0;
       
  1460 
       
  1461     cursor.movePosition(QTextCursor::Start);
       
  1462     QTextList *lastList = 0;
       
  1463     do {
       
  1464         QTextList *list = cursor.currentList();
       
  1465         if (list && list != lastList) {
       
  1466             lastList = list;
       
  1467             ++numberOfLists;
       
  1468         }
       
  1469     } while (cursor.movePosition(QTextCursor::NextBlock));
       
  1470 
       
  1471     QCOMPARE(numberOfLists, 2);
       
  1472 }
       
  1473 
       
  1474 void tst_QTextDocumentFragment::html_blockAfterList()
       
  1475 {
       
  1476     const char html[] = "<ul><li>Foo</ul>This should be a separate paragraph and not be indented at the same level as Foo";
       
  1477     cursor.insertFragment(QTextDocumentFragment::fromHtml(html));
       
  1478 
       
  1479     cursor.movePosition(QTextCursor::Start);
       
  1480 
       
  1481     QVERIFY(cursor.currentList());
       
  1482     QCOMPARE(cursor.currentList()->format().indent(), 1);
       
  1483 
       
  1484     QVERIFY(cursor.movePosition(QTextCursor::NextBlock));
       
  1485     QVERIFY(!cursor.currentList());
       
  1486     QCOMPARE(cursor.blockFormat().indent(), 0);
       
  1487 }
       
  1488 
       
  1489 void tst_QTextDocumentFragment::html_subAndSuperScript()
       
  1490 {
       
  1491     const char subHtml[] = "<sub>Subby</sub>";
       
  1492     const char superHtml[] = "<sup>Super</sup>";
       
  1493     const char subHtmlCss[] = "<span style=\"vertical-align: sub\">Subby</span>";
       
  1494     const char superHtmlCss[] = "<span style=\"vertical-align: super\">Super</span>";
       
  1495     const char alignmentInherited[] = "<sub><font face=\"Verdana\">Subby</font></sub>";
       
  1496 
       
  1497     setHtml(subHtml);
       
  1498     QVERIFY(cursor.charFormat().verticalAlignment() == QTextCharFormat::AlignSubScript);
       
  1499 
       
  1500     setHtml(subHtmlCss);
       
  1501     QVERIFY(cursor.charFormat().verticalAlignment() == QTextCharFormat::AlignSubScript);
       
  1502 
       
  1503     setHtml(superHtml);
       
  1504     QVERIFY(cursor.charFormat().verticalAlignment() == QTextCharFormat::AlignSuperScript);
       
  1505 
       
  1506     setHtml(superHtmlCss);
       
  1507     QVERIFY(cursor.charFormat().verticalAlignment() == QTextCharFormat::AlignSuperScript);
       
  1508 
       
  1509     setHtml(alignmentInherited);
       
  1510     QVERIFY(cursor.charFormat().verticalAlignment() == QTextCharFormat::AlignSubScript);
       
  1511 }
       
  1512 
       
  1513 void tst_QTextDocumentFragment::html_cssColors()
       
  1514 {
       
  1515     const char color[] = "<span style=\"color:red\"><span style=\"color:blue\">Blue</span></span>";
       
  1516     setHtml(color);
       
  1517     QVERIFY(cursor.charFormat().foreground().color() == Qt::blue);
       
  1518 
       
  1519     const char rgbColor[] = "<span style=\"color:red\"><span style=\"color:rgb(0, 0, 255)\">Blue</span></span>";
       
  1520     setHtml(rgbColor);
       
  1521     QVERIFY(cursor.charFormat().foreground().color() == Qt::blue);
       
  1522 }
       
  1523 
       
  1524 void tst_QTextDocumentFragment::obeyFragmentMarkersInImport()
       
  1525 {
       
  1526     const char html[] = "This leading text should not appear<!--StartFragment--><span>Text</span><!--EndFragment-->This text at the end should not appear";
       
  1527     setHtml(html);
       
  1528 
       
  1529     QCOMPARE(doc->toPlainText(), QString("Text"));
       
  1530 }
       
  1531 
       
  1532 void tst_QTextDocumentFragment::whitespaceWithFragmentMarkers()
       
  1533 {
       
  1534     QString text("    text with leading and trailing whitespace    ");
       
  1535     const char html[] = "This leading text should not appear<!--StartFragment-->%1<!--EndFragment-->This text at the end should not appear";
       
  1536     setHtml(QString::fromLatin1(html).arg(text));
       
  1537 
       
  1538     QString expected("text with leading and trailing whitespace ");
       
  1539     QCOMPARE(doc->toPlainText(), expected);
       
  1540 }
       
  1541 
       
  1542 void tst_QTextDocumentFragment::html_emptyParapgraphs1()
       
  1543 {
       
  1544     const char html[] = "<p style=\"-qt-paragraph-type:empty;\">&nbsp;</p><p>Two paragraphs</p>";
       
  1545     setHtml(html);
       
  1546 
       
  1547     QCOMPARE(doc->blockCount(), 2);
       
  1548     QVERIFY(doc->begin().text().isEmpty());
       
  1549     QCOMPARE(doc->begin().next().text(), QString("Two paragraphs"));
       
  1550 }
       
  1551 
       
  1552 void tst_QTextDocumentFragment::html_emptyParapgraphs2()
       
  1553 {
       
  1554     const char html[] = "<p style=\"margin-left:80px\"></p><p>One paragraph</p>";
       
  1555     setHtml(html);
       
  1556 
       
  1557     QCOMPARE(doc->blockCount(), 1);
       
  1558     QCOMPARE(cursor.blockFormat().leftMargin(), qreal(0));
       
  1559 
       
  1560     const char html2[] = "<p style=\"margin-left:80px\"></p>One paragraph";
       
  1561     setHtml(html2);
       
  1562     QCOMPARE(doc->blockCount(), 1);
       
  1563     QCOMPARE(cursor.blockFormat().leftMargin(), qreal(0));
       
  1564 
       
  1565     const char html3[] = "<p style=\"margin-left:80px\">Foo</p><p></p>Two paragraphs";
       
  1566     setHtml(html3);
       
  1567     QCOMPARE(doc->blockCount(), 2);
       
  1568     cursor = QTextCursor(doc);
       
  1569     QCOMPARE(cursor.blockFormat().leftMargin(), qreal(80));
       
  1570     QCOMPARE(cursor.block().next().blockFormat().leftMargin(), qreal(0));
       
  1571 }
       
  1572 
       
  1573 void tst_QTextDocumentFragment::html_emptyParagraphs3()
       
  1574 {
       
  1575     const char html[] = "<ul><p>Foo</p><p></p></ul><h4>Bar</h4>";
       
  1576 
       
  1577     setHtml(html);
       
  1578 
       
  1579     QCOMPARE(doc->blockCount(), 2);
       
  1580 
       
  1581     cursor = QTextCursor(doc);
       
  1582     QCOMPARE(cursor.block().next().blockFormat().indent(), 0);
       
  1583 }
       
  1584 
       
  1585 void tst_QTextDocumentFragment::html_emptyParagraphs4()
       
  1586 {
       
  1587     const char html[] = "<p>foo</p><p style=\"page-break-before: always\"></p><p>bar</p>";
       
  1588     setHtml(html);
       
  1589 
       
  1590     QTextBlock block = doc->begin();
       
  1591     QVERIFY(block.isValid());
       
  1592     QCOMPARE(block.text(), QString("foo"));
       
  1593     block = block.next();
       
  1594     QVERIFY(block.isValid());
       
  1595     QTextBlockFormat bf = block.blockFormat();
       
  1596     QVERIFY(bf.hasProperty(QTextFormat::PageBreakPolicy));
       
  1597     QCOMPARE(bf.pageBreakPolicy(), QTextFormat::PageBreak_AlwaysBefore);
       
  1598     QCOMPARE(block.text(), QString("bar"));
       
  1599 
       
  1600     const char html2[] = "<p>foo</p><p style=\"page-break-after: always\"></p><p>bar</p>";
       
  1601     setHtml(html2);
       
  1602 
       
  1603     block = doc->begin();
       
  1604     QVERIFY(block.isValid());
       
  1605     QCOMPARE(block.text(), QString("foo"));
       
  1606     block = block.next();
       
  1607     QVERIFY(block.isValid());
       
  1608     bf = block.blockFormat();
       
  1609     QVERIFY(bf.hasProperty(QTextFormat::PageBreakPolicy));
       
  1610     QCOMPARE(bf.pageBreakPolicy(), QTextFormat::PageBreak_AlwaysBefore); // after the empty line means it should appear for 'bar'
       
  1611     QCOMPARE(block.text(), QString("bar"));
       
  1612 }
       
  1613 
       
  1614 void tst_QTextDocumentFragment::html_font()
       
  1615 {
       
  1616     const char html[] = "<font color=\"blue\"><p>Hah</p></font>";
       
  1617     setHtml(html);
       
  1618 
       
  1619     QVERIFY(cursor.charFormat().foreground().color() == Qt::blue);
       
  1620     QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::blue);
       
  1621 }
       
  1622 
       
  1623 void tst_QTextDocumentFragment::html_fontSize()
       
  1624 {
       
  1625     const char html[] = "<font size=\"2\">Hah</font>";
       
  1626     setHtml(html);
       
  1627 
       
  1628     QCOMPARE(cursor.charFormat().property(QTextFormat::FontSizeAdjustment).toInt(), -1);
       
  1629 }
       
  1630 
       
  1631 void tst_QTextDocumentFragment::html_fontSizeAdjustment()
       
  1632 {
       
  1633     const char html[] = "<font size=\"7\"><b>Hah</b></font>";
       
  1634     setHtml(html);
       
  1635 
       
  1636     QCOMPARE(cursor.charFormat().property(QTextFormat::FontSizeAdjustment).toInt(), 4);
       
  1637     QCOMPARE(cursor.charFormat().fontWeight(), int(QFont::Bold));
       
  1638 }
       
  1639 
       
  1640 void tst_QTextDocumentFragment::html_cssFontSize()
       
  1641 {
       
  1642     const char html[] = "<span style=\"font-size: 50pt\">Foo</span>";
       
  1643     setHtml(html);
       
  1644 
       
  1645     QCOMPARE(cursor.charFormat().property(QTextFormat::FontPointSize).toInt(), 50);
       
  1646 
       
  1647     const char html2[] = "<span style=\"font-size: 50px\">Foo</span>";
       
  1648     setHtml(html2);
       
  1649 
       
  1650     QCOMPARE(cursor.charFormat().property(QTextFormat::FontPixelSize).toInt(), 50);
       
  1651 
       
  1652     const char html3[] = "<span style=\"font-size: large\">Foo</span>";
       
  1653     setHtml(html3);
       
  1654 
       
  1655     QCOMPARE(cursor.charFormat().property(QTextFormat::FontSizeAdjustment).toInt(), 1);
       
  1656 }
       
  1657 
       
  1658 void tst_QTextDocumentFragment::html_cssShorthandFont()
       
  1659 {
       
  1660     {
       
  1661         const char html[] = "<span style=\"font: 50px sans-serif\">Foo</span>";
       
  1662         setHtml(html);
       
  1663         QCOMPARE(cursor.charFormat().property(QTextFormat::FontPixelSize).toInt(), 50);
       
  1664         QCOMPARE(cursor.charFormat().property(QTextFormat::FontFamily).toString(), QString("sans-serif"));
       
  1665     }
       
  1666     {
       
  1667         const char html[] = "<span style=\"font: 50pt sans-serif\">Foo</span>";
       
  1668         setHtml(html);
       
  1669         QCOMPARE(cursor.charFormat().property(QTextFormat::FontPointSize).toInt(), 50);
       
  1670         QCOMPARE(cursor.charFormat().property(QTextFormat::FontFamily).toString(), QString("sans-serif"));
       
  1671     }
       
  1672     {
       
  1673         const char html[] = "<span style='font:7.0pt \"Times New Roman\"'>Foo</span>";
       
  1674         setHtml(html);
       
  1675         QCOMPARE(cursor.charFormat().property(QTextFormat::FontPointSize).toInt(), 7);
       
  1676         QCOMPARE(cursor.charFormat().property(QTextFormat::FontFamily).toString(), QString("Times New Roman"));
       
  1677     }
       
  1678     {
       
  1679         const char html[] = "<span style='font:bold 7.0pt'>Foo</span>";
       
  1680         setHtml(html);
       
  1681         QCOMPARE(cursor.charFormat().property(QTextFormat::FontWeight).toInt(), int(QFont::Bold));
       
  1682         QCOMPARE(cursor.charFormat().property(QTextFormat::FontPointSize).toInt(), 7);
       
  1683     }
       
  1684     {
       
  1685         const char html[] = "<span style='font:bold italic 7.0pt'>Foo</span>";
       
  1686         setHtml(html);
       
  1687         QCOMPARE(cursor.charFormat().property(QTextFormat::FontWeight).toInt(), int(QFont::Bold));
       
  1688         QCOMPARE(cursor.charFormat().property(QTextFormat::FontItalic).toBool(), true);
       
  1689     }
       
  1690 }
       
  1691 
       
  1692 void tst_QTextDocumentFragment::html_bodyBgColor()
       
  1693 {
       
  1694     const char html[] = "<body bgcolor=\"blue\">Foo</body>";
       
  1695     doc->setHtml(html);
       
  1696 
       
  1697     QVERIFY(doc->rootFrame()->frameFormat().background().color() == Qt::blue);
       
  1698 }
       
  1699 
       
  1700 void tst_QTextDocumentFragment::html_qtBgColor()
       
  1701 {
       
  1702     const char html[] = "<qt bgcolor=\"blue\">Foo</qt>";
       
  1703     doc->setHtml(html);
       
  1704 
       
  1705     QVERIFY(doc->rootFrame()->frameFormat().background().color() == Qt::blue);
       
  1706 }
       
  1707 
       
  1708 void tst_QTextDocumentFragment::html_bodyBackground()
       
  1709 {
       
  1710     const char html[] = "<body background=\"foo.png\">Foo</body>";
       
  1711     doc->setHtml(html);
       
  1712 
       
  1713     QVERIFY(doc->rootFrame()->frameFormat().background().style() == Qt::TexturePattern);
       
  1714 }
       
  1715 
       
  1716 void tst_QTextDocumentFragment::html_tableCellBackground()
       
  1717 {
       
  1718     const char html[] = "<body><table><tr><td background=\"foo.png\">Foo</td></tr></table></body>";
       
  1719     doc->setHtml(html);
       
  1720 
       
  1721     cursor.movePosition(QTextCursor::Start);
       
  1722     cursor.movePosition(QTextCursor::NextBlock);
       
  1723     QTextTable *table = cursor.currentTable();
       
  1724     QVERIFY(table);
       
  1725 
       
  1726     QTextTableCell cell = table->cellAt(0, 0);
       
  1727     QVERIFY(cell.format().background().style() == Qt::TexturePattern);
       
  1728 }
       
  1729 
       
  1730 void tst_QTextDocumentFragment::css_bodyBackground()
       
  1731 {
       
  1732     const char html[] = "<body style=\"background-image:url('foo.png')\">Foo</body>";
       
  1733     doc->setHtml(html);
       
  1734 
       
  1735     QVERIFY(doc->rootFrame()->frameFormat().background().style() == Qt::TexturePattern);
       
  1736 }
       
  1737 
       
  1738 void tst_QTextDocumentFragment::css_tableCellBackground()
       
  1739 {
       
  1740     const char html[] = "<body><table><tr><td style=\"background-image:url('foo.png')\">Foo</td></tr></table></body>";
       
  1741     doc->setHtml(html);
       
  1742 
       
  1743     cursor.movePosition(QTextCursor::Start);
       
  1744     cursor.movePosition(QTextCursor::NextBlock);
       
  1745     QTextTable *table = cursor.currentTable();
       
  1746     QVERIFY(table);
       
  1747 
       
  1748     QTextTableCell cell = table->cellAt(0, 0);
       
  1749     QVERIFY(cell.format().background().style() == Qt::TexturePattern);
       
  1750 }
       
  1751 
       
  1752 void tst_QTextDocumentFragment::css_cellPaddings()
       
  1753 {
       
  1754     const char html[] = "<body><table><tr><td style=\"padding-left:1\">Foo</td>"
       
  1755                         "<td style=\"padding-right:1\"></td><td style=\"padding-top:10\"></td>"
       
  1756                         "<td style=\"padding-bottom:5\"></td><td style=\"padding:15\"></td></tr></table></body>";
       
  1757     doc->setHtml(html);
       
  1758 
       
  1759     cursor.movePosition(QTextCursor::Start);
       
  1760     cursor.movePosition(QTextCursor::NextBlock);
       
  1761     QTextTable *table = cursor.currentTable();
       
  1762     QVERIFY(table);
       
  1763 
       
  1764     QTextTableCell cell = table->cellAt(0, 0);
       
  1765     QCOMPARE(cell.format().toTableCellFormat().leftPadding(), qreal(1));
       
  1766     cell = table->cellAt(0, 1);
       
  1767     QCOMPARE(cell.format().toTableCellFormat().rightPadding(), qreal(1));
       
  1768     cell = table->cellAt(0, 2);
       
  1769     QCOMPARE(cell.format().toTableCellFormat().topPadding(), qreal(10));
       
  1770     cell = table->cellAt(0, 3);
       
  1771     QCOMPARE(cell.format().toTableCellFormat().bottomPadding(), qreal(5));
       
  1772     cell = table->cellAt(0, 4);
       
  1773     QCOMPARE(cell.format().toTableCellFormat().leftPadding(), qreal(15));
       
  1774     QCOMPARE(cell.format().toTableCellFormat().rightPadding(), qreal(15));
       
  1775     QCOMPARE(cell.format().toTableCellFormat().topPadding(), qreal(15));
       
  1776     QCOMPARE(cell.format().toTableCellFormat().bottomPadding(), qreal(15));
       
  1777 }
       
  1778 
       
  1779 void tst_QTextDocumentFragment::html_blockLevelDiv()
       
  1780 {
       
  1781     const char html[] = "<div align=right><b>Hello World";
       
  1782     setHtml(html);
       
  1783 
       
  1784     QCOMPARE(doc->begin().blockFormat().alignment(), Qt::AlignRight|Qt::AlignAbsolute);
       
  1785     QVERIFY(doc->begin().next() == doc->end());
       
  1786 }
       
  1787 
       
  1788 void tst_QTextDocumentFragment::html_spanNesting()
       
  1789 {
       
  1790     const char html[] = "<span style=\"color:black\">a<span style=\"color:red\">b<span style=\"color:black\">c</span></span>d</span>";
       
  1791     setHtml(html);
       
  1792 
       
  1793     cursor.movePosition(QTextCursor::Start);
       
  1794     cursor.movePosition(QTextCursor::NextCharacter);
       
  1795     QVERIFY(cursor.charFormat().foreground() == Qt::black);
       
  1796     cursor.movePosition(QTextCursor::NextCharacter);
       
  1797     QVERIFY(cursor.charFormat().foreground() == Qt::red);
       
  1798     cursor.movePosition(QTextCursor::NextCharacter);
       
  1799     QVERIFY(cursor.charFormat().foreground() == Qt::black);
       
  1800     cursor.movePosition(QTextCursor::NextCharacter);
       
  1801     QVERIFY(cursor.charFormat().foreground() == Qt::black);
       
  1802 }
       
  1803 
       
  1804 void tst_QTextDocumentFragment::html_nestedLists()
       
  1805 {
       
  1806     const char html[] = "<p><ul><li>Foo<ul><li>In nested list</li></ul></li><li>Last item</li></ul></p>";
       
  1807     setHtml(html);
       
  1808 
       
  1809     cursor.movePosition(QTextCursor::Start);
       
  1810     QTextList *firstList = cursor.currentList();
       
  1811     QVERIFY(firstList);
       
  1812     QCOMPARE(firstList->format().indent(), 1);
       
  1813 
       
  1814     cursor.movePosition(QTextCursor::NextBlock);
       
  1815     QTextList *secondList = cursor.currentList();
       
  1816     QVERIFY(secondList);
       
  1817     QVERIFY(secondList != firstList);
       
  1818     QCOMPARE(cursor.currentList()->format().indent(), 2);
       
  1819 
       
  1820     cursor.movePosition(QTextCursor::NextBlock);
       
  1821     QTextList *thirdList = cursor.currentList();
       
  1822     QVERIFY(thirdList);
       
  1823     QVERIFY(thirdList == firstList);
       
  1824 }
       
  1825 
       
  1826 void tst_QTextDocumentFragment::noSpecialCharactersInPlainText()
       
  1827 {
       
  1828     cursor.insertTable(2, 2);
       
  1829     cursor.insertBlock();
       
  1830     cursor.insertText(QString(QChar::LineSeparator));
       
  1831     cursor.insertText(QString(QChar::Nbsp));
       
  1832 
       
  1833     QString plain = doc->toPlainText();
       
  1834     QVERIFY(!plain.contains(QChar::ParagraphSeparator));
       
  1835     QVERIFY(!plain.contains(QChar::Nbsp));
       
  1836     QVERIFY(!plain.contains(QTextBeginningOfFrame));
       
  1837     QVERIFY(!plain.contains(QTextEndOfFrame));
       
  1838     QVERIFY(!plain.contains(QChar::LineSeparator));
       
  1839 
       
  1840     plain = QTextDocumentFragment(doc).toPlainText();
       
  1841     QVERIFY(!plain.contains(QChar::ParagraphSeparator));
       
  1842     QVERIFY(!plain.contains(QChar::Nbsp));
       
  1843     QVERIFY(!plain.contains(QTextBeginningOfFrame));
       
  1844     QVERIFY(!plain.contains(QTextEndOfFrame));
       
  1845     QVERIFY(!plain.contains(QChar::LineSeparator));
       
  1846 }
       
  1847 
       
  1848 void tst_QTextDocumentFragment::html_doNotInheritBackground()
       
  1849 {
       
  1850     const char html[] = "<html><body bgcolor=\"blue\"><p>Blah</p></body></html>";
       
  1851     doc->setHtml(html);
       
  1852 
       
  1853     for (QTextBlock block = doc->begin();
       
  1854          block.isValid(); block = block.next()) {
       
  1855         QVERIFY(block.blockFormat().hasProperty(QTextFormat::BackgroundBrush) == false);
       
  1856     }
       
  1857 
       
  1858     QVERIFY(doc->rootFrame()->frameFormat().hasProperty(QTextFormat::BackgroundBrush));
       
  1859     QVERIFY(doc->rootFrame()->frameFormat().background().color() == Qt::blue);
       
  1860 }
       
  1861 
       
  1862 void tst_QTextDocumentFragment::html_inheritBackgroundToInlineElements()
       
  1863 {
       
  1864     const char html[] = "<span style=\"background: blue\">Foo<span>Bar</span></span>";
       
  1865     doc->setHtml(html);
       
  1866 
       
  1867     int fragmentCount = 0;
       
  1868 
       
  1869     QTextBlock block = doc->begin();
       
  1870     for (QTextBlock::Iterator it = block.begin();
       
  1871          !it.atEnd(); ++it, ++fragmentCount) {
       
  1872 
       
  1873         const QTextFragment fragment = it.fragment();
       
  1874         if (fragmentCount == 0) {
       
  1875             QCOMPARE(fragment.text(), QString("FooBar"));
       
  1876             QVERIFY(fragment.charFormat().background().color() == Qt::blue);
       
  1877         }
       
  1878     }
       
  1879 
       
  1880     QCOMPARE(fragmentCount, 1);
       
  1881 }
       
  1882 
       
  1883 void tst_QTextDocumentFragment::html_doNotInheritBackgroundFromBlockElements()
       
  1884 {
       
  1885     const char html[] = "<p style=\"background: blue\"><span>Foo</span></span>";
       
  1886     doc->setHtml(html);
       
  1887 
       
  1888     int fragmentCount = 0;
       
  1889 
       
  1890     QTextBlock block = doc->begin();
       
  1891     for (QTextBlock::Iterator it = block.begin();
       
  1892          !it.atEnd(); ++it, ++fragmentCount) {
       
  1893 
       
  1894         const QTextFragment fragment = it.fragment();
       
  1895         if (fragmentCount == 0) {
       
  1896             QCOMPARE(fragment.text(), QString("Foo"));
       
  1897             QVERIFY(!fragment.charFormat().hasProperty(QTextFormat::BackgroundBrush));
       
  1898         }
       
  1899     }
       
  1900 
       
  1901     QCOMPARE(fragmentCount, 1);
       
  1902 }
       
  1903 void tst_QTextDocumentFragment::html_nobr()
       
  1904 {
       
  1905     const QString input = "Blah Foo    Bar";
       
  1906     const QString html = QString::fromLatin1("<html><body><p><nobr>") + input + QString::fromLatin1("</nobr></p></body></html>");
       
  1907     setHtml(html);
       
  1908 
       
  1909     QString text = doc->begin().begin().fragment().text();
       
  1910     QString expectedText = input;
       
  1911     expectedText.replace(QRegExp("\\s+"), QString(QChar::Nbsp));
       
  1912     QCOMPARE(text, expectedText);
       
  1913 }
       
  1914 
       
  1915 void tst_QTextDocumentFragment::fromPlainText()
       
  1916 {
       
  1917     QString plainText;
       
  1918     plainText = "Hello\nWorld\r\nBlub";
       
  1919     plainText += QChar::ParagraphSeparator;
       
  1920     // TextEdit on OS 10 gives us OS 9 style linefeeds
       
  1921     // when copy & pasteing multi-line plaintext.
       
  1922     plainText += "OS9IsOldSchool\r";
       
  1923     plainText += "Last Parag";
       
  1924 
       
  1925     doc->setPlainText(plainText);
       
  1926 
       
  1927     int blockCount = 0;
       
  1928     for (QTextBlock block = doc->begin(); block.isValid(); block = block.next()) {
       
  1929         QVERIFY(!block.text().contains(QLatin1Char('\n')));
       
  1930         QVERIFY(!block.text().contains(QLatin1Char('\r')));
       
  1931         QVERIFY(!block.text().contains(QChar::ParagraphSeparator));
       
  1932 
       
  1933         if (blockCount == 0)
       
  1934             QCOMPARE(block.text(), QString("Hello"));
       
  1935         else if (blockCount == 1)
       
  1936             QCOMPARE(block.text(), QString("World"));
       
  1937         else if (blockCount == 2)
       
  1938             QCOMPARE(block.text(), QString("Blub"));
       
  1939         else if (blockCount == 3)
       
  1940             QCOMPARE(block.text(), QString("OS9IsOldSchool"));
       
  1941         else if (blockCount == 4)
       
  1942             QCOMPARE(block.text(), QString("Last Parag"));
       
  1943 
       
  1944 
       
  1945         ++blockCount;
       
  1946     }
       
  1947 
       
  1948     QCOMPARE(blockCount, 5);
       
  1949 }
       
  1950 
       
  1951 void tst_QTextDocumentFragment::fromPlainText2()
       
  1952 {
       
  1953     doc->setPlainText("Hello World");
       
  1954     QCOMPARE(QTextDocumentFragment(doc).toPlainText(), doc->toPlainText());
       
  1955 }
       
  1956 
       
  1957 void tst_QTextDocumentFragment::html_closingImageTag()
       
  1958 {
       
  1959     const char html[] = "<span style=\"font-size: 10pt\"><span style=\"font-size: 40pt\">Blah<img src=\"blah\"></img>Foo</span></span>";
       
  1960     setHtml(html);
       
  1961 
       
  1962     int fragmentCount = 0;
       
  1963 
       
  1964     QTextBlock block = doc->begin();
       
  1965     for (QTextBlock::Iterator it = block.begin();
       
  1966          !it.atEnd(); ++it, ++fragmentCount) {
       
  1967 
       
  1968         const QTextFragment fragment = it.fragment();
       
  1969         if (fragmentCount == 0) {
       
  1970             QCOMPARE(fragment.text(), QString("Blah"));
       
  1971             QCOMPARE(fragment.charFormat().fontPointSize(), qreal(40));
       
  1972         } else if (fragmentCount == 1) {
       
  1973             QCOMPARE(fragment.text(), QString(QChar::ObjectReplacementCharacter));
       
  1974         } else if (fragmentCount == 2) {
       
  1975             QCOMPARE(fragment.text(), QString("Foo"));
       
  1976             QCOMPARE(fragment.charFormat().fontPointSize(), qreal(40));
       
  1977         }
       
  1978     }
       
  1979 
       
  1980     QCOMPARE(fragmentCount, 3);
       
  1981 }
       
  1982 
       
  1983 void tst_QTextDocumentFragment::html_emptyDocument()
       
  1984 {
       
  1985     const char html[] = "<html><body><p style=\"-qt-paragraph-type:empty;\"></p></body></html>";
       
  1986     setHtml(html);
       
  1987     QCOMPARE(doc->blockCount(), 1);
       
  1988 }
       
  1989 
       
  1990 void tst_QTextDocumentFragment::html_closingTag()
       
  1991 {
       
  1992     const char html[] = "<i />text";
       
  1993     setHtml(html);
       
  1994 
       
  1995     QVERIFY(!cursor.charFormat().fontItalic());
       
  1996 }
       
  1997 
       
  1998 void tst_QTextDocumentFragment::html_anchorAroundImage()
       
  1999 {
       
  2000     const char html[] = "<a href=\"http://www.troll.no\"><img src=test.png></a>";
       
  2001     setHtml(html);
       
  2002 
       
  2003     cursor.movePosition(QTextCursor::Start);
       
  2004     cursor.movePosition(QTextCursor::NextCharacter);
       
  2005     QTextImageFormat fmt = cursor.charFormat().toImageFormat();
       
  2006     QCOMPARE(fmt.name(), QString("test.png"));
       
  2007     QVERIFY(fmt.isAnchor());
       
  2008     QCOMPARE(fmt.anchorHref(), QString("http://www.troll.no"));
       
  2009 }
       
  2010 
       
  2011 void tst_QTextDocumentFragment::html_floatBorder()
       
  2012 {
       
  2013     const char html[] = "<table border=1.2><tr><td>Foo";
       
  2014     cursor.insertFragment(QTextDocumentFragment::fromHtml(QString::fromLatin1(html)));
       
  2015     cursor.movePosition(QTextCursor::Start);
       
  2016     cursor.movePosition(QTextCursor::NextBlock);
       
  2017     QVERIFY(cursor.currentTable());
       
  2018     QCOMPARE(cursor.currentTable()->format().border(), qreal(1.2));
       
  2019 }
       
  2020 
       
  2021 void tst_QTextDocumentFragment::html_frameImport()
       
  2022 {
       
  2023     QTextFrameFormat ffmt;
       
  2024     ffmt.setBorder(1);
       
  2025     ffmt.setPosition(QTextFrameFormat::FloatRight);
       
  2026     ffmt.setMargin(2);
       
  2027     ffmt.setWidth(100);
       
  2028     ffmt.setHeight(50);
       
  2029     ffmt.setBackground(QColor("#00ff00"));
       
  2030     cursor.insertFrame(ffmt);
       
  2031     cursor.insertText("Hello World");
       
  2032 
       
  2033     QTextDocumentFragment frag(doc);
       
  2034     cleanup();
       
  2035     init();
       
  2036     frag = QTextDocumentFragment::fromHtml(frag.toHtml());
       
  2037     cursor.insertFragment(frag);
       
  2038 
       
  2039     QList<QTextFrame *> childFrames = doc->rootFrame()->childFrames();
       
  2040     QVERIFY(childFrames.count() == 1);
       
  2041     QTextFrame *frame = childFrames.first();
       
  2042     QCOMPARE(frame->frameFormat().margin(), ffmt.margin());
       
  2043     QCOMPARE(frame->frameFormat().border(), ffmt.border());
       
  2044 }
       
  2045 
       
  2046 void tst_QTextDocumentFragment::html_frameImport2()
       
  2047 {
       
  2048     QTextFrameFormat ffmt;
       
  2049     ffmt.setBorder(1);
       
  2050     ffmt.setPosition(QTextFrameFormat::FloatRight);
       
  2051     ffmt.setLeftMargin(200);
       
  2052     ffmt.setTopMargin(100);
       
  2053     ffmt.setBottomMargin(50);
       
  2054     ffmt.setRightMargin(250);
       
  2055     ffmt.setWidth(100);
       
  2056     ffmt.setHeight(50);
       
  2057     ffmt.setBackground(QColor("#00ff00"));
       
  2058     cursor.insertFrame(ffmt);
       
  2059     cursor.insertText("Hello World");
       
  2060 
       
  2061     QTextDocumentFragment frag(doc);
       
  2062     cleanup();
       
  2063     init();
       
  2064     frag = QTextDocumentFragment::fromHtml(frag.toHtml());
       
  2065     cursor.insertFragment(frag);
       
  2066 
       
  2067     QList<QTextFrame *> childFrames = doc->rootFrame()->childFrames();
       
  2068     QVERIFY(childFrames.count() == 1);
       
  2069     QTextFrame *frame = childFrames.first();
       
  2070     QCOMPARE(frame->frameFormat().topMargin(), ffmt.topMargin());
       
  2071     QCOMPARE(frame->frameFormat().bottomMargin(), ffmt.bottomMargin());
       
  2072     QCOMPARE(frame->frameFormat().leftMargin(), ffmt.leftMargin());
       
  2073     QCOMPARE(frame->frameFormat().rightMargin(), ffmt.rightMargin());
       
  2074     QCOMPARE(frame->frameFormat().border(), ffmt.border());
       
  2075 }
       
  2076 
       
  2077 void tst_QTextDocumentFragment::html_dontAddMarginsAcrossTableCells()
       
  2078 {
       
  2079     const char html[] = "<table style=\"margin-left: 100px;\"><tr><td><p style=\"margin-left:50px;\">Foo</p></td></tr></table>";
       
  2080     cursor.insertFragment(QTextDocumentFragment::fromHtml(QString::fromLatin1(html)));
       
  2081 
       
  2082     QList<QTextFrame *> childFrames = doc->rootFrame()->childFrames();
       
  2083     QVERIFY(childFrames.count() == 1);
       
  2084     QTextFrame *frame = childFrames.first();
       
  2085     cursor = frame->firstCursorPosition();
       
  2086     QCOMPARE(cursor.blockFormat().leftMargin(), qreal(50.0));
       
  2087 }
       
  2088 
       
  2089 void tst_QTextDocumentFragment::html_dontMergeCenterBlocks()
       
  2090 {
       
  2091     const char html[] = "<center>This should be centered</center>And this should not be centered anymore";
       
  2092     cursor.insertFragment(QTextDocumentFragment::fromHtml(QString::fromLatin1(html)));
       
  2093 
       
  2094     QCOMPARE(doc->blockCount(), 2);
       
  2095     QTextBlock blk = doc->begin();
       
  2096     QVERIFY(blk.blockFormat().alignment() == Qt::AlignCenter);
       
  2097     blk = blk.next();
       
  2098     QVERIFY(blk.blockFormat().alignment() != Qt::AlignCenter);
       
  2099 }
       
  2100 
       
  2101 void tst_QTextDocumentFragment::html_tableCellBgColor()
       
  2102 {
       
  2103     const char html[] = "<table><tr><td bgcolor=\"blue\">Test<p>Second Parag</p></td></tr></table>";
       
  2104     cursor.insertFragment(QTextDocumentFragment::fromHtml(QString::fromLatin1(html)));
       
  2105 
       
  2106     cursor.movePosition(QTextCursor::Start);
       
  2107     cursor.movePosition(QTextCursor::NextBlock);
       
  2108     QTextTable *table = cursor.currentTable();
       
  2109     QVERIFY(table);
       
  2110 
       
  2111     QTextTableCell cell = table->cellAt(0, 0);
       
  2112     QVERIFY(cell.format().background().color() == Qt::blue);
       
  2113 }
       
  2114 
       
  2115 void tst_QTextDocumentFragment::html_tableCellBgColor2()
       
  2116 {
       
  2117     const char html[] = "<table><tr><td bgcolor=\"blue\"><table><tr><td>Blah</td></tr></table></td></tr></table>";
       
  2118     cursor.insertFragment(QTextDocumentFragment::fromHtml(QString::fromLatin1(html)));
       
  2119 
       
  2120     cursor.movePosition(QTextCursor::Start);
       
  2121     cursor.movePosition(QTextCursor::NextBlock);
       
  2122     QTextTable *table = cursor.currentTable();
       
  2123     QVERIFY(table);
       
  2124 
       
  2125     QTextTableCell cell = table->cellAt(0, 0);
       
  2126     QVERIFY(cell.format().background().color() == Qt::blue);
       
  2127 
       
  2128     QTextFrame::Iterator it = cell.begin();
       
  2129     QVERIFY(!it.atEnd());
       
  2130     QVERIFY(it.currentFrame() == 0);
       
  2131     QVERIFY(it.currentBlock().isValid());
       
  2132 
       
  2133     ++it;
       
  2134     QVERIFY(!it.atEnd());
       
  2135     QVERIFY(it.currentFrame() != 0);
       
  2136     QVERIFY(!it.currentBlock().isValid());
       
  2137 
       
  2138     ++it;
       
  2139     QVERIFY(!it.atEnd());
       
  2140     QVERIFY(it.currentFrame() == 0);
       
  2141     QVERIFY(it.currentBlock().isValid());
       
  2142     QVERIFY(it.currentBlock().blockFormat().background() == QBrush(Qt::NoBrush));
       
  2143 
       
  2144     ++it;
       
  2145     QVERIFY(it.atEnd());
       
  2146 }
       
  2147 
       
  2148 void tst_QTextDocumentFragment::html_cellSkip()
       
  2149 {
       
  2150     const char html[] = ""
       
  2151 "<table border>"
       
  2152 "  <tr>"
       
  2153 "    <td>First Cell</td>"
       
  2154 "  </tr>"
       
  2155 "  <tr>"
       
  2156 "    <td>Second Cell</td>"
       
  2157 "    <td>Third Cell</td>"
       
  2158 "  </tr>"
       
  2159 "</table>";
       
  2160 
       
  2161     setHtml(html);
       
  2162     cursor.movePosition(QTextCursor::Start);
       
  2163     cursor.movePosition(QTextCursor::NextBlock);
       
  2164     QTextTable *table = cursor.currentTable();
       
  2165     QVERIFY(table);
       
  2166     QVERIFY(table->columns() == 2 && table->rows() == 2);
       
  2167 
       
  2168     QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("First Cell"));
       
  2169     QVERIFY(table->cellAt(0, 1).firstCursorPosition().block().text().isEmpty());
       
  2170     QCOMPARE(table->cellAt(1, 0).firstCursorPosition().block().text(), QString("Second Cell"));
       
  2171     QCOMPARE(table->cellAt(1, 1).firstCursorPosition().block().text(), QString("Third Cell"));
       
  2172 }
       
  2173 
       
  2174 void tst_QTextDocumentFragment::nonZeroMarginOnImport()
       
  2175 {
       
  2176     // specify bgcolor so that the html import creates a root frame format
       
  2177     setHtml("<html><body bgcolor=\"#00ff00\"><b>Hello World</b></body></html>");
       
  2178     QVERIFY(doc->rootFrame()->frameFormat().margin() > 0.0);
       
  2179 }
       
  2180 
       
  2181 void tst_QTextDocumentFragment::html_charFormatPropertiesUnset()
       
  2182 {
       
  2183     setHtml("Hello World");
       
  2184     QVERIFY(doc->begin().begin().fragment().charFormat().properties().isEmpty());
       
  2185 }
       
  2186 
       
  2187 void tst_QTextDocumentFragment::html_headings()
       
  2188 {
       
  2189     setHtml("<h1>foo</h1>bar");
       
  2190     QCOMPARE(doc->blockCount(), 2);
       
  2191 }
       
  2192 
       
  2193 void tst_QTextDocumentFragment::html_quotedFontFamily()
       
  2194 {
       
  2195     setHtml("<div style=\"font-family: 'Foo Bar';\">Test</div>");
       
  2196     QCOMPARE(doc->begin().begin().fragment().charFormat().fontFamily(), QString("Foo Bar"));
       
  2197 
       
  2198     setHtml("<div style='font-family: \"Foo Bar\";'>Test</div>");
       
  2199     QCOMPARE(doc->begin().begin().fragment().charFormat().fontFamily(), QString("Foo Bar"));
       
  2200 }
       
  2201 
       
  2202 void tst_QTextDocumentFragment::defaultFont()
       
  2203 {
       
  2204     QFont f;
       
  2205     f.setFamily("Courier New");
       
  2206     f.setBold(true);
       
  2207     f.setItalic(true);
       
  2208     f.setStrikeOut(true); // set here but deliberately ignored for the html export
       
  2209     f.setPointSize(100);
       
  2210     doc->setDefaultFont(f);
       
  2211     doc->setPlainText("Hello World");
       
  2212     const QString html = doc->toHtml();
       
  2213     QLatin1String str("<body style=\" font-family:'Courier New'; font-size:100pt; font-weight:600; font-style:italic;\">");
       
  2214     QVERIFY(html.contains(str));
       
  2215 }
       
  2216 
       
  2217 void tst_QTextDocumentFragment::html_spanBackgroundColor()
       
  2218 {
       
  2219     setHtml("<span style=\"background-color: blue\">Foo</span>");
       
  2220     QVERIFY(doc->begin().begin().fragment().charFormat().background().color() == QColor(Qt::blue));
       
  2221 }
       
  2222 
       
  2223 void tst_QTextDocumentFragment::html_brokenTitle_data()
       
  2224 {
       
  2225     QTest::addColumn<QString>("html");
       
  2226     QTest::addColumn<QString>("expectedBody");
       
  2227     QTest::addColumn<QString>("expectedTitle");
       
  2228 
       
  2229     QTest::newRow("brokentitle") << QString("<html><head><title>Foo<b>bar</b></title></head><body>Blah</body></html>")
       
  2230                                  << QString("Blah") << QString("Foo");
       
  2231     QTest::newRow("brokentitle2") << QString("<html><head><title>Foo<font color=red>i</font>t<font color=red>i</font>Blub</title></head><body>Blah</body></html>")
       
  2232                                  << QString("Blah") << QString("Foo");
       
  2233     QTest::newRow("entities") << QString("<html><head><title>Foo&lt;bar</title></head><body>Blah</body></html>")
       
  2234                               << QString("Blah") << QString("Foo<bar");
       
  2235     QTest::newRow("unclosedtitle") << QString("<html><head><title>Foo</head><body>Blah</body></html>")
       
  2236                                    << QString("Blah") << QString("Foo");
       
  2237 }
       
  2238 
       
  2239 void tst_QTextDocumentFragment::html_brokenTitle()
       
  2240 {
       
  2241     QFETCH(QString, html);
       
  2242     QFETCH(QString, expectedBody);
       
  2243     QFETCH(QString, expectedTitle);
       
  2244     doc->setHtml(html);
       
  2245     QCOMPARE(doc->toPlainText(), expectedBody);
       
  2246     QCOMPARE(doc->metaInformation(QTextDocument::DocumentTitle), expectedTitle);
       
  2247 }
       
  2248 
       
  2249 void tst_QTextDocumentFragment::html_blockVsInline()
       
  2250 {
       
  2251     {
       
  2252         setHtml("<html><body><div><b>Foo<div>Bar");
       
  2253         QVERIFY(cursor.charFormat().fontWeight() == QFont::Bold);
       
  2254         QVERIFY(cursor.blockCharFormat().fontWeight() == QFont::Bold);
       
  2255     }
       
  2256     {
       
  2257         setHtml("<html><body><p><b>Foo<p>Bar");
       
  2258         QVERIFY(cursor.charFormat().fontWeight() != QFont::Bold);
       
  2259         QVERIFY(cursor.blockCharFormat().fontWeight() != QFont::Bold);
       
  2260     }
       
  2261     {
       
  2262         setHtml("<html><body><b><center>Foo</center></b>");
       
  2263         QVERIFY(cursor.charFormat().fontWeight() == QFont::Bold);
       
  2264         QVERIFY(cursor.blockCharFormat().fontWeight() == QFont::Bold);
       
  2265     }
       
  2266     {
       
  2267         setHtml("<html><body><b><p>Foo");
       
  2268         QVERIFY(cursor.charFormat().fontWeight() == QFont::Bold);
       
  2269         QVERIFY(cursor.blockCharFormat().fontWeight() == QFont::Bold);
       
  2270     }
       
  2271     {
       
  2272         setHtml("<html><body><b><p>Foo<p>Bar");
       
  2273         QVERIFY(cursor.charFormat().fontWeight() == QFont::Bold);
       
  2274         QVERIFY(cursor.blockCharFormat().fontWeight() == QFont::Bold);
       
  2275     }
       
  2276     {
       
  2277         setHtml("<div><b>Foo<div>Bar");
       
  2278         QVERIFY(cursor.charFormat().fontWeight() == QFont::Bold);
       
  2279         QVERIFY(cursor.blockCharFormat().fontWeight() == QFont::Bold);
       
  2280     }
       
  2281     {
       
  2282         setHtml("<p><b>Foo<p>Bar");
       
  2283         QVERIFY(cursor.charFormat().fontWeight() != QFont::Bold);
       
  2284         QVERIFY(cursor.blockCharFormat().fontWeight() != QFont::Bold);
       
  2285     }
       
  2286     {
       
  2287         setHtml("<b><center>Foo</center></b>");
       
  2288         QVERIFY(cursor.charFormat().fontWeight() == QFont::Bold);
       
  2289         QVERIFY(cursor.blockCharFormat().fontWeight() == QFont::Bold);
       
  2290     }
       
  2291     {
       
  2292         setHtml("<b><p>Foo");
       
  2293         QVERIFY(cursor.charFormat().fontWeight() == QFont::Bold);
       
  2294         QVERIFY(cursor.blockCharFormat().fontWeight() == QFont::Bold);
       
  2295     }
       
  2296     {
       
  2297         setHtml("<b><p>Foo<p>Bar");
       
  2298         QVERIFY(cursor.charFormat().fontWeight() == QFont::Bold);
       
  2299         QVERIFY(cursor.blockCharFormat().fontWeight() == QFont::Bold);
       
  2300     }
       
  2301 }
       
  2302 
       
  2303 void tst_QTextDocumentFragment::html_tbody()
       
  2304 {
       
  2305     setHtml("<table><thead><tr><td>First Cell</td></tr></thead><tbody><tr><td>Second Cell</td></tr></tbody></table>");
       
  2306     cursor.movePosition(QTextCursor::Start);
       
  2307     cursor.movePosition(QTextCursor::NextBlock);
       
  2308     QTextTable *table = cursor.currentTable();
       
  2309     QVERIFY(table);
       
  2310     QCOMPARE(table->columns(), 1);
       
  2311     QCOMPARE(table->rows(), 2);
       
  2312     QCOMPARE(table->format().headerRowCount(), 1);
       
  2313     QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("First Cell"));
       
  2314     QCOMPARE(table->cellAt(1, 0).firstCursorPosition().block().text(), QString("Second Cell"));
       
  2315 }
       
  2316 
       
  2317 void tst_QTextDocumentFragment::html_nestedTables()
       
  2318 {
       
  2319     setHtml("<table>"
       
  2320             "  <tr><td>"
       
  2321             ""
       
  2322             "    <table>"
       
  2323             "      <tr><td>Hello</td></tr>"
       
  2324             "    </table>"
       
  2325             ""
       
  2326             "    <table>"
       
  2327             "      <tr><td>World</td></tr>"
       
  2328             "    </table>"
       
  2329             ""
       
  2330             "  </td></tr>"
       
  2331             "</table>"
       
  2332            );
       
  2333 
       
  2334     cursor.movePosition(QTextCursor::Start);
       
  2335     cursor.movePosition(QTextCursor::NextBlock);
       
  2336     QTextTable *table = cursor.currentTable();
       
  2337     QVERIFY(table);
       
  2338     QCOMPARE(table->rows(), 1);
       
  2339     QCOMPARE(table->columns(), 1);
       
  2340 
       
  2341     cursor = table->cellAt(0, 0).firstCursorPosition();
       
  2342     cursor.movePosition(QTextCursor::NextBlock);
       
  2343 
       
  2344     QTextTable *firstNestedTable = cursor.currentTable();
       
  2345     QVERIFY(firstNestedTable);
       
  2346     QVERIFY(firstNestedTable->parentFrame() == table);
       
  2347     QCOMPARE(firstNestedTable->rows(), 1);
       
  2348     QCOMPARE(firstNestedTable->columns(), 1);
       
  2349     QCOMPARE(firstNestedTable->cellAt(0, 0).firstCursorPosition().block().text(), QString("Hello"));
       
  2350 
       
  2351     while (cursor.currentTable() == firstNestedTable
       
  2352            && cursor.movePosition(QTextCursor::NextBlock))
       
  2353         ;
       
  2354 
       
  2355     QVERIFY(!cursor.isNull());
       
  2356     QVERIFY(cursor.currentTable() == table);
       
  2357 
       
  2358     cursor.movePosition(QTextCursor::NextBlock);
       
  2359 
       
  2360     QTextTable *secondNestedTable = cursor.currentTable();
       
  2361     QVERIFY(secondNestedTable);
       
  2362     QVERIFY(secondNestedTable->parentFrame() == table);
       
  2363     QCOMPARE(secondNestedTable->rows(), 1);
       
  2364     QCOMPARE(secondNestedTable->columns(), 1);
       
  2365     QCOMPARE(secondNestedTable->cellAt(0, 0).firstCursorPosition().block().text(), QString("World"));
       
  2366 }
       
  2367 
       
  2368 void tst_QTextDocumentFragment::html_rowSpans()
       
  2369 {
       
  2370     setHtml(""
       
  2371             "<table border=\"1\" width=\"100%\">"
       
  2372             "  <tr>"
       
  2373             "    <td rowspan=\"2\">blah</td>"
       
  2374             "    <td rowspan=\"2\">foo</td>"
       
  2375             "  </tr>"
       
  2376             "  <tr></tr>"
       
  2377             "  <tr>"
       
  2378             "    <td rowspan=\"2\">blubb</td>"
       
  2379             "    <td rowspan=\"2\">baz</td>"
       
  2380             "  </tr>"
       
  2381             "  <tr></tr>"
       
  2382             "</table>");
       
  2383 
       
  2384     cursor.movePosition(QTextCursor::Start);
       
  2385     cursor.movePosition(QTextCursor::NextBlock);
       
  2386     QTextTable *table = cursor.currentTable();
       
  2387     QVERIFY(table);
       
  2388     QCOMPARE(table->rows(), 4);
       
  2389     QCOMPARE(table->columns(), 2);
       
  2390 
       
  2391     QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("blah"));
       
  2392     QCOMPARE(table->cellAt(0, 1).firstCursorPosition().block().text(), QString("foo"));
       
  2393 
       
  2394     QCOMPARE(table->cellAt(1, 0).firstCursorPosition().block().text(), QString("blah"));
       
  2395     QCOMPARE(table->cellAt(1, 1).firstCursorPosition().block().text(), QString("foo"));
       
  2396 
       
  2397     QCOMPARE(table->cellAt(2, 0).firstCursorPosition().block().text(), QString("blubb"));
       
  2398     QCOMPARE(table->cellAt(2, 1).firstCursorPosition().block().text(), QString("baz"));
       
  2399 
       
  2400     QCOMPARE(table->cellAt(3, 0).firstCursorPosition().block().text(), QString("blubb"));
       
  2401     QCOMPARE(table->cellAt(3, 1).firstCursorPosition().block().text(), QString("baz"));
       
  2402 }
       
  2403 
       
  2404 void tst_QTextDocumentFragment::html_rowSpans2()
       
  2405 {
       
  2406     setHtml(""
       
  2407             "<html><body>"
       
  2408             "<table border=\"1\">"
       
  2409             "<tr>"
       
  2410             "<td>Row 1 col 1</td>"
       
  2411             "</tr>"
       
  2412             "<tr>"
       
  2413             "<td rowspan=\"3\">Row 2 col 1, rowspan 3</td>"
       
  2414             "<td>Row 2 col 2</td>"
       
  2415             "</tr>"
       
  2416             "<tr>"
       
  2417             "<td rowspan=\"2\">Row 3 col 2, rowspan 2</td>"
       
  2418             "</tr>"
       
  2419             "<tr>"
       
  2420             "</tr>"
       
  2421             "</table>"
       
  2422             "</body></html>");
       
  2423 
       
  2424     cursor.movePosition(QTextCursor::Start);
       
  2425     cursor.movePosition(QTextCursor::NextBlock);
       
  2426     QTextTable *table = cursor.currentTable();
       
  2427     QVERIFY(table);
       
  2428     QCOMPARE(table->rows(), 4);
       
  2429     QCOMPARE(table->columns(), 2);
       
  2430     QCOMPARE(table->cellAt(0, 1).rowSpan(), 1);
       
  2431     QCOMPARE(table->cellAt(1, 0).rowSpan(), 3);
       
  2432     QCOMPARE(table->cellAt(2, 1).rowSpan(), 2);
       
  2433 }
       
  2434 
       
  2435 void tst_QTextDocumentFragment::html_implicitParagraphs()
       
  2436 {
       
  2437     setHtml("<p>foo</p>bar");
       
  2438     QCOMPARE(doc->blockCount(), 2);
       
  2439 }
       
  2440 
       
  2441 void tst_QTextDocumentFragment::html_missingCloseTag()
       
  2442 {
       
  2443     setHtml("<font color=\"red\"><span style=\"color:blue\">blue</span></span>&nbsp;red</font>");
       
  2444     cursor.movePosition(QTextCursor::Start);
       
  2445     cursor.movePosition(QTextCursor::NextCharacter);
       
  2446     QVERIFY(cursor.charFormat().foreground().color() == Qt::blue);
       
  2447     cursor.movePosition(QTextCursor::NextWord);
       
  2448     cursor.movePosition(QTextCursor::NextCharacter);
       
  2449     QVERIFY(cursor.charFormat().foreground().color() == Qt::red);
       
  2450 }
       
  2451 
       
  2452 void tst_QTextDocumentFragment::html_anchorColor()
       
  2453 {
       
  2454     setHtml("<span style=\"color: red;\">Red</span>");
       
  2455     cursor.movePosition(QTextCursor::Start);
       
  2456     cursor.movePosition(QTextCursor::NextCharacter);
       
  2457     QVERIFY(cursor.charFormat().foreground().color() == Qt::red);
       
  2458 
       
  2459     setHtml("<span style=\"color: red;\"><a href=\"http://www.kde.org/\">Blue</a></span>");
       
  2460     cursor.movePosition(QTextCursor::Start);
       
  2461     cursor.movePosition(QTextCursor::NextCharacter);
       
  2462     QVERIFY(cursor.charFormat().foreground().color() == QApplication::palette().link().color());
       
  2463 
       
  2464     setHtml("<span style=\"color: red;\"><a href=\"http://www.kde.org/\" style=\"color: yellow;\">Green</a></span>");
       
  2465     cursor.movePosition(QTextCursor::Start);
       
  2466     cursor.movePosition(QTextCursor::NextCharacter);
       
  2467     QVERIFY(cursor.charFormat().foreground().color() == Qt::yellow);
       
  2468 }
       
  2469 
       
  2470 void tst_QTextDocumentFragment::html_lastParagraphClosing()
       
  2471 {
       
  2472     setHtml("<p>Foo<b>Bar</b>Baz");
       
  2473     QCOMPARE(doc->blockCount(), 1);
       
  2474 }
       
  2475 
       
  2476 void tst_QTextDocumentFragment::html_tableHeaderBodyFootParent()
       
  2477 {
       
  2478     // don't get confused by strange tags, keep tbody/thead/tfoot children of
       
  2479     // the table tag
       
  2480     setHtml("<table><col><col><col><tbody><tr><td>Hey</td></tr></tbody></table>");
       
  2481 
       
  2482     cursor.movePosition(QTextCursor::Start);
       
  2483     cursor.movePosition(QTextCursor::NextBlock);
       
  2484     QTextTable *table = cursor.currentTable();
       
  2485     QVERIFY(table);
       
  2486     QCOMPARE(table->columns(), 1);
       
  2487     QCOMPARE(table->rows(), 1);
       
  2488     QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("Hey"));
       
  2489 
       
  2490     setHtml("<table><col><col><col><thead><tr><td>Hey</td></tr></thead></table>");
       
  2491 
       
  2492     cursor.movePosition(QTextCursor::Start);
       
  2493     cursor.movePosition(QTextCursor::NextBlock);
       
  2494     table = cursor.currentTable();
       
  2495     QVERIFY(table);
       
  2496     QCOMPARE(table->columns(), 1);
       
  2497     QCOMPARE(table->rows(), 1);
       
  2498     QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("Hey"));
       
  2499 
       
  2500     setHtml("<table><col><col><col><tfoot><tr><td>Hey</td></tr></tfoot></table>");
       
  2501 
       
  2502     cursor.movePosition(QTextCursor::Start);
       
  2503     cursor.movePosition(QTextCursor::NextBlock);
       
  2504     table = cursor.currentTable();
       
  2505     QVERIFY(table);
       
  2506     QCOMPARE(table->columns(), 1);
       
  2507     QCOMPARE(table->rows(), 1);
       
  2508     QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("Hey"));
       
  2509 }
       
  2510 
       
  2511 void tst_QTextDocumentFragment::html_columnWidths()
       
  2512 {
       
  2513     setHtml("<table>"
       
  2514             " <tr>"
       
  2515             "   <td colspan=\"2\">Foo</td>"
       
  2516             " </tr>"
       
  2517             " <tr>"
       
  2518             "   <td>Bar</td>"
       
  2519             "   <td width=\"1%\">Baz</td>"
       
  2520             " </tr>"
       
  2521             "</table>");
       
  2522 
       
  2523     cursor.movePosition(QTextCursor::Start);
       
  2524     cursor.movePosition(QTextCursor::NextBlock);
       
  2525     QTextTable *table = cursor.currentTable();
       
  2526     QVERIFY(table);
       
  2527     QCOMPARE(table->columns(), 2);
       
  2528     QCOMPARE(table->rows(), 2);
       
  2529     QTextTableFormat fmt = table->format();
       
  2530 
       
  2531     const QVector<QTextLength> columnWidths = fmt.columnWidthConstraints();
       
  2532     QCOMPARE(columnWidths.count(), 2);
       
  2533     QVERIFY(columnWidths.at(0).type() == QTextLength::VariableLength);
       
  2534     QVERIFY(columnWidths.at(1).type() == QTextLength::PercentageLength);
       
  2535     QVERIFY(columnWidths.at(1).rawValue() == 1);
       
  2536 }
       
  2537 
       
  2538 void tst_QTextDocumentFragment::css_fontWeight()
       
  2539 {
       
  2540     setHtml("<p style=\"font-weight:bold\">blah</p>");
       
  2541     QVERIFY(doc->begin().charFormat().fontWeight() == QFont::Bold);
       
  2542     setHtml("<p style=\"font-weight:600\">blah</p>");
       
  2543     QVERIFY(doc->begin().charFormat().fontWeight() == QFont::Bold);
       
  2544 
       
  2545 }
       
  2546 
       
  2547 void tst_QTextDocumentFragment::css_float()
       
  2548 {
       
  2549     setHtml("<img src=\"foo\" style=\"float: right\">");
       
  2550     QTextCharFormat fmt = doc->begin().begin().fragment().charFormat();
       
  2551     QVERIFY(fmt.isImageFormat());
       
  2552     QTextObject *o = doc->objectForFormat(fmt);
       
  2553     QVERIFY(o);
       
  2554     QTextFormat f = o->format();
       
  2555     QVERIFY(f.isFrameFormat());
       
  2556     QVERIFY(f.toFrameFormat().position() == QTextFrameFormat::FloatRight);
       
  2557 
       
  2558     setHtml("<img src=\"foo\" align=right>");
       
  2559     fmt = doc->begin().begin().fragment().charFormat();
       
  2560     QVERIFY(fmt.isImageFormat());
       
  2561     o = doc->objectForFormat(fmt);
       
  2562     QVERIFY(o);
       
  2563     f = o->format();
       
  2564     QVERIFY(f.isFrameFormat());
       
  2565     QVERIFY(f.toFrameFormat().position() == QTextFrameFormat::FloatRight);
       
  2566 
       
  2567     setHtml("<img src=\"foo\" align=left>");
       
  2568     fmt = doc->begin().begin().fragment().charFormat();
       
  2569     QVERIFY(fmt.isImageFormat());
       
  2570     o = doc->objectForFormat(fmt);
       
  2571     QVERIFY(o);
       
  2572     f = o->format();
       
  2573     QVERIFY(f.isFrameFormat());
       
  2574     QVERIFY(f.toFrameFormat().position() == QTextFrameFormat::FloatLeft);
       
  2575 }
       
  2576 
       
  2577 void tst_QTextDocumentFragment::css_textIndent()
       
  2578 {
       
  2579     setHtml("<p style=\"text-indent: 42px\">foo</p>");
       
  2580     QTextBlockFormat fmt = doc->begin().blockFormat();
       
  2581     QCOMPARE(fmt.textIndent(), qreal(42));
       
  2582 }
       
  2583 
       
  2584 void tst_QTextDocumentFragment::css_inline()
       
  2585 {
       
  2586     setHtml(""
       
  2587             "<style>"
       
  2588             " p { background-color: green;}"
       
  2589             "</style>"
       
  2590             "<p>test</p>"
       
  2591             );
       
  2592     QTextBlockFormat fmt = doc->begin().blockFormat();
       
  2593     QVERIFY(fmt.background().color() == QColor("green"));
       
  2594 }
       
  2595 
       
  2596 void tst_QTextDocumentFragment::css_external()
       
  2597 {
       
  2598     doc->addResource(QTextDocument::StyleSheetResource, QUrl("test.css"), QString("p { background-color: green; }"));
       
  2599     doc->setHtml(""
       
  2600             "<link href=\"test.css\" type=\"text/css\" />"
       
  2601             "<p>test</p>"
       
  2602             );
       
  2603     QTextBlockFormat fmt = doc->begin().blockFormat();
       
  2604     QVERIFY(fmt.background().color() == QColor("green"));
       
  2605 }
       
  2606 
       
  2607 void tst_QTextDocumentFragment::css_import()
       
  2608 {
       
  2609     doc->addResource(QTextDocument::StyleSheetResource, QUrl("test.css"), QString("@import \"other.css\";"));
       
  2610     doc->addResource(QTextDocument::StyleSheetResource, QUrl("other.css"), QString("@import url(\"other2.css\");"));
       
  2611     doc->addResource(QTextDocument::StyleSheetResource, QUrl("other2.css"), QString("p { background-color: green; }"));
       
  2612     doc->setHtml(""
       
  2613             "<link href=\"test.css\" type=\"text/css\" />"
       
  2614             "<p>test</p>"
       
  2615             );
       
  2616     QTextBlockFormat fmt = doc->begin().blockFormat();
       
  2617     QVERIFY(fmt.background().color() == QColor("green"));
       
  2618 
       
  2619     doc->setHtml(""
       
  2620             "<style>@import \"test.css\" screen;</style>"
       
  2621             "<p>test</p>"
       
  2622             );
       
  2623     fmt = doc->begin().blockFormat();
       
  2624     QVERIFY(fmt.background().color() == QColor("green"));
       
  2625 }
       
  2626 
       
  2627 void tst_QTextDocumentFragment::css_selectors_data()
       
  2628 {
       
  2629     QTest::addColumn<bool>("match");
       
  2630     QTest::addColumn<QString>("selector");
       
  2631     QTest::addColumn<QString>("attributes");
       
  2632 
       
  2633     QTest::newRow("plain") << true << QString() << QString();
       
  2634 
       
  2635     QTest::newRow("class") << true << QString(".foo") << QString("class=foo");
       
  2636     QTest::newRow("notclass") << false << QString(".foo") << QString("class=bar");
       
  2637 
       
  2638     QTest::newRow("attrset") << true << QString("[justset]") << QString("justset");
       
  2639     QTest::newRow("notattrset") << false << QString("[justset]") << QString("otherattribute");
       
  2640 
       
  2641     QTest::newRow("attrmatch") << true << QString("[foo=bar]") << QString("foo=bar");
       
  2642     QTest::newRow("noattrmatch") << false << QString("[foo=bar]") << QString("foo=xyz");
       
  2643 
       
  2644     QTest::newRow("contains") << true << QString("[foo~=bar]") << QString("foo=\"baz bleh bar\"");
       
  2645     QTest::newRow("notcontains") << false << QString("[foo~=bar]") << QString("foo=\"test\"");
       
  2646 
       
  2647     QTest::newRow("beingswith") << true << QString("[foo|=bar]") << QString("foo=\"bar-bleh\"");
       
  2648     QTest::newRow("notbeingswith") << false << QString("[foo|=bar]") << QString("foo=\"bleh-bar\"");
       
  2649 
       
  2650     QTest::newRow("attr2") << true << QString("[bar=foo]") << QString("bleh=bar bar=foo");
       
  2651 }
       
  2652 
       
  2653 void tst_QTextDocumentFragment::css_selectors()
       
  2654 {
       
  2655     QFETCH(bool, match);
       
  2656     QFETCH(QString, selector);
       
  2657     QFETCH(QString, attributes);
       
  2658 
       
  2659     QString html = QString(""
       
  2660             "<style>"
       
  2661             " p { background-color: green }"
       
  2662             " p%1 { background-color: red }"
       
  2663             "</style>"
       
  2664             "<p %2>test</p>"
       
  2665             ).arg(selector).arg(attributes);
       
  2666     setHtml(html);
       
  2667 
       
  2668     QTextBlockFormat fmt = doc->begin().blockFormat();
       
  2669     if (match)
       
  2670         QVERIFY(fmt.background().color() == QColor("red"));
       
  2671     else
       
  2672         QVERIFY(fmt.background().color() == QColor("green"));
       
  2673 }
       
  2674 
       
  2675 void tst_QTextDocumentFragment::css_nodeNameCaseInsensitivity()
       
  2676 {
       
  2677     setHtml("<style>"
       
  2678             "P { background-color: green }"
       
  2679             "</style>"
       
  2680             "<p>test</p>");
       
  2681     QTextBlockFormat fmt = doc->begin().blockFormat();
       
  2682     QVERIFY(fmt.background().color() == QColor("green"));
       
  2683 }
       
  2684 
       
  2685 void tst_QTextDocumentFragment::css_textUnderlineStyle_data()
       
  2686 {
       
  2687     QTest::addColumn<QString>("styleName");
       
  2688     QTest::addColumn<int>("expectedStyle");
       
  2689 
       
  2690     QTest::newRow("none") << QString("none") << int(QTextCharFormat::NoUnderline);
       
  2691     QTest::newRow("solid") << QString("solid") << int(QTextCharFormat::SingleUnderline);
       
  2692     QTest::newRow("dash") << QString("dashed") << int(QTextCharFormat::DashUnderline);
       
  2693     QTest::newRow("dot") << QString("dotted") << int(QTextCharFormat::DotLine);
       
  2694     QTest::newRow("dashdot") << QString("dot-dash") << int(QTextCharFormat::DashDotLine);
       
  2695     QTest::newRow("dashdotdot") << QString("dot-dot-dash") << int(QTextCharFormat::DashDotDotLine);
       
  2696     QTest::newRow("wave") << QString("wave") << int(QTextCharFormat::WaveUnderline);
       
  2697 }
       
  2698 
       
  2699 void tst_QTextDocumentFragment::css_textUnderlineStyle()
       
  2700 {
       
  2701     QFETCH(QString, styleName);
       
  2702     QFETCH(int, expectedStyle);
       
  2703 
       
  2704     QString html = QString::fromLatin1("<span style=\"text-underline-style: %1\">Blah</span>").arg(styleName);
       
  2705     doc->setHtml(html);
       
  2706 
       
  2707     QTextFragment fragment = doc->begin().begin().fragment();
       
  2708     QVERIFY(fragment.isValid());
       
  2709     QCOMPARE(int(fragment.charFormat().underlineStyle()), expectedStyle);
       
  2710 }
       
  2711 
       
  2712 void tst_QTextDocumentFragment::css_textUnderlineStyleAndDecoration()
       
  2713 {
       
  2714     doc->setHtml("<span style=\"text-decoration: overline; text-underline-style: solid\">Test</span>");
       
  2715 
       
  2716     QTextFragment fragment = doc->begin().begin().fragment();
       
  2717     QVERIFY(fragment.isValid());
       
  2718     QVERIFY(fragment.charFormat().underlineStyle() == QTextCharFormat::SingleUnderline);
       
  2719     QVERIFY(fragment.charFormat().fontOverline());
       
  2720 
       
  2721     doc->setHtml("<span style=\"text-underline-style: solid; text-decoration: overline\">Test</span>");
       
  2722 
       
  2723     fragment = doc->begin().begin().fragment();
       
  2724     QVERIFY(fragment.isValid());
       
  2725     QVERIFY(fragment.charFormat().underlineStyle() == QTextCharFormat::SingleUnderline);
       
  2726     QVERIFY(fragment.charFormat().fontOverline());
       
  2727 }
       
  2728 
       
  2729 void tst_QTextDocumentFragment::css_listStyleType()
       
  2730 {
       
  2731     doc->setHtml("<ol style=\"list-style-type: disc\"><li>Blah</li></ol>");
       
  2732     cursor.movePosition(QTextCursor::End);
       
  2733     QVERIFY(cursor.currentList());
       
  2734     QVERIFY(cursor.currentList()->format().style() == QTextListFormat::ListDisc);
       
  2735 
       
  2736     doc->setHtml("<ul style=\"list-style-type: square\"><li>Blah</li></ul>");
       
  2737     cursor.movePosition(QTextCursor::End);
       
  2738     QVERIFY(cursor.currentList());
       
  2739     QVERIFY(cursor.currentList()->format().style() == QTextListFormat::ListSquare);
       
  2740 
       
  2741     doc->setHtml("<ul style=\"list-style-type: circle\"><li>Blah</li></ul>");
       
  2742     cursor.movePosition(QTextCursor::End);
       
  2743     QVERIFY(cursor.currentList());
       
  2744     QVERIFY(cursor.currentList()->format().style() == QTextListFormat::ListCircle);
       
  2745 
       
  2746     doc->setHtml("<ul style=\"list-style-type: decimal\"><li>Blah</li></ul>");
       
  2747     cursor.movePosition(QTextCursor::End);
       
  2748     QVERIFY(cursor.currentList());
       
  2749     QVERIFY(cursor.currentList()->format().style() == QTextListFormat::ListDecimal);
       
  2750 
       
  2751     doc->setHtml("<ul style=\"list-style-type: lower-alpha\"><li>Blah</li></ul>");
       
  2752     cursor.movePosition(QTextCursor::End);
       
  2753     QVERIFY(cursor.currentList());
       
  2754     QVERIFY(cursor.currentList()->format().style() == QTextListFormat::ListLowerAlpha);
       
  2755 
       
  2756     doc->setHtml("<ul style=\"list-style-type: upper-alpha\"><li>Blah</li></ul>");
       
  2757     cursor.movePosition(QTextCursor::End);
       
  2758     QVERIFY(cursor.currentList());
       
  2759     QVERIFY(cursor.currentList()->format().style() == QTextListFormat::ListUpperAlpha);
       
  2760 
       
  2761     doc->setHtml("<ul style=\"list-style-type: upper-roman\"><li>Blah</li></ul>");
       
  2762     cursor.movePosition(QTextCursor::End);
       
  2763     QVERIFY(cursor.currentList());
       
  2764     QVERIFY(cursor.currentList()->format().style() == QTextListFormat::ListUpperRoman);
       
  2765 
       
  2766     doc->setHtml("<ul style=\"list-style-type: lower-roman\"><li>Blah</li></ul>");
       
  2767     cursor.movePosition(QTextCursor::End);
       
  2768     QVERIFY(cursor.currentList());
       
  2769     QVERIFY(cursor.currentList()->format().style() == QTextListFormat::ListLowerRoman);
       
  2770 
       
  2771     // ignore the unsupported list-style-position inside the list-style shorthand property
       
  2772     doc->setHtml("<ul style=\"list-style: outside decimal\"><li>Blah</li></ul>");
       
  2773     cursor.movePosition(QTextCursor::End);
       
  2774     QVERIFY(cursor.currentList());
       
  2775     QVERIFY(cursor.currentList()->format().style() == QTextListFormat::ListDecimal);
       
  2776 }
       
  2777 
       
  2778 void tst_QTextDocumentFragment::css_linkPseudo()
       
  2779 {
       
  2780     doc->setHtml("<a href=\"foobar\">Blah</a>");
       
  2781     QVERIFY(doc->begin().begin().fragment().charFormat().fontUnderline());
       
  2782 
       
  2783     doc->setHtml("<style>a { text-decoration: none; }</style><a href=\"foobar\">Blah</a>");
       
  2784     QVERIFY(!doc->begin().begin().fragment().charFormat().fontUnderline());
       
  2785 
       
  2786     doc->setHtml("<style>a:link { text-decoration: none; }</style><a href=\"foobar\">Blah</a>");
       
  2787     QVERIFY(!doc->begin().begin().fragment().charFormat().fontUnderline());
       
  2788 }
       
  2789 
       
  2790 void tst_QTextDocumentFragment::css_pageBreaks()
       
  2791 {
       
  2792     doc->setHtml("<p>Foo</p>");
       
  2793     QVERIFY(doc->begin().blockFormat().pageBreakPolicy() == QTextFormat::PageBreak_Auto);
       
  2794 
       
  2795     doc->setHtml("<p style=\" page-break-before:always;\">Foo</p>");
       
  2796     QVERIFY(doc->begin().blockFormat().pageBreakPolicy() == QTextFormat::PageBreak_AlwaysBefore);
       
  2797 
       
  2798     doc->setHtml("<p style=\" page-break-after:always;\">Foo</p>");
       
  2799     QVERIFY(doc->begin().blockFormat().pageBreakPolicy() == QTextFormat::PageBreak_AlwaysAfter);
       
  2800 
       
  2801     doc->setHtml("<p style=\" page-break-before:always; page-break-after:always;\">Foo</p>");
       
  2802     QVERIFY(doc->begin().blockFormat().pageBreakPolicy() == (QTextFormat::PageBreak_AlwaysAfter | QTextFormat::PageBreak_AlwaysBefore));
       
  2803 }
       
  2804 
       
  2805 void tst_QTextDocumentFragment::universalSelectors_data()
       
  2806 {
       
  2807     QTest::addColumn<bool>("match");
       
  2808     QTest::addColumn<QString>("selector");
       
  2809     QTest::addColumn<QString>("attributes");
       
  2810 
       
  2811     QTest::newRow("1") << true << QString("*") << QString();
       
  2812     QTest::newRow("2") << false << QString() << QString(); // invalid totally empty selector
       
  2813 
       
  2814     QTest::newRow("3") << false << QString("*[foo=bar]") << QString("foo=bleh");
       
  2815     QTest::newRow("4") << true << QString("*[foo=bar]") << QString("foo=bar");
       
  2816 
       
  2817     QTest::newRow("5") << false << QString("[foo=bar]") << QString("foo=bleh");
       
  2818     QTest::newRow("6") << true << QString("[foo=bar]") << QString("foo=bar");
       
  2819 
       
  2820     QTest::newRow("7") << true << QString(".charfmt1") << QString("class=charfmt1");
       
  2821 }
       
  2822 
       
  2823 void tst_QTextDocumentFragment::universalSelectors()
       
  2824 {
       
  2825     QFETCH(bool, match);
       
  2826     QFETCH(QString, selector);
       
  2827     QFETCH(QString, attributes);
       
  2828 
       
  2829     QString html = QString(""
       
  2830             "<style>"
       
  2831             "%1 { background-color: green }"
       
  2832             "</style>"
       
  2833             "<p %2>test</p>"
       
  2834             ).arg(selector).arg(attributes);
       
  2835 
       
  2836     setHtml(html);
       
  2837 
       
  2838     QTextBlockFormat fmt = doc->begin().blockFormat();
       
  2839     if (match)
       
  2840         QVERIFY(fmt.background().color() == QColor("green"));
       
  2841     else
       
  2842         QVERIFY(!fmt.hasProperty(QTextFormat::BackgroundBrush));
       
  2843 }
       
  2844 
       
  2845 void tst_QTextDocumentFragment::screenMedia()
       
  2846 {
       
  2847     setHtml("<style>"
       
  2848             "@media screen {"
       
  2849             "p { background-color: green }"
       
  2850             "}"
       
  2851             "</style>"
       
  2852             "<p>test</p>"
       
  2853             "");
       
  2854     QTextBlockFormat fmt = doc->begin().blockFormat();
       
  2855     QVERIFY(fmt.background().color() == QColor("green"));
       
  2856 
       
  2857     setHtml("<style>"
       
  2858             "@media foobar {"
       
  2859             "p { background-color: green }"
       
  2860             "}"
       
  2861             "</style>"
       
  2862             "<p>test</p>"
       
  2863             "");
       
  2864     fmt = doc->begin().blockFormat();
       
  2865     QVERIFY(fmt.background().color() != QColor("green"));
       
  2866 
       
  2867     setHtml("<style>"
       
  2868             "@media sCrEeN {"
       
  2869             "p { background-color: green }"
       
  2870             "}"
       
  2871             "</style>"
       
  2872             "<p>test</p>"
       
  2873             "");
       
  2874     fmt = doc->begin().blockFormat();
       
  2875     QVERIFY(fmt.background().color() == QColor("green"));
       
  2876 }
       
  2877 
       
  2878 void tst_QTextDocumentFragment::htmlResourceLoading()
       
  2879 {
       
  2880     const QString html("<link href=\"test.css\" type=\"text/css\" />"
       
  2881                                    "<p>test</p>");
       
  2882 
       
  2883     QTextDocument tmp;
       
  2884     tmp.addResource(QTextDocument::StyleSheetResource, QUrl("test.css"), QString("p { background-color: green; }"));
       
  2885     QTextDocumentFragment frag = QTextDocumentFragment::fromHtml(html, &tmp);
       
  2886     doc->clear();
       
  2887     QTextCursor(doc).insertFragment(frag);
       
  2888     QTextBlockFormat fmt = doc->begin().blockFormat();
       
  2889     QVERIFY(fmt.background().color() == QColor("green"));
       
  2890 }
       
  2891 
       
  2892 void tst_QTextDocumentFragment::someCaseInsensitiveAttributeValues()
       
  2893 {
       
  2894     const char html1[] = "<ul type=sQUarE><li>Blah</li></ul>";
       
  2895     setHtml(QString::fromLatin1(html1));
       
  2896     cursor.movePosition(QTextCursor::End);
       
  2897     QVERIFY(cursor.currentList());
       
  2898     QVERIFY(cursor.currentList()->format().style() == QTextListFormat::ListSquare);
       
  2899 
       
  2900     const char html2[] = "<div align=ceNTeR><b>Hello World";
       
  2901     setHtml(html2);
       
  2902 
       
  2903     QCOMPARE(doc->begin().blockFormat().alignment(), Qt::AlignHCenter);
       
  2904 
       
  2905     const char html3[] = "<p dir=rTL><b>Hello World";
       
  2906     setHtml(html3);
       
  2907 
       
  2908     QCOMPARE(doc->begin().blockFormat().layoutDirection(), Qt::RightToLeft);
       
  2909 }
       
  2910 
       
  2911 class TestDocument : public QTextDocument
       
  2912 {
       
  2913 public:
       
  2914     inline TestDocument() {}
       
  2915 
       
  2916     QPixmap testPixmap;
       
  2917 
       
  2918     virtual QVariant loadResource(int type, const QUrl &name) {
       
  2919         if (name.toString() == QLatin1String("testPixmap")) {
       
  2920             return testPixmap;
       
  2921         }
       
  2922         return QTextDocument::loadResource(type, name);
       
  2923     }
       
  2924 };
       
  2925 
       
  2926 void tst_QTextDocumentFragment::backgroundImage()
       
  2927 {
       
  2928     TestDocument doc;
       
  2929     doc.testPixmap = QPixmap(100, 100);
       
  2930     doc.testPixmap.fill(Qt::blue);
       
  2931     doc.setHtml("<p style=\"background-image: url(testPixmap)\">Hello</p>");
       
  2932     QBrush bg = doc.begin().blockFormat().background();
       
  2933     QVERIFY(bg.style() == Qt::TexturePattern);
       
  2934     QVERIFY(bg.texture().serialNumber() == doc.testPixmap.serialNumber());
       
  2935 }
       
  2936 
       
  2937 void tst_QTextDocumentFragment::dontMergePreAndNonPre()
       
  2938 {
       
  2939     doc->setHtml("<pre>Pre text</pre>Text that should be wrapped");
       
  2940     QCOMPARE(doc->blockCount(), 2);
       
  2941     QCOMPARE(doc->begin().text(), QString("Pre text"));
       
  2942     QCOMPARE(doc->begin().next().text(), QString("Text that should be wrapped"));
       
  2943 }
       
  2944 
       
  2945 void tst_QTextDocumentFragment::leftMarginInsideHtml()
       
  2946 {
       
  2947     doc->setHtml("<html><dl><dd>Blah");
       
  2948     QCOMPARE(doc->blockCount(), 1);
       
  2949     QVERIFY(doc->begin().blockFormat().leftMargin() > 0);
       
  2950 }
       
  2951 
       
  2952 void tst_QTextDocumentFragment::html_margins()
       
  2953 {
       
  2954     doc->setHtml("<p style=\"margin-left: 42px\">Test");
       
  2955     QCOMPARE(doc->blockCount(), 1);
       
  2956     QCOMPARE(doc->begin().blockFormat().topMargin(), 12.);
       
  2957     QCOMPARE(doc->begin().blockFormat().bottomMargin(), 12.);
       
  2958     QCOMPARE(doc->begin().blockFormat().leftMargin(), 42.);
       
  2959 }
       
  2960 
       
  2961 void tst_QTextDocumentFragment::newlineInsidePreShouldBecomeNewParagraph()
       
  2962 {
       
  2963     // rationale: we used to map newlines inside <pre> to QChar::LineSeparator, but
       
  2964     // if you display a lot of text inside pre it all ended up inside one single paragraph,
       
  2965     // which doesn't scale very well with our text engine. Paragraphs spanning thousands of
       
  2966     // lines are not a common use-case otherwise.
       
  2967 
       
  2968     doc->setHtml("<pre>Foo\nBar</pre>");
       
  2969     QCOMPARE(doc->blockCount(), 2);
       
  2970     QTextBlock block = doc->begin();
       
  2971     QCOMPARE(block.blockFormat().topMargin(), qreal(12));
       
  2972     QVERIFY(qIsNull(block.blockFormat().bottomMargin()));
       
  2973 
       
  2974     block = block.next();
       
  2975 
       
  2976     QVERIFY(qIsNull(block.blockFormat().topMargin()));
       
  2977     QCOMPARE(block.blockFormat().bottomMargin(), qreal(12));
       
  2978 
       
  2979     doc->setHtml("<pre style=\"margin-top: 32px; margin-bottom: 45px; margin-left: 50px\">Foo\nBar</pre>");
       
  2980     QCOMPARE(doc->blockCount(), 2);
       
  2981     block = doc->begin();
       
  2982     QCOMPARE(block.blockFormat().topMargin(), qreal(32));
       
  2983     QVERIFY(qIsNull(block.blockFormat().bottomMargin()));
       
  2984     QCOMPARE(block.blockFormat().leftMargin(), qreal(50));
       
  2985 
       
  2986     block = block.next();
       
  2987 
       
  2988     QVERIFY(qIsNull(block.blockFormat().topMargin()));
       
  2989     QCOMPARE(block.blockFormat().bottomMargin(), qreal(45));
       
  2990     QCOMPARE(block.blockFormat().leftMargin(), qreal(50));
       
  2991 
       
  2992 }
       
  2993 
       
  2994 void tst_QTextDocumentFragment::invalidColspan()
       
  2995 {
       
  2996     doc->setHtml("<table><tr rowspan=-1><td colspan=-1>Blah</td></tr></table>");
       
  2997 
       
  2998     cursor.movePosition(QTextCursor::Start);
       
  2999     cursor.movePosition(QTextCursor::NextBlock);
       
  3000     QTextTable *table = cursor.currentTable();
       
  3001     QVERIFY(table);
       
  3002     QCOMPARE(table->columns(), 1);
       
  3003     QCOMPARE(table->rows(), 1);
       
  3004 }
       
  3005 
       
  3006 void tst_QTextDocumentFragment::html_brokenTableWithJustTr()
       
  3007 {
       
  3008     doc->setHtml("<tr><td>First Cell</td><tr><td>Second Cell");
       
  3009     cursor.movePosition(QTextCursor::Start);
       
  3010     cursor.movePosition(QTextCursor::NextBlock);
       
  3011     QTextTable *table = cursor.currentTable();
       
  3012     QVERIFY(table);
       
  3013     QCOMPARE(table->rows(), 2);
       
  3014     QCOMPARE(table->columns(), 1);
       
  3015     QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("First Cell"));
       
  3016     QCOMPARE(table->cellAt(1, 0).firstCursorPosition().block().text(), QString("Second Cell"));
       
  3017 
       
  3018     doc->setHtml(""
       
  3019         "<col width=286 style='mso-width-source:userset;mso-width-alt:10459;width:215pt'>"
       
  3020         "<col width=64 span=3 style='width:48pt'>"
       
  3021         "<tr height=17 style='height:12.75pt'>"
       
  3022         "<td height=17 width=286 style='height:12.75pt;width:215pt'>1a</td>"
       
  3023         "<td width=64 style='width:48pt'>1b</td>"
       
  3024         "<td width=64 style='width:48pt'>1c</td>"
       
  3025         "<td width=64 style='width:48pt'>1d</td>"
       
  3026         "</tr>"
       
  3027         "<tr height=17 style='height:12.75pt'>"
       
  3028         "<td height=17 style='height:12.75pt'>|2a</td>"
       
  3029         "<td>2b</td>"
       
  3030         "<td>2c</td>"
       
  3031         "<td>2d</td>"
       
  3032         "</tr>");
       
  3033     cursor.movePosition(QTextCursor::Start);
       
  3034     cursor.movePosition(QTextCursor::NextBlock);
       
  3035     table = cursor.currentTable();
       
  3036     QVERIFY(table);
       
  3037     QCOMPARE(table->rows(), 2);
       
  3038     QCOMPARE(table->columns(), 4);
       
  3039 }
       
  3040 
       
  3041 void tst_QTextDocumentFragment::html_brokenTableWithJustTd()
       
  3042 {
       
  3043     doc->setHtml("<td>First Cell</td><td>Second Cell");
       
  3044     cursor.movePosition(QTextCursor::Start);
       
  3045     cursor.movePosition(QTextCursor::NextBlock);
       
  3046     QTextTable *table = cursor.currentTable();
       
  3047     QVERIFY(table);
       
  3048     QCOMPARE(table->rows(), 1);
       
  3049     QCOMPARE(table->columns(), 2);
       
  3050     QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("First Cell"));
       
  3051     QCOMPARE(table->cellAt(0, 1).firstCursorPosition().block().text(), QString("Second Cell"));
       
  3052 
       
  3053     doc->setHtml("<td height=17 width=286 style='height:12.75pt;width:215pt'>1a</td>"
       
  3054                  "<td width=64 style='width:48pt'>1b</td>"
       
  3055                  "<td width=64 style='width:48pt'>1c</td>"
       
  3056                  "<td width=64 style='width:48pt'>1d</td>");
       
  3057     cursor.movePosition(QTextCursor::Start);
       
  3058     cursor.movePosition(QTextCursor::NextBlock);
       
  3059     table = cursor.currentTable();
       
  3060     QVERIFY(table);
       
  3061     QCOMPARE(table->rows(), 1);
       
  3062     QCOMPARE(table->columns(), 4);
       
  3063 }
       
  3064 
       
  3065 void tst_QTextDocumentFragment::html_preNewlineHandling_data()
       
  3066 {
       
  3067     QTest::addColumn<QString>("html");
       
  3068     QTest::addColumn<QString>("expectedPlainText");
       
  3069 
       
  3070     QTest::newRow("pre1") << QString("Foo<pre>Bar")
       
  3071                           << QString("Foo\nBar");
       
  3072     QTest::newRow("pre2") << QString("Foo<pre>\nBar")
       
  3073                           << QString("Foo\nBar");
       
  3074     QTest::newRow("pre2") << QString("Foo<pre>\n\nBar")
       
  3075                           << QString("Foo\n\nBar");
       
  3076     QTest::newRow("pre4") << QString("<html>Foo<pre>\nBar")
       
  3077                           << QString("Foo\nBar");
       
  3078     QTest::newRow("pre5") << QString("<pre>Foo\n</pre>\nBar")
       
  3079                           << QString("Foo\nBar");
       
  3080     QTest::newRow("pre6") << QString("<pre>Foo<b>Bar</b>Blah\n</pre>\nMooh")
       
  3081                           << QString("FooBarBlah\nMooh");
       
  3082     QTest::newRow("pre7") << QString("<pre>\nPara1\n</pre>\n<pre>\nPara2\n</pre>")
       
  3083                           << QString("Para1\nPara2");
       
  3084 }
       
  3085 
       
  3086 void tst_QTextDocumentFragment::html_preNewlineHandling()
       
  3087 {
       
  3088     QFETCH(QString, html);
       
  3089 
       
  3090     doc->setHtml(html);
       
  3091     QTEST(doc->toPlainText(), "expectedPlainText");
       
  3092 }
       
  3093 
       
  3094 void tst_QTextDocumentFragment::html_br()
       
  3095 {
       
  3096     doc->setHtml("Foo<br><br><br>Blah");
       
  3097     QCOMPARE(doc->toPlainText(), QString("Foo\n\n\nBlah"));
       
  3098 }
       
  3099 
       
  3100 void tst_QTextDocumentFragment::html_dl()
       
  3101 {
       
  3102     doc->setHtml("<dl><dt>term<dd>data</dl>Text afterwards");
       
  3103     QCOMPARE(doc->toPlainText(), QString("term\ndata\nText afterwards"));
       
  3104 }
       
  3105 
       
  3106 void tst_QTextDocumentFragment::html_tableStrangeNewline()
       
  3107 {
       
  3108     doc->setHtml("<table><tr><td>Foo</td></tr>\n</table>");
       
  3109     cursor.movePosition(QTextCursor::Start);
       
  3110     cursor.movePosition(QTextCursor::NextBlock);
       
  3111     QTextTable *table = cursor.currentTable();
       
  3112     QVERIFY(table);
       
  3113     QCOMPARE(table->rows(), 1);
       
  3114     QCOMPARE(table->columns(), 1);
       
  3115     const QTextTableCell cell = table->cellAt(0, 0);
       
  3116     QCOMPARE(cell.firstCursorPosition().block().text(), QString("Foo"));
       
  3117     QVERIFY(cell.firstCursorPosition().block() == cell.lastCursorPosition().block());
       
  3118 }
       
  3119 
       
  3120 void tst_QTextDocumentFragment::html_tableStrangeNewline2()
       
  3121 {
       
  3122     doc->setHtml("<table><tr><td>Foo</td></tr><tr>\n<td/></tr></table>");
       
  3123     cursor.movePosition(QTextCursor::Start);
       
  3124     cursor.movePosition(QTextCursor::NextBlock);
       
  3125     QTextTable *table = cursor.currentTable();
       
  3126     QVERIFY(table);
       
  3127     QCOMPARE(table->rows(), 2);
       
  3128     QCOMPARE(table->columns(), 1);
       
  3129     const QTextTableCell cell = table->cellAt(0, 0);
       
  3130     QCOMPARE(cell.firstCursorPosition().block().text(), QString("Foo"));
       
  3131     QVERIFY(cell.firstCursorPosition().block() == cell.lastCursorPosition().block());
       
  3132 }
       
  3133 
       
  3134 void tst_QTextDocumentFragment::html_tableStrangeNewline3()
       
  3135 {
       
  3136     doc->setHtml("<table border>"
       
  3137                  "<tr>"
       
  3138                  "<td>"
       
  3139                  "<ul>"
       
  3140                  "<li>Meh</li>"
       
  3141                  "</ul>"
       
  3142                  "</td>"
       
  3143                  "<td>\n"
       
  3144                  "<ul>"
       
  3145                  "<li>Foo</li>"
       
  3146                  "</ul>"
       
  3147                  "</td>"
       
  3148                  "</tr>"
       
  3149                  "</table>");
       
  3150 
       
  3151     cursor.movePosition(QTextCursor::Start);
       
  3152     cursor.movePosition(QTextCursor::NextBlock);
       
  3153     QTextTable *table = cursor.currentTable();
       
  3154     QVERIFY(table);
       
  3155     QCOMPARE(table->rows(), 1);
       
  3156     QCOMPARE(table->columns(), 2);
       
  3157 
       
  3158     QTextTableCell cell = table->cellAt(0, 0);
       
  3159     QCOMPARE(cell.firstCursorPosition().block().text(), QString("Meh"));
       
  3160     QVERIFY(cell.firstCursorPosition().block() == cell.lastCursorPosition().block());
       
  3161 
       
  3162     cell = table->cellAt(0, 1);
       
  3163     QCOMPARE(cell.firstCursorPosition().block().text(), QString("Foo"));
       
  3164     QVERIFY(cell.firstCursorPosition().block() == cell.lastCursorPosition().block());
       
  3165 }
       
  3166 
       
  3167 void tst_QTextDocumentFragment::html_caption()
       
  3168 {
       
  3169     doc->setHtml("<table border align=center>"
       
  3170                  "<caption>This <b>   is a</b> Caption!</caption>"
       
  3171                  "<tr><td>Blah</td></tr>"
       
  3172                  "</table>");
       
  3173 
       
  3174     cursor.movePosition(QTextCursor::Start);
       
  3175     cursor.movePosition(QTextCursor::NextBlock);
       
  3176 
       
  3177     QCOMPARE(cursor.block().text(), QString("This is a Caption!"));
       
  3178     QVERIFY(cursor.blockFormat().alignment() == Qt::AlignHCenter);
       
  3179 
       
  3180     cursor.movePosition(QTextCursor::NextBlock);
       
  3181     QTextTable *table = cursor.currentTable();
       
  3182     QVERIFY(table);
       
  3183     QCOMPARE(table->rows(), 1);
       
  3184     QCOMPARE(table->columns(), 1);
       
  3185 
       
  3186     QTextTableCell cell = table->cellAt(0, 0);
       
  3187     QCOMPARE(cell.firstCursorPosition().block().text(), QString("Blah"));
       
  3188 }
       
  3189 
       
  3190 static const uint windowsLatin1ExtendedCharacters[0xA0 - 0x80] = {
       
  3191     0x20ac, // 0x80
       
  3192     0x0081, // 0x81 direct mapping
       
  3193     0x201a, // 0x82
       
  3194     0x0192, // 0x83
       
  3195     0x201e, // 0x84
       
  3196     0x2026, // 0x85
       
  3197     0x2020, // 0x86
       
  3198     0x2021, // 0x87
       
  3199     0x02C6, // 0x88
       
  3200     0x2030, // 0x89
       
  3201     0x0160, // 0x8A
       
  3202     0x2039, // 0x8B
       
  3203     0x0152, // 0x8C
       
  3204     0x008D, // 0x8D direct mapping
       
  3205     0x017D, // 0x8E
       
  3206     0x008F, // 0x8F directmapping
       
  3207     0x0090, // 0x90 directmapping
       
  3208     0x2018, // 0x91
       
  3209     0x2019, // 0x92
       
  3210     0x201C, // 0x93
       
  3211     0X201D, // 0x94
       
  3212     0x2022, // 0x95
       
  3213     0x2013, // 0x96
       
  3214     0x2014, // 0x97
       
  3215     0x02DC, // 0x98
       
  3216     0x2122, // 0x99
       
  3217     0x0161, // 0x9A
       
  3218     0x203A, // 0x9B
       
  3219     0x0153, // 0x9C
       
  3220     0x009D, // 0x9D direct mapping
       
  3221     0x017E, // 0x9E
       
  3222     0x0178  // 0x9F
       
  3223 };
       
  3224 
       
  3225 void tst_QTextDocumentFragment::html_windowsEntities()
       
  3226 {
       
  3227     for (uint i = 0; i < sizeof(windowsLatin1ExtendedCharacters)/sizeof(windowsLatin1ExtendedCharacters[0]); ++i) {
       
  3228         QString html = QString::number(i + 0x80);
       
  3229         html.prepend("<p>&#");
       
  3230         html.append(";");
       
  3231         doc->setHtml(html);
       
  3232         QCOMPARE(doc->toPlainText(), QString(QChar(windowsLatin1ExtendedCharacters[i])));
       
  3233     }
       
  3234 }
       
  3235 
       
  3236 void tst_QTextDocumentFragment::html_eatenText()
       
  3237 {
       
  3238     doc->setHtml("<h1>Test1</h1>\nTest2<h1>Test3</h1>");
       
  3239     cursor.movePosition(QTextCursor::Start);
       
  3240     QCOMPARE(cursor.block().text(), QString("Test1"));
       
  3241     cursor.movePosition(QTextCursor::NextBlock);
       
  3242     QCOMPARE(cursor.block().text(), QString("Test2"));
       
  3243     cursor.movePosition(QTextCursor::NextBlock);
       
  3244     QCOMPARE(cursor.block().text(), QString("Test3"));
       
  3245 }
       
  3246 
       
  3247 void tst_QTextDocumentFragment::html_hr()
       
  3248 {
       
  3249     doc->setHtml("<hr />");
       
  3250     QCOMPARE(doc->blockCount(), 1);
       
  3251     QVERIFY(doc->begin().blockFormat().hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth));
       
  3252 }
       
  3253 
       
  3254 void tst_QTextDocumentFragment::html_hrMargins()
       
  3255 {
       
  3256     doc->setHtml("<p>Test<hr/>Blah");
       
  3257     QCOMPARE(doc->blockCount(), 3);
       
  3258 
       
  3259     cursor.movePosition(QTextCursor::Start);
       
  3260     QTextBlock block = cursor.block();
       
  3261     QCOMPARE(block.text(), QString("Test"));
       
  3262     QVERIFY(block.blockFormat().bottomMargin() <= qreal(12.));
       
  3263     QTextBlock first = block;
       
  3264 
       
  3265     cursor.movePosition(QTextCursor::NextBlock);
       
  3266     block = cursor.block();
       
  3267     QTextBlock hr = block;
       
  3268     QVERIFY(qMax(first.blockFormat().bottomMargin(), block.blockFormat().topMargin()) > 0);
       
  3269 
       
  3270     cursor.movePosition(QTextCursor::NextBlock);
       
  3271     block = cursor.block();
       
  3272 
       
  3273     QCOMPARE(block.text(), QString("Blah"));
       
  3274 }
       
  3275 
       
  3276 void tst_QTextDocumentFragment::html_blockQuoteMargins()
       
  3277 {
       
  3278     doc->setHtml("<blockquote>Bar</blockquote>");
       
  3279     QCOMPARE(doc->blockCount(), 1);
       
  3280     cursor.movePosition(QTextCursor::Start);
       
  3281     QTextBlock block = cursor.block();
       
  3282     QCOMPARE(block.text(), QString("Bar"));
       
  3283     QCOMPARE(block.blockFormat().leftMargin(), qreal(40.));
       
  3284     QCOMPARE(block.blockFormat().rightMargin(), qreal(40.));
       
  3285     QCOMPARE(block.blockFormat().topMargin(), qreal(12.));
       
  3286     QCOMPARE(block.blockFormat().bottomMargin(), qreal(12.));
       
  3287 }
       
  3288 
       
  3289 void tst_QTextDocumentFragment::html_definitionListMargins()
       
  3290 {
       
  3291     doc->setHtml("Foo<dl><dt>tag<dd>data</dl>Bar");
       
  3292     QCOMPARE(doc->blockCount(), 4);
       
  3293 
       
  3294     cursor.movePosition(QTextCursor::Start);
       
  3295     QTextBlock block = cursor.block();
       
  3296     QCOMPARE(block.text(), QString("Foo"));
       
  3297 
       
  3298     block = block.next();
       
  3299     QCOMPARE(block.text(), QString("tag"));
       
  3300     QCOMPARE(block.blockFormat().topMargin(), qreal(8.));
       
  3301 
       
  3302     block = block.next();
       
  3303     QCOMPARE(block.text(), QString("data"));
       
  3304     QCOMPARE(block.blockFormat().bottomMargin(), qreal(8.));
       
  3305 
       
  3306     block = block.next();
       
  3307     QCOMPARE(block.text(), QString("Bar"));
       
  3308 }
       
  3309 
       
  3310 void tst_QTextDocumentFragment::html_listMargins()
       
  3311 {
       
  3312     doc->setHtml("Foo<ol><li>First<li>Second</ol>Bar");
       
  3313     QCOMPARE(doc->blockCount(), 4);
       
  3314 
       
  3315     cursor.movePosition(QTextCursor::Start);
       
  3316     QTextBlock block = cursor.block();
       
  3317     QCOMPARE(block.text(), QString("Foo"));
       
  3318 
       
  3319     block = block.next();
       
  3320     QCOMPARE(block.text(), QString("First"));
       
  3321     QCOMPARE(block.blockFormat().topMargin(), qreal(12.));
       
  3322 
       
  3323     block = block.next();
       
  3324     QCOMPARE(block.text(), QString("Second"));
       
  3325     QCOMPARE(block.blockFormat().bottomMargin(), qreal(12.));
       
  3326 
       
  3327     block = block.next();
       
  3328     QCOMPARE(block.text(), QString("Bar"));
       
  3329 }
       
  3330 
       
  3331 void tst_QTextDocumentFragment::html_titleAttribute()
       
  3332 {
       
  3333     doc->setHtml("<span title=\"this is my title\">Test</span>");
       
  3334     cursor.movePosition(QTextCursor::Start);
       
  3335     cursor.movePosition(QTextCursor::NextCharacter);
       
  3336     QCOMPARE(cursor.charFormat().toolTip(), QString("this is my title"));
       
  3337 }
       
  3338 
       
  3339 void tst_QTextDocumentFragment::html_compressDivs()
       
  3340 {
       
  3341     doc->setHtml("<p/><div/><div/><div/><div/>Test");
       
  3342     QCOMPARE(doc->blockCount(), 1);
       
  3343     QCOMPARE(doc->begin().text(), QString("Test"));
       
  3344 }
       
  3345 
       
  3346 void tst_QTextDocumentFragment::completeToPlainText()
       
  3347 {
       
  3348     doc->setPlainText("Hello\nWorld");
       
  3349     QCOMPARE(doc->toPlainText(), QString("Hello\nWorld"));
       
  3350     QTextDocumentFragment fragment(doc);
       
  3351     QCOMPARE(fragment.toPlainText(), QString("Hello\nWorld"));
       
  3352 }
       
  3353 
       
  3354 void tst_QTextDocumentFragment::copyContents()
       
  3355 {
       
  3356     doc->setPlainText("Hello");
       
  3357     QFont f;
       
  3358     doc->setDefaultFont(f);
       
  3359     QTextFragment fragment = doc->begin().begin().fragment();
       
  3360     QCOMPARE(fragment.text(), QString("Hello"));
       
  3361     QCOMPARE(fragment.charFormat().font().pointSize(), f.pointSize());
       
  3362 
       
  3363     QTextDocumentFragment frag(doc);
       
  3364     doc->clear();
       
  3365     f.setPointSize(48);
       
  3366     doc->setDefaultFont(f);
       
  3367     QTextCursor(doc).insertFragment(QTextDocumentFragment::fromHtml(frag.toHtml()));
       
  3368     fragment = doc->begin().begin().fragment();
       
  3369     QCOMPARE(fragment.text(), QString("Hello"));
       
  3370     QCOMPARE(fragment.charFormat().font().pointSize(), f.pointSize());
       
  3371 }
       
  3372 
       
  3373 void tst_QTextDocumentFragment::html_textAfterHr()
       
  3374 {
       
  3375     doc->setHtml("<hr><nobr><b>After the centered text</b></nobr>");
       
  3376     QCOMPARE(doc->blockCount(), 2);
       
  3377     QTextBlock block = doc->begin();
       
  3378     QVERIFY(block.text().isEmpty());
       
  3379     QVERIFY(block.blockFormat().hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth));
       
  3380     block = block.next();
       
  3381 
       
  3382     QString txt("After the centered text");
       
  3383     txt.replace(QLatin1Char(' '), QChar::Nbsp);
       
  3384     QCOMPARE(block.text(), txt);
       
  3385     QVERIFY(!block.blockFormat().hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth));
       
  3386 }
       
  3387 
       
  3388 void tst_QTextDocumentFragment::blockTagClosing()
       
  3389 {
       
  3390     doc->setHtml("<p>foo<p>bar<span>baz</span>");
       
  3391     QCOMPARE(doc->blockCount(), 2);
       
  3392     QTextBlock block = doc->begin();
       
  3393     QCOMPARE(block.text(), QString("foo"));
       
  3394     block = block.next();
       
  3395     QCOMPARE(block.text(), QString("barbaz"));
       
  3396 }
       
  3397 
       
  3398 void tst_QTextDocumentFragment::isEmpty()
       
  3399 {
       
  3400     QTextDocumentFragment frag;
       
  3401     QVERIFY(frag.isEmpty());
       
  3402     frag = QTextDocumentFragment::fromHtml("test");
       
  3403     QVERIFY(!frag.isEmpty());
       
  3404     frag = QTextDocumentFragment::fromHtml("<hr />");
       
  3405     QVERIFY(!frag.isEmpty());
       
  3406 }
       
  3407 
       
  3408 void tst_QTextDocumentFragment::html_alignmentInheritance()
       
  3409 {
       
  3410     doc->setHtml("<center>Centered text<hr></center><b>After the centered text</b>");
       
  3411     QCOMPARE(doc->blockCount(), 3);
       
  3412     QTextBlock block = doc->begin();
       
  3413     QVERIFY(block.blockFormat().alignment() & Qt::AlignHCenter);
       
  3414     block = block.next();
       
  3415     QVERIFY(block.blockFormat().alignment() & Qt::AlignHCenter);
       
  3416     block = block.next();
       
  3417     QVERIFY(!(block.blockFormat().alignment() & Qt::AlignHCenter));
       
  3418 }
       
  3419 
       
  3420 void tst_QTextDocumentFragment::html_ignoreEmptyDivs()
       
  3421 {
       
  3422     doc->setHtml("<p><div/><b>Foo</b>");
       
  3423     QCOMPARE(doc->blockCount(), 1);
       
  3424     QCOMPARE(doc->begin().text(), QString("Foo"));
       
  3425 }
       
  3426 
       
  3427 void tst_QTextDocumentFragment::html_dontInheritAlignmentForFloatingImages()
       
  3428 {
       
  3429     doc->setHtml("<p align=right><img align=unknownignored src=\"foo\" /></p>");
       
  3430     QTextCharFormat fmt = doc->begin().begin().fragment().charFormat();
       
  3431     QVERIFY(fmt.isImageFormat());
       
  3432     QTextObject *o = doc->objectForFormat(fmt);
       
  3433     QVERIFY(o);
       
  3434     QTextFormat f = o->format();
       
  3435     QVERIFY(f.isFrameFormat());
       
  3436     QVERIFY(f.toFrameFormat().position() == QTextFrameFormat::InFlow);
       
  3437 }
       
  3438 
       
  3439 void tst_QTextDocumentFragment::html_verticalImageAlignment()
       
  3440 {
       
  3441     doc->setHtml("<img src=\"foo\"/>");
       
  3442     cursor.movePosition(QTextCursor::Start);
       
  3443     cursor.movePosition(QTextCursor::NextCharacter);
       
  3444     QVERIFY(cursor.charFormat().isImageFormat());
       
  3445     QTextImageFormat fmt = cursor.charFormat().toImageFormat();
       
  3446     QVERIFY(fmt.verticalAlignment() == QTextCharFormat::AlignNormal);
       
  3447 
       
  3448     doc->setHtml("<img src=\"foo\" align=middle />");
       
  3449     cursor.movePosition(QTextCursor::Start);
       
  3450     cursor.movePosition(QTextCursor::NextCharacter);
       
  3451     QVERIFY(cursor.charFormat().isImageFormat());
       
  3452     fmt = cursor.charFormat().toImageFormat();
       
  3453     QVERIFY(fmt.verticalAlignment() == QTextCharFormat::AlignMiddle);
       
  3454 
       
  3455     doc->setHtml("<img src=\"foo\" style=\"vertical-align: middle\" />");
       
  3456     cursor.movePosition(QTextCursor::Start);
       
  3457     cursor.movePosition(QTextCursor::NextCharacter);
       
  3458     QVERIFY(cursor.charFormat().isImageFormat());
       
  3459     fmt = cursor.charFormat().toImageFormat();
       
  3460     QVERIFY(fmt.verticalAlignment() == QTextCharFormat::AlignMiddle);
       
  3461 
       
  3462     doc->setHtml("<img src=\"foo\" align=top />");
       
  3463     cursor.movePosition(QTextCursor::Start);
       
  3464     cursor.movePosition(QTextCursor::NextCharacter);
       
  3465     QVERIFY(cursor.charFormat().isImageFormat());
       
  3466     fmt = cursor.charFormat().toImageFormat();
       
  3467     QVERIFY(fmt.verticalAlignment() == QTextCharFormat::AlignTop);
       
  3468 
       
  3469     doc->setHtml("<img src=\"foo\" style=\"vertical-align: top\" />");
       
  3470     cursor.movePosition(QTextCursor::Start);
       
  3471     cursor.movePosition(QTextCursor::NextCharacter);
       
  3472     QVERIFY(cursor.charFormat().isImageFormat());
       
  3473     fmt = cursor.charFormat().toImageFormat();
       
  3474     QVERIFY(fmt.verticalAlignment() == QTextCharFormat::AlignTop);
       
  3475 }
       
  3476 
       
  3477 void tst_QTextDocumentFragment::html_verticalCellAlignment()
       
  3478 {
       
  3479     const char *alt[] =
       
  3480     {
       
  3481         // vertical-align property
       
  3482         "<table>"
       
  3483         "<tr>"
       
  3484         "<td style=\"vertical-align: middle\"></td>"
       
  3485         "<td style=\"vertical-align: top\"></td>"
       
  3486         "<td style=\"vertical-align: bottom\"></td>"
       
  3487         "</tr>"
       
  3488         "</table>",
       
  3489         // valign property
       
  3490         "<table>"
       
  3491         "<tr>"
       
  3492         "<td valign=\"middle\"></td>"
       
  3493         "<td valign=\"top\"></td>"
       
  3494         "<td valign=\"bottom\"></td>"
       
  3495         "</tr>"
       
  3496         "</table>",
       
  3497         // test td override of tr property
       
  3498         "<table>"
       
  3499         "<tr valign=\"bottom\">"
       
  3500         "<td valign=\"middle\"></td>"
       
  3501         "<td valign=\"top\"></td>"
       
  3502         "<td></td>"
       
  3503         "</tr>"
       
  3504         "</table>"
       
  3505     };
       
  3506 
       
  3507     const int numTestCases = sizeof(alt) / sizeof(*alt);
       
  3508     for (int i = 0; i < numTestCases; ++i) {
       
  3509         doc->setHtml(alt[i]);
       
  3510 
       
  3511         QTextTable *table = qobject_cast<QTextTable *>(doc->rootFrame()->childFrames().at(0));
       
  3512         QVERIFY(table);
       
  3513 
       
  3514         QCOMPARE(table->cellAt(0, 0).format().verticalAlignment(), QTextCharFormat::AlignMiddle);
       
  3515         QCOMPARE(table->cellAt(0, 1).format().verticalAlignment(), QTextCharFormat::AlignTop);
       
  3516         QCOMPARE(table->cellAt(0, 2).format().verticalAlignment(), QTextCharFormat::AlignBottom);
       
  3517     }
       
  3518 }
       
  3519 
       
  3520 void tst_QTextDocumentFragment::html_borderColor()
       
  3521 {
       
  3522     const char html[] = "<table border=1 style=\"border-color:#0000ff;\"><tr><td>Foo</td></tr></table>";
       
  3523     cursor.insertFragment(QTextDocumentFragment::fromHtml(QString::fromLatin1(html)));
       
  3524     cursor.movePosition(QTextCursor::Start);
       
  3525     cursor.movePosition(QTextCursor::NextBlock);
       
  3526     QVERIFY(cursor.currentTable());
       
  3527     QCOMPARE(cursor.currentTable()->format().borderStyle(), QTextFrameFormat::BorderStyle_Outset);
       
  3528     QCOMPARE(cursor.currentTable()->format().borderBrush(), QBrush(QColor("#0000ff")));
       
  3529 }
       
  3530 
       
  3531 void tst_QTextDocumentFragment::html_borderStyle()
       
  3532 {
       
  3533     const char html[] = "<table border=1 style=\"border-style:solid;\"><tr><td>Foo</td></tr></table>";
       
  3534     cursor.insertFragment(QTextDocumentFragment::fromHtml(QString::fromLatin1(html)));
       
  3535     cursor.movePosition(QTextCursor::Start);
       
  3536     cursor.movePosition(QTextCursor::NextBlock);
       
  3537     QVERIFY(cursor.currentTable());
       
  3538     QCOMPARE(cursor.currentTable()->format().borderStyle(), QTextFrameFormat::BorderStyle_Solid);
       
  3539     QCOMPARE(cursor.currentTable()->format().borderBrush(), QBrush(Qt::darkGray));
       
  3540 }
       
  3541 
       
  3542 void tst_QTextDocumentFragment::html_borderWidth()
       
  3543 {
       
  3544     const char *html[2] = { "<table style=\"border-width:2;\"><tr><td>Foo</td></tr></table>",
       
  3545                             "<table style=\"border-width:2px;\"><tr><td>Foo</td></tr></table>" };
       
  3546 
       
  3547     for (int i = 0; i < 2; ++i) {
       
  3548         cursor.insertFragment(QTextDocumentFragment::fromHtml(QString::fromLatin1(html[i])));
       
  3549         cursor.movePosition(QTextCursor::Start);
       
  3550         cursor.movePosition(QTextCursor::NextBlock);
       
  3551         QVERIFY(cursor.currentTable());
       
  3552         QCOMPARE(cursor.currentTable()->format().border(), qreal(2));
       
  3553     }
       
  3554 }
       
  3555 
       
  3556 void tst_QTextDocumentFragment::html_userState()
       
  3557 {
       
  3558     const char html[] = "<p style=\"-qt-user-state:42;\">A</p><p style=\"-qt-user-state:0;\">B</p><p>C</p>";
       
  3559     cursor.insertFragment(QTextDocumentFragment::fromHtml(QString::fromLatin1(html)));
       
  3560     QTextBlock block = doc->begin();
       
  3561     QCOMPARE(block.userState(), 42);
       
  3562     QCOMPARE(block.next().userState(), 0);
       
  3563     QCOMPARE(block.next().next().userState(), -1);
       
  3564 }
       
  3565 
       
  3566 void tst_QTextDocumentFragment::html_rootFrameProperties()
       
  3567 {
       
  3568     const char html[] = "<table border=1 style=\"-qt-table-type:root; margin-top:10px;\"><tr><td>Foo</tr></td>";
       
  3569     doc->setHtml(html);
       
  3570 
       
  3571     QCOMPARE(doc->rootFrame()->childFrames().size(), 0);
       
  3572 
       
  3573     QTextFrameFormat fmt = doc->rootFrame()->frameFormat();
       
  3574     QCOMPARE(fmt.topMargin(), qreal(10));
       
  3575     QCOMPARE(fmt.bottomMargin(), qreal(0));
       
  3576     QCOMPARE(fmt.leftMargin(), qreal(0));
       
  3577     QCOMPARE(fmt.rightMargin(), qreal(0));
       
  3578     QCOMPARE(fmt.border(), qreal(1));
       
  3579 
       
  3580     QString normalFrameHtml = QLatin1String(html);
       
  3581     normalFrameHtml.replace(QLatin1String("root"), QLatin1String("frame"));
       
  3582 
       
  3583     doc->setHtml(normalFrameHtml);
       
  3584     QCOMPARE(doc->rootFrame()->childFrames().size(), 1);
       
  3585 }
       
  3586 
       
  3587 void tst_QTextDocumentFragment::html_appendList()
       
  3588 {
       
  3589     appendHtml("<p>foo</p>");
       
  3590     appendHtml("<ul><li>Line 1</li><li>Line 2</li></ul>");
       
  3591 
       
  3592     QCOMPARE(doc->blockCount(), 3);
       
  3593     QVERIFY(doc->begin().next().textList() != 0);
       
  3594 }
       
  3595 
       
  3596 void tst_QTextDocumentFragment::html_appendList2()
       
  3597 {
       
  3598     appendHtml("1");
       
  3599     appendHtml("<ul><li><img src=\"/foo/bar\" /></li></ul>");
       
  3600 
       
  3601     QCOMPARE(doc->blockCount(), 2);
       
  3602     QVERIFY(doc->begin().next().textList() != 0);
       
  3603 }
       
  3604 
       
  3605 void tst_QTextDocumentFragment::html_alignmentPropertySet()
       
  3606 {
       
  3607     const char html[] = "<p>Test</p>";
       
  3608     setHtml(QString::fromLatin1(html));
       
  3609     QVERIFY(!doc->begin().blockFormat().hasProperty(QTextFormat::BlockAlignment));
       
  3610 }
       
  3611 
       
  3612 void tst_QTextDocumentFragment::html_qt3RichtextWhitespaceMode()
       
  3613 {
       
  3614     setHtml(QString::fromLatin1("<html><head><meta name=\"qrichtext\" content=\"1\" /></head><p>   line with whitespace</p><p>    another line with whitespace</p></body></html>"));
       
  3615     QCOMPARE(doc->blockCount(), 2);
       
  3616 
       
  3617     QTextBlock block = doc->begin();
       
  3618     QVERIFY(block.text().startsWith("   "));
       
  3619 
       
  3620     block = block.next();
       
  3621     QVERIFY(block.text().startsWith("   "));
       
  3622 }
       
  3623 
       
  3624 void tst_QTextDocumentFragment::html_brAfterHr()
       
  3625 {
       
  3626     setHtml(QString::fromLatin1("Text A<br><hr><br>Text B<hr>"));
       
  3627 
       
  3628     QCOMPARE(doc->blockCount(), 4);
       
  3629 
       
  3630     QTextBlock block = doc->begin();
       
  3631     QCOMPARE(block.text(), QString("Text A") + QChar(QChar::LineSeparator));
       
  3632 
       
  3633     block = block.next();
       
  3634     QVERIFY(block.text().isEmpty());
       
  3635 
       
  3636     block = block.next();
       
  3637     QCOMPARE(block.text(), QChar(QChar::LineSeparator) + QString("Text B"));
       
  3638 
       
  3639     block = block.next();
       
  3640     QVERIFY(block.text().isEmpty());
       
  3641 }
       
  3642 
       
  3643 void tst_QTextDocumentFragment::html_unclosedHead()
       
  3644 {
       
  3645     doc->setHtml(QString::fromLatin1("<html><head><title>Test</title><body>Blah</body></html>"));
       
  3646     QCOMPARE(doc->metaInformation(QTextDocument::DocumentTitle), QString::fromLatin1("Test"));
       
  3647     QCOMPARE(doc->toPlainText(), QString::fromLatin1("Blah"));
       
  3648 }
       
  3649 
       
  3650 // duplicated from qtexthtmlparser.cpp
       
  3651 #define MAX_ENTITY 258
       
  3652 static const struct { const char *name; quint16 code; } entities[MAX_ENTITY]= {
       
  3653     { "AElig", 0x00c6 },
       
  3654     { "Aacute", 0x00c1 },
       
  3655     { "Acirc", 0x00c2 },
       
  3656     { "Agrave", 0x00c0 },
       
  3657     { "Alpha", 0x0391 },
       
  3658     { "AMP", 38 },
       
  3659     { "Aring", 0x00c5 },
       
  3660     { "Atilde", 0x00c3 },
       
  3661     { "Auml", 0x00c4 },
       
  3662     { "Beta", 0x0392 },
       
  3663     { "Ccedil", 0x00c7 },
       
  3664     { "Chi", 0x03a7 },
       
  3665     { "Dagger", 0x2021 },
       
  3666     { "Delta", 0x0394 },
       
  3667     { "ETH", 0x00d0 },
       
  3668     { "Eacute", 0x00c9 },
       
  3669     { "Ecirc", 0x00ca },
       
  3670     { "Egrave", 0x00c8 },
       
  3671     { "Epsilon", 0x0395 },
       
  3672     { "Eta", 0x0397 },
       
  3673     { "Euml", 0x00cb },
       
  3674     { "Gamma", 0x0393 },
       
  3675     { "GT", 62 },
       
  3676     { "Iacute", 0x00cd },
       
  3677     { "Icirc", 0x00ce },
       
  3678     { "Igrave", 0x00cc },
       
  3679     { "Iota", 0x0399 },
       
  3680     { "Iuml", 0x00cf },
       
  3681     { "Kappa", 0x039a },
       
  3682     { "Lambda", 0x039b },
       
  3683     { "LT", 60 },
       
  3684     { "Mu", 0x039c },
       
  3685     { "Ntilde", 0x00d1 },
       
  3686     { "Nu", 0x039d },
       
  3687     { "OElig", 0x0152 },
       
  3688     { "Oacute", 0x00d3 },
       
  3689     { "Ocirc", 0x00d4 },
       
  3690     { "Ograve", 0x00d2 },
       
  3691     { "Omega", 0x03a9 },
       
  3692     { "Omicron", 0x039f },
       
  3693     { "Oslash", 0x00d8 },
       
  3694     { "Otilde", 0x00d5 },
       
  3695     { "Ouml", 0x00d6 },
       
  3696     { "Phi", 0x03a6 },
       
  3697     { "Pi", 0x03a0 },
       
  3698     { "Prime", 0x2033 },
       
  3699     { "Psi", 0x03a8 },
       
  3700     { "QUOT", 34 },
       
  3701     { "Rho", 0x03a1 },
       
  3702     { "Scaron", 0x0160 },
       
  3703     { "Sigma", 0x03a3 },
       
  3704     { "THORN", 0x00de },
       
  3705     { "Tau", 0x03a4 },
       
  3706     { "Theta", 0x0398 },
       
  3707     { "Uacute", 0x00da },
       
  3708     { "Ucirc", 0x00db },
       
  3709     { "Ugrave", 0x00d9 },
       
  3710     { "Upsilon", 0x03a5 },
       
  3711     { "Uuml", 0x00dc },
       
  3712     { "Xi", 0x039e },
       
  3713     { "Yacute", 0x00dd },
       
  3714     { "Yuml", 0x0178 },
       
  3715     { "Zeta", 0x0396 },
       
  3716     { "aacute", 0x00e1 },
       
  3717     { "acirc", 0x00e2 },
       
  3718     { "acute", 0x00b4 },
       
  3719     { "aelig", 0x00e6 },
       
  3720     { "agrave", 0x00e0 },
       
  3721     { "alefsym", 0x2135 },
       
  3722     { "alpha", 0x03b1 },
       
  3723     { "amp", 38 },
       
  3724     { "and", 0x22a5 },
       
  3725     { "ang", 0x2220 },
       
  3726     { "apos", 0x0027 },
       
  3727     { "aring", 0x00e5 },
       
  3728     { "asymp", 0x2248 },
       
  3729     { "atilde", 0x00e3 },
       
  3730     { "auml", 0x00e4 },
       
  3731     { "bdquo", 0x201e },
       
  3732     { "beta", 0x03b2 },
       
  3733     { "brvbar", 0x00a6 },
       
  3734     { "bull", 0x2022 },
       
  3735     { "cap", 0x2229 },
       
  3736     { "ccedil", 0x00e7 },
       
  3737     { "cedil", 0x00b8 },
       
  3738     { "cent", 0x00a2 },
       
  3739     { "chi", 0x03c7 },
       
  3740     { "circ", 0x02c6 },
       
  3741     { "clubs", 0x2663 },
       
  3742     { "cong", 0x2245 },
       
  3743     { "copy", 0x00a9 },
       
  3744     { "crarr", 0x21b5 },
       
  3745     { "cup", 0x222a },
       
  3746     { "curren", 0x00a4 },
       
  3747     { "dArr", 0x21d3 },
       
  3748     { "dagger", 0x2020 },
       
  3749     { "darr", 0x2193 },
       
  3750     { "deg", 0x00b0 },
       
  3751     { "delta", 0x03b4 },
       
  3752     { "diams", 0x2666 },
       
  3753     { "divide", 0x00f7 },
       
  3754     { "eacute", 0x00e9 },
       
  3755     { "ecirc", 0x00ea },
       
  3756     { "egrave", 0x00e8 },
       
  3757     { "empty", 0x2205 },
       
  3758     { "emsp", 0x2003 },
       
  3759     { "ensp", 0x2002 },
       
  3760     { "epsilon", 0x03b5 },
       
  3761     { "equiv", 0x2261 },
       
  3762     { "eta", 0x03b7 },
       
  3763     { "eth", 0x00f0 },
       
  3764     { "euml", 0x00eb },
       
  3765     { "euro", 0x20ac },
       
  3766     { "exist", 0x2203 },
       
  3767     { "fnof", 0x0192 },
       
  3768     { "forall", 0x2200 },
       
  3769     { "frac12", 0x00bd },
       
  3770     { "frac14", 0x00bc },
       
  3771     { "frac34", 0x00be },
       
  3772     { "frasl", 0x2044 },
       
  3773     { "gamma", 0x03b3 },
       
  3774     { "ge", 0x2265 },
       
  3775     { "gt", 62 },
       
  3776     { "hArr", 0x21d4 },
       
  3777     { "harr", 0x2194 },
       
  3778     { "hearts", 0x2665 },
       
  3779     { "hellip", 0x2026 },
       
  3780     { "iacute", 0x00ed },
       
  3781     { "icirc", 0x00ee },
       
  3782     { "iexcl", 0x00a1 },
       
  3783     { "igrave", 0x00ec },
       
  3784     { "image", 0x2111 },
       
  3785     { "infin", 0x221e },
       
  3786     { "int", 0x222b },
       
  3787     { "iota", 0x03b9 },
       
  3788     { "iquest", 0x00bf },
       
  3789     { "isin", 0x2208 },
       
  3790     { "iuml", 0x00ef },
       
  3791     { "kappa", 0x03ba },
       
  3792     { "lArr", 0x21d0 },
       
  3793     { "lambda", 0x03bb },
       
  3794     { "lang", 0x2329 },
       
  3795     { "laquo", 0x00ab },
       
  3796     { "larr", 0x2190 },
       
  3797     { "lceil", 0x2308 },
       
  3798     { "ldquo", 0x201c },
       
  3799     { "le", 0x2264 },
       
  3800     { "lfloor", 0x230a },
       
  3801     { "lowast", 0x2217 },
       
  3802     { "loz", 0x25ca },
       
  3803     { "lrm", 0x200e },
       
  3804     { "lsaquo", 0x2039 },
       
  3805     { "lsquo", 0x2018 },
       
  3806     { "lt", 60 },
       
  3807     { "macr", 0x00af },
       
  3808     { "mdash", 0x2014 },
       
  3809     { "micro", 0x00b5 },
       
  3810     { "middot", 0x00b7 },
       
  3811     { "minus", 0x2212 },
       
  3812     { "mu", 0x03bc },
       
  3813     { "nabla", 0x2207 },
       
  3814     { "nbsp", 0x00a0 },
       
  3815     { "ndash", 0x2013 },
       
  3816     { "ne", 0x2260 },
       
  3817     { "ni", 0x220b },
       
  3818     { "not", 0x00ac },
       
  3819     { "notin", 0x2209 },
       
  3820     { "nsub", 0x2284 },
       
  3821     { "ntilde", 0x00f1 },
       
  3822     { "nu", 0x03bd },
       
  3823     { "oacute", 0x00f3 },
       
  3824     { "ocirc", 0x00f4 },
       
  3825     { "oelig", 0x0153 },
       
  3826     { "ograve", 0x00f2 },
       
  3827     { "oline", 0x203e },
       
  3828     { "omega", 0x03c9 },
       
  3829     { "omicron", 0x03bf },
       
  3830     { "oplus", 0x2295 },
       
  3831     { "or", 0x22a6 },
       
  3832     { "ordf", 0x00aa },
       
  3833     { "ordm", 0x00ba },
       
  3834     { "oslash", 0x00f8 },
       
  3835     { "otilde", 0x00f5 },
       
  3836     { "otimes", 0x2297 },
       
  3837     { "ouml", 0x00f6 },
       
  3838     { "para", 0x00b6 },
       
  3839     { "part", 0x2202 },
       
  3840     { "percnt", 0x0025 },
       
  3841     { "permil", 0x2030 },
       
  3842     { "perp", 0x22a5 },
       
  3843     { "phi", 0x03c6 },
       
  3844     { "pi", 0x03c0 },
       
  3845     { "piv", 0x03d6 },
       
  3846     { "plusmn", 0x00b1 },
       
  3847     { "pound", 0x00a3 },
       
  3848     { "prime", 0x2032 },
       
  3849     { "prod", 0x220f },
       
  3850     { "prop", 0x221d },
       
  3851     { "psi", 0x03c8 },
       
  3852     { "quot", 34 },
       
  3853     { "rArr", 0x21d2 },
       
  3854     { "radic", 0x221a },
       
  3855     { "rang", 0x232a },
       
  3856     { "raquo", 0x00bb },
       
  3857     { "rarr", 0x2192 },
       
  3858     { "rceil", 0x2309 },
       
  3859     { "rdquo", 0x201d },
       
  3860     { "real", 0x211c },
       
  3861     { "reg", 0x00ae },
       
  3862     { "rfloor", 0x230b },
       
  3863     { "rho", 0x03c1 },
       
  3864     { "rlm", 0x200f },
       
  3865     { "rsaquo", 0x203a },
       
  3866     { "rsquo", 0x2019 },
       
  3867     { "sbquo", 0x201a },
       
  3868     { "scaron", 0x0161 },
       
  3869     { "sdot", 0x22c5 },
       
  3870     { "sect", 0x00a7 },
       
  3871     { "shy", 0x00ad },
       
  3872     { "sigma", 0x03c3 },
       
  3873     { "sigmaf", 0x03c2 },
       
  3874     { "sim", 0x223c },
       
  3875     { "spades", 0x2660 },
       
  3876     { "sub", 0x2282 },
       
  3877     { "sube", 0x2286 },
       
  3878     { "sum", 0x2211 },
       
  3879     { "sup1", 0x00b9 },
       
  3880     { "sup2", 0x00b2 },
       
  3881     { "sup3", 0x00b3 },
       
  3882     { "sup", 0x2283 },
       
  3883     { "supe", 0x2287 },
       
  3884     { "szlig", 0x00df },
       
  3885     { "tau", 0x03c4 },
       
  3886     { "there4", 0x2234 },
       
  3887     { "theta", 0x03b8 },
       
  3888     { "thetasym", 0x03d1 },
       
  3889     { "thinsp", 0x2009 },
       
  3890     { "thorn", 0x00fe },
       
  3891     { "tilde", 0x02dc },
       
  3892     { "times", 0x00d7 },
       
  3893     { "trade", 0x2122 },
       
  3894     { "uArr", 0x21d1 },
       
  3895     { "uacute", 0x00fa },
       
  3896     { "uarr", 0x2191 },
       
  3897     { "ucirc", 0x00fb },
       
  3898     { "ugrave", 0x00f9 },
       
  3899     { "uml", 0x00a8 },
       
  3900     { "upsih", 0x03d2 },
       
  3901     { "upsilon", 0x03c5 },
       
  3902     { "uuml", 0x00fc },
       
  3903     { "weierp", 0x2118 },
       
  3904     { "xi", 0x03be },
       
  3905     { "yacute", 0x00fd },
       
  3906     { "yen", 0x00a5 },
       
  3907     { "yuml", 0x00ff },
       
  3908     { "zeta", 0x03b6 },
       
  3909     { "zwj", 0x200d },
       
  3910     { "zwnj", 0x200c }
       
  3911 };
       
  3912 
       
  3913 void tst_QTextDocumentFragment::html_entities_data()
       
  3914 {
       
  3915     QTest::addColumn<QString>("html");
       
  3916     QTest::addColumn<quint16>("code");
       
  3917 
       
  3918     for (int i = 0; i < MAX_ENTITY; ++i) {
       
  3919         QTest::newRow(entities[i].name) << QString("<pre>&") + QString::fromLatin1(entities[i].name) + QString(";</pre>")
       
  3920                                         << entities[i].code;
       
  3921     }
       
  3922 }
       
  3923 
       
  3924 void tst_QTextDocumentFragment::html_entities()
       
  3925 {
       
  3926     QFETCH(QString, html);
       
  3927     QFETCH(quint16, code);
       
  3928 
       
  3929     setHtml(html);
       
  3930     QCOMPARE(doc->blockCount(), 1);
       
  3931     QString txt = doc->begin().text();
       
  3932     QCOMPARE(txt.length(), 1);
       
  3933     QCOMPARE(txt.at(0).unicode(), code);
       
  3934 }
       
  3935 
       
  3936 void tst_QTextDocumentFragment::html_ignore_script()
       
  3937 {
       
  3938     doc->setHtml(QString::fromLatin1("<html><script>Test</script><body>Blah</body></html>"));
       
  3939     QCOMPARE(doc->toPlainText(), QString("Blah"));
       
  3940 }
       
  3941 
       
  3942 void tst_QTextDocumentFragment::html_directionWithHtml()
       
  3943 {
       
  3944     doc->setHtml(QString::fromLatin1("<html><body><p>Test<p dir=rtl>RTL<p dir=ltr>LTR"));
       
  3945     QCOMPARE(doc->blockCount(), 3);
       
  3946 
       
  3947     QTextBlock block = doc->firstBlock();
       
  3948     QVERIFY(block.blockFormat().hasProperty(QTextFormat::LayoutDirection));
       
  3949     QVERIFY(block.blockFormat().layoutDirection() == Qt::LeftToRight); // HTML default
       
  3950 
       
  3951     block = block.next();
       
  3952     QVERIFY(block.blockFormat().hasProperty(QTextFormat::LayoutDirection));
       
  3953     QVERIFY(block.blockFormat().layoutDirection() == Qt::RightToLeft);
       
  3954 
       
  3955     block = block.next();
       
  3956     QVERIFY(block.blockFormat().hasProperty(QTextFormat::LayoutDirection));
       
  3957     QVERIFY(block.blockFormat().layoutDirection() == Qt::LeftToRight);
       
  3958 }
       
  3959 
       
  3960 void tst_QTextDocumentFragment::html_directionWithRichText()
       
  3961 {
       
  3962     doc->setHtml(QString::fromLatin1("<p>Test<p dir=rtl>RTL<p dir=ltr>LTR"));
       
  3963     QCOMPARE(doc->blockCount(), 3);
       
  3964 
       
  3965     QTextBlock block = doc->firstBlock();
       
  3966     QVERIFY(!block.blockFormat().hasProperty(QTextFormat::LayoutDirection));
       
  3967 
       
  3968     block = block.next();
       
  3969     QVERIFY(block.blockFormat().hasProperty(QTextFormat::LayoutDirection));
       
  3970     QVERIFY(block.blockFormat().layoutDirection() == Qt::RightToLeft);
       
  3971 
       
  3972     block = block.next();
       
  3973     QVERIFY(block.blockFormat().hasProperty(QTextFormat::LayoutDirection));
       
  3974     QVERIFY(block.blockFormat().layoutDirection() == Qt::LeftToRight);
       
  3975 }
       
  3976 
       
  3977 void tst_QTextDocumentFragment::html_metaInBody()
       
  3978 {
       
  3979     setHtml("<body>Hello<meta>World</body>");
       
  3980     QCOMPARE(doc->toPlainText(), QString("HelloWorld"));
       
  3981 }
       
  3982 
       
  3983 void tst_QTextDocumentFragment::html_importImageWithoutAspectRatio()
       
  3984 {
       
  3985     doc->setHtml("<img src=\"foo\" width=\"100%\" height=\"43\">");
       
  3986     cursor.movePosition(QTextCursor::Start);
       
  3987     cursor.movePosition(QTextCursor::NextCharacter);
       
  3988     QVERIFY(cursor.charFormat().isImageFormat());
       
  3989     QTextImageFormat fmt = cursor.charFormat().toImageFormat();
       
  3990     // qDebug() << fmt.width() << fmt.height();
       
  3991     QVERIFY (fmt.hasProperty(QTextFormat::ImageWidth));
       
  3992     QCOMPARE (fmt.height(), 43.);
       
  3993 
       
  3994     doc->setHtml("<img src=\"foo\" height=\"43\">");
       
  3995     cursor.movePosition(QTextCursor::Start);
       
  3996     cursor.movePosition(QTextCursor::NextCharacter);
       
  3997     QVERIFY(cursor.charFormat().isImageFormat());
       
  3998     fmt = cursor.charFormat().toImageFormat();
       
  3999     QVERIFY (! fmt.hasProperty(QTextFormat::ImageWidth));
       
  4000     QCOMPARE (fmt.height(), 43.);
       
  4001 
       
  4002     doc->setHtml("<img src=\"foo\" width=\"200\">");
       
  4003     cursor.movePosition(QTextCursor::Start);
       
  4004     cursor.movePosition(QTextCursor::NextCharacter);
       
  4005     QVERIFY(cursor.charFormat().isImageFormat());
       
  4006     fmt = cursor.charFormat().toImageFormat();
       
  4007     QVERIFY (! fmt.hasProperty(QTextFormat::ImageHeight));
       
  4008     QCOMPARE (fmt.width(), 200.);
       
  4009 }
       
  4010 
       
  4011 void tst_QTextDocumentFragment::html_fromFirefox()
       
  4012 {
       
  4013     // if you have a html loaded in firefox like <html>Test\nText</html>  then selecting all and copying will
       
  4014     // result in the following text on the clipboard (for text/html)
       
  4015     doc->setHtml(QString::fromLatin1("<!--StartFragment-->Test\nText\n\n<!--EndFragment-->"));
       
  4016     QCOMPARE(doc->toPlainText(), QString::fromLatin1("Test Text "));
       
  4017 }
       
  4018 
       
  4019 QTEST_MAIN(tst_QTextDocumentFragment)
       
  4020 #include "tst_qtextdocumentfragment.moc"