tests/auto/qtextdocument/tst_qtextdocument.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 <qdebug.h>
       
    48 
       
    49 #include <qtextcursor.h>
       
    50 #include <qtextdocumentfragment.h>
       
    51 #include <qtextformat.h>
       
    52 #include <qtextobject.h>
       
    53 #include <qtexttable.h>
       
    54 #include <qabstracttextdocumentlayout.h>
       
    55 #include <qtextlist.h>
       
    56 #include <qtextcodec.h>
       
    57 #include <qurl.h>
       
    58 #include <qpainter.h>
       
    59 #include <qfontmetrics.h>
       
    60 #include <qimage.h>
       
    61 #include <qtextlayout.h>
       
    62 #include "common.h"
       
    63 
       
    64 
       
    65 QT_FORWARD_DECLARE_CLASS(QTextDocument)
       
    66 
       
    67 //TESTED_CLASS=
       
    68 //TESTED_FILES=
       
    69 
       
    70 class tst_QTextDocument : public QObject
       
    71 {
       
    72     Q_OBJECT
       
    73 
       
    74 public:
       
    75     tst_QTextDocument();
       
    76     virtual ~tst_QTextDocument();
       
    77 
       
    78 public slots:
       
    79     void init();
       
    80     void cleanup();
       
    81 private slots:
       
    82     void getSetCheck();
       
    83     void isEmpty();
       
    84     void find_data();
       
    85     void find();
       
    86     void find2();
       
    87     void findWithRegExp_data();
       
    88     void findWithRegExp();
       
    89     void findMultiple();
       
    90     void basicIsModifiedChecks();
       
    91     void moreIsModified();
       
    92     void isModified2();
       
    93     void isModified3();
       
    94     void isModified4();
       
    95     void noundo_basicIsModifiedChecks();
       
    96     void noundo_moreIsModified();
       
    97     void noundo_isModified2();
       
    98     void noundo_isModified3();
       
    99     void mightBeRichText();
       
   100 
       
   101     void task240325();
       
   102 
       
   103     void stylesheetFont_data();
       
   104     void stylesheetFont();
       
   105 
       
   106     void toHtml_data();
       
   107     void toHtml();
       
   108     void toHtml2();
       
   109 
       
   110     void setFragmentMarkersInHtmlExport();
       
   111 
       
   112     void toHtmlBodyBgColor();
       
   113     void toHtmlRootFrameProperties();
       
   114     void capitalizationHtmlInExport();
       
   115     void wordspacingHtmlExport();
       
   116 
       
   117     void cursorPositionChanged();
       
   118     void cursorPositionChangedOnSetText();
       
   119 
       
   120     void textFrameIterator();
       
   121 
       
   122     void codecForHtml();
       
   123 
       
   124     void markContentsDirty();
       
   125 
       
   126     void clonePreservesMetaInformation();
       
   127     void clonePreservesPageSize();
       
   128     void clonePreservesPageBreakPolicies();
       
   129     void clonePreservesDefaultFont();
       
   130     void clonePreservesRootFrameFormat();
       
   131     void clonePreservesResources();
       
   132     void clonePreservesUserStates();
       
   133     void clonePreservesIndentWidth();
       
   134     void blockCount();
       
   135     void defaultStyleSheet();
       
   136 
       
   137     void resolvedFontInEmptyFormat();
       
   138 
       
   139     void defaultRootFrameMargin();
       
   140 
       
   141     void clearResources();
       
   142 
       
   143     void setPlainText();
       
   144     void toPlainText();
       
   145 
       
   146     void deleteTextObjectsOnClear();
       
   147 
       
   148     void maximumBlockCount();
       
   149     void adjustSize();
       
   150     void initialUserData();
       
   151 
       
   152     void html_defaultFont();
       
   153 
       
   154     void blockCountChanged();
       
   155 
       
   156     void nonZeroDocumentLengthOnClear();
       
   157 
       
   158     void setTextPreservesUndoRedoEnabled();
       
   159 
       
   160     void firstLast();
       
   161 
       
   162     void backgroundImage_toHtml();
       
   163     void backgroundImage_toHtml2();
       
   164     void backgroundImage_clone();
       
   165     void backgroundImage_copy();
       
   166 
       
   167     void documentCleanup();
       
   168 
       
   169     void characterAt();
       
   170     void revisions();
       
   171     void revisionWithUndoCompressionAndUndo();
       
   172 
       
   173     void testUndoCommandAdded();
       
   174 
       
   175     void testUndoBlocks();
       
   176 
       
   177     void receiveCursorPositionChangedAfterContentsChange();
       
   178 
       
   179 private:
       
   180     void backgroundImage_checkExpectedHtml(const QTextDocument &doc);
       
   181 
       
   182     QTextDocument *doc;
       
   183     QTextCursor cursor;
       
   184     QFont defaultFont;
       
   185     QString htmlHead;
       
   186     QString htmlTail;
       
   187 };
       
   188 
       
   189 class MyAbstractTextDocumentLayout : public QAbstractTextDocumentLayout
       
   190 {
       
   191 public:
       
   192     MyAbstractTextDocumentLayout(QTextDocument *doc) : QAbstractTextDocumentLayout(doc) {}
       
   193     void draw(QPainter *, const PaintContext &) {}
       
   194     int hitTest(const QPointF &, Qt::HitTestAccuracy) const { return 0; }
       
   195     int pageCount() const { return 0; }
       
   196     QSizeF documentSize() const { return QSizeF(); }
       
   197     QRectF frameBoundingRect(QTextFrame *) const { return QRectF(); }
       
   198     QRectF blockBoundingRect(const QTextBlock &) const { return QRectF(); }
       
   199     void documentChanged(int, int, int) {}
       
   200 };
       
   201 
       
   202 // Testing get/set functions
       
   203 void tst_QTextDocument::getSetCheck()
       
   204 {
       
   205     QTextDocument obj1;
       
   206     // QAbstractTextDocumentLayout * QTextDocument::documentLayout()
       
   207     // void QTextDocument::setDocumentLayout(QAbstractTextDocumentLayout *)
       
   208     QPointer<MyAbstractTextDocumentLayout> var1 = new MyAbstractTextDocumentLayout(0);
       
   209     obj1.setDocumentLayout(var1);
       
   210     QCOMPARE(static_cast<QAbstractTextDocumentLayout *>(var1), obj1.documentLayout());
       
   211     obj1.setDocumentLayout((QAbstractTextDocumentLayout *)0);
       
   212     QVERIFY(var1.isNull());
       
   213     QVERIFY(obj1.documentLayout());
       
   214 
       
   215     // bool QTextDocument::useDesignMetrics()
       
   216     // void QTextDocument::setUseDesignMetrics(bool)
       
   217     obj1.setUseDesignMetrics(false);
       
   218     QCOMPARE(false, obj1.useDesignMetrics());
       
   219     obj1.setUseDesignMetrics(true);
       
   220     QCOMPARE(true, obj1.useDesignMetrics());
       
   221 }
       
   222 
       
   223 tst_QTextDocument::tst_QTextDocument()
       
   224 {
       
   225     QImage img(16, 16, QImage::Format_ARGB32_Premultiplied);
       
   226     img.save("foo.png");
       
   227 }
       
   228 
       
   229 tst_QTextDocument::~tst_QTextDocument()
       
   230 {
       
   231     QFile::remove(QLatin1String("foo.png"));
       
   232 }
       
   233 
       
   234 void tst_QTextDocument::init()
       
   235 {
       
   236     doc = new QTextDocument;
       
   237     cursor = QTextCursor(doc);
       
   238     defaultFont = QFont();
       
   239 
       
   240     htmlHead = QString("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" "
       
   241             "\"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
       
   242             "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
       
   243             "p, li { white-space: pre-wrap; }\n"
       
   244             "</style></head>"
       
   245             "<body style=\" font-family:'%1'; font-size:%2pt; font-weight:%3; font-style:%4;\">\n");
       
   246     htmlHead = htmlHead.arg(defaultFont.family()).arg(defaultFont.pointSizeF()).arg(defaultFont.weight() * 8).arg((defaultFont.italic() ? "italic" : "normal"));
       
   247 
       
   248     htmlTail = QString("</body></html>");
       
   249 }
       
   250 
       
   251 void tst_QTextDocument::cleanup()
       
   252 {
       
   253     cursor = QTextCursor();
       
   254     delete doc;
       
   255     doc = 0;
       
   256 }
       
   257 
       
   258 void tst_QTextDocument::isEmpty()
       
   259 {
       
   260     QVERIFY(doc->isEmpty());
       
   261 }
       
   262 
       
   263 void tst_QTextDocument::find_data()
       
   264 {
       
   265     QTest::addColumn<QString>("haystack");
       
   266     QTest::addColumn<QString>("needle");
       
   267     QTest::addColumn<int>("flags");
       
   268     QTest::addColumn<int>("from");
       
   269     QTest::addColumn<int>("anchor");
       
   270     QTest::addColumn<int>("position");
       
   271 
       
   272     QTest::newRow("1") << "Hello World" << "World" << int(QTextDocument::FindCaseSensitively) << 0 << 6 << 11;
       
   273 
       
   274     QTest::newRow("2") << QString::fromAscii("Hello") + QString(QChar::ParagraphSeparator) + QString::fromAscii("World")
       
   275                     << "World" << int(QTextDocument::FindCaseSensitively) << 1 << 6 << 11;
       
   276 
       
   277     QTest::newRow("3") << QString::fromAscii("Hello") + QString(QChar::ParagraphSeparator) + QString::fromAscii("World")
       
   278                     << "Hello" << int(QTextDocument::FindCaseSensitively | QTextDocument::FindBackward) << 10 << 0 << 5;
       
   279     QTest::newRow("4wholewords") << QString::fromAscii("Hello Blah World")
       
   280                               << "Blah" << int(QTextDocument::FindWholeWords) << 0 << 6 << 10;
       
   281     QTest::newRow("5wholewords") << QString::fromAscii("HelloBlahWorld")
       
   282                               << "Blah" << int(QTextDocument::FindWholeWords) << 0 << -1 << -1;
       
   283     QTest::newRow("6wholewords") << QString::fromAscii("HelloBlahWorld Blah Hah")
       
   284                               << "Blah" << int(QTextDocument::FindWholeWords) << 0 << 15 << 19;
       
   285     QTest::newRow("7wholewords") << QString::fromAscii("HelloBlahWorld Blah Hah")
       
   286                               << "Blah" << int(QTextDocument::FindWholeWords | QTextDocument::FindBackward) << 23 << 15 << 19;
       
   287     QTest::newRow("8wholewords") << QString::fromAscii("Hello: World\n")
       
   288                               << "orld" << int(QTextDocument::FindWholeWords) << 0 << -1 << -1;
       
   289 
       
   290     QTest::newRow("across-paragraphs") << QString::fromAscii("First Parag\nSecond Parag with a lot more text")
       
   291                                        << "Parag" << int(QTextDocument::FindBackward)
       
   292                                        << 15 << 6 << 11;
       
   293 
       
   294     QTest::newRow("nbsp") << "Hello" + QString(QChar(QChar::Nbsp)) +"World" << " " << int(QTextDocument::FindCaseSensitively) << 0 << 5 << 6;
       
   295 }
       
   296 
       
   297 void tst_QTextDocument::find()
       
   298 {
       
   299     QFETCH(QString, haystack);
       
   300     QFETCH(QString, needle);
       
   301     QFETCH(int, flags);
       
   302     QFETCH(int, from);
       
   303     QFETCH(int, anchor);
       
   304     QFETCH(int, position);
       
   305 
       
   306     cursor.insertText(haystack);
       
   307     cursor = doc->find(needle, from, QTextDocument::FindFlags(flags));
       
   308 
       
   309     if (anchor != -1) {
       
   310         QCOMPARE(cursor.anchor(), anchor);
       
   311         QCOMPARE(cursor.position(), position);
       
   312     } else {
       
   313         QVERIFY(cursor.isNull());
       
   314     }
       
   315 
       
   316     //search using a regular expression
       
   317     QRegExp expr(needle);
       
   318     expr.setPatternSyntax(QRegExp::FixedString);
       
   319     QTextDocument::FindFlags flg(flags);
       
   320     expr.setCaseSensitivity((flg & QTextDocument::FindCaseSensitively) ? Qt::CaseSensitive : Qt::CaseInsensitive);
       
   321     cursor = doc->find(expr, from, flg);
       
   322 
       
   323     if (anchor != -1) {
       
   324         QCOMPARE(cursor.anchor(), anchor);
       
   325         QCOMPARE(cursor.position(), position);
       
   326     } else {
       
   327         QVERIFY(cursor.isNull());
       
   328     }
       
   329 }
       
   330 
       
   331 void tst_QTextDocument::findWithRegExp_data()
       
   332 {
       
   333     QTest::addColumn<QString>("haystack");
       
   334     QTest::addColumn<QString>("needle");
       
   335     QTest::addColumn<int>("flags");
       
   336     QTest::addColumn<int>("from");
       
   337     QTest::addColumn<int>("anchor");
       
   338     QTest::addColumn<int>("position");
       
   339 
       
   340     // match integers 0 to 99
       
   341     QTest::newRow("1") << "23" << "^\\d\\d?$" << int(QTextDocument::FindCaseSensitively) << 0 << 0 << 2;
       
   342     // match ampersands but not &amp;
       
   343     QTest::newRow("2") << "His &amp; hers & theirs" << "&(?!amp;)"<< int(QTextDocument::FindCaseSensitively) << 0 << 15 << 16;
       
   344     //backward search
       
   345     QTest::newRow("3") << QString::fromAscii("HelloBlahWorld Blah Hah")
       
   346                               << "h" << int(QTextDocument::FindBackward) << 18 << 8 << 9;
       
   347 
       
   348 }
       
   349 
       
   350 void tst_QTextDocument::findWithRegExp()
       
   351 {
       
   352     QFETCH(QString, haystack);
       
   353     QFETCH(QString, needle);
       
   354     QFETCH(int, flags);
       
   355     QFETCH(int, from);
       
   356     QFETCH(int, anchor);
       
   357     QFETCH(int, position);
       
   358 
       
   359     cursor.insertText(haystack);
       
   360     //search using a regular expression
       
   361     QRegExp expr(needle);
       
   362     QTextDocument::FindFlags flg(flags);
       
   363     expr.setCaseSensitivity((flg & QTextDocument::FindCaseSensitively) ? Qt::CaseSensitive : Qt::CaseInsensitive);
       
   364     cursor = doc->find(expr, from, flg);
       
   365 
       
   366     if (anchor != -1) {
       
   367         QCOMPARE(cursor.anchor(), anchor);
       
   368         QCOMPARE(cursor.position(), position);
       
   369     } else {
       
   370         QVERIFY(cursor.isNull());
       
   371     }
       
   372 }
       
   373 
       
   374 void tst_QTextDocument::find2()
       
   375 {
       
   376     doc->setPlainText("aaa");
       
   377     cursor.movePosition(QTextCursor::Start);
       
   378     cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
       
   379     QTextCursor hit = doc->find("a", cursor);
       
   380     QCOMPARE(hit.position(), 2);
       
   381     QCOMPARE(hit.anchor(), 1);
       
   382 }
       
   383 
       
   384 void tst_QTextDocument::findMultiple()
       
   385 {
       
   386     const QString text("foo bar baz foo bar baz");
       
   387     doc->setPlainText(text);
       
   388 
       
   389     cursor.movePosition(QTextCursor::Start);
       
   390     cursor = doc->find("bar", cursor);
       
   391     QCOMPARE(cursor.selectionStart(), text.indexOf("bar"));
       
   392     QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3);
       
   393     cursor = doc->find("bar", cursor);
       
   394     QCOMPARE(cursor.selectionStart(), text.lastIndexOf("bar"));
       
   395     QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3);
       
   396 
       
   397     cursor.movePosition(QTextCursor::End);
       
   398     cursor = doc->find("bar", cursor, QTextDocument::FindBackward);
       
   399     QCOMPARE(cursor.selectionStart(), text.lastIndexOf("bar"));
       
   400     QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3);
       
   401     cursor = doc->find("bar", cursor, QTextDocument::FindBackward);
       
   402     QCOMPARE(cursor.selectionStart(), text.indexOf("bar"));
       
   403     QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3);
       
   404 
       
   405 
       
   406     QRegExp expr("bar");
       
   407     expr.setPatternSyntax(QRegExp::FixedString);
       
   408 
       
   409     cursor.movePosition(QTextCursor::End);
       
   410     cursor = doc->find(expr, cursor, QTextDocument::FindBackward);
       
   411     QCOMPARE(cursor.selectionStart(), text.lastIndexOf("bar"));
       
   412     QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3);
       
   413     cursor = doc->find(expr, cursor, QTextDocument::FindBackward);
       
   414     QCOMPARE(cursor.selectionStart(), text.indexOf("bar"));
       
   415     QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3);
       
   416 
       
   417     cursor.movePosition(QTextCursor::Start);
       
   418     cursor = doc->find(expr, cursor);
       
   419     QCOMPARE(cursor.selectionStart(), text.indexOf("bar"));
       
   420     QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3);
       
   421     cursor = doc->find(expr, cursor);
       
   422     QCOMPARE(cursor.selectionStart(), text.lastIndexOf("bar"));
       
   423     QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3);
       
   424 }
       
   425 
       
   426 void tst_QTextDocument::basicIsModifiedChecks()
       
   427 {
       
   428     QSignalSpy spy(doc, SIGNAL(modificationChanged(bool)));
       
   429 
       
   430     QVERIFY(!doc->isModified());
       
   431     cursor.insertText("Hello World");
       
   432     QVERIFY(doc->isModified());
       
   433     QCOMPARE(spy.count(), 1);
       
   434     QVERIFY(spy.takeFirst().at(0).toBool());
       
   435 
       
   436     doc->undo();
       
   437     QVERIFY(!doc->isModified());
       
   438     QCOMPARE(spy.count(), 1);
       
   439     QVERIFY(!spy.takeFirst().at(0).toBool());
       
   440 
       
   441     doc->redo();
       
   442     QVERIFY(doc->isModified());
       
   443     QCOMPARE(spy.count(), 1);
       
   444     QVERIFY(spy.takeFirst().at(0).toBool());
       
   445 }
       
   446 
       
   447 void tst_QTextDocument::moreIsModified()
       
   448 {
       
   449     QVERIFY(!doc->isModified());
       
   450 
       
   451     cursor.insertText("Hello");
       
   452     QVERIFY(doc->isModified());
       
   453 
       
   454     doc->undo();
       
   455     QVERIFY(!doc->isModified());
       
   456 
       
   457     cursor.insertText("Hello");
       
   458 
       
   459     doc->undo();
       
   460     QVERIFY(!doc->isModified());
       
   461 }
       
   462 
       
   463 void tst_QTextDocument::isModified2()
       
   464 {
       
   465     // reported on qt4-preview-feedback
       
   466     QVERIFY(!doc->isModified());
       
   467 
       
   468     cursor.insertText("Hello");
       
   469     QVERIFY(doc->isModified());
       
   470 
       
   471     doc->setModified(false);
       
   472     QVERIFY(!doc->isModified());
       
   473 
       
   474     cursor.insertText("Hello");
       
   475     QVERIFY(doc->isModified());
       
   476 }
       
   477 
       
   478 void tst_QTextDocument::isModified3()
       
   479 {
       
   480     QVERIFY(!doc->isModified());
       
   481 
       
   482     doc->setUndoRedoEnabled(false);
       
   483     doc->setUndoRedoEnabled(true);
       
   484 
       
   485     cursor.insertText("Hello");
       
   486 
       
   487     QVERIFY(doc->isModified());
       
   488     doc->undo();
       
   489     QVERIFY(!doc->isModified());
       
   490 }
       
   491 
       
   492 void tst_QTextDocument::isModified4()
       
   493 {
       
   494     QVERIFY(!doc->isModified());
       
   495 
       
   496     cursor.insertText("Hello");
       
   497     cursor.insertText("World");
       
   498 
       
   499     doc->setModified(false);
       
   500 
       
   501     QVERIFY(!doc->isModified());
       
   502 
       
   503     cursor.insertText("Again");
       
   504     QVERIFY(doc->isModified());
       
   505 
       
   506     doc->undo();
       
   507     QVERIFY(!doc->isModified());
       
   508     doc->undo();
       
   509     QVERIFY(doc->isModified());
       
   510 
       
   511     doc->redo();
       
   512     QVERIFY(!doc->isModified());
       
   513     doc->redo();
       
   514     QVERIFY(doc->isModified());
       
   515 
       
   516     doc->undo();
       
   517     QVERIFY(!doc->isModified());
       
   518     doc->undo();
       
   519     QVERIFY(doc->isModified());
       
   520 
       
   521     //task 197769
       
   522     cursor.insertText("Hello");
       
   523     QVERIFY(doc->isModified());
       
   524 }
       
   525 
       
   526 void tst_QTextDocument::noundo_basicIsModifiedChecks()
       
   527 {
       
   528     doc->setUndoRedoEnabled(false);
       
   529     QSignalSpy spy(doc, SIGNAL(modificationChanged(bool)));
       
   530 
       
   531     QVERIFY(!doc->isModified());
       
   532     cursor.insertText("Hello World");
       
   533     QVERIFY(doc->isModified());
       
   534     QCOMPARE(spy.count(), 1);
       
   535     QVERIFY(spy.takeFirst().at(0).toBool());
       
   536 
       
   537     doc->undo();
       
   538     QVERIFY(doc->isModified());
       
   539     QCOMPARE(spy.count(), 0);
       
   540 
       
   541     doc->redo();
       
   542     QVERIFY(doc->isModified());
       
   543     QCOMPARE(spy.count(), 0);
       
   544 }
       
   545 
       
   546 void tst_QTextDocument::task240325()
       
   547 {
       
   548     doc->setHtml("<html><img width=\"100\" height=\"100\" align=\"right\"/>Foobar Foobar Foobar Foobar</html>");
       
   549 
       
   550     QImage img(1000, 7000, QImage::Format_ARGB32_Premultiplied);
       
   551     QPainter p(&img);
       
   552     QFontMetrics fm(p.font());
       
   553 
       
   554     // Set page size to contain image and one "Foobar"
       
   555     doc->setPageSize(QSize(100 + fm.width("Foobar")*2, 1000));
       
   556 
       
   557     // Force layout
       
   558     doc->drawContents(&p);
       
   559 
       
   560     QCOMPARE(doc->blockCount(), 1);
       
   561     for (QTextBlock block = doc->begin() ; block!=doc->end() ; block = block.next()) {
       
   562         QTextLayout *layout = block.layout();
       
   563         QCOMPARE(layout->lineCount(), 4);
       
   564         for (int lineIdx=0;lineIdx<layout->lineCount();++lineIdx) {
       
   565             QTextLine line = layout->lineAt(lineIdx);
       
   566 
       
   567             QString text = block.text().mid(line.textStart(), line.textLength()).trimmed();
       
   568 
       
   569             // Remove start token
       
   570             if (lineIdx == 0)
       
   571                 text = text.mid(1);
       
   572 
       
   573             QCOMPARE(text, QString::fromLatin1("Foobar"));
       
   574         }
       
   575     }
       
   576 }
       
   577 
       
   578 void tst_QTextDocument::stylesheetFont_data()
       
   579 {    
       
   580     QTest::addColumn<QString>("stylesheet");
       
   581     QTest::addColumn<QFont>("font");
       
   582 
       
   583     {
       
   584         QFont font;
       
   585         font.setBold(true);
       
   586         font.setPixelSize(64);
       
   587 
       
   588         QTest::newRow("Regular font specification")
       
   589                  << "font-size: 64px; font-weight: bold;"
       
   590                  << font;
       
   591     }
       
   592 
       
   593 
       
   594     {
       
   595         QFont font;
       
   596         font.setBold(true);
       
   597         font.setPixelSize(64);
       
   598 
       
   599         QTest::newRow("Shorthand font specification")
       
   600                 << "font: normal bold 64px Arial;"
       
   601                 << font;
       
   602     }
       
   603 
       
   604 }
       
   605 
       
   606 void tst_QTextDocument::stylesheetFont()
       
   607 {
       
   608     QFETCH(QString, stylesheet);
       
   609     QFETCH(QFont, font);
       
   610 
       
   611     QString html = QString::fromLatin1("<html>"
       
   612                                        "<body>"
       
   613                                        "<div style=\"%1\" >"
       
   614                                        "Foobar"
       
   615                                        "</div>"
       
   616                                        "</body>"
       
   617                                        "</html>").arg(stylesheet);
       
   618 
       
   619     qDebug() << html;
       
   620     doc->setHtml(html);
       
   621     QCOMPARE(doc->blockCount(), 1);
       
   622 
       
   623     // First and only block
       
   624     QTextBlock block = doc->firstBlock();
       
   625 
       
   626     QString text = block.text();
       
   627     QCOMPARE(text, QString::fromLatin1("Foobar"));
       
   628 
       
   629     QFont actualFont = block.charFormat().font();
       
   630 
       
   631     QCOMPARE(actualFont.bold(), font.bold());
       
   632     QCOMPARE(actualFont.pixelSize(), font.pixelSize());
       
   633 }
       
   634 
       
   635 void tst_QTextDocument::noundo_moreIsModified()
       
   636 {
       
   637     doc->setUndoRedoEnabled(false);
       
   638     QVERIFY(!doc->isModified());
       
   639 
       
   640     cursor.insertText("Hello");
       
   641     QVERIFY(doc->isModified());
       
   642 
       
   643     doc->undo();
       
   644     QVERIFY(doc->isModified());
       
   645 
       
   646     cursor.insertText("Hello");
       
   647 
       
   648     doc->undo();
       
   649     QVERIFY(doc->isModified());
       
   650 }
       
   651 
       
   652 void tst_QTextDocument::noundo_isModified2()
       
   653 {
       
   654     // reported on qt4-preview-feedback
       
   655     QVERIFY(!doc->isModified());
       
   656 
       
   657     cursor.insertText("Hello");
       
   658     QVERIFY(doc->isModified());
       
   659 
       
   660     doc->setModified(false);
       
   661     QVERIFY(!doc->isModified());
       
   662 
       
   663     cursor.insertText("Hello");
       
   664     QVERIFY(doc->isModified());
       
   665 }
       
   666 
       
   667 void tst_QTextDocument::noundo_isModified3()
       
   668 {
       
   669     doc->setUndoRedoEnabled(false);
       
   670     QVERIFY(!doc->isModified());
       
   671 
       
   672     cursor.insertText("Hello");
       
   673 
       
   674     QVERIFY(doc->isModified());
       
   675     doc->undo();
       
   676     QVERIFY(doc->isModified());
       
   677 }
       
   678 
       
   679 void tst_QTextDocument::mightBeRichText()
       
   680 {
       
   681     const char qtDocuHeader[] = "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
       
   682                                 "<!DOCTYPE html\n"
       
   683                                 "    PUBLIC ""-//W3C//DTD XHTML 1.0 Strict//EN\" \"DTD/xhtml1-strict.dtd\">\n"
       
   684                                 "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">";
       
   685     QVERIFY(Qt::mightBeRichText(QString::fromLatin1(qtDocuHeader)));
       
   686 }
       
   687 
       
   688 Q_DECLARE_METATYPE(QTextDocumentFragment)
       
   689 
       
   690 #define CREATE_DOC_AND_CURSOR() \
       
   691         QTextDocument doc; \
       
   692         doc.setDefaultFont(defaultFont); \
       
   693         QTextCursor cursor(&doc);
       
   694 
       
   695 void tst_QTextDocument::toHtml_data()
       
   696 {
       
   697     QTest::addColumn<QTextDocumentFragment>("input");
       
   698     QTest::addColumn<QString>("expectedOutput");
       
   699 
       
   700     {
       
   701         CREATE_DOC_AND_CURSOR();
       
   702 
       
   703         cursor.insertText("Blah");
       
   704 
       
   705         QTest::newRow("simple") << QTextDocumentFragment(&doc) << QString("<p DEFAULTBLOCKSTYLE>Blah</p>");
       
   706     }
       
   707 
       
   708     {
       
   709         CREATE_DOC_AND_CURSOR();
       
   710 
       
   711         cursor.insertText("&<>");
       
   712 
       
   713         QTest::newRow("entities") << QTextDocumentFragment(&doc) << QString("<p DEFAULTBLOCKSTYLE>&amp;&lt;&gt;</p>");
       
   714     }
       
   715 
       
   716     {
       
   717         CREATE_DOC_AND_CURSOR();
       
   718 
       
   719         QTextCharFormat fmt;
       
   720         fmt.setFontFamily("Times");
       
   721         cursor.insertText("Blah", fmt);
       
   722 
       
   723         QTest::newRow("font-family") << QTextDocumentFragment(&doc)
       
   724                                   << QString("<p DEFAULTBLOCKSTYLE><span style=\" font-family:'Times';\">Blah</span></p>");
       
   725     }
       
   726 
       
   727     {
       
   728         CREATE_DOC_AND_CURSOR();
       
   729 
       
   730         QTextCharFormat fmt;
       
   731         fmt.setFontFamily("Foo's Family");
       
   732         cursor.insertText("Blah", fmt);
       
   733 
       
   734         QTest::newRow("font-family-with-quotes1") << QTextDocumentFragment(&doc)
       
   735                                   << QString("<p DEFAULTBLOCKSTYLE><span style=\" font-family:\"Foo's Family\";\">Blah</span></p>");
       
   736     }
       
   737 
       
   738     {
       
   739         CREATE_DOC_AND_CURSOR();
       
   740 
       
   741         QTextCharFormat fmt;
       
   742         fmt.setFontFamily("Foo\"s Family");
       
   743         cursor.insertText("Blah", fmt);
       
   744 
       
   745         QTest::newRow("font-family-with-quotes2") << QTextDocumentFragment(&doc)
       
   746                                   << QString("<p DEFAULTBLOCKSTYLE><span style=\" font-family:'Foo\"s Family';\">Blah</span></p>");
       
   747     }
       
   748 
       
   749     {
       
   750         CREATE_DOC_AND_CURSOR();
       
   751 
       
   752         QTextBlockFormat fmt;
       
   753         fmt.setNonBreakableLines(true);
       
   754         cursor.insertBlock(fmt);
       
   755         cursor.insertText("Blah");
       
   756 
       
   757         QTest::newRow("pre") << QTextDocumentFragment(&doc)
       
   758                           <<
       
   759                              QString("EMPTYBLOCK") +
       
   760                              QString("<pre DEFAULTBLOCKSTYLE>Blah</pre>");
       
   761     }
       
   762 
       
   763     {
       
   764         CREATE_DOC_AND_CURSOR();
       
   765 
       
   766         QTextCharFormat fmt;
       
   767         fmt.setFontPointSize(40);
       
   768         cursor.insertText("Blah", fmt);
       
   769 
       
   770         QTest::newRow("font-size") << QTextDocumentFragment(&doc)
       
   771                                 << QString("<p DEFAULTBLOCKSTYLE><span style=\" font-size:40pt;\">Blah</span></p>");
       
   772     }
       
   773 
       
   774     {
       
   775         CREATE_DOC_AND_CURSOR();
       
   776 
       
   777         QTextCharFormat fmt;
       
   778         fmt.setProperty(QTextFormat::FontSizeIncrement, 2);
       
   779         cursor.insertText("Blah", fmt);
       
   780 
       
   781         QTest::newRow("logical-font-size") << QTextDocumentFragment(&doc)
       
   782                                         << QString("<p DEFAULTBLOCKSTYLE><span style=\" font-size:x-large;\">Blah</span></p>");
       
   783     }
       
   784 
       
   785     {
       
   786         CREATE_DOC_AND_CURSOR();
       
   787 
       
   788         cursor.insertText("Foo");
       
   789 
       
   790         QTextCharFormat fmt;
       
   791         fmt.setFontPointSize(40);
       
   792         cursor.insertBlock(QTextBlockFormat(), fmt);
       
   793 
       
   794         fmt.clearProperty(QTextFormat::FontPointSize);
       
   795         cursor.insertText("Blub", fmt);
       
   796 
       
   797         QTest::newRow("no-font-size") << QTextDocumentFragment(&doc)
       
   798                                    << QString("<p DEFAULTBLOCKSTYLE>Foo</p>\n<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Blub</p>");
       
   799     }
       
   800 
       
   801     {
       
   802         CREATE_DOC_AND_CURSOR();
       
   803 
       
   804         QTextBlockFormat fmt;
       
   805         fmt.setLayoutDirection(Qt::RightToLeft);
       
   806         cursor.insertBlock(fmt);
       
   807         cursor.insertText("Blah");
       
   808 
       
   809         QTest::newRow("rtl") << QTextDocumentFragment(&doc)
       
   810                           <<
       
   811                              QString("EMPTYBLOCK") +
       
   812                              QString("<p dir='rtl' DEFAULTBLOCKSTYLE>Blah</p>");
       
   813     }
       
   814 
       
   815     {
       
   816         CREATE_DOC_AND_CURSOR();
       
   817 
       
   818         QTextBlockFormat fmt;
       
   819         fmt.setAlignment(Qt::AlignJustify);
       
   820         cursor.insertBlock(fmt);
       
   821         cursor.insertText("Blah");
       
   822 
       
   823         QTest::newRow("blockalign") << QTextDocumentFragment(&doc)
       
   824                                  <<
       
   825                                     QString("EMPTYBLOCK") +
       
   826                                     QString("<p align=\"justify\" DEFAULTBLOCKSTYLE>Blah</p>");
       
   827     }
       
   828 
       
   829     {
       
   830         CREATE_DOC_AND_CURSOR();
       
   831 
       
   832         QTextBlockFormat fmt;
       
   833         fmt.setAlignment(Qt::AlignCenter);
       
   834         cursor.insertBlock(fmt);
       
   835         cursor.insertText("Blah");
       
   836 
       
   837         QTest::newRow("blockalign2") << QTextDocumentFragment(&doc)
       
   838                                   <<
       
   839                                     QString("EMPTYBLOCK") +
       
   840                                     QString("<p align=\"center\" DEFAULTBLOCKSTYLE>Blah</p>");
       
   841     }
       
   842 
       
   843     {
       
   844         CREATE_DOC_AND_CURSOR();
       
   845 
       
   846         QTextBlockFormat fmt;
       
   847         fmt.setAlignment(Qt::AlignRight | Qt::AlignAbsolute);
       
   848         cursor.insertBlock(fmt);
       
   849         cursor.insertText("Blah");
       
   850 
       
   851         QTest::newRow("blockalign3") << QTextDocumentFragment(&doc)
       
   852                                   <<
       
   853                                     QString("EMPTYBLOCK") +
       
   854                                     QString("<p align=\"right\" DEFAULTBLOCKSTYLE>Blah</p>");
       
   855     }
       
   856 
       
   857     {
       
   858         CREATE_DOC_AND_CURSOR();
       
   859 
       
   860         QTextBlockFormat fmt;
       
   861         fmt.setBackground(QColor("#0000ff"));
       
   862         cursor.insertBlock(fmt);
       
   863         cursor.insertText("Blah");
       
   864 
       
   865         QTest::newRow("bgcolor") << QTextDocumentFragment(&doc)
       
   866                                  << QString("EMPTYBLOCK") +
       
   867                                     QString("<p OPENDEFAULTBLOCKSTYLE background-color:#0000ff;\">Blah</p>");
       
   868     }
       
   869 
       
   870     {
       
   871         CREATE_DOC_AND_CURSOR();
       
   872 
       
   873         QTextCharFormat fmt;
       
   874         fmt.setFontWeight(40);
       
   875         cursor.insertText("Blah", fmt);
       
   876 
       
   877         QTest::newRow("font-weight") << QTextDocumentFragment(&doc)
       
   878                                   << QString("<p DEFAULTBLOCKSTYLE><span style=\" font-weight:320;\">Blah</span></p>");
       
   879     }
       
   880 
       
   881     {
       
   882         CREATE_DOC_AND_CURSOR();
       
   883 
       
   884         QTextCharFormat fmt;
       
   885         fmt.setFontItalic(true);
       
   886         cursor.insertText("Blah", fmt);
       
   887 
       
   888         QTest::newRow("font-italic") << QTextDocumentFragment(&doc)
       
   889                                   << QString("<p DEFAULTBLOCKSTYLE><span style=\" font-style:italic;\">Blah</span></p>");
       
   890     }
       
   891 
       
   892     {
       
   893         CREATE_DOC_AND_CURSOR();
       
   894 
       
   895         QTextCharFormat fmt;
       
   896         fmt.setFontUnderline(true);
       
   897         fmt.setFontOverline(false);
       
   898         cursor.insertText("Blah", fmt);
       
   899 
       
   900         QTest::newRow("text-decoration-1") << QTextDocumentFragment(&doc)
       
   901                                   << QString("<p DEFAULTBLOCKSTYLE><span style=\" text-decoration: underline;\">Blah</span></p>");
       
   902     }
       
   903 
       
   904     {
       
   905         CREATE_DOC_AND_CURSOR();
       
   906 
       
   907         QTextCharFormat fmt;
       
   908         fmt.setForeground(QColor("#00ff00"));
       
   909         cursor.insertText("Blah", fmt);
       
   910 
       
   911         QTest::newRow("color") << QTextDocumentFragment(&doc)
       
   912                             << QString("<p DEFAULTBLOCKSTYLE><span style=\" color:#00ff00;\">Blah</span></p>");
       
   913     }
       
   914 
       
   915     {
       
   916         CREATE_DOC_AND_CURSOR();
       
   917 
       
   918         QTextCharFormat fmt;
       
   919         fmt.setBackground(QColor("#00ff00"));
       
   920         cursor.insertText("Blah", fmt);
       
   921 
       
   922         QTest::newRow("span-bgcolor") << QTextDocumentFragment(&doc)
       
   923                             << QString("<p DEFAULTBLOCKSTYLE><span style=\" background-color:#00ff00;\">Blah</span></p>");
       
   924     }
       
   925 
       
   926     {
       
   927         CREATE_DOC_AND_CURSOR();
       
   928 
       
   929         QTextCharFormat fmt;
       
   930         fmt.setVerticalAlignment(QTextCharFormat::AlignSubScript);
       
   931         cursor.insertText("Blah", fmt);
       
   932 
       
   933         QTest::newRow("valign-sub") << QTextDocumentFragment(&doc)
       
   934                                  << QString("<p DEFAULTBLOCKSTYLE><span style=\" vertical-align:sub;\">Blah</span></p>");
       
   935 
       
   936     }
       
   937 
       
   938     {
       
   939         CREATE_DOC_AND_CURSOR();
       
   940 
       
   941         QTextCharFormat fmt;
       
   942         fmt.setVerticalAlignment(QTextCharFormat::AlignSuperScript);
       
   943         cursor.insertText("Blah", fmt);
       
   944 
       
   945         QTest::newRow("valign-super") << QTextDocumentFragment(&doc)
       
   946                                    << QString("<p DEFAULTBLOCKSTYLE><span style=\" vertical-align:super;\">Blah</span></p>");
       
   947 
       
   948     }
       
   949 
       
   950     {
       
   951         CREATE_DOC_AND_CURSOR();
       
   952 
       
   953         QTextCharFormat fmt;
       
   954         fmt.setAnchor(true);
       
   955         fmt.setAnchorName("blub");
       
   956         cursor.insertText("Blah", fmt);
       
   957 
       
   958         QTest::newRow("named anchor") << QTextDocumentFragment(&doc)
       
   959                                    << QString("<p DEFAULTBLOCKSTYLE><a name=\"blub\"></a>Blah</p>");
       
   960     }
       
   961 
       
   962     {
       
   963         CREATE_DOC_AND_CURSOR();
       
   964 
       
   965         QTextCharFormat fmt;
       
   966         fmt.setAnchor(true);
       
   967         fmt.setAnchorHref("http://www.kde.org/");
       
   968         cursor.insertText("Blah", fmt);
       
   969 
       
   970         QTest::newRow("href anchor") << QTextDocumentFragment(&doc)
       
   971                                   << QString("<p DEFAULTBLOCKSTYLE><a href=\"http://www.kde.org/\">Blah</a></p>");
       
   972     }
       
   973 
       
   974     {
       
   975         CREATE_DOC_AND_CURSOR();
       
   976 
       
   977         cursor.insertTable(2, 2);
       
   978 
       
   979         QTest::newRow("simpletable") << QTextDocumentFragment(&doc)
       
   980                                   << QString("<table border=\"1\" cellspacing=\"2\">"
       
   981                                              "\n<tr>\n<td></td>\n<td></td></tr>"
       
   982                                              "\n<tr>\n<td></td>\n<td></td></tr>"
       
   983                                              "</table>");
       
   984     }
       
   985 
       
   986     {
       
   987         CREATE_DOC_AND_CURSOR();
       
   988 
       
   989         QTextTable *table = cursor.insertTable(1, 4);
       
   990         table->mergeCells(0, 0, 1, 2);
       
   991         table->mergeCells(0, 2, 1, 2);
       
   992 
       
   993         QTest::newRow("tablespans") << QTextDocumentFragment(&doc)
       
   994                                  << QString("<table border=\"1\" cellspacing=\"2\">"
       
   995                                              "\n<tr>\n<td colspan=\"2\"></td>\n<td colspan=\"2\"></td></tr>"
       
   996                                              "</table>");
       
   997     }
       
   998 
       
   999     {
       
  1000         CREATE_DOC_AND_CURSOR();
       
  1001 
       
  1002         QTextTableFormat fmt;
       
  1003         fmt.setBorder(1);
       
  1004         fmt.setCellSpacing(3);
       
  1005         fmt.setCellPadding(3);
       
  1006         fmt.setBackground(QColor("#ff00ff"));
       
  1007         fmt.setWidth(QTextLength(QTextLength::PercentageLength, 50));
       
  1008         fmt.setAlignment(Qt::AlignHCenter);
       
  1009         fmt.setPosition(QTextFrameFormat::FloatRight);
       
  1010         cursor.insertTable(2, 2, fmt);
       
  1011 
       
  1012         QTest::newRow("tableattrs") << QTextDocumentFragment(&doc)
       
  1013                                   << QString("<table border=\"1\" style=\" float: right;\" align=\"center\" width=\"50%\" cellspacing=\"3\" cellpadding=\"3\" bgcolor=\"#ff00ff\">"
       
  1014                                              "\n<tr>\n<td></td>\n<td></td></tr>"
       
  1015                                              "\n<tr>\n<td></td>\n<td></td></tr>"
       
  1016                                              "</table>");
       
  1017     }
       
  1018 
       
  1019     {
       
  1020         CREATE_DOC_AND_CURSOR();
       
  1021 
       
  1022         QTextTableFormat fmt;
       
  1023         fmt.setBorder(1);
       
  1024         fmt.setCellSpacing(3);
       
  1025         fmt.setCellPadding(3);
       
  1026         fmt.setBackground(QColor("#ff00ff"));
       
  1027         fmt.setWidth(QTextLength(QTextLength::PercentageLength, 50));
       
  1028         fmt.setAlignment(Qt::AlignHCenter);
       
  1029         fmt.setPosition(QTextFrameFormat::FloatRight);
       
  1030         fmt.setLeftMargin(25);
       
  1031         fmt.setBottomMargin(35);
       
  1032         cursor.insertTable(2, 2, fmt);
       
  1033 
       
  1034         QTest::newRow("tableattrs2") << QTextDocumentFragment(&doc)
       
  1035                                   << QString("<table border=\"1\" style=\" float: right; margin-top:0px; margin-bottom:35px; margin-left:25px; margin-right:0px;\" align=\"center\" width=\"50%\" cellspacing=\"3\" cellpadding=\"3\" bgcolor=\"#ff00ff\">"
       
  1036                                              "\n<tr>\n<td></td>\n<td></td></tr>"
       
  1037                                              "\n<tr>\n<td></td>\n<td></td></tr>"
       
  1038                                              "</table>");
       
  1039     }
       
  1040 
       
  1041     {
       
  1042         CREATE_DOC_AND_CURSOR();
       
  1043 
       
  1044         QTextTableFormat fmt;
       
  1045         fmt.setHeaderRowCount(2);
       
  1046         cursor.insertTable(4, 2, fmt);
       
  1047 
       
  1048         QTest::newRow("tableheader") << QTextDocumentFragment(&doc)
       
  1049                                   << QString("<table border=\"1\" cellspacing=\"2\">"
       
  1050                                              "<thead>\n<tr>\n<td></td>\n<td></td></tr>"
       
  1051                                              "\n<tr>\n<td></td>\n<td></td></tr></thead>"
       
  1052                                              "\n<tr>\n<td></td>\n<td></td></tr>"
       
  1053                                              "\n<tr>\n<td></td>\n<td></td></tr>"
       
  1054                                              "</table>");
       
  1055     }
       
  1056 
       
  1057     {
       
  1058         CREATE_DOC_AND_CURSOR();
       
  1059 
       
  1060         QTextTable *table = cursor.insertTable(2, 2);
       
  1061         QTextTable *subTable = table->cellAt(0, 1).firstCursorPosition().insertTable(1, 1);
       
  1062         subTable->cellAt(0, 0).firstCursorPosition().insertText("Hey");
       
  1063 
       
  1064         QTest::newRow("nestedtable") << QTextDocumentFragment(&doc)
       
  1065                                   << QString("<table border=\"1\" cellspacing=\"2\">"
       
  1066                                              "\n<tr>\n<td></td>\n<td>\n<table border=\"1\" cellspacing=\"2\">\n<tr>\n<td>\n<p DEFAULTBLOCKSTYLE>Hey</p></td></tr></table></td></tr>"
       
  1067                                              "\n<tr>\n<td></td>\n<td></td></tr>"
       
  1068                                              "</table>");
       
  1069     }
       
  1070 
       
  1071     {
       
  1072         CREATE_DOC_AND_CURSOR();
       
  1073 
       
  1074         QTextTableFormat fmt;
       
  1075         QVector<QTextLength> widths;
       
  1076         widths.append(QTextLength());
       
  1077         widths.append(QTextLength(QTextLength::PercentageLength, 30));
       
  1078         widths.append(QTextLength(QTextLength::FixedLength, 40));
       
  1079         fmt.setColumnWidthConstraints(widths);
       
  1080         cursor.insertTable(1, 3, fmt);
       
  1081 
       
  1082         QTest::newRow("colwidths") << QTextDocumentFragment(&doc)
       
  1083                                   << QString("<table border=\"1\" cellspacing=\"2\">"
       
  1084                                              "\n<tr>\n<td></td>\n<td width=\"30%\"></td>\n<td width=\"40\"></td></tr>"
       
  1085                                              "</table>");
       
  1086     }
       
  1087 
       
  1088     // ### rowspan/colspan tests, once texttable api for that is back again
       
  1089     //
       
  1090     {
       
  1091         CREATE_DOC_AND_CURSOR();
       
  1092 
       
  1093         QTextTable *table = cursor.insertTable(1, 1);
       
  1094         QTextCursor cellCurs = table->cellAt(0, 0).firstCursorPosition();
       
  1095         QTextCharFormat fmt;
       
  1096         fmt.setBackground(QColor("#ffffff"));
       
  1097         cellCurs.mergeBlockCharFormat(fmt);
       
  1098 
       
  1099         QTest::newRow("cellproperties") << QTextDocumentFragment(&doc)
       
  1100                                      << QString("<table border=\"1\" cellspacing=\"2\">"
       
  1101                                                 "\n<tr>\n<td bgcolor=\"#ffffff\"></td></tr>"
       
  1102                                                 "</table>");
       
  1103     }
       
  1104 
       
  1105     {
       
  1106         CREATE_DOC_AND_CURSOR();
       
  1107 
       
  1108         // ### fixme: use programmatic api as soon as we can create floats through it
       
  1109         const char html[] = "<html><body>Blah<img src=\"image.png\" width=\"10\" height=\"20\" style=\"float: right;\" />Blubb</body></html>";
       
  1110 
       
  1111         QTest::newRow("image") << QTextDocumentFragment::fromHtml(QString::fromLatin1(html))
       
  1112                             << QString("<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Blah<img src=\"image.png\" width=\"10\" height=\"20\" style=\"float: right;\" />Blubb</p>");
       
  1113     }
       
  1114 
       
  1115     {
       
  1116         CREATE_DOC_AND_CURSOR();
       
  1117 
       
  1118         QTextImageFormat fmt;
       
  1119         fmt.setName("foo");
       
  1120         fmt.setVerticalAlignment(QTextCharFormat::AlignMiddle);
       
  1121         cursor.insertImage(fmt);
       
  1122 
       
  1123         QTest::newRow("image-malign") << QTextDocumentFragment(&doc)
       
  1124                             << QString("<p DEFAULTBLOCKSTYLE><img src=\"foo\" style=\"vertical-align: middle;\" /></p>");
       
  1125     }
       
  1126 
       
  1127     {
       
  1128         CREATE_DOC_AND_CURSOR();
       
  1129 
       
  1130         QTextImageFormat fmt;
       
  1131         fmt.setName("foo");
       
  1132         fmt.setVerticalAlignment(QTextCharFormat::AlignTop);
       
  1133         cursor.insertImage(fmt);
       
  1134 
       
  1135         QTest::newRow("image-malign") << QTextDocumentFragment(&doc)
       
  1136                             << QString("<p DEFAULTBLOCKSTYLE><img src=\"foo\" style=\"vertical-align: top;\" /></p>");
       
  1137     }
       
  1138 
       
  1139     {
       
  1140         CREATE_DOC_AND_CURSOR();
       
  1141 
       
  1142         QTextImageFormat fmt;
       
  1143         fmt.setName("foo");
       
  1144         cursor.insertImage(fmt);
       
  1145         cursor.insertImage(fmt);
       
  1146 
       
  1147         QTest::newRow("2images") << QTextDocumentFragment(&doc)
       
  1148                             << QString("<p DEFAULTBLOCKSTYLE><img src=\"foo\" /><img src=\"foo\" /></p>");
       
  1149     }
       
  1150 
       
  1151     {
       
  1152         CREATE_DOC_AND_CURSOR();
       
  1153 
       
  1154         QString txt = QLatin1String("Blah");
       
  1155         txt += QChar::LineSeparator;
       
  1156         txt += QLatin1String("Bar");
       
  1157         cursor.insertText(txt);
       
  1158 
       
  1159         QTest::newRow("linebreaks") << QTextDocumentFragment(&doc)
       
  1160                                  << QString("<p DEFAULTBLOCKSTYLE>Blah<br />Bar</p>");
       
  1161     }
       
  1162 
       
  1163     {
       
  1164         CREATE_DOC_AND_CURSOR();
       
  1165 
       
  1166         QTextBlockFormat fmt;
       
  1167         fmt.setTopMargin(10);
       
  1168         fmt.setBottomMargin(20);
       
  1169         fmt.setLeftMargin(30);
       
  1170         fmt.setRightMargin(40);
       
  1171         cursor.insertBlock(fmt);
       
  1172         cursor.insertText("Blah");
       
  1173 
       
  1174         QTest::newRow("blockmargins") << QTextDocumentFragment(&doc)
       
  1175                           <<
       
  1176                              QString("EMPTYBLOCK") +
       
  1177                              QString("<p style=\" margin-top:10px; margin-bottom:20px; margin-left:30px; margin-right:40px; -qt-block-indent:0; text-indent:0px;\">Blah</p>");
       
  1178     }
       
  1179 
       
  1180     {
       
  1181         CREATE_DOC_AND_CURSOR();
       
  1182 
       
  1183         QTextList *list = cursor.insertList(QTextListFormat::ListDisc);
       
  1184         cursor.insertText("Blubb");
       
  1185         cursor.insertBlock();
       
  1186         cursor.insertText("Blah");
       
  1187         QCOMPARE(list->count(), 2);
       
  1188 
       
  1189         QTest::newRow("lists") << QTextDocumentFragment(&doc)
       
  1190                           <<
       
  1191                              QString("EMPTYBLOCK") +
       
  1192                              QString("<ul style=\"margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;\"><li DEFAULTBLOCKSTYLE>Blubb</li>\n<li DEFAULTBLOCKSTYLE>Blah</li></ul>");
       
  1193     }
       
  1194 
       
  1195     {
       
  1196         CREATE_DOC_AND_CURSOR();
       
  1197 
       
  1198         QTextList *list = cursor.insertList(QTextListFormat::ListDisc);
       
  1199         cursor.insertText("Blubb");
       
  1200 
       
  1201         cursor.insertBlock();
       
  1202 
       
  1203         QTextCharFormat blockCharFmt;
       
  1204         blockCharFmt.setForeground(QColor("#0000ff"));
       
  1205         cursor.mergeBlockCharFormat(blockCharFmt);
       
  1206 
       
  1207         QTextCharFormat fmt;
       
  1208         fmt.setForeground(QColor("#ff0000"));
       
  1209         cursor.insertText("Blah", fmt);
       
  1210         QCOMPARE(list->count(), 2);
       
  1211 
       
  1212         QTest::newRow("charfmt-for-list-item") << QTextDocumentFragment(&doc)
       
  1213                           <<
       
  1214                              QString("EMPTYBLOCK") +
       
  1215                              QString("<ul style=\"margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;\"><li DEFAULTBLOCKSTYLE>Blubb</li>\n<li style=\" color:#0000ff;\" DEFAULTBLOCKSTYLE><span style=\" color:#ff0000;\">Blah</span></li></ul>");
       
  1216     }
       
  1217 
       
  1218     {
       
  1219         CREATE_DOC_AND_CURSOR();
       
  1220 
       
  1221         QTextBlockFormat fmt;
       
  1222         fmt.setIndent(3);
       
  1223         fmt.setTextIndent(30);
       
  1224         cursor.insertBlock(fmt);
       
  1225         cursor.insertText("Test");
       
  1226 
       
  1227         QTest::newRow("block-indent") << QTextDocumentFragment(&doc)
       
  1228                                    <<
       
  1229                                     QString("EMPTYBLOCK") +
       
  1230                                     QString("<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:3; text-indent:30px;\">Test</p>");
       
  1231     }
       
  1232 
       
  1233     {
       
  1234         CREATE_DOC_AND_CURSOR();
       
  1235 
       
  1236         QTextListFormat fmt;
       
  1237         fmt.setStyle(QTextListFormat::ListDisc);
       
  1238         fmt.setIndent(4);
       
  1239         cursor.insertList(fmt);
       
  1240         cursor.insertText("Blah");
       
  1241 
       
  1242         QTest::newRow("list-indent") << QTextDocumentFragment(&doc)
       
  1243                                   <<
       
  1244                                     QString("EMPTYBLOCK") +
       
  1245                                     QString("<ul style=\"margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 4;\"><li DEFAULTBLOCKSTYLE>Blah</li></ul>");
       
  1246     }
       
  1247 
       
  1248     {
       
  1249         CREATE_DOC_AND_CURSOR();
       
  1250 
       
  1251         cursor.insertBlock();
       
  1252 
       
  1253 
       
  1254         QTest::newRow("emptyblock") << QTextDocumentFragment(&doc)
       
  1255                                     // after insertBlock() we /do/ have two blocks in the document, so also expect
       
  1256                                     // these in the html output
       
  1257                                     << QString("EMPTYBLOCK") + QString("EMPTYBLOCK");
       
  1258     }
       
  1259 
       
  1260     {
       
  1261         CREATE_DOC_AND_CURSOR();
       
  1262 
       
  1263         // if you press enter twice in an empty textedit and then insert 'Test'
       
  1264         // you actually get three visible paragraphs, two empty leading ones and
       
  1265         // a third with the actual text. the corresponding html representation
       
  1266         // therefore should also contain three paragraphs.
       
  1267 
       
  1268         cursor.insertBlock();
       
  1269         QTextCharFormat fmt;
       
  1270         fmt.setForeground(QColor("#00ff00"));
       
  1271         fmt.setProperty(QTextFormat::FontSizeIncrement, 1);
       
  1272         cursor.mergeBlockCharFormat(fmt);
       
  1273 
       
  1274         fmt.setProperty(QTextFormat::FontSizeIncrement, 2);
       
  1275         cursor.insertText("Test", fmt);
       
  1276 
       
  1277         QTest::newRow("blockcharfmt") << QTextDocumentFragment(&doc)
       
  1278                                    << QString("EMPTYBLOCK<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-size:x-large; color:#00ff00;\">Test</span></p>");
       
  1279     }
       
  1280 
       
  1281     {
       
  1282         CREATE_DOC_AND_CURSOR();
       
  1283 
       
  1284         QTextCharFormat fmt;
       
  1285         fmt.setForeground(QColor("#00ff00"));
       
  1286         cursor.setBlockCharFormat(fmt);
       
  1287         fmt.setForeground(QColor("#0000ff"));
       
  1288         cursor.insertText("Test", fmt);
       
  1289 
       
  1290         QTest::newRow("blockcharfmt2") << QTextDocumentFragment(&doc)
       
  1291                                    << QString("<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" color:#0000ff;\">Test</span></p>");
       
  1292     }
       
  1293 
       
  1294     {
       
  1295         QTest::newRow("horizontal-ruler") << QTextDocumentFragment::fromHtml("<hr />")
       
  1296                                        <<
       
  1297                                           QString("EMPTYBLOCK") +
       
  1298                                           QString("<hr />");
       
  1299     }
       
  1300     {
       
  1301         QTest::newRow("horizontal-ruler-with-width") << QTextDocumentFragment::fromHtml("<hr width=\"50%\"/>")
       
  1302                                                   <<
       
  1303                                                       QString("EMPTYBLOCK") +
       
  1304                                                       QString("<hr width=\"50%\"/>");
       
  1305     }
       
  1306     {
       
  1307         CREATE_DOC_AND_CURSOR();
       
  1308 
       
  1309         QTextFrame *mainFrame = cursor.currentFrame();
       
  1310 
       
  1311         QTextFrameFormat ffmt;
       
  1312         ffmt.setBorder(1);
       
  1313         ffmt.setPosition(QTextFrameFormat::FloatRight);
       
  1314         ffmt.setMargin(2);
       
  1315         ffmt.setWidth(100);
       
  1316         ffmt.setHeight(50);
       
  1317         ffmt.setBackground(QColor("#00ff00"));
       
  1318         cursor.insertFrame(ffmt);
       
  1319         cursor.insertText("Hello World");
       
  1320         cursor = mainFrame->lastCursorPosition();
       
  1321 
       
  1322         QTest::newRow("frame") << QTextDocumentFragment(&doc)
       
  1323                             << QString("<table border=\"1\" style=\"-qt-table-type: frame; float: right; margin-top:2px; margin-bottom:2px; margin-left:2px; margin-right:2px;\" width=\"100\" height=\"50\" bgcolor=\"#00ff00\">\n<tr>\n<td style=\"border: none;\">\n<p DEFAULTBLOCKSTYLE>Hello World</p></td></tr></table>");
       
  1324     }
       
  1325 
       
  1326     {
       
  1327         CREATE_DOC_AND_CURSOR();
       
  1328 
       
  1329         QTextCharFormat fmt;
       
  1330         fmt.setForeground(QColor("#00ff00"));
       
  1331 //        fmt.setBackground(QColor("#0000ff"));
       
  1332         cursor.setBlockCharFormat(fmt);
       
  1333 
       
  1334         fmt.setForeground(QBrush());
       
  1335 //        fmt.setBackground(QBrush());
       
  1336         cursor.insertText("Test", fmt);
       
  1337 
       
  1338 //        QTest::newRow("nostylebrush") << QTextDocumentFragment(&doc) << QString("<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; color:#00ff00; -qt-blockcharfmt-background-color:#0000ff;\">Test</p>");
       
  1339         QTest::newRow("nostylebrush") << QTextDocumentFragment(&doc) << QString("<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Test</p>");
       
  1340     }
       
  1341 
       
  1342     {
       
  1343         CREATE_DOC_AND_CURSOR();
       
  1344 
       
  1345         QTextTable *table = cursor.insertTable(2, 2);
       
  1346         table->mergeCells(0, 0, 1, 2);
       
  1347         QTextTableFormat fmt = table->format();
       
  1348         QVector<QTextLength> widths;
       
  1349         widths.append(QTextLength(QTextLength::FixedLength, 20));
       
  1350         widths.append(QTextLength(QTextLength::FixedLength, 40));
       
  1351         fmt.setColumnWidthConstraints(widths);
       
  1352         table->setFormat(fmt);
       
  1353 
       
  1354         QTest::newRow("mergedtablecolwidths") << QTextDocumentFragment(&doc)
       
  1355                                   << QString("<table border=\"1\" cellspacing=\"2\">"
       
  1356                                              "\n<tr>\n<td colspan=\"2\"></td></tr>"
       
  1357                                              "\n<tr>\n<td width=\"20\"></td>\n<td width=\"40\"></td></tr>"
       
  1358                                              "</table>");
       
  1359     }
       
  1360 
       
  1361     {
       
  1362         CREATE_DOC_AND_CURSOR();
       
  1363 
       
  1364         QTextCharFormat fmt;
       
  1365 
       
  1366         cursor.insertText("Blah\nGreen yellow green");
       
  1367         cursor.setPosition(0);
       
  1368         cursor.setPosition(23, QTextCursor::KeepAnchor);
       
  1369         fmt.setBackground(Qt::green);
       
  1370         cursor.mergeCharFormat(fmt);
       
  1371         cursor.clearSelection();
       
  1372         cursor.setPosition(11);
       
  1373         cursor.setPosition(17, QTextCursor::KeepAnchor);
       
  1374         fmt.setBackground(Qt::yellow);
       
  1375         cursor.mergeCharFormat(fmt);
       
  1376         cursor.clearSelection();
       
  1377 
       
  1378         QTest::newRow("multiparagraph-bgcolor") << QTextDocumentFragment(&doc)
       
  1379                                  << QString("<p DEFAULTBLOCKSTYLE><span style=\" background-color:#00ff00;\">Blah</span></p>\n"
       
  1380                                             "<p DEFAULTBLOCKSTYLE><span style=\" background-color:#00ff00;\">Green </span>"
       
  1381                                             "<span style=\" background-color:#ffff00;\">yellow</span>"
       
  1382                                             "<span style=\" background-color:#00ff00;\"> green</span></p>");
       
  1383     }
       
  1384 
       
  1385     {
       
  1386         CREATE_DOC_AND_CURSOR();
       
  1387 
       
  1388         QTextBlockFormat fmt;
       
  1389         fmt.setBackground(QColor("#0000ff"));
       
  1390         cursor.insertBlock(fmt);
       
  1391 
       
  1392         QTextCharFormat charfmt;
       
  1393         charfmt.setBackground(QColor("#0000ff"));
       
  1394         cursor.insertText("Blah", charfmt);
       
  1395 
       
  1396         QTest::newRow("nospan-bgcolor") << QTextDocumentFragment(&doc)
       
  1397                                  << QString("EMPTYBLOCK") +
       
  1398                                     QString("<p OPENDEFAULTBLOCKSTYLE background-color:#0000ff;\"><span style=\" background-color:#0000ff;\">Blah</span></p>");
       
  1399     }
       
  1400 
       
  1401     {
       
  1402         CREATE_DOC_AND_CURSOR();
       
  1403 
       
  1404         QTextTable *table = cursor.insertTable(2, 2);
       
  1405         QTextCharFormat fmt = table->cellAt(0, 0).format();
       
  1406         fmt.setVerticalAlignment(QTextCharFormat::AlignMiddle);
       
  1407         table->cellAt(0, 0).setFormat(fmt);
       
  1408         fmt = table->cellAt(0, 1).format();
       
  1409         fmt.setVerticalAlignment(QTextCharFormat::AlignTop);
       
  1410         table->cellAt(0, 1).setFormat(fmt);
       
  1411         fmt = table->cellAt(1, 0).format();
       
  1412         fmt.setVerticalAlignment(QTextCharFormat::AlignBottom);
       
  1413         table->cellAt(1, 0).setFormat(fmt);
       
  1414 
       
  1415         table->cellAt(0, 0).firstCursorPosition().insertText("Blah");
       
  1416 
       
  1417         QTest::newRow("table-vertical-alignment") << QTextDocumentFragment(&doc)
       
  1418                                   << QString("<table border=\"1\" cellspacing=\"2\">"
       
  1419                                              "\n<tr>\n<td style=\" vertical-align:middle;\">\n"
       
  1420                                              "<p DEFAULTBLOCKSTYLE>Blah</p></td>"
       
  1421                                              "\n<td style=\" vertical-align:top;\"></td></tr>"
       
  1422                                              "\n<tr>\n<td style=\" vertical-align:bottom;\"></td>"
       
  1423                                              "\n<td></td></tr>"
       
  1424                                              "</table>");
       
  1425     }
       
  1426 
       
  1427     {
       
  1428         CREATE_DOC_AND_CURSOR();
       
  1429 
       
  1430         QTextTable *table = cursor.insertTable(2, 2);
       
  1431         QTextTableCellFormat fmt = table->cellAt(0, 0).format().toTableCellFormat();
       
  1432         fmt.setLeftPadding(1);
       
  1433         table->cellAt(0, 0).setFormat(fmt);
       
  1434         fmt = table->cellAt(0, 1).format().toTableCellFormat();
       
  1435         fmt.setRightPadding(1);
       
  1436         table->cellAt(0, 1).setFormat(fmt);
       
  1437         fmt = table->cellAt(1, 0).format().toTableCellFormat();
       
  1438         fmt.setTopPadding(1);
       
  1439         table->cellAt(1, 0).setFormat(fmt);
       
  1440         fmt = table->cellAt(1, 1).format().toTableCellFormat();
       
  1441         fmt.setBottomPadding(1);
       
  1442         table->cellAt(1, 1).setFormat(fmt);
       
  1443 
       
  1444         table->cellAt(0, 0).firstCursorPosition().insertText("Blah");
       
  1445 
       
  1446         QTest::newRow("table-cell-paddings") << QTextDocumentFragment(&doc)
       
  1447                                   << QString("<table border=\"1\" cellspacing=\"2\">"
       
  1448                                              "\n<tr>\n<td style=\" padding-left:1;\">\n"
       
  1449                                              "<p DEFAULTBLOCKSTYLE>Blah</p></td>"
       
  1450                                              "\n<td style=\" padding-right:1;\"></td></tr>"
       
  1451                                              "\n<tr>\n<td style=\" padding-top:1;\"></td>"
       
  1452                                              "\n<td style=\" padding-bottom:1;\"></td></tr>"
       
  1453                                              "</table>");
       
  1454     }
       
  1455 
       
  1456     {
       
  1457         CREATE_DOC_AND_CURSOR();
       
  1458 
       
  1459         QTextTableFormat fmt;
       
  1460         fmt.setBorderBrush(QColor("#0000ff"));
       
  1461         fmt.setBorderStyle(QTextFrameFormat::BorderStyle_Solid);
       
  1462         cursor.insertTable(2, 2, fmt);
       
  1463 
       
  1464         QTest::newRow("tableborder") << QTextDocumentFragment(&doc)
       
  1465                                      << QString("<table border=\"1\" style=\" border-color:#0000ff; border-style:solid;\" cellspacing=\"2\">"
       
  1466                                                 "\n<tr>\n<td></td>\n<td></td></tr>"
       
  1467                                                 "\n<tr>\n<td></td>\n<td></td></tr>"
       
  1468                                                 "</table>");
       
  1469     }
       
  1470 
       
  1471     {
       
  1472         CREATE_DOC_AND_CURSOR();
       
  1473 
       
  1474         cursor.insertBlock();
       
  1475         cursor.insertText("Foo");
       
  1476 
       
  1477         cursor.block().setUserState(42);
       
  1478 
       
  1479         QTest::newRow("userstate") << QTextDocumentFragment(&doc)
       
  1480                                    << QString("EMPTYBLOCK") +
       
  1481                                       QString("<p OPENDEFAULTBLOCKSTYLE -qt-user-state:42;\">Foo</p>");
       
  1482     }
       
  1483 
       
  1484     {
       
  1485         CREATE_DOC_AND_CURSOR();
       
  1486 
       
  1487         QTextBlockFormat blockFmt;
       
  1488         blockFmt.setPageBreakPolicy(QTextFormat::PageBreak_AlwaysBefore);
       
  1489 
       
  1490         cursor.insertBlock(blockFmt);
       
  1491         cursor.insertText("Foo");
       
  1492 
       
  1493         blockFmt.setPageBreakPolicy(QTextFormat::PageBreak_AlwaysBefore | QTextFormat::PageBreak_AlwaysAfter);
       
  1494 
       
  1495         cursor.insertBlock(blockFmt);
       
  1496         cursor.insertText("Bar");
       
  1497 
       
  1498         QTextTableFormat tableFmt;
       
  1499         tableFmt.setPageBreakPolicy(QTextFormat::PageBreak_AlwaysAfter);
       
  1500 
       
  1501         cursor.insertTable(1, 1, tableFmt);
       
  1502 
       
  1503         QTest::newRow("pagebreak") << QTextDocumentFragment(&doc)
       
  1504                                    << QString("EMPTYBLOCK") +
       
  1505                                       QString("<p OPENDEFAULTBLOCKSTYLE page-break-before:always;\">Foo</p>"
       
  1506                                               "\n<p OPENDEFAULTBLOCKSTYLE page-break-before:always; page-break-after:always;\">Bar</p>"
       
  1507                                               "\n<table border=\"1\" style=\" page-break-after:always;\" cellspacing=\"2\">\n<tr>\n<td></td></tr></table>");
       
  1508     }
       
  1509 
       
  1510     {
       
  1511         CREATE_DOC_AND_CURSOR();
       
  1512 
       
  1513         QTextListFormat listFmt;
       
  1514         listFmt.setStyle(QTextListFormat::ListDisc);
       
  1515 
       
  1516         cursor.insertList(listFmt);
       
  1517         cursor.insertText("Blah");
       
  1518 
       
  1519         QTest::newRow("list-ul-margin") << QTextDocumentFragment(&doc)
       
  1520                                         << QString("EMPTYBLOCK") +
       
  1521                                            QString("<ul style=\"margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;\"><li DEFAULTBLOCKSTYLE>Blah</li></ul>");
       
  1522     }
       
  1523 }
       
  1524 
       
  1525 void tst_QTextDocument::toHtml()
       
  1526 {
       
  1527     QFETCH(QTextDocumentFragment, input);
       
  1528     QFETCH(QString, expectedOutput);
       
  1529 
       
  1530     cursor.insertFragment(input);
       
  1531 
       
  1532     expectedOutput.prepend(htmlHead);
       
  1533 
       
  1534     expectedOutput.replace("OPENDEFAULTBLOCKSTYLE", "style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;");
       
  1535     expectedOutput.replace("DEFAULTBLOCKSTYLE", "style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"");
       
  1536     expectedOutput.replace("EMPTYBLOCK", "<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p>\n");
       
  1537     if (expectedOutput.endsWith(QLatin1Char('\n')))
       
  1538         expectedOutput.chop(1);
       
  1539     expectedOutput.append(htmlTail);
       
  1540 
       
  1541     QString output = doc->toHtml();
       
  1542 
       
  1543     QCOMPARE(output, expectedOutput);
       
  1544 }
       
  1545 
       
  1546 void tst_QTextDocument::toHtml2()
       
  1547 {
       
  1548     QTextDocument doc;
       
  1549     doc.setHtml("<p>text <img src=\"\">    text</p>"); // 4 spaces before the second 'text'
       
  1550     QTextBlock block = doc.firstBlock();
       
  1551     QTextBlock::Iterator iter = block.begin();
       
  1552     QTextFragment f = iter.fragment();
       
  1553     QVERIFY(f.isValid());
       
  1554     QCOMPARE(f.position(), 0);
       
  1555     QCOMPARE(f.length(), 5);
       
  1556     //qDebug() << block.text().mid(f.position(), f.length());
       
  1557 
       
  1558     iter++;
       
  1559     f = iter.fragment();
       
  1560     QVERIFY(f.isValid());
       
  1561     QCOMPARE(f.position(), 5);
       
  1562     QCOMPARE(f.length(), 1);
       
  1563     //qDebug() << block.text().mid(f.position(), f.length());
       
  1564 
       
  1565     iter++;
       
  1566     f = iter.fragment();
       
  1567     //qDebug() << block.text().mid(f.position(), f.length());
       
  1568     QVERIFY(f.isValid());
       
  1569     QCOMPARE(f.position(), 6);
       
  1570     QCOMPARE(f.length(), 5); // 1 space should be preserved.
       
  1571     QCOMPARE(block.text().mid(f.position(), f.length()), QString(" text"));
       
  1572 
       
  1573     doc.setHtml("<table><tr><td>   foo</td></tr></table>    text"); // 4 spaces before the second 'text'
       
  1574     block = doc.firstBlock().next();
       
  1575     //qDebug() << block.text();
       
  1576     QCOMPARE(block.text(), QString("foo"));
       
  1577 
       
  1578     block = block.next();
       
  1579     //qDebug() << block.text();
       
  1580     QCOMPARE(block.text(), QString("text"));
       
  1581 }
       
  1582 
       
  1583 void tst_QTextDocument::setFragmentMarkersInHtmlExport()
       
  1584 {
       
  1585     {
       
  1586         CREATE_DOC_AND_CURSOR();
       
  1587 
       
  1588         cursor.insertText("Leadin");
       
  1589         const int startPos = cursor.position();
       
  1590 
       
  1591         cursor.insertText("Test");
       
  1592         QTextCharFormat fmt;
       
  1593         fmt.setForeground(QColor("#00ff00"));
       
  1594         cursor.insertText("Blah", fmt);
       
  1595 
       
  1596         const int endPos = cursor.position();
       
  1597         cursor.insertText("Leadout", QTextCharFormat());
       
  1598 
       
  1599         cursor.setPosition(startPos);
       
  1600         cursor.setPosition(endPos, QTextCursor::KeepAnchor);
       
  1601         QTextDocumentFragment fragment(cursor);
       
  1602 
       
  1603         QString expected = htmlHead;
       
  1604         expected.replace(QRegExp("<body.*>"), QString("<body>"));
       
  1605         expected += QString("<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><!--StartFragment-->Test<span style=\" color:#00ff00;\">Blah</span><!--EndFragment--></p>") + htmlTail;
       
  1606         QCOMPARE(fragment.toHtml(), expected);
       
  1607     }
       
  1608     {
       
  1609         CREATE_DOC_AND_CURSOR();
       
  1610 
       
  1611         cursor.insertText("Leadin");
       
  1612         const int startPos = cursor.position();
       
  1613 
       
  1614         cursor.insertText("Test");
       
  1615 
       
  1616         const int endPos = cursor.position();
       
  1617         cursor.insertText("Leadout", QTextCharFormat());
       
  1618 
       
  1619         cursor.setPosition(startPos);
       
  1620         cursor.setPosition(endPos, QTextCursor::KeepAnchor);
       
  1621         QTextDocumentFragment fragment(cursor);
       
  1622 
       
  1623         QString expected = htmlHead;
       
  1624         expected.replace(QRegExp("<body.*>"), QString("<body>"));
       
  1625         expected += QString("<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><!--StartFragment-->Test<!--EndFragment--></p>") + htmlTail;
       
  1626         QCOMPARE(fragment.toHtml(), expected);
       
  1627     }
       
  1628 }
       
  1629 
       
  1630 void tst_QTextDocument::toHtmlBodyBgColor()
       
  1631 {
       
  1632     CREATE_DOC_AND_CURSOR();
       
  1633 
       
  1634     cursor.insertText("Blah");
       
  1635 
       
  1636     QTextFrameFormat fmt = doc.rootFrame()->frameFormat();
       
  1637     fmt.setBackground(QColor("#0000ff"));
       
  1638     doc.rootFrame()->setFrameFormat(fmt);
       
  1639 
       
  1640     QString expectedHtml("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" "
       
  1641             "\"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
       
  1642             "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
       
  1643             "p, li { white-space: pre-wrap; }\n"
       
  1644             "</style></head>"
       
  1645             "<body style=\" font-family:'%1'; font-size:%2pt; font-weight:%3; font-style:%4;\""
       
  1646             " bgcolor=\"#0000ff\">\n"
       
  1647             "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Blah</p>"
       
  1648             "</body></html>");
       
  1649 
       
  1650     expectedHtml = expectedHtml.arg(defaultFont.family()).arg(defaultFont.pointSizeF()).arg(defaultFont.weight() * 8).arg((defaultFont.italic() ? "italic" : "normal"));
       
  1651 
       
  1652     QCOMPARE(doc.toHtml(), expectedHtml);
       
  1653 }
       
  1654 
       
  1655 void tst_QTextDocument::toHtmlRootFrameProperties()
       
  1656 {
       
  1657     CREATE_DOC_AND_CURSOR();
       
  1658 
       
  1659     QTextFrameFormat fmt = doc.rootFrame()->frameFormat();
       
  1660     fmt.setTopMargin(10);
       
  1661     fmt.setLeftMargin(10);
       
  1662     fmt.setBorder(2);
       
  1663     doc.rootFrame()->setFrameFormat(fmt);
       
  1664 
       
  1665     cursor.insertText("Blah");
       
  1666 
       
  1667     QString expectedOutput("<table border=\"2\" style=\"-qt-table-type: root; margin-top:10px; "
       
  1668                            "margin-bottom:4px; margin-left:10px; margin-right:4px;\">\n"
       
  1669                            "<tr>\n<td style=\"border: none;\">\n"
       
  1670                            "<p DEFAULTBLOCKSTYLE>Blah</p></td></tr></table>");
       
  1671 
       
  1672     expectedOutput.prepend(htmlHead);
       
  1673     expectedOutput.replace("DEFAULTBLOCKSTYLE", "style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"");
       
  1674     expectedOutput.append(htmlTail);
       
  1675 
       
  1676     QCOMPARE(doc.toHtml(), expectedOutput);
       
  1677 }
       
  1678 
       
  1679 void tst_QTextDocument::capitalizationHtmlInExport()
       
  1680 {
       
  1681     doc->setPlainText("Test");
       
  1682 
       
  1683     QRegExp re(".*span style=\"(.*)\">Test.*");
       
  1684     QVERIFY(re.exactMatch(doc->toHtml()) == false); // no span
       
  1685 
       
  1686     QTextCursor cursor(doc);
       
  1687     cursor.setPosition(4, QTextCursor::KeepAnchor);
       
  1688     QTextCharFormat cf;
       
  1689     cf.setFontCapitalization(QFont::SmallCaps);
       
  1690     cursor.mergeCharFormat(cf);
       
  1691 
       
  1692     const QString smallcaps = doc->toHtml();
       
  1693     QVERIFY(re.exactMatch(doc->toHtml()));
       
  1694     QCOMPARE(re.numCaptures(), 1);
       
  1695     QCOMPARE(re.cap(1).trimmed(), QString("font-variant:small-caps;"));
       
  1696 
       
  1697     cf.setFontCapitalization(QFont::AllUppercase);
       
  1698     cursor.mergeCharFormat(cf);
       
  1699     const QString uppercase = doc->toHtml();
       
  1700     QVERIFY(re.exactMatch(doc->toHtml()));
       
  1701     QCOMPARE(re.numCaptures(), 1);
       
  1702     QCOMPARE(re.cap(1).trimmed(), QString("text-transform:uppercase;"));
       
  1703 
       
  1704     cf.setFontCapitalization(QFont::AllLowercase);
       
  1705     cursor.mergeCharFormat(cf);
       
  1706     const QString lowercase = doc->toHtml();
       
  1707     QVERIFY(re.exactMatch(doc->toHtml()));
       
  1708     QCOMPARE(re.numCaptures(), 1);
       
  1709     QCOMPARE(re.cap(1).trimmed(), QString("text-transform:lowercase;"));
       
  1710 
       
  1711     doc->setHtml(smallcaps);
       
  1712     cursor.setPosition(1);
       
  1713     QCOMPARE(cursor.charFormat().fontCapitalization(), QFont::SmallCaps);
       
  1714     doc->setHtml(uppercase);
       
  1715     QCOMPARE(cursor.charFormat().fontCapitalization(), QFont::AllUppercase);
       
  1716     doc->setHtml(lowercase);
       
  1717     QCOMPARE(cursor.charFormat().fontCapitalization(), QFont::AllLowercase);
       
  1718 }
       
  1719 
       
  1720 void tst_QTextDocument::wordspacingHtmlExport()
       
  1721 {
       
  1722     doc->setPlainText("Test");
       
  1723 
       
  1724     QRegExp re(".*span style=\"(.*)\">Test.*");
       
  1725     QVERIFY(re.exactMatch(doc->toHtml()) == false); // no span
       
  1726 
       
  1727     QTextCursor cursor(doc);
       
  1728     cursor.setPosition(4, QTextCursor::KeepAnchor);
       
  1729     QTextCharFormat cf;
       
  1730     cf.setFontWordSpacing(4);
       
  1731     cursor.mergeCharFormat(cf);
       
  1732 
       
  1733     QVERIFY(re.exactMatch(doc->toHtml()));
       
  1734     QCOMPARE(re.numCaptures(), 1);
       
  1735     QCOMPARE(re.cap(1).trimmed(), QString("word-spacing:4px;"));
       
  1736 
       
  1737     cf.setFontWordSpacing(-8.5);
       
  1738     cursor.mergeCharFormat(cf);
       
  1739 
       
  1740     QVERIFY(re.exactMatch(doc->toHtml()));
       
  1741     QCOMPARE(re.numCaptures(), 1);
       
  1742     QCOMPARE(re.cap(1).trimmed(), QString("word-spacing:-8.5px;"));
       
  1743 }
       
  1744 
       
  1745 class CursorPosSignalSpy : public QObject
       
  1746 {
       
  1747     Q_OBJECT
       
  1748 public:
       
  1749     CursorPosSignalSpy(QTextDocument *doc)
       
  1750     {
       
  1751         calls = 0;
       
  1752         connect(doc, SIGNAL(cursorPositionChanged(const QTextCursor &)),
       
  1753                 this, SLOT(cursorPositionChanged(const QTextCursor &)));
       
  1754     }
       
  1755 
       
  1756     int calls;
       
  1757 
       
  1758 private slots:
       
  1759     void cursorPositionChanged(const QTextCursor &)
       
  1760     {
       
  1761         ++calls;
       
  1762     }
       
  1763 };
       
  1764 
       
  1765 void tst_QTextDocument::cursorPositionChanged()
       
  1766 {
       
  1767     CursorPosSignalSpy spy(doc);
       
  1768 
       
  1769     cursor.insertText("Test");
       
  1770     QCOMPARE(spy.calls, 1);
       
  1771 
       
  1772     spy.calls = 0;
       
  1773     QTextCursor unrelatedCursor(doc);
       
  1774     unrelatedCursor.insertText("Blah");
       
  1775     QCOMPARE(spy.calls, 2);
       
  1776 
       
  1777     spy.calls = 0;
       
  1778     cursor.insertText("Blah");
       
  1779     QCOMPARE(spy.calls, 1);
       
  1780 
       
  1781     spy.calls = 0;
       
  1782     cursor.movePosition(QTextCursor::PreviousCharacter);
       
  1783     QCOMPARE(spy.calls, 0);
       
  1784 }
       
  1785 
       
  1786 void tst_QTextDocument::cursorPositionChangedOnSetText()
       
  1787 {
       
  1788     CursorPosSignalSpy spy(doc);
       
  1789 
       
  1790     // doc has one QTextCursor stored in the
       
  1791     // cursor member variable, thus the signal
       
  1792     // gets emitted once.
       
  1793 
       
  1794     doc->setPlainText("Foo\nBar\nBaz\nBlub\nBlah");
       
  1795 
       
  1796     QCOMPARE(spy.calls, 1);
       
  1797 
       
  1798     spy.calls = 0;
       
  1799     doc->setHtml("<p>Foo<p>Bar<p>Baz<p>Blah");
       
  1800 
       
  1801     QCOMPARE(spy.calls, 1);
       
  1802 }
       
  1803 
       
  1804 void tst_QTextDocument::textFrameIterator()
       
  1805 {
       
  1806     cursor.insertTable(1, 1);
       
  1807 
       
  1808     int blockCount = 0;
       
  1809     int frameCount = 0;
       
  1810 
       
  1811     for (QTextFrame::Iterator frameIt = doc->rootFrame()->begin();
       
  1812          !frameIt.atEnd(); ++frameIt) {
       
  1813         if (frameIt.currentFrame())
       
  1814             ++frameCount;
       
  1815         else if (frameIt.currentBlock().isValid())
       
  1816             ++blockCount;
       
  1817 
       
  1818     }
       
  1819 
       
  1820     QEXPECT_FAIL("", "This is currently worked around in the html export but needs fixing!", Continue);
       
  1821     QCOMPARE(blockCount, 0);
       
  1822     QCOMPARE(frameCount, 1);
       
  1823 }
       
  1824 
       
  1825 void tst_QTextDocument::codecForHtml()
       
  1826 {
       
  1827     const QByteArray header("<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html;charset=utf-16\">");
       
  1828     QTextCodec *c = Qt::codecForHtml(header);
       
  1829     QVERIFY(c);
       
  1830     QCOMPARE(c->name(), QByteArray("UTF-16"));
       
  1831 }
       
  1832 
       
  1833 class TestSyntaxHighlighter : public QObject
       
  1834 {
       
  1835     Q_OBJECT
       
  1836 public:
       
  1837     inline TestSyntaxHighlighter(QTextDocument *doc) : QObject(doc), ok(false) {}
       
  1838 
       
  1839     bool ok;
       
  1840 
       
  1841 private slots:
       
  1842     inline void markBlockDirty(int from, int charsRemoved, int charsAdded)
       
  1843     {
       
  1844         Q_UNUSED(charsRemoved);
       
  1845         Q_UNUSED(charsAdded);
       
  1846         QTextDocument *doc = static_cast<QTextDocument *>(parent());
       
  1847         QTextBlock block = doc->findBlock(from);
       
  1848 
       
  1849         QTestDocumentLayout *lout = qobject_cast<QTestDocumentLayout *>(doc->documentLayout());
       
  1850         lout->called = false;
       
  1851 
       
  1852         doc->markContentsDirty(block.position(), block.length());
       
  1853 
       
  1854         ok = (lout->called == false);
       
  1855     }
       
  1856 
       
  1857     inline void modifyBlockAgain(int from, int charsRemoved, int charsAdded)
       
  1858     {
       
  1859         Q_UNUSED(charsRemoved);
       
  1860         Q_UNUSED(charsAdded);
       
  1861         QTextDocument *doc = static_cast<QTextDocument *>(parent());
       
  1862         QTextBlock block = doc->findBlock(from);
       
  1863         QTextCursor cursor(block);
       
  1864 
       
  1865         QTestDocumentLayout *lout = qobject_cast<QTestDocumentLayout *>(doc->documentLayout());
       
  1866         lout->called = false;
       
  1867 
       
  1868         cursor.insertText("Foo");
       
  1869 
       
  1870         ok = (lout->called == true);
       
  1871     }
       
  1872 };
       
  1873 
       
  1874 void tst_QTextDocument::markContentsDirty()
       
  1875 {
       
  1876     QTestDocumentLayout *lout = new QTestDocumentLayout(doc);
       
  1877     doc->setDocumentLayout(lout);
       
  1878     TestSyntaxHighlighter *highlighter = new TestSyntaxHighlighter(doc);
       
  1879     connect(doc, SIGNAL(contentsChange(int, int, int)),
       
  1880             highlighter, SLOT(markBlockDirty(int, int, int)));
       
  1881 
       
  1882     highlighter->ok = false;
       
  1883     cursor.insertText("Some dummy text blah blah");
       
  1884     QVERIFY(highlighter->ok);
       
  1885 
       
  1886     disconnect(doc, SIGNAL(contentsChange(int, int, int)),
       
  1887                highlighter, SLOT(markBlockDirty(int, int, int)));
       
  1888     connect(doc, SIGNAL(contentsChange(int, int, int)),
       
  1889             highlighter, SLOT(modifyBlockAgain(int, int, int)));
       
  1890     highlighter->ok = false;
       
  1891     cursor.insertText("FooBar");
       
  1892     QVERIFY(highlighter->ok);
       
  1893 
       
  1894     lout->called = false;
       
  1895 
       
  1896     doc->markContentsDirty(1, 4);
       
  1897 
       
  1898     QVERIFY(lout->called);
       
  1899 }
       
  1900 
       
  1901 void tst_QTextDocument::clonePreservesMetaInformation()
       
  1902 {
       
  1903     const QString title("Foobar");
       
  1904     const QString url("about:blank");
       
  1905     doc->setHtml("<html><head><title>" + title + "</title></head><body>Hrm</body></html>");
       
  1906     doc->setMetaInformation(QTextDocument::DocumentUrl, url);
       
  1907     QCOMPARE(doc->metaInformation(QTextDocument::DocumentTitle), title);
       
  1908     QCOMPARE(doc->metaInformation(QTextDocument::DocumentUrl), url);
       
  1909 
       
  1910     QTextDocument *clone = doc->clone();
       
  1911     QCOMPARE(clone->metaInformation(QTextDocument::DocumentTitle), title);
       
  1912     QCOMPARE(clone->metaInformation(QTextDocument::DocumentUrl), url);
       
  1913     delete clone;
       
  1914 }
       
  1915 
       
  1916 void tst_QTextDocument::clonePreservesPageSize()
       
  1917 {
       
  1918     QSizeF sz(100., 100.);
       
  1919     doc->setPageSize(sz);
       
  1920     QTextDocument *clone = doc->clone();
       
  1921     QCOMPARE(clone->pageSize(), sz);
       
  1922     delete clone;
       
  1923 }
       
  1924 
       
  1925 void tst_QTextDocument::clonePreservesPageBreakPolicies()
       
  1926 {
       
  1927     QTextTableFormat tableFmt;
       
  1928     tableFmt.setPageBreakPolicy(QTextFormat::PageBreak_AlwaysAfter);
       
  1929 
       
  1930     QTextBlockFormat blockFmt;
       
  1931     blockFmt.setPageBreakPolicy(QTextFormat::PageBreak_AlwaysBefore);
       
  1932 
       
  1933     QTextCursor cursor(doc);
       
  1934 
       
  1935     cursor.setBlockFormat(blockFmt);
       
  1936     cursor.insertText("foo");
       
  1937     cursor.insertTable(2, 2, tableFmt);
       
  1938 
       
  1939     QTextDocument *clone = doc->clone();
       
  1940     QCOMPARE(clone->begin().blockFormat().pageBreakPolicy(), QTextFormat::PageBreak_AlwaysBefore);
       
  1941     QVERIFY(!clone->rootFrame()->childFrames().isEmpty());
       
  1942     QCOMPARE(clone->rootFrame()->childFrames().first()->frameFormat().pageBreakPolicy(), QTextFormat::PageBreak_AlwaysAfter);
       
  1943     delete clone;
       
  1944 }
       
  1945 
       
  1946 void tst_QTextDocument::clonePreservesDefaultFont()
       
  1947 {
       
  1948     QFont f = doc->defaultFont();
       
  1949     QVERIFY(f.pointSize() != 100);
       
  1950     f.setPointSize(100);
       
  1951     doc->setDefaultFont(f);
       
  1952     QTextDocument *clone = doc->clone();
       
  1953     QCOMPARE(clone->defaultFont(), f);
       
  1954     delete clone;
       
  1955 }
       
  1956 
       
  1957 void tst_QTextDocument::clonePreservesResources()
       
  1958 {
       
  1959     QUrl testUrl(":/foobar");
       
  1960     QVariant testResource("hello world");
       
  1961 
       
  1962     doc->addResource(QTextDocument::ImageResource, testUrl, testResource);
       
  1963     QTextDocument *clone = doc->clone();
       
  1964     QVERIFY(clone->resource(QTextDocument::ImageResource, testUrl) == testResource);
       
  1965     delete clone;
       
  1966 }
       
  1967 
       
  1968 void tst_QTextDocument::clonePreservesUserStates()
       
  1969 {
       
  1970     QTextCursor cursor(doc);
       
  1971     cursor.insertText("bla bla bla");
       
  1972     cursor.block().setUserState(1);
       
  1973     cursor.insertBlock();
       
  1974     cursor.insertText("foo bar");
       
  1975     cursor.block().setUserState(2);
       
  1976     cursor.insertBlock();
       
  1977     cursor.insertText("no user state");
       
  1978 
       
  1979     QTextDocument *clone = doc->clone();
       
  1980     QTextBlock b1 = doc->begin(), b2 = clone->begin();
       
  1981     while (b1 != doc->end()) {
       
  1982         b1 = b1.next();
       
  1983         b2 = b2.next();
       
  1984         QCOMPARE(b1.userState(), b2.userState());
       
  1985     }
       
  1986     QVERIFY(b2 == clone->end());
       
  1987     delete clone;
       
  1988 }
       
  1989 
       
  1990 void tst_QTextDocument::clonePreservesRootFrameFormat()
       
  1991 {
       
  1992     doc->setPlainText("Hello");
       
  1993     QTextFrameFormat fmt = doc->rootFrame()->frameFormat();
       
  1994     fmt.setMargin(200);
       
  1995     doc->rootFrame()->setFrameFormat(fmt);
       
  1996     QCOMPARE(doc->rootFrame()->frameFormat().margin(), qreal(200));
       
  1997     QTextDocument *copy = doc->clone();
       
  1998     QCOMPARE(copy->rootFrame()->frameFormat().margin(), qreal(200));
       
  1999     delete copy;
       
  2000 }
       
  2001 
       
  2002 void tst_QTextDocument::clonePreservesIndentWidth()
       
  2003 {
       
  2004     doc->setIndentWidth(42);
       
  2005     QTextDocument *clone = doc->clone();
       
  2006     QCOMPARE(clone->indentWidth(), qreal(42));
       
  2007 }
       
  2008 
       
  2009 void tst_QTextDocument::blockCount()
       
  2010 {
       
  2011     QCOMPARE(doc->blockCount(), 1);
       
  2012     cursor.insertBlock();
       
  2013     QCOMPARE(doc->blockCount(), 2);
       
  2014     cursor.insertBlock();
       
  2015     QCOMPARE(doc->blockCount(), 3);
       
  2016     cursor.insertText("blah blah");
       
  2017     QCOMPARE(doc->blockCount(), 3);
       
  2018     doc->undo();
       
  2019     doc->undo();
       
  2020     QCOMPARE(doc->blockCount(), 2);
       
  2021     doc->undo();
       
  2022     QCOMPARE(doc->blockCount(), 1);
       
  2023 }
       
  2024 
       
  2025 void tst_QTextDocument::resolvedFontInEmptyFormat()
       
  2026 {
       
  2027     QFont font;
       
  2028     font.setPointSize(42);
       
  2029     doc->setDefaultFont(font);
       
  2030     QTextCharFormat fmt = doc->begin().charFormat();
       
  2031     QVERIFY(fmt.properties().isEmpty());
       
  2032     QVERIFY(fmt.font() == font);
       
  2033 }
       
  2034 
       
  2035 void tst_QTextDocument::defaultRootFrameMargin()
       
  2036 {
       
  2037     QCOMPARE(doc->rootFrame()->frameFormat().margin(), 4.0);
       
  2038 }
       
  2039 
       
  2040 class TestDocument : public QTextDocument
       
  2041 {
       
  2042 public:
       
  2043     inline TestDocument(const QUrl &testUrl, const QString &testString)
       
  2044        : url(testUrl), string(testString), resourceLoaded(false) {}
       
  2045 
       
  2046     bool hasResourceCached();
       
  2047 
       
  2048 protected:
       
  2049     virtual QVariant loadResource(int type, const QUrl &name);
       
  2050 
       
  2051 private:
       
  2052     QUrl url;
       
  2053     QString string;
       
  2054     bool resourceLoaded;
       
  2055 };
       
  2056 
       
  2057 bool TestDocument::hasResourceCached()
       
  2058 {
       
  2059     resourceLoaded = false;
       
  2060     resource(QTextDocument::ImageResource, url);
       
  2061     return !resourceLoaded;
       
  2062 }
       
  2063 
       
  2064 QVariant TestDocument::loadResource(int type, const QUrl &name)
       
  2065 {
       
  2066     if (type == QTextDocument::ImageResource
       
  2067         && name == url) {
       
  2068         resourceLoaded = true;
       
  2069         return string;
       
  2070     }
       
  2071     return QTextDocument::loadResource(type, name);
       
  2072 }
       
  2073 
       
  2074 void tst_QTextDocument::clearResources()
       
  2075 {
       
  2076     // regular resource for QTextDocument
       
  2077     QUrl testUrl(":/foobar");
       
  2078     QVariant testResource("hello world");
       
  2079 
       
  2080     // implicitly cached resource, initially loaded through TestDocument::loadResource()
       
  2081     QUrl cacheUrl(":/blub");
       
  2082     QString cacheResource("mah");
       
  2083 
       
  2084     TestDocument doc(cacheUrl, cacheResource);
       
  2085     doc.addResource(QTextDocument::ImageResource, testUrl, testResource);
       
  2086 
       
  2087     QVERIFY(doc.resource(QTextDocument::ImageResource, testUrl) == testResource);
       
  2088 
       
  2089     doc.setPlainText("Hah");
       
  2090     QVERIFY(doc.resource(QTextDocument::ImageResource, testUrl) == testResource);
       
  2091 
       
  2092     doc.setHtml("<b>Mooo</b><img src=\":/blub\"/>");
       
  2093     QVERIFY(doc.resource(QTextDocument::ImageResource, testUrl) == testResource);
       
  2094     QVERIFY(doc.resource(QTextDocument::ImageResource, cacheUrl) == cacheResource);
       
  2095 
       
  2096     doc.clear();
       
  2097     QVERIFY(!doc.resource(QTextDocument::ImageResource, testUrl).isValid());
       
  2098     QVERIFY(!doc.hasResourceCached());
       
  2099     doc.clear();
       
  2100 
       
  2101     doc.setHtml("<b>Mooo</b><img src=\":/blub\"/>");
       
  2102     QVERIFY(doc.resource(QTextDocument::ImageResource, cacheUrl) == cacheResource);
       
  2103 
       
  2104     doc.setPlainText("Foob");
       
  2105     QVERIFY(!doc.hasResourceCached());
       
  2106 }
       
  2107 
       
  2108 void tst_QTextDocument::setPlainText()
       
  2109 {
       
  2110     doc->setPlainText("Hello World");
       
  2111     QString s("");
       
  2112     doc->setPlainText(s);
       
  2113     QCOMPARE(doc->toPlainText(), s);
       
  2114 }
       
  2115 
       
  2116 void tst_QTextDocument::toPlainText()
       
  2117 {
       
  2118     doc->setHtml("Hello&nbsp;World");
       
  2119     QCOMPARE(doc->toPlainText(), QLatin1String("Hello World"));
       
  2120 }
       
  2121 
       
  2122 void tst_QTextDocument::deleteTextObjectsOnClear()
       
  2123 {
       
  2124     QPointer<QTextTable> table = cursor.insertTable(2, 2);
       
  2125     QVERIFY(!table.isNull());
       
  2126     doc->clear();
       
  2127     QVERIFY(table.isNull());
       
  2128 }
       
  2129 
       
  2130 void tst_QTextDocument::defaultStyleSheet()
       
  2131 {
       
  2132     const QString sheet("p { background-color: green; }");
       
  2133     QVERIFY(doc->defaultStyleSheet().isEmpty());
       
  2134     doc->setDefaultStyleSheet(sheet);
       
  2135     QCOMPARE(doc->defaultStyleSheet(), sheet);
       
  2136 
       
  2137     cursor.insertHtml("<p>test");
       
  2138     QTextBlockFormat fmt = doc->begin().blockFormat();
       
  2139     QVERIFY(fmt.background().color() == QColor("green"));
       
  2140 
       
  2141     doc->clear();
       
  2142     cursor.insertHtml("<p>test");
       
  2143     fmt = doc->begin().blockFormat();
       
  2144     QVERIFY(fmt.background().color() == QColor("green"));
       
  2145 
       
  2146     QTextDocument *clone = doc->clone();
       
  2147     QCOMPARE(clone->defaultStyleSheet(), sheet);
       
  2148     cursor = QTextCursor(clone);
       
  2149     cursor.insertHtml("<p>test");
       
  2150     fmt = clone->begin().blockFormat();
       
  2151     QVERIFY(fmt.background().color() == QColor("green"));
       
  2152     delete clone;
       
  2153 
       
  2154     cursor = QTextCursor(doc);
       
  2155     cursor.insertHtml("<p>test");
       
  2156     fmt = doc->begin().blockFormat();
       
  2157     QVERIFY(fmt.background().color() == QColor("green"));
       
  2158 
       
  2159     doc->clear();
       
  2160     cursor.insertHtml("<style>p { background-color: red; }</style><p>test");
       
  2161     fmt = doc->begin().blockFormat();
       
  2162     QVERIFY(fmt.background().color() == QColor("red"));
       
  2163 
       
  2164     doc->clear();
       
  2165     doc->setDefaultStyleSheet("invalid style sheet....");
       
  2166     cursor.insertHtml("<p>test");
       
  2167     fmt = doc->begin().blockFormat();
       
  2168     QVERIFY(fmt.background().color() != QColor("green"));
       
  2169 }
       
  2170 
       
  2171 void tst_QTextDocument::maximumBlockCount()
       
  2172 {
       
  2173     QCOMPARE(doc->maximumBlockCount(), 0);
       
  2174     QVERIFY(doc->isUndoRedoEnabled());
       
  2175 
       
  2176     cursor.insertBlock();
       
  2177     cursor.insertText("Blah");
       
  2178     cursor.insertBlock();
       
  2179     cursor.insertText("Foo");
       
  2180     QCOMPARE(doc->blockCount(), 3);
       
  2181     QCOMPARE(doc->toPlainText(), QString("\nBlah\nFoo"));
       
  2182 
       
  2183     doc->setMaximumBlockCount(1);
       
  2184     QVERIFY(!doc->isUndoRedoEnabled());
       
  2185 
       
  2186     QCOMPARE(doc->blockCount(), 1);
       
  2187     QCOMPARE(doc->toPlainText(), QString("Foo"));
       
  2188 
       
  2189     cursor.insertBlock();
       
  2190     cursor.insertText("Hello");
       
  2191     doc->setMaximumBlockCount(1);
       
  2192     QCOMPARE(doc->blockCount(), 1);
       
  2193     QCOMPARE(doc->toPlainText(), QString("Hello"));
       
  2194 
       
  2195     doc->setMaximumBlockCount(100);
       
  2196     for (int i = 0; i < 1000; ++i) {
       
  2197         cursor.insertBlock();
       
  2198         cursor.insertText("Blah)");
       
  2199         QVERIFY(doc->blockCount() <= 100);
       
  2200     }
       
  2201 
       
  2202     cursor.movePosition(QTextCursor::End);
       
  2203     QCOMPARE(cursor.blockNumber(), 99);
       
  2204     QTextCharFormat fmt;
       
  2205     fmt.setFontItalic(true);
       
  2206     cursor.setBlockCharFormat(fmt);
       
  2207     cursor.movePosition(QTextCursor::Start);
       
  2208     QVERIFY(!cursor.blockCharFormat().fontItalic());
       
  2209 
       
  2210     doc->setMaximumBlockCount(1);
       
  2211     QVERIFY(cursor.blockCharFormat().fontItalic());
       
  2212 
       
  2213     cursor.insertTable(2, 2);
       
  2214     QCOMPARE(doc->blockCount(), 6);
       
  2215     cursor.insertBlock();
       
  2216     QCOMPARE(doc->blockCount(), 1);
       
  2217 }
       
  2218 
       
  2219 void tst_QTextDocument::adjustSize()
       
  2220 {
       
  2221     // avoid ugly tooltips like in task 125583
       
  2222     QString text("Test Text");
       
  2223     doc->setPlainText(text);
       
  2224     doc->rootFrame()->setFrameFormat(QTextFrameFormat());
       
  2225     doc->adjustSize();
       
  2226     QCOMPARE(doc->size().width(), doc->idealWidth());
       
  2227 }
       
  2228 
       
  2229 void tst_QTextDocument::initialUserData()
       
  2230 {
       
  2231     doc->setPlainText("Hello");
       
  2232     QTextBlock block = doc->begin();
       
  2233     block.setUserData(new QTextBlockUserData);
       
  2234     QVERIFY(block.userData());
       
  2235     doc->documentLayout();
       
  2236     QVERIFY(block.userData());
       
  2237     doc->setDocumentLayout(new QTestDocumentLayout(doc));
       
  2238     QVERIFY(!block.userData());
       
  2239 }
       
  2240 
       
  2241 void tst_QTextDocument::html_defaultFont()
       
  2242 {
       
  2243     QFont f;
       
  2244     f.setItalic(true);
       
  2245     f.setWeight(QFont::Bold);
       
  2246     doc->setDefaultFont(f);
       
  2247     doc->setPlainText("Test");
       
  2248 
       
  2249     QString bodyPart = QString::fromLatin1("<body style=\" font-family:'%1'; font-size:%2pt; font-weight:%3; font-style:italic;\">")
       
  2250                        .arg(f.family()).arg(f.pointSizeF()).arg(f.weight() * 8);
       
  2251 
       
  2252     QString html = doc->toHtml();
       
  2253     if (!html.contains(bodyPart)) {
       
  2254         qDebug() << "html:" << html;
       
  2255         qDebug() << "expected body:" << bodyPart;
       
  2256         QVERIFY(html.contains(bodyPart));
       
  2257     }
       
  2258 
       
  2259     if (html.contains("span"))
       
  2260         qDebug() << "html:" << html;
       
  2261     QVERIFY(!html.contains("<span style"));
       
  2262 }
       
  2263 
       
  2264 void tst_QTextDocument::blockCountChanged()
       
  2265 {
       
  2266     QSignalSpy spy(doc, SIGNAL(blockCountChanged(int)));
       
  2267 
       
  2268     doc->setPlainText("Foo");
       
  2269 
       
  2270     QCOMPARE(doc->blockCount(), 1);
       
  2271     QCOMPARE(spy.count(), 0);
       
  2272 
       
  2273     spy.clear();
       
  2274 
       
  2275     doc->setPlainText("Foo\nBar");
       
  2276     QCOMPARE(doc->blockCount(), 2);
       
  2277     QCOMPARE(spy.count(), 1);
       
  2278     QCOMPARE(spy.at(0).value(0).toInt(), 2);
       
  2279 
       
  2280     spy.clear();
       
  2281 
       
  2282     cursor.movePosition(QTextCursor::End);
       
  2283     cursor.insertText("Blahblah");
       
  2284 
       
  2285     QCOMPARE(spy.count(), 0);
       
  2286 
       
  2287     cursor.insertBlock();
       
  2288     QCOMPARE(spy.count(), 1);
       
  2289     QCOMPARE(spy.at(0).value(0).toInt(), 3);
       
  2290 
       
  2291     spy.clear();
       
  2292     doc->undo();
       
  2293 
       
  2294     QCOMPARE(spy.count(), 1);
       
  2295     QCOMPARE(spy.at(0).value(0).toInt(), 2);
       
  2296 }
       
  2297 
       
  2298 void tst_QTextDocument::nonZeroDocumentLengthOnClear()
       
  2299 {
       
  2300     QTestDocumentLayout *lout = new QTestDocumentLayout(doc);
       
  2301     doc->setDocumentLayout(lout);
       
  2302 
       
  2303     doc->clear();
       
  2304     QVERIFY(lout->called);
       
  2305     QVERIFY(!lout->lastDocumentLengths.contains(0));
       
  2306 }
       
  2307 
       
  2308 void tst_QTextDocument::setTextPreservesUndoRedoEnabled()
       
  2309 {
       
  2310     QVERIFY(doc->isUndoRedoEnabled());
       
  2311 
       
  2312     doc->setPlainText("Test");
       
  2313 
       
  2314     QVERIFY(doc->isUndoRedoEnabled());
       
  2315 
       
  2316     doc->setUndoRedoEnabled(false);
       
  2317     QVERIFY(!doc->isUndoRedoEnabled());
       
  2318     doc->setPlainText("Test2");
       
  2319     QVERIFY(!doc->isUndoRedoEnabled());
       
  2320 
       
  2321     doc->setHtml("<p>hello");
       
  2322     QVERIFY(!doc->isUndoRedoEnabled());
       
  2323 }
       
  2324 
       
  2325 void tst_QTextDocument::firstLast()
       
  2326 {
       
  2327     QCOMPARE(doc->blockCount(), 1);
       
  2328     QVERIFY(doc->firstBlock() == doc->lastBlock());
       
  2329 
       
  2330     doc->setPlainText("Hello\nTest\nWorld");
       
  2331 
       
  2332     QCOMPARE(doc->blockCount(), 3);
       
  2333     QVERIFY(doc->firstBlock() != doc->lastBlock());
       
  2334 
       
  2335     QCOMPARE(doc->firstBlock().text(), QString("Hello"));
       
  2336     QCOMPARE(doc->lastBlock().text(), QString("World"));
       
  2337 
       
  2338     // manual forward loop
       
  2339     QTextBlock block = doc->firstBlock();
       
  2340 
       
  2341     QVERIFY(block.isValid());
       
  2342     QCOMPARE(block.text(), QString("Hello"));
       
  2343 
       
  2344     block = block.next();
       
  2345 
       
  2346     QVERIFY(block.isValid());
       
  2347     QCOMPARE(block.text(), QString("Test"));
       
  2348 
       
  2349     block = block.next();
       
  2350 
       
  2351     QVERIFY(block.isValid());
       
  2352     QCOMPARE(block.text(), QString("World"));
       
  2353 
       
  2354     block = block.next();
       
  2355     QVERIFY(!block.isValid());
       
  2356 
       
  2357     // manual backward loop
       
  2358     block = doc->lastBlock();
       
  2359 
       
  2360     QVERIFY(block.isValid());
       
  2361     QCOMPARE(block.text(), QString("World"));
       
  2362 
       
  2363     block = block.previous();
       
  2364 
       
  2365     QVERIFY(block.isValid());
       
  2366     QCOMPARE(block.text(), QString("Test"));
       
  2367 
       
  2368     block = block.previous();
       
  2369 
       
  2370     QVERIFY(block.isValid());
       
  2371     QCOMPARE(block.text(), QString("Hello"));
       
  2372 
       
  2373     block = block.previous();
       
  2374     QVERIFY(!block.isValid());
       
  2375 }
       
  2376 
       
  2377 const QString backgroundImage_html("<body><table><tr><td background=\"foo.png\">Blah</td></tr></table></body>");
       
  2378 
       
  2379 void tst_QTextDocument::backgroundImage_checkExpectedHtml(const QTextDocument &doc)
       
  2380 {
       
  2381     QString expectedHtml("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" "
       
  2382             "\"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
       
  2383             "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
       
  2384             "p, li { white-space: pre-wrap; }\n"
       
  2385             "</style></head>"
       
  2386             "<body style=\" font-family:'%1'; font-size:%2pt; font-weight:%3; font-style:%4;\">\n"
       
  2387             "<table border=\"0\" style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px;\" cellspacing=\"2\" cellpadding=\"0\">"
       
  2388             "\n<tr>\n<td background=\"foo.png\">"
       
  2389             "\n<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Blah</p>"
       
  2390             "</td></tr></table></body></html>");
       
  2391 
       
  2392     expectedHtml = expectedHtml.arg(defaultFont.family()).arg(defaultFont.pointSizeF()).arg(defaultFont.weight() * 8).arg((defaultFont.italic() ? "italic" : "normal"));
       
  2393 
       
  2394     QCOMPARE(doc.toHtml(), expectedHtml);
       
  2395 }
       
  2396 
       
  2397 void tst_QTextDocument::backgroundImage_toHtml()
       
  2398 {
       
  2399     CREATE_DOC_AND_CURSOR();
       
  2400 
       
  2401     doc.setHtml(backgroundImage_html);
       
  2402     backgroundImage_checkExpectedHtml(doc);
       
  2403 }
       
  2404 
       
  2405 void tst_QTextDocument::backgroundImage_toHtml2()
       
  2406 {
       
  2407     CREATE_DOC_AND_CURSOR();
       
  2408 
       
  2409     cursor.insertHtml(backgroundImage_html);
       
  2410     backgroundImage_checkExpectedHtml(doc);
       
  2411 }
       
  2412 
       
  2413 void tst_QTextDocument::backgroundImage_clone()
       
  2414 {
       
  2415     CREATE_DOC_AND_CURSOR();
       
  2416 
       
  2417     doc.setHtml(backgroundImage_html);
       
  2418     QTextDocument *clone = doc.clone();
       
  2419     backgroundImage_checkExpectedHtml(*clone);
       
  2420     delete clone;
       
  2421 }
       
  2422 
       
  2423 void tst_QTextDocument::backgroundImage_copy()
       
  2424 {
       
  2425     CREATE_DOC_AND_CURSOR();
       
  2426 
       
  2427     doc.setHtml(backgroundImage_html);
       
  2428     QTextDocumentFragment fragment(&doc);
       
  2429 
       
  2430     {
       
  2431         CREATE_DOC_AND_CURSOR();
       
  2432 
       
  2433         cursor.insertFragment(fragment);
       
  2434         backgroundImage_checkExpectedHtml(doc);
       
  2435     }
       
  2436 }
       
  2437 
       
  2438 void tst_QTextDocument::documentCleanup()
       
  2439 {
       
  2440     QTextDocument doc;
       
  2441     QTextCursor cursor(&doc);
       
  2442     cursor.insertText("d\nfoo\nbar\n");
       
  2443     doc.documentLayout(); // forces relayout
       
  2444 
       
  2445     // remove char 1
       
  2446     cursor.setPosition(0);
       
  2447     QSizeF size = doc.documentLayout()->documentSize();
       
  2448     cursor.deleteChar();
       
  2449     // the size should be unchanged.
       
  2450     QCOMPARE(doc.documentLayout()->documentSize(), size);
       
  2451 }
       
  2452 
       
  2453 void tst_QTextDocument::characterAt()
       
  2454 {
       
  2455     QTextDocument doc;
       
  2456     QTextCursor cursor(&doc);
       
  2457     QString text("12345\n67890");
       
  2458     cursor.insertText(text);
       
  2459     int length = doc.characterCount();
       
  2460     QCOMPARE(length, text.length() + 1);
       
  2461     QCOMPARE(doc.characterAt(length-1), QChar(QChar::ParagraphSeparator));
       
  2462     QCOMPARE(doc.characterAt(-1), QChar());
       
  2463     QCOMPARE(doc.characterAt(length), QChar());
       
  2464     QCOMPARE(doc.characterAt(length + 1), QChar());
       
  2465     for (int i = 0; i < text.length(); ++i) {
       
  2466         QChar c = text.at(i);
       
  2467         if (c == QLatin1Char('\n'))
       
  2468             c = QChar(QChar::ParagraphSeparator);
       
  2469         QCOMPARE(doc.characterAt(i), c);
       
  2470     }
       
  2471 }
       
  2472 
       
  2473 void tst_QTextDocument::revisions()
       
  2474 {
       
  2475     QTextDocument doc;
       
  2476     QTextCursor cursor(&doc);
       
  2477     QString text("Hello World");
       
  2478     QCOMPARE(doc.firstBlock().revision(), 0);
       
  2479     cursor.insertText(text);
       
  2480     QCOMPARE(doc.firstBlock().revision(), 1);
       
  2481     cursor.setPosition(6);
       
  2482     cursor.insertBlock();
       
  2483     QCOMPARE(cursor.block().previous().revision(), 2);
       
  2484     QCOMPARE(cursor.block().revision(), 2);
       
  2485     cursor.insertText("candle");
       
  2486     QCOMPARE(cursor.block().revision(), 3);
       
  2487     cursor.movePosition(QTextCursor::EndOfBlock);
       
  2488     cursor.insertBlock(); // we are at the block end
       
  2489     QCOMPARE(cursor.block().previous().revision(), 3);
       
  2490     QCOMPARE(cursor.block().revision(), 4);
       
  2491     cursor.insertText("lightbulb");
       
  2492     QCOMPARE(cursor.block().revision(), 5);
       
  2493     cursor.movePosition(QTextCursor::StartOfBlock);
       
  2494     cursor.insertBlock(); // we are the block start
       
  2495     QCOMPARE(cursor.block().previous().revision(), 6);
       
  2496     QCOMPARE(cursor.block().revision(), 5);
       
  2497 }
       
  2498 
       
  2499 void tst_QTextDocument::revisionWithUndoCompressionAndUndo()
       
  2500 {
       
  2501     QTextDocument doc;
       
  2502     QTextCursor cursor(&doc);
       
  2503     cursor.insertText("This is the beginning of it all.");
       
  2504     QCOMPARE(doc.firstBlock().revision(), 1);
       
  2505     QCOMPARE(doc.revision(), 1);
       
  2506     cursor.insertBlock();
       
  2507     QCOMPARE(doc.revision(), 2);
       
  2508     cursor.insertText("this");
       
  2509     QCOMPARE(doc.revision(), 3);
       
  2510     cursor.insertText("is");
       
  2511     QCOMPARE(doc.revision(), 4);
       
  2512     cursor.insertText("compressed");
       
  2513     QCOMPARE(doc.revision(), 5);
       
  2514     doc.undo();
       
  2515     QCOMPARE(doc.revision(), 6);
       
  2516     QCOMPARE(doc.toPlainText(), QString("This is the beginning of it all.\n"))  ;
       
  2517     cursor.setPosition(0);
       
  2518     QCOMPARE(doc.firstBlock().revision(), 1);
       
  2519     cursor.insertText("Very beginnig");
       
  2520     QCOMPARE(doc.firstBlock().revision(), 7);
       
  2521     doc.undo();
       
  2522     QCOMPARE(doc.revision(), 8);
       
  2523     QCOMPARE(doc.firstBlock().revision(), 1);
       
  2524 
       
  2525     cursor.beginEditBlock();
       
  2526     cursor.insertText("Hello");
       
  2527     cursor.insertBlock();
       
  2528     cursor.insertText("world");
       
  2529     cursor.endEditBlock();
       
  2530     QCOMPARE(doc.revision(), 9);
       
  2531     doc.undo();
       
  2532     QCOMPARE(doc.revision(), 10);
       
  2533 
       
  2534 
       
  2535 }
       
  2536 
       
  2537 void tst_QTextDocument::testUndoCommandAdded()
       
  2538 {
       
  2539     QVERIFY(doc);
       
  2540     QSignalSpy spy(doc, SIGNAL(undoCommandAdded()));
       
  2541     QVERIFY(spy.isValid());
       
  2542     QVERIFY(spy.isEmpty());
       
  2543 
       
  2544     cursor.insertText("a");
       
  2545     QCOMPARE(spy.count(), 1);
       
  2546     cursor.insertText("b"); // should be merged
       
  2547     QCOMPARE(spy.count(), 1);
       
  2548     cursor.insertText("c"); // should be merged
       
  2549     QCOMPARE(spy.count(), 1);
       
  2550     QCOMPARE(doc->toPlainText(), QString("abc"));
       
  2551     doc->undo();
       
  2552     QCOMPARE(doc->toPlainText(), QString(""));
       
  2553 
       
  2554     doc->clear();
       
  2555     spy.clear();
       
  2556     cursor.insertText("aaa");
       
  2557     QCOMPARE(spy.count(), 1);
       
  2558 
       
  2559     spy.clear();
       
  2560     cursor.insertText("aaaa\nbcd");
       
  2561     QCOMPARE(spy.count(), 1);
       
  2562 
       
  2563     spy.clear();
       
  2564     cursor.beginEditBlock();
       
  2565     cursor.insertText("aa");
       
  2566     cursor.insertText("bbb\n");
       
  2567     cursor.setCharFormat(QTextCharFormat());
       
  2568     cursor.insertText("\nccc");
       
  2569     QVERIFY(spy.isEmpty());
       
  2570     cursor.endEditBlock();
       
  2571     QCOMPARE(spy.count(), 1);
       
  2572 
       
  2573     spy.clear();
       
  2574     cursor.insertBlock();
       
  2575     QCOMPARE(spy.count(), 1);
       
  2576 
       
  2577     spy.clear();
       
  2578     cursor.setPosition(5);
       
  2579     QVERIFY(spy.isEmpty());
       
  2580     cursor.setCharFormat(QTextCharFormat());
       
  2581     QVERIFY(spy.isEmpty());
       
  2582     cursor.setPosition(10, QTextCursor::KeepAnchor);
       
  2583     QVERIFY(spy.isEmpty());
       
  2584     QTextCharFormat cf;
       
  2585     cf.setFontItalic(true);
       
  2586     cursor.mergeCharFormat(cf);
       
  2587     QCOMPARE(spy.count(), 1);
       
  2588 }
       
  2589 
       
  2590 void tst_QTextDocument::testUndoBlocks()
       
  2591 {
       
  2592     QVERIFY(doc);
       
  2593     cursor.insertText("Hello World");
       
  2594     cursor.insertText("period");
       
  2595     doc->undo();
       
  2596     QCOMPARE(doc->toPlainText(), QString(""));
       
  2597     cursor.insertText("Hello World");
       
  2598     cursor.insertText("One\nTwo\nThree");
       
  2599     QCOMPARE(doc->toPlainText(), QString("Hello WorldOne\nTwo\nThree"));
       
  2600     doc->undo();
       
  2601     QCOMPARE(doc->toPlainText(), QString("Hello World"));
       
  2602     cursor.insertText("One\nTwo\nThree");
       
  2603     cursor.insertText("Trailing text");
       
  2604     doc->undo();
       
  2605     QCOMPARE(doc->toPlainText(), QString("Hello WorldOne\nTwo\nThree"));
       
  2606     doc->undo();
       
  2607     QCOMPARE(doc->toPlainText(), QString("Hello World"));
       
  2608     doc->undo();
       
  2609     QCOMPARE(doc->toPlainText(), QString(""));
       
  2610 
       
  2611     cursor.insertText("quod");
       
  2612     cursor.beginEditBlock();
       
  2613     cursor.insertText(" erat");
       
  2614     cursor.endEditBlock();
       
  2615     cursor.insertText(" demonstrandum");
       
  2616     QCOMPARE(doc->toPlainText(), QString("quod erat demonstrandum"));
       
  2617     doc->undo();
       
  2618     QCOMPARE(doc->toPlainText(), QString("quod erat"));
       
  2619     doc->undo();
       
  2620     QCOMPARE(doc->toPlainText(), QString("quod"));
       
  2621     doc->undo();
       
  2622     QCOMPARE(doc->toPlainText(), QString(""));
       
  2623 }
       
  2624 
       
  2625 class Receiver : public QObject
       
  2626 {
       
  2627     Q_OBJECT
       
  2628  public:
       
  2629     QString first;
       
  2630  public slots:
       
  2631     void cursorPositionChanged() {
       
  2632         if (first.isEmpty())
       
  2633             first = QLatin1String("cursorPositionChanged");
       
  2634     }
       
  2635 
       
  2636     void contentsChange() {
       
  2637         if (first.isEmpty())
       
  2638             first = QLatin1String("contentsChanged");
       
  2639     }
       
  2640 };
       
  2641 
       
  2642 void tst_QTextDocument::receiveCursorPositionChangedAfterContentsChange()
       
  2643 {
       
  2644     QVERIFY(doc);
       
  2645     doc->setDocumentLayout(new MyAbstractTextDocumentLayout(doc));
       
  2646     Receiver rec;
       
  2647     connect(doc, SIGNAL(cursorPositionChanged(QTextCursor)),
       
  2648             &rec, SLOT(cursorPositionChanged()));
       
  2649     connect(doc, SIGNAL(contentsChange(int,int,int)),
       
  2650             &rec, SLOT(contentsChange()));
       
  2651     cursor.insertText("Hello World");
       
  2652     QCOMPARE(rec.first, QString("contentsChanged"));
       
  2653 }
       
  2654 
       
  2655 QTEST_MAIN(tst_QTextDocument)
       
  2656 #include "tst_qtextdocument.moc"