tests/auto/qtextedit/tst_qtextedit.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 <qtextedit.h>
       
    47 #include <qtextcursor.h>
       
    48 #include <qtextlist.h>
       
    49 #include <qdebug.h>
       
    50 #include <qapplication.h>
       
    51 #include <qclipboard.h>
       
    52 #include <qtextbrowser.h>
       
    53 #include <private/qtextcontrol_p.h>
       
    54 #include <qscrollbar.h>
       
    55 #include <qtextobject.h>
       
    56 #include <qtexttable.h>
       
    57 #include <qpainter.h>
       
    58 #include <qimagereader.h>
       
    59 #include <qimagewriter.h>
       
    60 #include <qcommonstyle.h>
       
    61 
       
    62 #include <qabstracttextdocumentlayout.h>
       
    63 #include <qtextdocumentfragment.h>
       
    64 
       
    65 //Used in copyAvailable
       
    66 typedef QPair<Qt::Key, Qt::KeyboardModifier> keyPairType;
       
    67 typedef QList<keyPairType> pairListType;
       
    68 Q_DECLARE_METATYPE(pairListType);
       
    69 Q_DECLARE_METATYPE(keyPairType);
       
    70 Q_DECLARE_METATYPE(QList<bool>);
       
    71 
       
    72 #ifdef Q_WS_MAC
       
    73 #include <Carbon/Carbon.h>
       
    74 #endif
       
    75 
       
    76 #if defined(Q_OS_SYMBIAN)
       
    77 # define SRCDIR ""
       
    78 #undef QT3_SUPPORT
       
    79 #endif
       
    80 
       
    81 
       
    82 bool nativeClipboardWorking()
       
    83 {
       
    84 #ifdef Q_WS_MAC
       
    85     PasteboardRef pasteboard;
       
    86     OSStatus status = PasteboardCreate(0, &pasteboard);
       
    87     if (status == noErr)
       
    88         CFRelease(pasteboard);
       
    89     return status == noErr;
       
    90 #endif
       
    91     return true;
       
    92 }
       
    93 
       
    94 
       
    95 QT_FORWARD_DECLARE_CLASS(QTextEdit)
       
    96 
       
    97 //TESTED_CLASS=
       
    98 //TESTED_FILES=
       
    99 
       
   100 class tst_QTextEdit : public QObject
       
   101 {
       
   102     Q_OBJECT
       
   103 public:
       
   104     tst_QTextEdit();
       
   105 
       
   106 public slots:
       
   107     void init();
       
   108     void cleanup();
       
   109 private slots:
       
   110     void getSetCheck();
       
   111     void inlineAttributesOnInsert();
       
   112     void inlineAttributesOnSelection();
       
   113     void inlineAttributeSymmetry();
       
   114     void inlineAttributeSymmetryWithSelection();
       
   115     void autoBulletList1();
       
   116     void autoBulletList2();
       
   117     void preserveCharFormatAfterNewline();
       
   118 #ifndef QT_NO_CLIPBOARD
       
   119     void clearMustNotChangeClipboard();
       
   120 #endif
       
   121     void clearMustNotResetRootFrameMarginToDefault();
       
   122     void clearShouldPreserveTheCurrentCharFormat();
       
   123     void clearShouldClearExtraSelections();
       
   124     void paragSeparatorOnPlaintextAppend();
       
   125     void layoutingLoop();
       
   126 #ifndef QT_NO_CLIPBOARD
       
   127     void selectAllSetsNotSelection();
       
   128 #endif
       
   129     void asciiTab();
       
   130     void setDocument();
       
   131     void setDocument_shared();
       
   132     void mergeCurrentCharFormat();
       
   133     void mergeCurrentBlockCharFormat();
       
   134     void emptyAppend();
       
   135     void appendOnEmptyDocumentShouldReuseInitialParagraph();
       
   136 #ifdef QT3_SUPPORT
       
   137     void textSemantics();
       
   138 #endif
       
   139     void cursorPositionChanged();
       
   140     void setTextCursor();
       
   141 #ifndef QT_NO_CLIPBOARD
       
   142     void undoAvailableAfterPaste();
       
   143 #endif
       
   144     void undoRedoAvailableRepetition();
       
   145     void appendShouldUseCurrentFormat();
       
   146     void appendShouldNotTouchTheSelection();
       
   147     void backspace();
       
   148     void shiftBackspace();
       
   149     void undoRedo();
       
   150     void preserveCharFormatInAppend();
       
   151 #ifndef QT_NO_CLIPBOARD
       
   152     void copyAndSelectAllInReadonly();
       
   153 #endif
       
   154     void ctrlAltInput();
       
   155     void noPropertiesOnDefaultTextEditCharFormat();
       
   156     void setPlainTextShouldUseCurrentCharFormat();
       
   157     void setPlainTextShouldEmitTextChangedOnce();
       
   158     void overwriteMode();
       
   159     void shiftDownInLineLastShouldSelectToEnd_data();
       
   160     void shiftDownInLineLastShouldSelectToEnd();
       
   161     void undoRedoShouldRepositionTextEditCursor();
       
   162     void lineWrapModes();
       
   163     void mouseCursorShape();
       
   164     void implicitClear();
       
   165     void undoRedoAfterSetContent();
       
   166     void numPadKeyNavigation();
       
   167     void moveCursor();
       
   168 #ifndef QT_NO_CLIPBOARD
       
   169     void mimeDataReimplementations();
       
   170 #endif
       
   171     void ctrlEnterShouldInsertLineSeparator_NOT();
       
   172     void shiftEnterShouldInsertLineSeparator();
       
   173     void selectWordsFromStringsContainingSeparators_data();
       
   174     void selectWordsFromStringsContainingSeparators();
       
   175 #ifndef QT_NO_CLIPBOARD
       
   176     void canPaste();
       
   177     void copyAvailable_data();
       
   178     void copyAvailable();
       
   179 #endif
       
   180     void ensureCursorVisibleOnInitialShow();
       
   181     void setHtmlInsideResizeEvent();
       
   182     void colorfulAppend();
       
   183     void ensureVisibleWithRtl();
       
   184     void preserveCharFormatAfterSetPlainText();
       
   185     void extraSelections();
       
   186     void adjustScrollbars();
       
   187     void currentCharFormatChanged();
       
   188     void textObscuredByScrollbars();
       
   189     void setTextPreservesUndoRedoEnabled();
       
   190     void wordWrapProperty();
       
   191     void lineWrapProperty();
       
   192     void selectionChanged();
       
   193     void copyPasteBackgroundImage();
       
   194     void setText();
       
   195     void fullWidthSelection_data();
       
   196     void fullWidthSelection();
       
   197     void fullWidthSelection2();
       
   198     void cursorRect();
       
   199     void setDocumentPreservesPalette();
       
   200     void pasteFromQt3RichText();
       
   201     void noWrapBackgrounds();
       
   202     void preserveCharFormatAfterUnchangingSetPosition();
       
   203 
       
   204 private:
       
   205     void createSelection();
       
   206     int blockCount() const;
       
   207     bool nativeClipboardWorking();
       
   208     void compareWidgetAndImage(QTextEdit &widget, const QString &imageFileName);
       
   209 
       
   210     QTextEdit *ed;
       
   211     qreal rootFrameMargin;
       
   212 };
       
   213 
       
   214 bool tst_QTextEdit::nativeClipboardWorking()
       
   215 {
       
   216 #ifdef Q_WS_MAC
       
   217     PasteboardRef pasteboard;
       
   218     OSStatus status = PasteboardCreate(0, &pasteboard);
       
   219     if (status == noErr)
       
   220         CFRelease(pasteboard);
       
   221     return status == noErr;
       
   222 #endif
       
   223     return true;
       
   224 }
       
   225 
       
   226 // Testing get/set functions
       
   227 void tst_QTextEdit::getSetCheck()
       
   228 {
       
   229     QTextEdit obj1;
       
   230     // QTextDocument * QTextEdit::document()
       
   231     // void QTextEdit::setDocument(QTextDocument *)
       
   232     QTextDocument *var1 = new QTextDocument;
       
   233     obj1.setDocument(var1);
       
   234     QCOMPARE(var1, obj1.document());
       
   235     obj1.setDocument((QTextDocument *)0);
       
   236     QVERIFY(var1 != obj1.document()); // QTextEdit creates a new document when setting 0
       
   237     QVERIFY((QTextDocument *)0 != obj1.document());
       
   238     delete var1;
       
   239 
       
   240     // AutoFormatting QTextEdit::autoFormatting()
       
   241     // void QTextEdit::setAutoFormatting(AutoFormatting)
       
   242     obj1.setAutoFormatting(QTextEdit::AutoFormatting(QTextEdit::AutoNone));
       
   243     QCOMPARE(QTextEdit::AutoFormatting(QTextEdit::AutoNone), obj1.autoFormatting());
       
   244     obj1.setAutoFormatting(QTextEdit::AutoFormatting(QTextEdit::AutoBulletList));
       
   245     QCOMPARE(QTextEdit::AutoFormatting(QTextEdit::AutoBulletList), obj1.autoFormatting());
       
   246     obj1.setAutoFormatting(QTextEdit::AutoFormatting(QTextEdit::AutoAll));
       
   247     QCOMPARE(QTextEdit::AutoFormatting(QTextEdit::AutoAll), obj1.autoFormatting());
       
   248 
       
   249     // bool QTextEdit::tabChangesFocus()
       
   250     // void QTextEdit::setTabChangesFocus(bool)
       
   251     obj1.setTabChangesFocus(false);
       
   252     QCOMPARE(false, obj1.tabChangesFocus());
       
   253     obj1.setTabChangesFocus(true);
       
   254     QCOMPARE(true, obj1.tabChangesFocus());
       
   255 
       
   256     // LineWrapMode QTextEdit::lineWrapMode()
       
   257     // void QTextEdit::setLineWrapMode(LineWrapMode)
       
   258     obj1.setLineWrapMode(QTextEdit::LineWrapMode(QTextEdit::NoWrap));
       
   259     QCOMPARE(QTextEdit::LineWrapMode(QTextEdit::NoWrap), obj1.lineWrapMode());
       
   260     obj1.setLineWrapMode(QTextEdit::LineWrapMode(QTextEdit::WidgetWidth));
       
   261     QCOMPARE(QTextEdit::LineWrapMode(QTextEdit::WidgetWidth), obj1.lineWrapMode());
       
   262     obj1.setLineWrapMode(QTextEdit::LineWrapMode(QTextEdit::FixedPixelWidth));
       
   263     QCOMPARE(QTextEdit::LineWrapMode(QTextEdit::FixedPixelWidth), obj1.lineWrapMode());
       
   264     obj1.setLineWrapMode(QTextEdit::LineWrapMode(QTextEdit::FixedColumnWidth));
       
   265     QCOMPARE(QTextEdit::LineWrapMode(QTextEdit::FixedColumnWidth), obj1.lineWrapMode());
       
   266 
       
   267     // int QTextEdit::lineWrapColumnOrWidth()
       
   268     // void QTextEdit::setLineWrapColumnOrWidth(int)
       
   269     obj1.setLineWrapColumnOrWidth(0);
       
   270     QCOMPARE(0, obj1.lineWrapColumnOrWidth());
       
   271     obj1.setLineWrapColumnOrWidth(INT_MIN);
       
   272     QCOMPARE(INT_MIN, obj1.lineWrapColumnOrWidth());
       
   273     obj1.setLineWrapColumnOrWidth(INT_MAX);
       
   274     QCOMPARE(INT_MAX, obj1.lineWrapColumnOrWidth());
       
   275 
       
   276     // bool QTextEdit::overwriteMode()
       
   277     // void QTextEdit::setOverwriteMode(bool)
       
   278     obj1.setOverwriteMode(false);
       
   279     QCOMPARE(false, obj1.overwriteMode());
       
   280     obj1.setOverwriteMode(true);
       
   281     QCOMPARE(true, obj1.overwriteMode());
       
   282 
       
   283     // int QTextEdit::tabStopWidth()
       
   284     // void QTextEdit::setTabStopWidth(int)
       
   285     obj1.setTabStopWidth(0);
       
   286     QCOMPARE(0, obj1.tabStopWidth());
       
   287     obj1.setTabStopWidth(INT_MIN);
       
   288     QCOMPARE(0, obj1.tabStopWidth()); // Makes no sense to set a negative tabstop value
       
   289 #if defined(QT_ARCH_WINDOWSCE)
       
   290     // due to rounding error in qRound when qreal==float
       
   291     // we cannot use INT_MAX for this check
       
   292     obj1.setTabStopWidth(SHRT_MAX*2);
       
   293     QCOMPARE(SHRT_MAX*2, obj1.tabStopWidth());
       
   294 #else
       
   295     obj1.setTabStopWidth(INT_MAX);
       
   296     QCOMPARE(INT_MAX, obj1.tabStopWidth());
       
   297 #endif
       
   298 
       
   299     // bool QTextEdit::acceptRichText()
       
   300     // void QTextEdit::setAcceptRichText(bool)
       
   301     obj1.setAcceptRichText(false);
       
   302     QCOMPARE(false, obj1.acceptRichText());
       
   303     obj1.setAcceptRichText(true);
       
   304     QCOMPARE(true, obj1.acceptRichText());
       
   305 
       
   306     // qreal QTextEdit::fontPointSize()
       
   307     // void QTextEdit::setFontPointSize(qreal)
       
   308     obj1.setFontPointSize(qreal(1.1));
       
   309     QCOMPARE(qreal(1.1), obj1.fontPointSize());
       
   310     // we currently Q_ASSERT_X in QFont::setPointSizeF for that
       
   311     //obj1.setFontPointSize(0.0);
       
   312     //QCOMPARE(1.1, obj1.fontPointSize()); // Should not accept 0.0 => keep old
       
   313 
       
   314     // int QTextEdit::fontWeight()
       
   315     // void QTextEdit::setFontWeight(int)
       
   316     obj1.setFontWeight(1);
       
   317     QCOMPARE(1, obj1.fontWeight()); // Range<1, 99>
       
   318     obj1.setFontWeight(99);
       
   319     QCOMPARE(99, obj1.fontWeight()); // Range<1, 99>
       
   320     /* Q_ASSERT_X in qfont.cpp
       
   321     obj1.setFontWeight(INT_MIN);
       
   322     QCOMPARE(1, obj1.fontWeight()); // Range<1, 99>
       
   323     obj1.setFontWeight(INT_MAX);
       
   324     QCOMPARE(99, obj1.fontWeight()); // Range<1, 99>
       
   325     */
       
   326 
       
   327     // bool QTextEdit::fontUnderline()
       
   328     // void QTextEdit::setFontUnderline(bool)
       
   329     obj1.setFontUnderline(false);
       
   330     QCOMPARE(false, obj1.fontUnderline());
       
   331     obj1.setFontUnderline(true);
       
   332     QCOMPARE(true, obj1.fontUnderline());
       
   333 
       
   334     // bool QTextEdit::fontItalic()
       
   335     // void QTextEdit::setFontItalic(bool)
       
   336     obj1.setFontItalic(false);
       
   337     QCOMPARE(false, obj1.fontItalic());
       
   338     obj1.setFontItalic(true);
       
   339     QCOMPARE(true, obj1.fontItalic());
       
   340 }
       
   341 
       
   342 class QtTestDocumentLayout : public QAbstractTextDocumentLayout
       
   343 {
       
   344     Q_OBJECT
       
   345 public:
       
   346     inline QtTestDocumentLayout(QTextEdit *edit, QTextDocument *doc, int &itCount)
       
   347         : QAbstractTextDocumentLayout(doc), useBiggerSize(false), ed(edit), iterationCounter(itCount) {}
       
   348 
       
   349     virtual void draw(QPainter *, const QAbstractTextDocumentLayout::PaintContext &)  {}
       
   350 
       
   351     virtual int hitTest(const QPointF &, Qt::HitTestAccuracy ) const { return 0; }
       
   352 
       
   353     virtual void documentChanged(int, int, int) {}
       
   354 
       
   355     virtual int pageCount() const { return 1; }
       
   356 
       
   357     virtual QSizeF documentSize() const { return usedSize; }
       
   358 
       
   359     virtual QRectF frameBoundingRect(QTextFrame *) const { return QRectF(); }
       
   360     virtual QRectF blockBoundingRect(const QTextBlock &) const { return QRectF(); }
       
   361 
       
   362     bool useBiggerSize;
       
   363     QSize usedSize;
       
   364 
       
   365     QTextEdit *ed;
       
   366 
       
   367     int &iterationCounter;
       
   368 };
       
   369 
       
   370 tst_QTextEdit::tst_QTextEdit()
       
   371 {}
       
   372 
       
   373 void tst_QTextEdit::init()
       
   374 {
       
   375 #ifdef Q_OS_WINCE //disable magic for WindowsCE
       
   376     qApp->setAutoMaximizeThreshold(-1);
       
   377 #endif
       
   378 
       
   379     ed = new QTextEdit(0);
       
   380     rootFrameMargin = ed->document()->documentMargin();
       
   381 }
       
   382 
       
   383 void tst_QTextEdit::cleanup()
       
   384 {
       
   385     delete ed;
       
   386     ed = 0;
       
   387 }
       
   388 
       
   389 void tst_QTextEdit::inlineAttributesOnInsert()
       
   390 {
       
   391     QVERIFY(ed->textCursor().charFormat().foreground().color() != Qt::blue);
       
   392 
       
   393     ed->setTextColor(Qt::blue);
       
   394     QTest::keyClick(ed, Qt::Key_A);
       
   395 
       
   396     QVERIFY(ed->textCursor().charFormat().foreground().color() == Qt::blue);
       
   397 }
       
   398 
       
   399 void tst_QTextEdit::inlineAttributesOnSelection()
       
   400 {
       
   401     createSelection();
       
   402 
       
   403     ed->setFontItalic(true);
       
   404 
       
   405     QVERIFY(ed->textCursor().charFormat().fontItalic());
       
   406 }
       
   407 
       
   408 void tst_QTextEdit::inlineAttributeSymmetry()
       
   409 {
       
   410     ed->setFontPointSize(42.0);
       
   411     QCOMPARE(double(ed->fontPointSize()), 42.0);
       
   412 
       
   413     ed->setFontFamily("Test");
       
   414     QCOMPARE(ed->fontFamily(), QString("Test"));
       
   415 
       
   416     ed->setFontWeight(QFont::Bold);
       
   417     QCOMPARE((int)ed->fontWeight(), (int)QFont::Bold);
       
   418 
       
   419     ed->setFontUnderline(true);
       
   420     QCOMPARE(ed->fontUnderline(), true);
       
   421 
       
   422     ed->setFontItalic(true);
       
   423     QCOMPARE(ed->fontItalic(), true);
       
   424 
       
   425     ed->setTextColor(Qt::blue);
       
   426     QCOMPARE(ed->textColor(), QColor(Qt::blue));
       
   427 
       
   428     ed->setTextBackgroundColor(Qt::red);
       
   429     QCOMPARE(ed->textBackgroundColor(), QColor(Qt::red));
       
   430 
       
   431     ed->setAlignment(Qt::AlignRight);
       
   432     QCOMPARE((int)ed->alignment(), (int)Qt::AlignRight);
       
   433 }
       
   434 
       
   435 void tst_QTextEdit::inlineAttributeSymmetryWithSelection()
       
   436 {
       
   437     createSelection();
       
   438 
       
   439     inlineAttributeSymmetry();
       
   440 }
       
   441 
       
   442 void tst_QTextEdit::autoBulletList1()
       
   443 {
       
   444     ed->setAutoFormatting(QTextEdit::AutoBulletList);
       
   445 
       
   446     QTest::keyClick(ed, Qt::Key_Return);
       
   447     QTest::keyClicks(ed, "*This should become a list");
       
   448 
       
   449     QVERIFY(ed->textCursor().currentList());
       
   450     QVERIFY(ed->textCursor().currentList()->format().style() == QTextListFormat::ListDisc);
       
   451 }
       
   452 
       
   453 void tst_QTextEdit::autoBulletList2()
       
   454 {
       
   455     ed->setAutoFormatting(QTextEdit::AutoNone);
       
   456     QTest::keyClick(ed, Qt::Key_Return);
       
   457     QTest::keyClicks(ed, "*This should NOT become a list");
       
   458 
       
   459     QVERIFY(!ed->textCursor().currentList());
       
   460 }
       
   461 
       
   462 void tst_QTextEdit::preserveCharFormatAfterNewline()
       
   463 {
       
   464     ed->setTextColor(Qt::blue);
       
   465     QTest::keyClicks(ed, "Hello");
       
   466 
       
   467     QTest::keyClick(ed, Qt::Key_Return);
       
   468 
       
   469     QCOMPARE(ed->textColor(), QColor(Qt::blue));
       
   470 }
       
   471 
       
   472 void tst_QTextEdit::createSelection()
       
   473 {
       
   474     QTest::keyClicks(ed, "Hello World");
       
   475     /* go to start */
       
   476 #ifndef Q_WS_MAC
       
   477     QTest::keyClick(ed, Qt::Key_Home, Qt::ControlModifier);
       
   478 #else
       
   479     QTest::keyClick(ed, Qt::Key_Home);
       
   480 #endif
       
   481     QCOMPARE(ed->textCursor().position(), 0);
       
   482     /* select until end of text */
       
   483 #ifndef Q_WS_MAC
       
   484     QTest::keyClick(ed, Qt::Key_End, Qt::ControlModifier | Qt::ShiftModifier);
       
   485 #else
       
   486     QTest::keyClick(ed, Qt::Key_End, Qt::ShiftModifier);
       
   487 #endif
       
   488     QCOMPARE(ed->textCursor().position(), 11);
       
   489 }
       
   490 
       
   491 #ifndef QT_NO_CLIPBOARD
       
   492 void tst_QTextEdit::clearMustNotChangeClipboard()
       
   493 {
       
   494     if (!nativeClipboardWorking())
       
   495         QSKIP("Clipboard not working with cron-started unit tests", SkipAll);
       
   496     ed->textCursor().insertText("Hello World");
       
   497     QString txt("This is different text");
       
   498     QApplication::clipboard()->setText(txt);
       
   499     ed->clear();
       
   500     QCOMPARE(QApplication::clipboard()->text(), txt);
       
   501 }
       
   502 #endif
       
   503 
       
   504 void tst_QTextEdit::clearMustNotResetRootFrameMarginToDefault()
       
   505 {
       
   506     QCOMPARE(ed->document()->rootFrame()->frameFormat().margin(), rootFrameMargin);
       
   507     ed->clear();
       
   508     QCOMPARE(ed->document()->rootFrame()->frameFormat().margin(), rootFrameMargin);
       
   509 }
       
   510 
       
   511 void tst_QTextEdit::clearShouldPreserveTheCurrentCharFormat()
       
   512 {
       
   513     ed->setFontUnderline(true);
       
   514     QVERIFY(ed->fontUnderline());
       
   515     ed->clear();
       
   516     QVERIFY(ed->fontUnderline());
       
   517 }
       
   518 
       
   519 void tst_QTextEdit::clearShouldClearExtraSelections()
       
   520 {
       
   521     QTextEdit::ExtraSelection sel;
       
   522     sel.cursor = ed->textCursor();
       
   523     sel.format.setProperty(QTextFormat::FullWidthSelection, true);
       
   524     ed->setExtraSelections(QList<QTextEdit::ExtraSelection>() << sel);
       
   525     QCOMPARE(ed->extraSelections().count(), 1);
       
   526     ed->clear();
       
   527     QCOMPARE(ed->extraSelections().count(), 0);
       
   528 }
       
   529 
       
   530 void tst_QTextEdit::paragSeparatorOnPlaintextAppend()
       
   531 {
       
   532     ed->append("Hello\nWorld");
       
   533     int cnt = 0;
       
   534     QTextBlock blk = ed->document()->begin();
       
   535     while (blk.isValid()) {
       
   536         ++cnt;
       
   537         blk = blk.next();
       
   538     }
       
   539     QCOMPARE(cnt, 2);
       
   540 }
       
   541 
       
   542 void tst_QTextEdit::layoutingLoop()
       
   543 {
       
   544     QPointer<QTextEdit> ed = new QTextEdit(0);
       
   545     // this is a testcase for an ugly layouting problem, causing an infinite loop.
       
   546     // QTextEdit's resizeEvent has a long comment about what and why it can happen.
       
   547 
       
   548     int callsToSetPageSize = 0;
       
   549 
       
   550     QTextDocument *doc = new QTextDocument;
       
   551     QtTestDocumentLayout *lout = new QtTestDocumentLayout(ed, doc, callsToSetPageSize);
       
   552     doc->setDocumentLayout(lout);
       
   553     ed->setDocument(doc);
       
   554 
       
   555     ed->show();
       
   556     ed->resize(100, 100);
       
   557 
       
   558     qApp->processEvents();
       
   559     delete doc;
       
   560     delete ed;
       
   561 
       
   562     // ###### should need less!
       
   563     QVERIFY(callsToSetPageSize < 10);
       
   564 }
       
   565 
       
   566 #ifndef QT_NO_CLIPBOARD
       
   567 void tst_QTextEdit::selectAllSetsNotSelection()
       
   568 {
       
   569     if (!QApplication::clipboard()->supportsSelection()) {
       
   570         QSKIP("Test only relevant for systems with selection", SkipAll);
       
   571         return;
       
   572     }
       
   573 
       
   574     QApplication::clipboard()->setText(QString("foobar"), QClipboard::Selection);
       
   575     QVERIFY(QApplication::clipboard()->text(QClipboard::Selection) == QString("foobar"));
       
   576 
       
   577     ed->insertPlainText("Hello World");
       
   578     ed->selectAll();
       
   579 
       
   580     QCOMPARE(QApplication::clipboard()->text(QClipboard::Selection), QString::fromAscii("foobar"));
       
   581 }
       
   582 #endif
       
   583 void tst_QTextEdit::asciiTab()
       
   584 {
       
   585     QTextEdit edit;
       
   586     edit.setPlainText("\t");
       
   587     edit.show();
       
   588     qApp->processEvents();
       
   589     QCOMPARE(edit.toPlainText().at(0), QChar('\t'));
       
   590 }
       
   591 
       
   592 
       
   593 void tst_QTextEdit::setDocument()
       
   594 {
       
   595     QTextDocument *document = new QTextDocument(ed);
       
   596     QCOMPARE(document->isModified(), false);
       
   597     QCOMPARE(document->isUndoAvailable(), false);
       
   598     QTextCursor(document).insertText("Test");
       
   599     QCOMPARE(document->isUndoAvailable(), true);
       
   600     QCOMPARE(document->isModified(), true);
       
   601     ed->setDocument(document);
       
   602     QCOMPARE(ed->toPlainText(), QString("Test"));
       
   603     QCOMPARE(document->isUndoAvailable(), true);
       
   604     QCOMPARE(document->isModified(), true);
       
   605 }
       
   606 
       
   607 void tst_QTextEdit::setDocument_shared()
       
   608 {
       
   609     QTextDocument *document = new QTextDocument(ed);
       
   610     QCOMPARE(document->isModified(), false);
       
   611     QCOMPARE(document->isUndoAvailable(), false);
       
   612     QTextCursor(document).insertText("Test");
       
   613     QCOMPARE(document->isUndoAvailable(), true);
       
   614     document->setModified(false);
       
   615     ed->setDocument(document);
       
   616     QCOMPARE(ed->toPlainText(), QString("Test"));
       
   617     QCOMPARE(document->isUndoAvailable(), true);
       
   618     QCOMPARE(document->isModified(), false);
       
   619     QTextCursor(document).insertText("Test2");
       
   620     QCOMPARE(document->isModified(), true);
       
   621     QTextEdit editor2;
       
   622     editor2.setDocument(document);
       
   623     QCOMPARE(document->isUndoAvailable(), true);
       
   624     QCOMPARE(document->isModified(), true);
       
   625 }
       
   626 
       
   627 void tst_QTextEdit::mergeCurrentCharFormat()
       
   628 {
       
   629     ed->setPlainText("Hello Test World");
       
   630     QTextCursor cursor = ed->textCursor();
       
   631     cursor.setPosition(7);
       
   632     ed->setTextCursor(cursor);
       
   633 
       
   634     QTextCharFormat mod;
       
   635     mod.setFontItalic(true);
       
   636     mod.setForeground(Qt::red);
       
   637     ed->mergeCurrentCharFormat(mod);
       
   638 
       
   639     cursor.movePosition(QTextCursor::Right);
       
   640     cursor.movePosition(QTextCursor::Right);
       
   641     // do NOT select the current word under the cursor, /JUST/
       
   642     // call mergeCharFormat on the cursor
       
   643     QVERIFY(!cursor.charFormat().fontItalic());
       
   644     QVERIFY(cursor.charFormat().foreground().color() != Qt::red);
       
   645 }
       
   646 
       
   647 void tst_QTextEdit::mergeCurrentBlockCharFormat()
       
   648 {
       
   649     ed->setPlainText("FirstLine\n\nThirdLine");
       
   650     QTextCursor cursor = ed->textCursor();
       
   651     cursor.movePosition(QTextCursor::Start);
       
   652     cursor.movePosition(QTextCursor::Down);
       
   653 
       
   654     // make sure we're in the empty second line
       
   655     QVERIFY(cursor.atBlockStart());
       
   656     QVERIFY(cursor.atBlockEnd());
       
   657 
       
   658     ed->setTextCursor(cursor);
       
   659 
       
   660     QTextCharFormat mod;
       
   661     mod.setForeground(Qt::red);
       
   662     ed->mergeCurrentCharFormat(mod);
       
   663 
       
   664     QVERIFY(cursor.blockCharFormat().foreground().color() != Qt::red);
       
   665     cursor.movePosition(QTextCursor::Up);
       
   666     QVERIFY(cursor.blockCharFormat().foreground().color() != Qt::red);
       
   667     cursor.movePosition(QTextCursor::Down);
       
   668     cursor.movePosition(QTextCursor::Down);
       
   669     QVERIFY(cursor.blockCharFormat().foreground().color() != Qt::red);
       
   670 }
       
   671 
       
   672 int tst_QTextEdit::blockCount() const
       
   673 {
       
   674     int blocks = 0;
       
   675     for (QTextBlock block = ed->document()->begin(); block.isValid(); block = block.next())
       
   676         ++blocks;
       
   677     return blocks;
       
   678 }
       
   679 
       
   680 // Supporter issue #56783
       
   681 void tst_QTextEdit::emptyAppend()
       
   682 {
       
   683     ed->append("Blah");
       
   684     QCOMPARE(blockCount(), 1);
       
   685     ed->append(QString::null);
       
   686     QCOMPARE(blockCount(), 2);
       
   687     ed->append(QString("   "));
       
   688     QCOMPARE(blockCount(), 3);
       
   689 }
       
   690 
       
   691 void tst_QTextEdit::appendOnEmptyDocumentShouldReuseInitialParagraph()
       
   692 {
       
   693     QCOMPARE(blockCount(), 1);
       
   694     ed->append("Blah");
       
   695     QCOMPARE(blockCount(), 1);
       
   696 }
       
   697 
       
   698 #ifdef QT3_SUPPORT
       
   699 void tst_QTextEdit::textSemantics()
       
   700 {
       
   701     ed->setTextFormat(Qt::AutoText);
       
   702 
       
   703     ed->setPlainText("Hello World");
       
   704     QVERIFY(!Qt::mightBeRichText(ed->text()));
       
   705 
       
   706     ed->setHtml("<b>Hey</b>");
       
   707     QVERIFY(Qt::mightBeRichText(ed->text()));
       
   708 }
       
   709 #endif
       
   710 
       
   711 class CursorPositionChangedRecorder : public QObject
       
   712 {
       
   713     Q_OBJECT
       
   714 public:
       
   715     inline CursorPositionChangedRecorder(QTextEdit *ed)
       
   716         : editor(ed)
       
   717     {
       
   718         connect(editor, SIGNAL(cursorPositionChanged()), this, SLOT(recordCursorPos()));
       
   719     }
       
   720 
       
   721     QList<int> cursorPositions;
       
   722 
       
   723 private slots:
       
   724     void recordCursorPos()
       
   725     {
       
   726         cursorPositions.append(editor->textCursor().position());
       
   727     }
       
   728 
       
   729 private:
       
   730     QTextEdit *editor;
       
   731 };
       
   732 
       
   733 void tst_QTextEdit::cursorPositionChanged()
       
   734 {
       
   735     QSignalSpy spy(ed, SIGNAL(cursorPositionChanged()));
       
   736     ed->show();
       
   737 
       
   738     spy.clear();
       
   739     QTest::keyClick(ed, Qt::Key_A);
       
   740     QCOMPARE(spy.count(), 1);
       
   741 
       
   742     QTextCursor cursor = ed->textCursor();
       
   743     cursor.movePosition(QTextCursor::Start);
       
   744     ed->setTextCursor(cursor);
       
   745     cursor.movePosition(QTextCursor::End);
       
   746     spy.clear();
       
   747     cursor.insertText("Test");
       
   748     QCOMPARE(spy.count(), 0);
       
   749 
       
   750     cursor.movePosition(QTextCursor::End);
       
   751     ed->setTextCursor(cursor);
       
   752     cursor.movePosition(QTextCursor::Start);
       
   753     spy.clear();
       
   754     cursor.insertText("Test");
       
   755     QCOMPARE(spy.count(), 1);
       
   756 
       
   757     spy.clear();
       
   758     QTest::keyClick(ed, Qt::Key_Left);
       
   759     QCOMPARE(spy.count(), 1);
       
   760 
       
   761     cursor.movePosition(QTextCursor::Start);
       
   762     ed->setTextCursor(cursor);
       
   763     spy.clear();
       
   764     QVERIFY(!ed->textCursor().hasSelection());
       
   765     QTest::mouseDClick(ed->viewport(), Qt::LeftButton, 0, ed->cursorRect().center());
       
   766     QVERIFY(ed->textCursor().hasSelection());
       
   767 
       
   768     QCOMPARE(spy.count(), 1);
       
   769 
       
   770     CursorPositionChangedRecorder spy2(ed);
       
   771     QVERIFY(ed->textCursor().position() > 0);
       
   772     ed->setPlainText("Hello World");
       
   773     QCOMPARE(spy2.cursorPositions.count(), 1);
       
   774     QCOMPARE(spy2.cursorPositions.at(0), 0);
       
   775     QCOMPARE(ed->textCursor().position(), 0);
       
   776 }
       
   777 
       
   778 void tst_QTextEdit::setTextCursor()
       
   779 {
       
   780     QSignalSpy spy(ed, SIGNAL(cursorPositionChanged()));
       
   781 
       
   782     ed->setPlainText("Test");
       
   783     QTextCursor cursor = ed->textCursor();
       
   784     cursor.movePosition(QTextCursor::Start);
       
   785     cursor.movePosition(QTextCursor::NextCharacter);
       
   786 
       
   787     spy.clear();
       
   788 
       
   789     ed->setTextCursor(cursor);
       
   790     QCOMPARE(spy.count(), 1);
       
   791 }
       
   792 
       
   793 #ifndef QT_NO_CLIPBOARD
       
   794 void tst_QTextEdit::undoAvailableAfterPaste()
       
   795 {
       
   796     if (!nativeClipboardWorking())
       
   797         QSKIP("Clipboard not working with cron-started unit tests", SkipAll);
       
   798 
       
   799     QSignalSpy spy(ed->document(), SIGNAL(undoAvailable(bool)));
       
   800 
       
   801     const QString txt("Test");
       
   802     QApplication::clipboard()->setText(txt);
       
   803     ed->paste();
       
   804     QVERIFY(spy.count() >= 1);
       
   805     QCOMPARE(ed->toPlainText(), txt);
       
   806 }
       
   807 #endif
       
   808 
       
   809 class UndoRedoRecorder : public QObject
       
   810 {
       
   811     Q_OBJECT
       
   812 public:
       
   813     UndoRedoRecorder(QTextDocument *doc)
       
   814         : undoRepetitions(false)
       
   815         , redoRepetitions(false)
       
   816         , undoCount(0)
       
   817         , redoCount(0)
       
   818     {
       
   819         connect(doc, SIGNAL(undoAvailable(bool)), this, SLOT(undoAvailable(bool)));
       
   820         connect(doc, SIGNAL(redoAvailable(bool)), this, SLOT(redoAvailable(bool)));
       
   821     }
       
   822 
       
   823     bool undoRepetitions;
       
   824     bool redoRepetitions;
       
   825 
       
   826 private slots:
       
   827     void undoAvailable(bool enabled) {
       
   828         if (undoCount > 0 && enabled == lastUndoEnabled)
       
   829             undoRepetitions = true;
       
   830 
       
   831         ++undoCount;
       
   832         lastUndoEnabled = enabled;
       
   833     }
       
   834 
       
   835     void redoAvailable(bool enabled) {
       
   836         if (redoCount > 0 && enabled == lastRedoEnabled)
       
   837             redoRepetitions = true;
       
   838 
       
   839         ++redoCount;
       
   840         lastRedoEnabled = enabled;
       
   841     }
       
   842 
       
   843 private:
       
   844     bool lastUndoEnabled;
       
   845     bool lastRedoEnabled;
       
   846 
       
   847     int undoCount;
       
   848     int redoCount;
       
   849 };
       
   850 
       
   851 void tst_QTextEdit::undoRedoAvailableRepetition()
       
   852 {
       
   853     UndoRedoRecorder spy(ed->document());
       
   854 
       
   855     ed->textCursor().insertText("ABC\n\nDEF\n\nGHI\n");
       
   856     ed->textCursor().insertText("foo\n");
       
   857     ed->textCursor().insertText("bar\n");
       
   858     ed->undo(); ed->undo(); ed->undo();
       
   859     ed->redo(); ed->redo(); ed->redo();
       
   860 
       
   861     QVERIFY(!spy.undoRepetitions);
       
   862     QVERIFY(!spy.redoRepetitions);
       
   863 }
       
   864 
       
   865 void tst_QTextEdit::appendShouldUseCurrentFormat()
       
   866 {
       
   867     ed->textCursor().insertText("A");
       
   868     QTextCharFormat fmt;
       
   869     fmt.setForeground(Qt::blue);
       
   870     fmt.setFontItalic(true);
       
   871     ed->setCurrentCharFormat(fmt);
       
   872     ed->append("Hello");
       
   873 
       
   874     QTextCursor cursor(ed->document());
       
   875 
       
   876     QVERIFY(cursor.movePosition(QTextCursor::NextCharacter));
       
   877     QVERIFY(cursor.charFormat().foreground().color() != Qt::blue);
       
   878     QVERIFY(!cursor.charFormat().fontItalic());
       
   879 
       
   880     QVERIFY(cursor.movePosition(QTextCursor::NextBlock));
       
   881 
       
   882     {
       
   883         QTextCursor tmp = cursor;
       
   884         tmp.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
       
   885         QCOMPARE(tmp.selectedText(), QString::fromLatin1("Hello"));
       
   886     }
       
   887 
       
   888     QVERIFY(cursor.movePosition(QTextCursor::NextCharacter));
       
   889     QVERIFY(cursor.charFormat().foreground().color() == Qt::blue);
       
   890     QVERIFY(cursor.charFormat().fontItalic());
       
   891 }
       
   892 
       
   893 void tst_QTextEdit::appendShouldNotTouchTheSelection()
       
   894 {
       
   895     QTextCursor cursor(ed->document());
       
   896     QTextCharFormat fmt;
       
   897     fmt.setForeground(Qt::blue);
       
   898     cursor.insertText("H", fmt);
       
   899     fmt.setForeground(Qt::red);
       
   900     cursor.insertText("ey", fmt);
       
   901 
       
   902     cursor.insertText("some random text inbetween");
       
   903 
       
   904     cursor.movePosition(QTextCursor::Start);
       
   905     cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
       
   906     QCOMPARE(cursor.charFormat().foreground().color(), QColor(Qt::blue));
       
   907     cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
       
   908     QCOMPARE(cursor.charFormat().foreground().color(), QColor(Qt::red));
       
   909     cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
       
   910     QCOMPARE(cursor.charFormat().foreground().color(), QColor(Qt::red));
       
   911     QCOMPARE(cursor.selectedText(), QString("Hey"));
       
   912 
       
   913     ed->setTextCursor(cursor);
       
   914     QVERIFY(ed->textCursor().hasSelection());
       
   915 
       
   916     ed->append("<b>Some Bold Text</b>");
       
   917     cursor.movePosition(QTextCursor::Start);
       
   918     cursor.movePosition(QTextCursor::NextCharacter);
       
   919     QCOMPARE(cursor.charFormat().foreground().color(), QColor(Qt::blue));
       
   920 }
       
   921 
       
   922 void tst_QTextEdit::backspace()
       
   923 {
       
   924     QTextCursor cursor = ed->textCursor();
       
   925 
       
   926     QTextListFormat listFmt;
       
   927     listFmt.setStyle(QTextListFormat::ListDisc);
       
   928     listFmt.setIndent(1);
       
   929     cursor.insertList(listFmt);
       
   930     cursor.insertText("A");
       
   931 
       
   932     ed->setTextCursor(cursor);
       
   933 
       
   934     // delete 'A'
       
   935     QTest::keyClick(ed, Qt::Key_Backspace);
       
   936     QVERIFY(ed->textCursor().currentList());
       
   937     // delete list
       
   938     QTest::keyClick(ed, Qt::Key_Backspace);
       
   939     QVERIFY(!ed->textCursor().currentList());
       
   940     QCOMPARE(ed->textCursor().blockFormat().indent(), 1);
       
   941     // outdent paragraph
       
   942     QTest::keyClick(ed, Qt::Key_Backspace);
       
   943     QCOMPARE(ed->textCursor().blockFormat().indent(), 0);
       
   944 }
       
   945 
       
   946 void tst_QTextEdit::shiftBackspace()
       
   947 {
       
   948     QTextCursor cursor = ed->textCursor();
       
   949 
       
   950     QTextListFormat listFmt;
       
   951     listFmt.setStyle(QTextListFormat::ListDisc);
       
   952     listFmt.setIndent(1);
       
   953     cursor.insertList(listFmt);
       
   954     cursor.insertText("A");
       
   955 
       
   956     ed->setTextCursor(cursor);
       
   957 
       
   958     // delete 'A'
       
   959     QTest::keyClick(ed, Qt::Key_Backspace, Qt::ShiftModifier);
       
   960     QVERIFY(ed->textCursor().currentList());
       
   961     // delete list
       
   962     QTest::keyClick(ed, Qt::Key_Backspace, Qt::ShiftModifier);
       
   963     QVERIFY(!ed->textCursor().currentList());
       
   964     QCOMPARE(ed->textCursor().blockFormat().indent(), 1);
       
   965     // outdent paragraph
       
   966     QTest::keyClick(ed, Qt::Key_Backspace, Qt::ShiftModifier);
       
   967     QCOMPARE(ed->textCursor().blockFormat().indent(), 0);
       
   968 }
       
   969 
       
   970 void tst_QTextEdit::undoRedo()
       
   971 {
       
   972     ed->clear();
       
   973     QTest::keyClicks(ed, "abc d");
       
   974     QCOMPARE(ed->toPlainText(), QString("abc d"));
       
   975     ed->undo();
       
   976     QCOMPARE(ed->toPlainText(), QString());
       
   977     ed->redo();
       
   978     QCOMPARE(ed->toPlainText(), QString("abc d"));
       
   979 #ifdef Q_WS_WIN
       
   980     // shortcut for undo
       
   981     QTest::keyClick(ed, Qt::Key_Backspace, Qt::AltModifier);
       
   982     QCOMPARE(ed->toPlainText(), QString());
       
   983     // shortcut for redo
       
   984     QTest::keyClick(ed, Qt::Key_Backspace, Qt::ShiftModifier|Qt::AltModifier);
       
   985     QCOMPARE(ed->toPlainText(), QString("abc d"));
       
   986 #endif
       
   987 }
       
   988 
       
   989 // Task #70465
       
   990 void tst_QTextEdit::preserveCharFormatInAppend()
       
   991 {
       
   992     ed->append("First para");
       
   993     ed->append("<b>Second para</b>");
       
   994     ed->append("third para");
       
   995 
       
   996     QTextCursor cursor(ed->textCursor());
       
   997 
       
   998     cursor.movePosition(QTextCursor::Start);
       
   999     cursor.movePosition(QTextCursor::NextCharacter);
       
  1000     QCOMPARE(cursor.charFormat().fontWeight(), (int)QFont::Normal);
       
  1001     QCOMPARE(cursor.block().text(), QString("First para"));
       
  1002 
       
  1003     cursor.movePosition(QTextCursor::NextBlock);
       
  1004     cursor.movePosition(QTextCursor::NextCharacter);
       
  1005     QCOMPARE(cursor.charFormat().fontWeight(), (int)QFont::Bold);
       
  1006     QCOMPARE(cursor.block().text(), QString("Second para"));
       
  1007 
       
  1008     cursor.movePosition(QTextCursor::NextBlock);
       
  1009     cursor.movePosition(QTextCursor::NextCharacter);
       
  1010     QCOMPARE(cursor.charFormat().fontWeight(), (int)QFont::Normal);
       
  1011     QCOMPARE(cursor.block().text(), QString("third para"));
       
  1012 }
       
  1013 
       
  1014 #ifndef QT_NO_CLIPBOARD
       
  1015 void tst_QTextEdit::copyAndSelectAllInReadonly()
       
  1016 {
       
  1017     if (!nativeClipboardWorking())
       
  1018         QSKIP("Clipboard not working with cron-started unit tests", SkipAll);
       
  1019 
       
  1020     ed->setReadOnly(true);
       
  1021     ed->setPlainText("Hello World");
       
  1022 
       
  1023     QTextCursor cursor = ed->textCursor();
       
  1024     cursor.clearSelection();
       
  1025     ed->setTextCursor(cursor);
       
  1026     QVERIFY(!ed->textCursor().hasSelection());
       
  1027 
       
  1028     QCOMPARE(ed->toPlainText(), QString("Hello World"));
       
  1029 
       
  1030     // shouldn't do anything
       
  1031     QTest::keyClick(ed, Qt::Key_A);
       
  1032 
       
  1033     QCOMPARE(ed->toPlainText(), QString("Hello World"));
       
  1034 
       
  1035     QTest::keyClick(ed, Qt::Key_A, Qt::ControlModifier);
       
  1036 
       
  1037     QVERIFY(ed->textCursor().hasSelection());
       
  1038 
       
  1039     QApplication::clipboard()->setText(QString());
       
  1040     QVERIFY(QApplication::clipboard()->text().isEmpty());
       
  1041 
       
  1042     QTest::keyClick(ed, Qt::Key_C, Qt::ControlModifier);
       
  1043     QCOMPARE(QApplication::clipboard()->text(), QString("Hello World"));
       
  1044 }
       
  1045 #endif
       
  1046 
       
  1047 void tst_QTextEdit::ctrlAltInput()
       
  1048 {
       
  1049     QTest::keyClick(ed, Qt::Key_At, Qt::ControlModifier | Qt::AltModifier);
       
  1050     QCOMPARE(ed->toPlainText(), QString("@"));
       
  1051 }
       
  1052 
       
  1053 void tst_QTextEdit::noPropertiesOnDefaultTextEditCharFormat()
       
  1054 {
       
  1055     // there should be no properties set on the default/initial char format
       
  1056     // on a text edit. Font properties instead should be taken from the
       
  1057     // widget's font (in sync with defaultFont property in document) and the
       
  1058     // foreground color should be taken from the palette.
       
  1059     QCOMPARE(ed->currentCharFormat().properties().count(), 0);
       
  1060 }
       
  1061 
       
  1062 void tst_QTextEdit::setPlainTextShouldUseCurrentCharFormat()
       
  1063 {
       
  1064     ed->setFontUnderline(true);
       
  1065     ed->setPlainText("Hello World");
       
  1066     QTextCursor cursor(ed->document());
       
  1067     cursor.movePosition(QTextCursor::NextCharacter);
       
  1068     QCOMPARE(cursor.charFormat().fontUnderline(), true);
       
  1069 
       
  1070     ed->setHtml("<p style=\"color:blue\">Foo</p>");
       
  1071     ed->setPlainText("Hello World");
       
  1072     cursor = QTextCursor(ed->document());
       
  1073     cursor.movePosition(QTextCursor::NextCharacter);
       
  1074     QCOMPARE(cursor.charFormat().fontUnderline(), true);
       
  1075 }
       
  1076 
       
  1077 void tst_QTextEdit::setPlainTextShouldEmitTextChangedOnce()
       
  1078 {
       
  1079     QSignalSpy spy(ed, SIGNAL(textChanged()));
       
  1080     ed->setPlainText("Yankee Doodle");
       
  1081     QCOMPARE(spy.count(), 1);
       
  1082     ed->setPlainText("");
       
  1083     QCOMPARE(spy.count(), 2);
       
  1084 }
       
  1085 
       
  1086 void tst_QTextEdit::overwriteMode()
       
  1087 {
       
  1088     QVERIFY(!ed->overwriteMode());
       
  1089     QTest::keyClicks(ed, "Some first text");
       
  1090 
       
  1091     QCOMPARE(ed->toPlainText(), QString("Some first text"));
       
  1092 
       
  1093     ed->setOverwriteMode(true);
       
  1094 
       
  1095     QTextCursor cursor = ed->textCursor();
       
  1096     cursor.setPosition(5);
       
  1097     ed->setTextCursor(cursor);
       
  1098 
       
  1099     QTest::keyClicks(ed, "shiny");
       
  1100     QCOMPARE(ed->toPlainText(), QString("Some shiny text"));
       
  1101 
       
  1102     cursor.movePosition(QTextCursor::End);
       
  1103     ed->setTextCursor(cursor);
       
  1104 
       
  1105     QTest::keyClick(ed, Qt::Key_Enter);
       
  1106 
       
  1107     ed->setOverwriteMode(false);
       
  1108     QTest::keyClicks(ed, "Second paragraph");
       
  1109 
       
  1110     QCOMPARE(blockCount(), 2);
       
  1111 
       
  1112     cursor.movePosition(QTextCursor::Start);
       
  1113     cursor.movePosition(QTextCursor::EndOfBlock);
       
  1114 
       
  1115     QCOMPARE(cursor.position(), 15);
       
  1116     ed->setTextCursor(cursor);
       
  1117 
       
  1118     ed->setOverwriteMode(true);
       
  1119 
       
  1120     QTest::keyClicks(ed, " blah");
       
  1121 
       
  1122     QCOMPARE(blockCount(), 2);
       
  1123 
       
  1124     QTextBlock block = ed->document()->begin();
       
  1125     QCOMPARE(block.text(), QString("Some shiny text blah"));
       
  1126     block = block.next();
       
  1127     QCOMPARE(block.text(), QString("Second paragraph"));
       
  1128 }
       
  1129 
       
  1130 void tst_QTextEdit::shiftDownInLineLastShouldSelectToEnd_data()
       
  1131 {
       
  1132     // shift cursor-down in the last line should select to the end of the document
       
  1133 
       
  1134     QTest::addColumn<QString>("input");
       
  1135     QTest::addColumn<int>("totalLineCount");
       
  1136 
       
  1137     QTest::newRow("1") << QString("Foo\nBar") << 2;
       
  1138     QTest::newRow("2") << QString("Foo\nBar") + QChar(QChar::LineSeparator) + QString("Baz") << 3;
       
  1139 }
       
  1140 
       
  1141 void tst_QTextEdit::shiftDownInLineLastShouldSelectToEnd()
       
  1142 {
       
  1143     QFETCH(QString, input);
       
  1144     QFETCH(int, totalLineCount);
       
  1145 
       
  1146     ed->setPlainText(input);
       
  1147     ed->show();
       
  1148 
       
  1149     // ensure we're layouted
       
  1150     ed->document()->documentLayout()->documentSize();
       
  1151 
       
  1152     QCOMPARE(blockCount(), 2);
       
  1153 
       
  1154     int lineCount = 0;
       
  1155     for (QTextBlock block = ed->document()->begin(); block.isValid(); block = block.next())
       
  1156         lineCount += block.layout()->lineCount();
       
  1157     QCOMPARE(lineCount, totalLineCount);
       
  1158 
       
  1159     QTextCursor cursor = ed->textCursor();
       
  1160     cursor.movePosition(QTextCursor::Start);
       
  1161     ed->setTextCursor(cursor);
       
  1162 
       
  1163     for (int i = 0; i < lineCount; ++i) {
       
  1164         QTest::keyClick(ed, Qt::Key_Down, Qt::ShiftModifier);
       
  1165     }
       
  1166 
       
  1167     input.replace(QLatin1Char('\n'), QChar(QChar::ParagraphSeparator));
       
  1168     QCOMPARE(ed->textCursor().selectedText(), input);
       
  1169     QVERIFY(ed->textCursor().atEnd());
       
  1170 
       
  1171     // also test that without shift modifier the cursor does not move to the end
       
  1172     // for Key_Down in the last line
       
  1173     cursor.movePosition(QTextCursor::Start);
       
  1174     ed->setTextCursor(cursor);
       
  1175     for (int i = 0; i < lineCount; ++i) {
       
  1176         QTest::keyClick(ed, Qt::Key_Down);
       
  1177     }
       
  1178     QVERIFY(!ed->textCursor().atEnd());
       
  1179 }
       
  1180 
       
  1181 void tst_QTextEdit::undoRedoShouldRepositionTextEditCursor()
       
  1182 {
       
  1183     ed->setPlainText("five\nlines\nin\nthis\ntextedit");
       
  1184     QTextCursor cursor = ed->textCursor();
       
  1185     cursor.movePosition(QTextCursor::Start);
       
  1186 
       
  1187     ed->setUndoRedoEnabled(false);
       
  1188     ed->setUndoRedoEnabled(true);
       
  1189 
       
  1190     QVERIFY(!ed->document()->isUndoAvailable());
       
  1191     QVERIFY(!ed->document()->isRedoAvailable());
       
  1192 
       
  1193     cursor.insertText("Blah");
       
  1194 
       
  1195     QVERIFY(ed->document()->isUndoAvailable());
       
  1196     QVERIFY(!ed->document()->isRedoAvailable());
       
  1197 
       
  1198     cursor.movePosition(QTextCursor::End);
       
  1199     ed->setTextCursor(cursor);
       
  1200 
       
  1201     QVERIFY(QMetaObject::invokeMethod(ed, "undo"));
       
  1202 
       
  1203     QVERIFY(!ed->document()->isUndoAvailable());
       
  1204     QVERIFY(ed->document()->isRedoAvailable());
       
  1205 
       
  1206     QCOMPARE(ed->textCursor().position(), 0);
       
  1207 
       
  1208     cursor.movePosition(QTextCursor::End);
       
  1209     ed->setTextCursor(cursor);
       
  1210 
       
  1211     QVERIFY(QMetaObject::invokeMethod(ed, "redo"));
       
  1212 
       
  1213     QVERIFY(ed->document()->isUndoAvailable());
       
  1214     QVERIFY(!ed->document()->isRedoAvailable());
       
  1215 
       
  1216     QCOMPARE(ed->textCursor().position(), 4);
       
  1217 }
       
  1218 
       
  1219 void tst_QTextEdit::lineWrapModes()
       
  1220 {
       
  1221     ed->setLineWrapMode(QTextEdit::NoWrap);
       
  1222     // NoWrap at the same time as having all lines that are all left aligned means we optimize to only layout once. The effect is that the width is always 0
       
  1223     QVERIFY(ed->document()->pageSize().width() == qreal(0));
       
  1224 
       
  1225     QTextCursor cursor = QTextCursor(ed->document());
       
  1226     cursor.insertText(QString("A simple line"));
       
  1227     cursor.insertBlock();
       
  1228     QTextBlockFormat fmt;
       
  1229     fmt.setAlignment(Qt::AlignRight);
       
  1230     cursor.mergeBlockFormat(fmt);
       
  1231     cursor.insertText(QString("Another line"));
       
  1232     ed->show(); // relayout;
       
  1233     QVERIFY(ed->document()->pageSize().width() > qreal(0));
       
  1234 
       
  1235     ed->setLineWrapColumnOrWidth(10);
       
  1236     ed->setLineWrapMode(QTextEdit::FixedColumnWidth);
       
  1237     QVERIFY(!qIsNull(ed->document()->pageSize().width()));
       
  1238 
       
  1239     ed->setLineWrapColumnOrWidth(1000);
       
  1240     ed->setLineWrapMode(QTextEdit::FixedPixelWidth);
       
  1241     QCOMPARE(ed->document()->pageSize().width(), qreal(1000));
       
  1242 }
       
  1243 
       
  1244 void tst_QTextEdit::mouseCursorShape()
       
  1245 {
       
  1246 #ifndef QT_NO_CURSOR
       
  1247     // always show an IBeamCursor, see change 170146
       
  1248     QVERIFY(!ed->isReadOnly());
       
  1249     QVERIFY(ed->viewport()->cursor().shape() == Qt::IBeamCursor);
       
  1250 
       
  1251     ed->setReadOnly(true);
       
  1252     QVERIFY(ed->viewport()->cursor().shape() == Qt::IBeamCursor);
       
  1253 
       
  1254     ed->setPlainText("Foo");
       
  1255     QVERIFY(ed->viewport()->cursor().shape() == Qt::IBeamCursor);
       
  1256 #endif
       
  1257 }
       
  1258 
       
  1259 void tst_QTextEdit::implicitClear()
       
  1260 {
       
  1261     // test that QTextEdit::setHtml, etc. avoid calling clear() but instead call
       
  1262     // QTextDocument::setHtml/etc. instead, which also clear the contents and
       
  1263     // cached resource but preserve manually added resources. setHtml on a textedit
       
  1264     // should behave the same as on a document with respect to that.
       
  1265     // see also clearResources() autotest in qtextdocument
       
  1266 
       
  1267     // regular resource for QTextDocument
       
  1268     QUrl testUrl(":/foobar");
       
  1269     QVariant testResource("hello world");
       
  1270 
       
  1271     ed->document()->addResource(QTextDocument::ImageResource, testUrl, testResource);
       
  1272     QVERIFY(ed->document()->resource(QTextDocument::ImageResource, testUrl) == testResource);
       
  1273 
       
  1274     ed->setPlainText("Blah");
       
  1275     QVERIFY(ed->document()->resource(QTextDocument::ImageResource, testUrl) == testResource);
       
  1276 
       
  1277     ed->setPlainText("<b>Blah</b>");
       
  1278     QVERIFY(ed->document()->resource(QTextDocument::ImageResource, testUrl) == testResource);
       
  1279 
       
  1280     ed->clear();
       
  1281     QVERIFY(!ed->document()->resource(QTextDocument::ImageResource, testUrl).isValid());
       
  1282     QVERIFY(ed->toPlainText().isEmpty());
       
  1283 }
       
  1284 
       
  1285 #ifndef QT_NO_CLIPBOARD
       
  1286 void tst_QTextEdit::copyAvailable_data()
       
  1287 {
       
  1288     QTest::addColumn<pairListType>("keystrokes");
       
  1289     QTest::addColumn<QList<bool> >("copyAvailable");
       
  1290     QTest::addColumn<QString>("function");
       
  1291 
       
  1292     pairListType keystrokes;
       
  1293     QList<bool> copyAvailable;
       
  1294 
       
  1295     keystrokes << qMakePair(Qt::Key_B, Qt::NoModifier) <<  qMakePair(Qt::Key_B, Qt::NoModifier)
       
  1296                << qMakePair(Qt::Key_Left, Qt::ShiftModifier);
       
  1297     copyAvailable << true ;
       
  1298     QTest::newRow(QString("Case1 B,B, <- + shift | signals: true").toLatin1())
       
  1299         << keystrokes << copyAvailable << QString();
       
  1300 
       
  1301     keystrokes.clear();
       
  1302     copyAvailable.clear();
       
  1303 
       
  1304     keystrokes << qMakePair(Qt::Key_T, Qt::NoModifier) << qMakePair(Qt::Key_A, Qt::NoModifier)
       
  1305                <<  qMakePair(Qt::Key_A, Qt::NoModifier) << qMakePair(Qt::Key_Left, Qt::ShiftModifier);
       
  1306     copyAvailable << true << false;
       
  1307     QTest::newRow(QString("Case2 T,A,A, <- + shift, cut() | signals: true, false").toLatin1())
       
  1308         << keystrokes << copyAvailable << QString("cut");
       
  1309 
       
  1310     keystrokes.clear();
       
  1311     copyAvailable.clear();
       
  1312 
       
  1313     keystrokes << qMakePair(Qt::Key_T, Qt::NoModifier) << qMakePair(Qt::Key_A, Qt::NoModifier)
       
  1314                <<  qMakePair(Qt::Key_A, Qt::NoModifier) << qMakePair(Qt::Key_Left, Qt::ShiftModifier)
       
  1315                << qMakePair(Qt::Key_Left, Qt::ShiftModifier)  << qMakePair(Qt::Key_Left, Qt::ShiftModifier);
       
  1316     copyAvailable << true;
       
  1317     QTest::newRow(QString("Case3 T,A,A, <- + shift, <- + shift, <- + shift, copy() | signals: true").toLatin1())
       
  1318         << keystrokes << copyAvailable << QString("copy");
       
  1319 
       
  1320     keystrokes.clear();
       
  1321     copyAvailable.clear();
       
  1322 
       
  1323     keystrokes << qMakePair(Qt::Key_T, Qt::NoModifier) << qMakePair(Qt::Key_A, Qt::NoModifier)
       
  1324                <<  qMakePair(Qt::Key_A, Qt::NoModifier) << qMakePair(Qt::Key_Left, Qt::ShiftModifier)
       
  1325                << qMakePair(Qt::Key_Left, Qt::ShiftModifier)  << qMakePair(Qt::Key_Left, Qt::ShiftModifier)
       
  1326                << qMakePair(Qt::Key_X, Qt::ControlModifier);
       
  1327     copyAvailable << true << false;
       
  1328     QTest::newRow(QString("Case4 T,A,A, <- + shift, <- + shift, <- + shift, ctrl + x, paste() | signals: true, false").toLatin1())
       
  1329         << keystrokes << copyAvailable << QString("paste");
       
  1330 
       
  1331     keystrokes.clear();
       
  1332     copyAvailable.clear();
       
  1333 
       
  1334     keystrokes << qMakePair(Qt::Key_B, Qt::NoModifier) <<  qMakePair(Qt::Key_B, Qt::NoModifier)
       
  1335                << qMakePair(Qt::Key_Left, Qt::ShiftModifier) << qMakePair(Qt::Key_Left, Qt::NoModifier);
       
  1336     copyAvailable << true << false;
       
  1337     QTest::newRow(QString("Case5 B,B, <- + shift, <- | signals: true, false").toLatin1())
       
  1338         << keystrokes << copyAvailable << QString();
       
  1339 
       
  1340     keystrokes.clear();
       
  1341     copyAvailable.clear();
       
  1342 
       
  1343     keystrokes << qMakePair(Qt::Key_B, Qt::NoModifier) <<  qMakePair(Qt::Key_A, Qt::NoModifier)
       
  1344                << qMakePair(Qt::Key_Left, Qt::ShiftModifier) << qMakePair(Qt::Key_Left, Qt::NoModifier)
       
  1345                << qMakePair(Qt::Key_Right, Qt::ShiftModifier);
       
  1346     copyAvailable << true << false << true << false;
       
  1347     QTest::newRow(QString("Case6 B,A, <- + shift, ->, <- + shift | signals: true, false, true, false").toLatin1())
       
  1348         << keystrokes << copyAvailable << QString("cut");
       
  1349 
       
  1350     keystrokes.clear();
       
  1351     copyAvailable.clear();
       
  1352 
       
  1353     keystrokes << qMakePair(Qt::Key_T, Qt::NoModifier) << qMakePair(Qt::Key_A, Qt::NoModifier)
       
  1354                <<  qMakePair(Qt::Key_A, Qt::NoModifier) << qMakePair(Qt::Key_Left, Qt::ShiftModifier)
       
  1355                << qMakePair(Qt::Key_Left, Qt::ShiftModifier)  << qMakePair(Qt::Key_Left, Qt::ShiftModifier)
       
  1356                << qMakePair(Qt::Key_X, Qt::ControlModifier);
       
  1357     copyAvailable << true << false << true;
       
  1358     QTest::newRow(QString("Case7 T,A,A, <- + shift, <- + shift, <- + shift, ctrl + x, undo() | signals: true, false, true").toLatin1())
       
  1359         << keystrokes << copyAvailable << QString("undo");
       
  1360 }
       
  1361 
       
  1362 //Tests the copyAvailable slot for several cases
       
  1363 void tst_QTextEdit::copyAvailable()
       
  1364 {
       
  1365     QFETCH(pairListType,keystrokes);
       
  1366     QFETCH(QList<bool>, copyAvailable);
       
  1367     QFETCH(QString, function);
       
  1368 
       
  1369 #ifdef Q_WS_MAC
       
  1370     QSKIP("copyAvailable has never passed on Mac, task to fix is 132482", SkipAll);
       
  1371 #endif
       
  1372     ed->clear();
       
  1373     QApplication::clipboard()->clear();
       
  1374     QVERIFY(!ed->canPaste());
       
  1375     QSignalSpy spyCopyAvailabe(ed, SIGNAL(copyAvailable(bool)));
       
  1376 
       
  1377     //Execute Keystrokes
       
  1378     foreach(keyPairType keyPair, keystrokes) {
       
  1379         QTest::keyClick(ed, keyPair.first, keyPair.second );
       
  1380     }
       
  1381 
       
  1382     //Execute ed->"function"
       
  1383     if (function == "cut")
       
  1384         ed->cut();
       
  1385     else if (function == "copy")
       
  1386         ed->copy();
       
  1387     else if (function == "paste")
       
  1388         ed->paste();
       
  1389     else if (function == "undo")
       
  1390         ed->paste();
       
  1391     else if (function == "redo")
       
  1392         ed->paste();
       
  1393 
       
  1394     //Compare spied signals
       
  1395     QEXPECT_FAIL("Case7 T,A,A, <- + shift, <- + shift, <- + shift, ctrl + x, undo() | signals: true, false, true",
       
  1396         "Wrong undo selection behaviour. Should be fixed in some future release. (See task: 132482)", Abort);
       
  1397     QCOMPARE(spyCopyAvailabe.count(), copyAvailable.count());
       
  1398     for (int i=0;i<spyCopyAvailabe.count(); i++) {
       
  1399         QVariant variantSpyCopyAvailable = spyCopyAvailabe.at(i).at(0);
       
  1400         QVERIFY2(variantSpyCopyAvailable.toBool() == copyAvailable.at(i), QString("Spied singnal: %1").arg(i).toLatin1());
       
  1401     }
       
  1402 }
       
  1403 #endif
       
  1404 
       
  1405 void tst_QTextEdit::undoRedoAfterSetContent()
       
  1406 {
       
  1407     QVERIFY(!ed->document()->isUndoAvailable());
       
  1408     QVERIFY(!ed->document()->isRedoAvailable());
       
  1409     ed->setPlainText("Foobar");
       
  1410     QVERIFY(!ed->document()->isUndoAvailable());
       
  1411     QVERIFY(!ed->document()->isRedoAvailable());
       
  1412     ed->setHtml("<p>bleh</p>");
       
  1413     QVERIFY(!ed->document()->isUndoAvailable());
       
  1414     QVERIFY(!ed->document()->isRedoAvailable());
       
  1415 }
       
  1416 
       
  1417 void tst_QTextEdit::numPadKeyNavigation()
       
  1418 {
       
  1419     ed->setText("Hello World");
       
  1420     QCOMPARE(ed->textCursor().position(), 0);
       
  1421     QTest::keyClick(ed, Qt::Key_Right, Qt::KeypadModifier);
       
  1422     QCOMPARE(ed->textCursor().position(), 1);
       
  1423 }
       
  1424 
       
  1425 void tst_QTextEdit::moveCursor()
       
  1426 {
       
  1427     ed->setText("Test");
       
  1428 
       
  1429     QSignalSpy cursorMovedSpy(ed, SIGNAL(cursorPositionChanged()));
       
  1430 
       
  1431     QCOMPARE(ed->textCursor().position(), 0);
       
  1432     ed->moveCursor(QTextCursor::NextCharacter);
       
  1433     QCOMPARE(ed->textCursor().position(), 1);
       
  1434     QCOMPARE(cursorMovedSpy.count(), 1);
       
  1435     ed->moveCursor(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
       
  1436     QCOMPARE(ed->textCursor().position(), 2);
       
  1437     QCOMPARE(cursorMovedSpy.count(), 2);
       
  1438     QCOMPARE(ed->textCursor().selectedText(), QString("e"));
       
  1439 }
       
  1440 
       
  1441 class MyTextEdit : public QTextEdit
       
  1442 {
       
  1443 public:
       
  1444     inline MyTextEdit()
       
  1445         : createMimeDataCallCount(0),
       
  1446           canInsertCallCount(0),
       
  1447           insertCallCount(0)
       
  1448     {}
       
  1449 
       
  1450     mutable int createMimeDataCallCount;
       
  1451     mutable int canInsertCallCount;
       
  1452     mutable int insertCallCount;
       
  1453 
       
  1454     virtual QMimeData *createMimeDataFromSelection() const {
       
  1455         createMimeDataCallCount++;
       
  1456         return QTextEdit::createMimeDataFromSelection();
       
  1457     }
       
  1458     virtual bool canInsertFromMimeData(const QMimeData *source) const {
       
  1459         canInsertCallCount++;
       
  1460         return QTextEdit::canInsertFromMimeData(source);
       
  1461     }
       
  1462     virtual void insertFromMimeData(const QMimeData *source) {
       
  1463         insertCallCount++;
       
  1464         QTextEdit::insertFromMimeData(source);
       
  1465     }
       
  1466 
       
  1467 };
       
  1468 
       
  1469 #ifndef QT_NO_CLIPBOARD
       
  1470 void tst_QTextEdit::mimeDataReimplementations()
       
  1471 {
       
  1472     MyTextEdit ed;
       
  1473     ed.setPlainText("Hello World");
       
  1474 
       
  1475     QCOMPARE(ed.createMimeDataCallCount, 0);
       
  1476     QCOMPARE(ed.canInsertCallCount, 0);
       
  1477     QCOMPARE(ed.insertCallCount, 0);
       
  1478 
       
  1479     ed.selectAll();
       
  1480 
       
  1481     QCOMPARE(ed.createMimeDataCallCount, 0);
       
  1482     QCOMPARE(ed.canInsertCallCount, 0);
       
  1483     QCOMPARE(ed.insertCallCount, 0);
       
  1484 
       
  1485     ed.copy();
       
  1486 
       
  1487     QCOMPARE(ed.createMimeDataCallCount, 1);
       
  1488     QCOMPARE(ed.canInsertCallCount, 0);
       
  1489     QCOMPARE(ed.insertCallCount, 0);
       
  1490 
       
  1491 #ifdef QT_BUILD_INTERNAL
       
  1492     QTextControl *control = qFindChild<QTextControl *>(&ed);
       
  1493     QVERIFY(control);
       
  1494 
       
  1495     control->canInsertFromMimeData(QApplication::clipboard()->mimeData());
       
  1496 
       
  1497     QCOMPARE(ed.createMimeDataCallCount, 1);
       
  1498     QCOMPARE(ed.canInsertCallCount, 1);
       
  1499     QCOMPARE(ed.insertCallCount, 0);
       
  1500 
       
  1501     ed.paste();
       
  1502 
       
  1503     QCOMPARE(ed.createMimeDataCallCount, 1);
       
  1504     QCOMPARE(ed.canInsertCallCount, 1);
       
  1505     QCOMPARE(ed.insertCallCount, 1);
       
  1506 #endif
       
  1507 }
       
  1508 #endif
       
  1509 
       
  1510 void tst_QTextEdit::ctrlEnterShouldInsertLineSeparator_NOT()
       
  1511 {
       
  1512     QTest::keyClick(ed, Qt::Key_A);
       
  1513     QTest::keyClick(ed, Qt::Key_Enter, Qt::ControlModifier);
       
  1514     QTest::keyClick(ed, Qt::Key_B);
       
  1515     QString expected;
       
  1516     expected += 'a';
       
  1517 //    expected += QChar::LineSeparator; // do NOT insert
       
  1518     expected += 'b';
       
  1519     QCOMPARE(ed->textCursor().block().text(), expected);
       
  1520 }
       
  1521 
       
  1522 void tst_QTextEdit::shiftEnterShouldInsertLineSeparator()
       
  1523 {
       
  1524     QTest::keyClick(ed, Qt::Key_A);
       
  1525     QTest::keyClick(ed, Qt::Key_Enter, Qt::ShiftModifier);
       
  1526     QTest::keyClick(ed, Qt::Key_B);
       
  1527     QString expected;
       
  1528     expected += 'a';
       
  1529     expected += QChar::LineSeparator;
       
  1530     expected += 'b';
       
  1531     QCOMPARE(ed->textCursor().block().text(), expected);
       
  1532 }
       
  1533 
       
  1534 void tst_QTextEdit::selectWordsFromStringsContainingSeparators_data()
       
  1535 {
       
  1536     QTest::addColumn<QString>("testString");
       
  1537     QTest::addColumn<QString>("selectedWord");
       
  1538 
       
  1539     QStringList wordSeparators;
       
  1540     wordSeparators << "." << "," << "?" << "!" << ":" << ";" << "-" << "<" << ">" << "["
       
  1541                    << "]" << "(" << ")" << "{" << "}" << "=" << "\t"<< QString(QChar::Nbsp);
       
  1542 
       
  1543     foreach (QString s, wordSeparators)
       
  1544         QTest::newRow(QString("separator: " + s).toLocal8Bit()) << QString("foo") + s + QString("bar") << QString("foo");
       
  1545 }
       
  1546 
       
  1547 void tst_QTextEdit::selectWordsFromStringsContainingSeparators()
       
  1548 {
       
  1549     QFETCH(QString, testString);
       
  1550     QFETCH(QString, selectedWord);
       
  1551     ed->setText(testString);
       
  1552     QTextCursor cursor = ed->textCursor();
       
  1553     cursor.movePosition(QTextCursor::StartOfLine);
       
  1554     cursor.select(QTextCursor::WordUnderCursor);
       
  1555     QVERIFY(cursor.hasSelection());
       
  1556     QCOMPARE(cursor.selection().toPlainText(), selectedWord);
       
  1557     cursor.clearSelection();
       
  1558 }
       
  1559 
       
  1560 #ifndef QT_NO_CLIPBOARD
       
  1561 void tst_QTextEdit::canPaste()
       
  1562 {
       
  1563     if (!nativeClipboardWorking())
       
  1564         QSKIP("Clipboard not working with cron-started unit tests", SkipAll);
       
  1565 
       
  1566     QApplication::clipboard()->setText(QString());
       
  1567     QVERIFY(!ed->canPaste());
       
  1568     QApplication::clipboard()->setText("Test");
       
  1569     QVERIFY(ed->canPaste());
       
  1570     ed->setTextInteractionFlags(Qt::NoTextInteraction);
       
  1571     QVERIFY(!ed->canPaste());
       
  1572 }
       
  1573 #endif
       
  1574 
       
  1575 void tst_QTextEdit::ensureCursorVisibleOnInitialShow()
       
  1576 {
       
  1577     QString manyPagesOfPlainText;
       
  1578     for (int i = 0; i < 800; ++i)
       
  1579         manyPagesOfPlainText += QLatin1String("Blah blah blah blah blah blah\n");
       
  1580 
       
  1581     ed->setPlainText(manyPagesOfPlainText);
       
  1582     QCOMPARE(ed->textCursor().position(), 0);
       
  1583 
       
  1584     ed->moveCursor(QTextCursor::End);
       
  1585     ed->show();
       
  1586     QVERIFY(ed->verticalScrollBar()->value() > 10);
       
  1587 
       
  1588     ed->moveCursor(QTextCursor::Start);
       
  1589     QVERIFY(ed->verticalScrollBar()->value() < 10);
       
  1590     ed->hide();
       
  1591     ed->verticalScrollBar()->setValue(ed->verticalScrollBar()->maximum());
       
  1592     ed->show();
       
  1593     QCOMPARE(ed->verticalScrollBar()->value(), ed->verticalScrollBar()->maximum());
       
  1594 }
       
  1595 
       
  1596 class TestEdit : public QTextEdit
       
  1597 {
       
  1598 public:
       
  1599     TestEdit() : resizeEventCalled(false) {}
       
  1600 
       
  1601     bool resizeEventCalled;
       
  1602 
       
  1603 protected:
       
  1604     virtual void resizeEvent(QResizeEvent *e)
       
  1605     {
       
  1606         QTextEdit::resizeEvent(e);
       
  1607         setHtml("<img src=qtextbrowser-resizeevent.png width=" + QString::number(size().width()) + "><br>Size is " + QString::number(size().width()) + " x " + QString::number(size().height()));
       
  1608         resizeEventCalled = true;
       
  1609     }
       
  1610 };
       
  1611 
       
  1612 void tst_QTextEdit::setHtmlInsideResizeEvent()
       
  1613 {
       
  1614     TestEdit edit;
       
  1615     edit.show();
       
  1616     edit.resize(800, 600);
       
  1617     QVERIFY(edit.resizeEventCalled);
       
  1618 }
       
  1619 
       
  1620 void tst_QTextEdit::colorfulAppend()
       
  1621 {
       
  1622     ed->setTextColor(Qt::red);
       
  1623     ed->append("Red");
       
  1624     ed->setTextColor(Qt::blue);
       
  1625     ed->append("Blue");
       
  1626     ed->setTextColor(Qt::green);
       
  1627     ed->append("Green");
       
  1628 
       
  1629     QCOMPARE(ed->document()->blockCount(), 3);
       
  1630     QTextBlock block = ed->document()->begin();
       
  1631     QCOMPARE(block.begin().fragment().text(), QString("Red"));
       
  1632     QVERIFY(block.begin().fragment().charFormat().foreground().color() == Qt::red);
       
  1633     block = block.next();
       
  1634     QCOMPARE(block.begin().fragment().text(), QString("Blue"));
       
  1635     QVERIFY(block.begin().fragment().charFormat().foreground().color() == Qt::blue);
       
  1636     block = block.next();
       
  1637     QCOMPARE(block.begin().fragment().text(), QString("Green"));
       
  1638     QVERIFY(block.begin().fragment().charFormat().foreground().color() == Qt::green);
       
  1639 }
       
  1640 
       
  1641 void tst_QTextEdit::ensureVisibleWithRtl()
       
  1642 {
       
  1643     ed->setLayoutDirection(Qt::RightToLeft);
       
  1644     ed->setLineWrapMode(QTextEdit::NoWrap);
       
  1645     QString txt(500, QChar(QLatin1Char('a')));
       
  1646     QCOMPARE(txt.length(), 500);
       
  1647     ed->setPlainText(txt);
       
  1648     ed->resize(100, 100);
       
  1649     ed->show();
       
  1650 
       
  1651     qApp->processEvents();
       
  1652 
       
  1653     QVERIFY(ed->horizontalScrollBar()->maximum() > 0);
       
  1654 
       
  1655     ed->moveCursor(QTextCursor::Start);
       
  1656     QCOMPARE(ed->horizontalScrollBar()->value(), ed->horizontalScrollBar()->maximum());
       
  1657     ed->moveCursor(QTextCursor::End);
       
  1658     QCOMPARE(ed->horizontalScrollBar()->value(), 0);
       
  1659     ed->moveCursor(QTextCursor::Start);
       
  1660     QCOMPARE(ed->horizontalScrollBar()->value(), ed->horizontalScrollBar()->maximum());
       
  1661     ed->moveCursor(QTextCursor::End);
       
  1662     QCOMPARE(ed->horizontalScrollBar()->value(), 0);
       
  1663 }
       
  1664 
       
  1665 void tst_QTextEdit::preserveCharFormatAfterSetPlainText()
       
  1666 {
       
  1667     ed->setTextColor(Qt::blue);
       
  1668     ed->setPlainText("This is blue");
       
  1669     ed->append("This should still be blue");
       
  1670     QTextBlock block = ed->document()->begin();
       
  1671     block = block.next();
       
  1672     QCOMPARE(block.text(), QString("This should still be blue"));
       
  1673     QVERIFY(block.begin().fragment().charFormat().foreground().color() == QColor(Qt::blue));
       
  1674 }
       
  1675 
       
  1676 void tst_QTextEdit::extraSelections()
       
  1677 {
       
  1678     ed->setPlainText("Hello World");
       
  1679 
       
  1680     QTextCursor c = ed->textCursor();
       
  1681     c.movePosition(QTextCursor::Start);
       
  1682     c.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
       
  1683     const int endPos = c.position();
       
  1684 
       
  1685     QTextEdit::ExtraSelection sel;
       
  1686     sel.cursor = c;
       
  1687     ed->setExtraSelections(QList<QTextEdit::ExtraSelection>() << sel);
       
  1688 
       
  1689     c.movePosition(QTextCursor::Start);
       
  1690     c.movePosition(QTextCursor::NextWord);
       
  1691     const int wordPos = c.position();
       
  1692     c.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
       
  1693     sel.cursor = c;
       
  1694     ed->setExtraSelections(QList<QTextEdit::ExtraSelection>() << sel);
       
  1695 
       
  1696     QList<QTextEdit::ExtraSelection> selections = ed->extraSelections();
       
  1697     QCOMPARE(selections.count(), 1);
       
  1698     QCOMPARE(selections.at(0).cursor.position(), endPos);
       
  1699     QCOMPARE(selections.at(0).cursor.anchor(), wordPos);
       
  1700 }
       
  1701 
       
  1702 void tst_QTextEdit::adjustScrollbars()
       
  1703 {
       
  1704 // For some reason ff is defined to be << on Mac Panther / gcc 3.3
       
  1705 #undef ff
       
  1706     QFont ff(ed->font());
       
  1707     ff.setFamily("Tahoma");
       
  1708     ff.setPointSize(11);
       
  1709     ed->setFont(ff);
       
  1710     ed->setMinimumSize(140, 100);
       
  1711     ed->setMaximumSize(140, 100);
       
  1712     ed->show();
       
  1713     QLatin1String txt("\nabc def ghi jkl mno pqr stu vwx");
       
  1714     ed->setText(txt + txt + txt + txt);
       
  1715 
       
  1716     QVERIFY(ed->verticalScrollBar()->maximum() > 0);
       
  1717 
       
  1718     ed->moveCursor(QTextCursor::End);
       
  1719     int oldMaximum = ed->verticalScrollBar()->maximum();
       
  1720     QTextCursor cursor = ed->textCursor();
       
  1721     cursor.insertText(QLatin1String("\n"));
       
  1722     cursor.deletePreviousChar();
       
  1723     QCOMPARE(ed->verticalScrollBar()->maximum(), oldMaximum);
       
  1724 }
       
  1725 
       
  1726 class SignalReceiver : public QObject
       
  1727 {
       
  1728     Q_OBJECT
       
  1729 public:
       
  1730     SignalReceiver() : received(0) {}
       
  1731 
       
  1732     int receivedSignals() const { return received; }
       
  1733     QTextCharFormat charFormat() const { return format; }
       
  1734 
       
  1735 public slots:
       
  1736     void charFormatChanged(const QTextCharFormat &tcf) { ++received; format = tcf; }
       
  1737 
       
  1738 private:
       
  1739     QTextCharFormat format;
       
  1740     int received;
       
  1741 };
       
  1742 
       
  1743 void tst_QTextEdit::currentCharFormatChanged()
       
  1744 {
       
  1745     QFont ff(ed->font());
       
  1746     ff.setFamily("Tahoma");
       
  1747     ff.setPointSize(11);
       
  1748 
       
  1749     SignalReceiver receiver;
       
  1750     QObject::connect(ed, SIGNAL(currentCharFormatChanged(const QTextCharFormat &)) , &receiver, SLOT(charFormatChanged(const QTextCharFormat &)));
       
  1751 
       
  1752     ed->show();
       
  1753     ed->setCurrentFont(ff);
       
  1754 
       
  1755     QVERIFY(receiver.receivedSignals() > 0);
       
  1756     QCOMPARE(receiver.charFormat().font(), ff);
       
  1757 }
       
  1758 
       
  1759 void tst_QTextEdit::textObscuredByScrollbars()
       
  1760 {
       
  1761     ed->textCursor().insertText(
       
  1762             "ab cab cab c abca kjsdf lka sjd lfk jsal df j kasdf abc ab abc "
       
  1763             "a b c d e f g h i j k l m n o p q r s t u v w x y z "
       
  1764             "abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc "
       
  1765             "ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab"
       
  1766             "abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc "
       
  1767             "ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab"
       
  1768             "abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc "
       
  1769             "ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab"
       
  1770             "abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc "
       
  1771             "ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab"
       
  1772             "abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc "
       
  1773             "ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab"
       
  1774     );
       
  1775     ed->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
       
  1776     ed->show();
       
  1777 
       
  1778     QSize documentSize = ed->document()->documentLayout()->documentSize().toSize();
       
  1779     QSize viewportSize = ed->viewport()->size();
       
  1780 
       
  1781     QVERIFY(documentSize.width() <= viewportSize.width());
       
  1782 }
       
  1783 
       
  1784 void tst_QTextEdit::setTextPreservesUndoRedoEnabled()
       
  1785 {
       
  1786     QVERIFY(ed->isUndoRedoEnabled());
       
  1787 
       
  1788     ed->setPlainText("Test");
       
  1789 
       
  1790     QVERIFY(ed->isUndoRedoEnabled());
       
  1791 
       
  1792     ed->setUndoRedoEnabled(false);
       
  1793     QVERIFY(!ed->isUndoRedoEnabled());
       
  1794     ed->setPlainText("Test2");
       
  1795     QVERIFY(!ed->isUndoRedoEnabled());
       
  1796 
       
  1797     ed->setHtml("<p>hello");
       
  1798     QVERIFY(!ed->isUndoRedoEnabled());
       
  1799 }
       
  1800 
       
  1801 void tst_QTextEdit::wordWrapProperty()
       
  1802 {
       
  1803     {
       
  1804         QTextEdit edit;
       
  1805         QTextDocument *doc = new QTextDocument(&edit);
       
  1806         edit.setDocument(doc);
       
  1807         edit.setWordWrapMode(QTextOption::NoWrap);
       
  1808         QVERIFY(doc->defaultTextOption().wrapMode() == QTextOption::NoWrap);
       
  1809     }
       
  1810     {
       
  1811         QTextEdit edit;
       
  1812         QTextDocument *doc = new QTextDocument(&edit);
       
  1813         edit.setWordWrapMode(QTextOption::NoWrap);
       
  1814         edit.setDocument(doc);
       
  1815         QVERIFY(doc->defaultTextOption().wrapMode() == QTextOption::NoWrap);
       
  1816     }
       
  1817 }
       
  1818 
       
  1819 void tst_QTextEdit::lineWrapProperty()
       
  1820 {
       
  1821     QVERIFY(ed->wordWrapMode() == QTextOption::WrapAtWordBoundaryOrAnywhere);
       
  1822     QVERIFY(ed->lineWrapMode() == QTextEdit::WidgetWidth);
       
  1823     ed->setLineWrapMode(QTextEdit::NoWrap);
       
  1824     QVERIFY(ed->lineWrapMode() == QTextEdit::NoWrap);
       
  1825     QVERIFY(ed->wordWrapMode() == QTextOption::WrapAtWordBoundaryOrAnywhere);
       
  1826     QVERIFY(ed->document()->defaultTextOption().wrapMode() == QTextOption::NoWrap);
       
  1827 }
       
  1828 
       
  1829 void tst_QTextEdit::selectionChanged()
       
  1830 {
       
  1831     ed->setPlainText("Hello World");
       
  1832 
       
  1833     ed->moveCursor(QTextCursor::Start);
       
  1834 
       
  1835     QSignalSpy selectionChangedSpy(ed, SIGNAL(selectionChanged()));
       
  1836 
       
  1837     QTest::keyClick(ed, Qt::Key_Right);
       
  1838     QCOMPARE(ed->textCursor().position(), 1);
       
  1839     QCOMPARE(selectionChangedSpy.count(), 0);
       
  1840 
       
  1841     QTest::keyClick(ed, Qt::Key_Right, Qt::ShiftModifier);
       
  1842     QCOMPARE(ed->textCursor().position(), 2);
       
  1843     QCOMPARE(selectionChangedSpy.count(), 1);
       
  1844 
       
  1845     QTest::keyClick(ed, Qt::Key_Right, Qt::ShiftModifier);
       
  1846     QCOMPARE(ed->textCursor().position(), 3);
       
  1847     QCOMPARE(selectionChangedSpy.count(), 2);
       
  1848 
       
  1849     QTest::keyClick(ed, Qt::Key_Right, Qt::ShiftModifier);
       
  1850     QCOMPARE(ed->textCursor().position(), 4);
       
  1851     QCOMPARE(selectionChangedSpy.count(), 3);
       
  1852 
       
  1853     QTest::keyClick(ed, Qt::Key_Right);
       
  1854     QCOMPARE(ed->textCursor().position(), 5);
       
  1855     QCOMPARE(selectionChangedSpy.count(), 4);
       
  1856 
       
  1857     QTest::keyClick(ed, Qt::Key_Right);
       
  1858     QCOMPARE(ed->textCursor().position(), 6);
       
  1859     QCOMPARE(selectionChangedSpy.count(), 4);
       
  1860 }
       
  1861 
       
  1862 void tst_QTextEdit::copyPasteBackgroundImage()
       
  1863 {
       
  1864 #ifndef QT_NO_CLIPBOARD
       
  1865     if (!nativeClipboardWorking())
       
  1866         QSKIP("Native clipboard not working in this setup", SkipAll);
       
  1867 
       
  1868     QImage foo(16, 16, QImage::Format_ARGB32_Premultiplied);
       
  1869     foo.save("foo.png");
       
  1870     ed->setHtml("<body><table><tr><td background=\"foo.png\">Foo</td></tr></table></body>");
       
  1871 
       
  1872     ed->moveCursor(QTextCursor::Start);
       
  1873     ed->moveCursor(QTextCursor::End, QTextCursor::KeepAnchor);
       
  1874 
       
  1875     ed->copy();
       
  1876 
       
  1877     ed->moveCursor(QTextCursor::End, QTextCursor::MoveAnchor);
       
  1878     ed->paste();
       
  1879 
       
  1880     ed->moveCursor(QTextCursor::Start);
       
  1881 
       
  1882     ed->moveCursor(QTextCursor::NextBlock);
       
  1883     QTextTable *a = ed->textCursor().currentTable();
       
  1884 
       
  1885     ed->moveCursor(QTextCursor::End);
       
  1886     ed->moveCursor(QTextCursor::PreviousBlock);
       
  1887     QTextTable *b = ed->textCursor().currentTable();
       
  1888 
       
  1889     QVERIFY(a);
       
  1890     QVERIFY(b);
       
  1891     QVERIFY(a != b);
       
  1892 
       
  1893     QBrush ba = a->cellAt(0, 0).format().background();
       
  1894     QBrush bb = b->cellAt(0, 0).format().background();
       
  1895 
       
  1896     QCOMPARE(ba.style(), Qt::TexturePattern);
       
  1897     QCOMPARE(ba.style(), bb.style());
       
  1898 
       
  1899     // we don't want a copy/paste of the background image to cause
       
  1900     // a new image/pixmap to be created, it should use the cached resource
       
  1901     // already in the document
       
  1902     QVERIFY(ba.textureImage().cacheKey() == bb.textureImage().cacheKey() ||
       
  1903             ba.texture().cacheKey() == bb.texture().cacheKey());
       
  1904     QFile::remove(QLatin1String("foo.png"));
       
  1905 #endif
       
  1906 }
       
  1907 
       
  1908 void tst_QTextEdit::setText()
       
  1909 {
       
  1910     QTextEdit browser;
       
  1911     browser.setText(QLatin1String("hello"));
       
  1912     QCOMPARE(browser.toPlainText(), QLatin1String("hello"));
       
  1913     browser.setText(QLatin1String("<b>bold   bold</b>"));
       
  1914     QCOMPARE(browser.toPlainText(), QLatin1String("bold bold"));
       
  1915     browser.setText(QLatin1String("with   space"));
       
  1916     QCOMPARE(browser.toPlainText(), QLatin1String("with   space"));
       
  1917 }
       
  1918 
       
  1919 QT_BEGIN_NAMESPACE
       
  1920 extern void qt_setQtEnableTestFont(bool value);
       
  1921 QT_END_NAMESPACE
       
  1922 
       
  1923 void tst_QTextEdit::fullWidthSelection_data()
       
  1924 {
       
  1925     QTest::addColumn<int>("cursorFrom");
       
  1926     QTest::addColumn<int>("cursorTo");
       
  1927     QTest::addColumn<QString>("imageFileName");
       
  1928 
       
  1929     QTest::newRow("centered fully selected") << 0 << 15 << QString("fullWidthSelection/centered-fully-selected.png");
       
  1930     QTest::newRow("centered partly selected") << 2 << 15 << QString("fullWidthSelection/centered-partly-selected.png");
       
  1931     QTest::newRow("last char on line") << 42 << 44 << QString("fullWidthSelection/last-char-on-line.png");
       
  1932     QTest::newRow("last char on parag") << 545 << 548 << QString("fullWidthSelection/last-char-on-parag.png");
       
  1933     QTest::newRow("multiple full width lines") << 20 << 60 << QString("fullWidthSelection/multiple-full-width-lines.png");
       
  1934     QTest::newRow("single full width line") << 20 << 30 << QString("fullWidthSelection/single-full-width-line.png");
       
  1935 }
       
  1936 
       
  1937 void tst_QTextEdit::fullWidthSelection()
       
  1938 {
       
  1939     QFETCH(int, cursorFrom);
       
  1940     QFETCH(int, cursorTo);
       
  1941     QFETCH(QString, imageFileName);
       
  1942 
       
  1943     // enable full-width-selection for our test widget.
       
  1944     class FullWidthStyle : public QCommonStyle {
       
  1945         int styleHint(StyleHint stylehint, const QStyleOption *opt, const QWidget *widget, QStyleHintReturn *returnData) const {
       
  1946             if (stylehint == QStyle::SH_RichText_FullWidthSelection)
       
  1947                 return 1;
       
  1948             return QCommonStyle::styleHint(stylehint, opt, widget, returnData);
       
  1949         };
       
  1950     };
       
  1951     FullWidthStyle myStyle;
       
  1952 
       
  1953     QPalette myPalette = myStyle.standardPalette();
       
  1954     myPalette.setColor(QPalette::All, QPalette::HighlightedText, QColor(0,0,0,0));
       
  1955     myPalette.setColor(QPalette::All, QPalette::Highlight, QColor(239,221,85));
       
  1956 
       
  1957     QTextEdit widget;
       
  1958     widget.document()->setDocumentMargin(2);
       
  1959     widget.setPalette(myPalette);
       
  1960     widget.setStyle(&myStyle);
       
  1961     QTextCursor cursor = widget.textCursor();
       
  1962     QTextBlockFormat bf1;
       
  1963     bf1.setAlignment(Qt::AlignCenter);
       
  1964     cursor.setBlockFormat(bf1);
       
  1965 
       
  1966     // use the test font so we always know where stuff will end up.
       
  1967     qt_setQtEnableTestFont(true);
       
  1968     QFont testFont;
       
  1969     testFont.setFamily("__Qt__Box__Engine__");
       
  1970     testFont.setPixelSize(12);
       
  1971     testFont.setWeight(QFont::Normal);
       
  1972     QTextCharFormat cf;
       
  1973     cf.setFont(testFont);
       
  1974     cf.setForeground(QColor(0,0,0,0)); // tricky bit, this :)
       
  1975     cursor.setCharFormat(cf);
       
  1976 
       
  1977     // populate with some demo text.
       
  1978     cursor.insertText("centered");
       
  1979     QTextBlockFormat bf;
       
  1980     cursor.insertBlock(bf, cf);
       
  1981     cursor.insertText("Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo cons.\nfoo\n");
       
  1982 
       
  1983     // Usecase 1 for full-width-selections; the 'show-cursor-position' one.
       
  1984     QList<QTextEdit::ExtraSelection> selections;
       
  1985     QTextCursor cursor2(widget.document());
       
  1986     QTextEdit::ExtraSelection es;
       
  1987     cursor2.setPosition(300);
       
  1988     es.cursor = cursor2;
       
  1989     es.format.setProperty( QTextFormat::FullWidthSelection, true );
       
  1990     es.format.setBackground(QColor(255, 0, 0));
       
  1991     selections.append(es);
       
  1992     widget.setExtraSelections(selections);
       
  1993 
       
  1994     // Usecase 2; show it based on the style.
       
  1995     // Select part of the centered text and part of the next; which means we should show the part right of the centered text.
       
  1996     cursor.setPosition(cursorFrom);
       
  1997     cursor.setPosition(cursorTo, QTextCursor::KeepAnchor);
       
  1998     widget.setTextCursor(cursor);
       
  1999 
       
  2000     compareWidgetAndImage(widget, imageFileName);
       
  2001 }
       
  2002 
       
  2003 void tst_QTextEdit::fullWidthSelection2()
       
  2004 {
       
  2005     QPalette myPalette;
       
  2006     myPalette.setColor(QPalette::All, QPalette::HighlightedText, QColor(0,0,0,0));
       
  2007     myPalette.setColor(QPalette::All, QPalette::Highlight, QColor(239,221,85));
       
  2008 
       
  2009     QTextEdit widget;
       
  2010     widget.setPalette(myPalette);
       
  2011     widget.setLineWrapMode(QTextEdit::NoWrap);
       
  2012     QTextCursor cursor = widget.textCursor();
       
  2013 
       
  2014     // use the test font so we always know where stuff will end up.
       
  2015     qt_setQtEnableTestFont(true);
       
  2016     QFont testFont;
       
  2017     testFont.setFamily("__Qt__Box__Engine__");
       
  2018     testFont.setPixelSize(12);
       
  2019     testFont.setWeight(QFont::Normal);
       
  2020     QTextCharFormat cf;
       
  2021     cf.setFont(testFont);
       
  2022     cf.setForeground(QColor(0,0,0,0)); // tricky bit, this :)
       
  2023     cursor.setCharFormat(cf);
       
  2024     cursor.insertText("foo");
       
  2025 
       
  2026     QList<QTextEdit::ExtraSelection> selections;
       
  2027     QTextCursor cursor2(widget.document());
       
  2028     QTextEdit::ExtraSelection es;
       
  2029     cursor2.setPosition(1);
       
  2030     es.cursor = cursor2;
       
  2031     es.format.setProperty( QTextFormat::FullWidthSelection, true );
       
  2032     es.format.setBackground(QColor(255, 0, 0));
       
  2033     selections.append(es);
       
  2034     widget.setExtraSelections(selections);
       
  2035 
       
  2036     compareWidgetAndImage(widget, "fullWidthSelection/nowrap_long.png");
       
  2037 
       
  2038     QTextLine line = widget.document()->begin().layout()->lineAt(0);
       
  2039     // qDebug() << line.width();
       
  2040 }
       
  2041 
       
  2042 void tst_QTextEdit::compareWidgetAndImage(QTextEdit &widget, const QString &imageFileName)
       
  2043 {
       
  2044     widget.setGeometry(0, 0, 300, 390);
       
  2045     widget.setFrameShape(QFrame::NoFrame);
       
  2046 
       
  2047     QImage image(300, 390, QImage::Format_RGB32);
       
  2048     QPainter painter(&image);
       
  2049     widget.viewport()->render(&painter);
       
  2050     painter.end();
       
  2051     // qDebug() << "file: " << QString(SRCDIR) + imageFileName;
       
  2052     QImageReader reader(QString(SRCDIR) + imageFileName, "PNG");
       
  2053     QImage original = reader.read();
       
  2054 
       
  2055     QCOMPARE(original.isNull(), false);
       
  2056     QCOMPARE(original.size(), image.size());
       
  2057     Q_ASSERT(image.depth() == 32);
       
  2058     QCOMPARE(original.depth(), image.depth());
       
  2059 
       
  2060     const int bytesPerLine = image.bytesPerLine();
       
  2061     const int width = image.width();
       
  2062     const int height = image.height();
       
  2063 
       
  2064     for (int y = 0; y < height; ++y) {
       
  2065         const QRgb * const firstLine = reinterpret_cast<const QRgb *>(image.scanLine(y));
       
  2066         const QRgb * const secondLine = reinterpret_cast<const QRgb *>(original.scanLine(y));
       
  2067 
       
  2068         if (memcmp(firstLine, secondLine, bytesPerLine) != 0) {
       
  2069             for (int x = 0; x < width; ++x) {
       
  2070                 const QRgb a = firstLine[x];
       
  2071                 const QRgb b = secondLine[x];
       
  2072                 const bool same = qAbs(qRed(a) - qRed(b)) <= 20
       
  2073                     && qAbs(qGreen(a) - qGreen(b)) <= 20
       
  2074                     && qAbs(qBlue(a) - qBlue(b)) <= 20;
       
  2075                 if (!same) {
       
  2076                     QString fileName = imageFileName;
       
  2077                     QImageWriter writer("failed_"+ fileName.replace('/','_'), "PNG");
       
  2078                     writer.write(image);
       
  2079                 }
       
  2080                 QVERIFY(same);
       
  2081             }
       
  2082         }
       
  2083     }
       
  2084 }
       
  2085 
       
  2086 void tst_QTextEdit::cursorRect()
       
  2087 {
       
  2088     ed->show();
       
  2089     ed->setPlainText("Hello Test World");
       
  2090     ed->setCursorWidth(1);
       
  2091     QCOMPARE(ed->cursorRect().width(), 1);
       
  2092     ed->setCursorWidth(2);
       
  2093     QCOMPARE(ed->cursorRect().width(), 2);
       
  2094     ed->setCursorWidth(4);
       
  2095     QCOMPARE(ed->cursorRect().width(), 4);
       
  2096     ed->setCursorWidth(10);
       
  2097     QCOMPARE(ed->cursorRect().width(), 10);
       
  2098 }
       
  2099 
       
  2100 void tst_QTextEdit::setDocumentPreservesPalette()
       
  2101 {
       
  2102 #ifdef QT_BUILD_INTERNAL
       
  2103     QTextControl *control = qFindChild<QTextControl *>(ed);
       
  2104     QVERIFY(control);
       
  2105 
       
  2106     QPalette defaultPal = ed->palette();
       
  2107     QPalette whitePal = ed->palette();
       
  2108     whitePal.setColor(QPalette::Active, QPalette::Text, "white");
       
  2109 
       
  2110     QVERIFY(whitePal != ed->palette());
       
  2111     ed->setPalette(whitePal);
       
  2112     QVERIFY(whitePal.color(QPalette::Active, QPalette::Text)
       
  2113             == ed->palette().color(QPalette::Active, QPalette::Text));
       
  2114     QVERIFY(whitePal.color(QPalette::Active, QPalette::Text)
       
  2115             == control->palette().color(QPalette::Active, QPalette::Text));
       
  2116 
       
  2117     QTextDocument *newDoc = new QTextDocument(ed);
       
  2118     ed->setDocument(newDoc);
       
  2119     QVERIFY(control->document() == newDoc);
       
  2120     QVERIFY(whitePal.color(QPalette::Active, QPalette::Text)
       
  2121             == control->palette().color(QPalette::Active, QPalette::Text));
       
  2122 #endif
       
  2123 }
       
  2124 
       
  2125 class PublicTextEdit : public QTextEdit
       
  2126 {
       
  2127 public:
       
  2128     void publicInsertFromMimeData(const QMimeData *source)
       
  2129     { insertFromMimeData(source); }
       
  2130 };
       
  2131 
       
  2132 void tst_QTextEdit::pasteFromQt3RichText()
       
  2133 {
       
  2134     QByteArray richtext("<!--StartFragment--><p>  QTextEdit is an  ");
       
  2135 
       
  2136     QMimeData mimeData;
       
  2137     mimeData.setData("application/x-qrichtext", richtext);
       
  2138 
       
  2139     static_cast<PublicTextEdit *>(ed)->publicInsertFromMimeData(&mimeData);
       
  2140 
       
  2141     QCOMPARE(ed->toPlainText(), QString::fromLatin1("  QTextEdit is an  "));
       
  2142     ed->clear();
       
  2143 
       
  2144     richtext = "<!--StartFragment-->  QTextEdit is an  ";
       
  2145     mimeData.setData("application/x-qrichtext", richtext);
       
  2146 
       
  2147     static_cast<PublicTextEdit *>(ed)->publicInsertFromMimeData(&mimeData);
       
  2148 
       
  2149     QCOMPARE(ed->toPlainText(), QString::fromLatin1("  QTextEdit is an  "));
       
  2150 }
       
  2151 
       
  2152 void tst_QTextEdit::noWrapBackgrounds()
       
  2153 {
       
  2154     QTextEdit edit;
       
  2155     edit.setLineWrapMode(QTextEdit::NoWrap);
       
  2156 
       
  2157     QTextFrame *root = edit.document()->rootFrame();
       
  2158     QTextFrameFormat frameFormat = root->frameFormat();
       
  2159     frameFormat.setLeftMargin(2);
       
  2160     frameFormat.setRightMargin(2);
       
  2161     root->setFrameFormat(frameFormat);
       
  2162 
       
  2163     QTextBlockFormat format;
       
  2164     format.setBackground(Qt::red);
       
  2165     edit.textCursor().setBlockFormat(format);
       
  2166     edit.insertPlainText(QLatin1String(" \n  \n   \n    \n"));
       
  2167     edit.setFixedSize(100, 200);
       
  2168 
       
  2169     QImage img = QPixmap::grabWidget(edit.viewport()).toImage();
       
  2170     QCOMPARE(img, img.mirrored(true, false));
       
  2171 }
       
  2172 
       
  2173 void tst_QTextEdit::preserveCharFormatAfterUnchangingSetPosition()
       
  2174 {
       
  2175     QColor color(Qt::yellow);
       
  2176     QTextEdit edit;
       
  2177     edit.setTextColor(color);
       
  2178 
       
  2179     QTextCursor c = edit.textCursor();
       
  2180     c.setPosition(c.position());
       
  2181     edit.setTextCursor(c);
       
  2182 
       
  2183     QCOMPARE(edit.textColor(), color);
       
  2184 }
       
  2185 
       
  2186 QTEST_MAIN(tst_QTextEdit)
       
  2187 #include "tst_qtextedit.moc"