2023-10-30 06:33:08 +08:00
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
# include <QTest>
# include <QSignalSpy>
# include <qtextdocument.h>
# include <qdebug.h>
# include <qtextcursor.h>
# include <qtextdocumentfragment.h>
# include <qtextformat.h>
# include <qtextobject.h>
# include <qtexttable.h>
# include <qabstracttextdocumentlayout.h>
# include <qtextlist.h>
# include <qguiapplication.h>
# include <qurl.h>
# include <qpainter.h>
# include <qfontmetrics.h>
# include <qimage.h>
# include <qtextlayout.h>
# include <QDomDocument>
# include "common.h"
// #define DEBUG_WRITE_OUTPUT
QT_FORWARD_DECLARE_CLASS ( QTextDocument )
class tst_QTextDocument : public QObject
{
Q_OBJECT
public :
tst_QTextDocument ( ) ;
private slots :
void init ( ) ;
void cleanup ( ) ;
void cleanupTestCase ( ) ;
void getSetCheck ( ) ;
void isEmpty ( ) ;
void find_data ( ) ;
void find ( ) ;
void find2 ( ) ;
void findWithRegularExpression_data ( ) ;
void findWithRegularExpression ( ) ;
void findMultiple ( ) ;
void basicIsModifiedChecks ( ) ;
void moreIsModified ( ) ;
void isModified2 ( ) ;
void isModified3 ( ) ;
void isModified4 ( ) ;
void noundo_basicIsModifiedChecks ( ) ;
void noundo_moreIsModified ( ) ;
void noundo_isModified2 ( ) ;
void noundo_isModified3 ( ) ;
void mightBeRichText ( ) ;
void mightBeRichText_data ( ) ;
void task240325 ( ) ;
void preFont ( ) ;
void stylesheetFont_data ( ) ;
void stylesheetFont ( ) ;
void toHtml_data ( ) ;
void toHtml ( ) ;
void toHtml2 ( ) ;
void setFragmentMarkersInHtmlExport ( ) ;
void setMediaRule ( ) ;
void toHtmlBodyBgColor ( ) ;
void toHtmlBodyBgColorRgba ( ) ;
void toHtmlBodyBgColorTransparent ( ) ;
void toHtmlRootFrameProperties ( ) ;
void toHtmlLineHeightProperties ( ) ;
void toHtmlDefaultFontSpacingProperties ( ) ;
void toHtmlTextDecorationUnderline ( ) ;
void capitalizationHtmlInExport ( ) ;
void wordspacingHtmlExport ( ) ;
void cursorPositionChanged ( ) ;
void cursorPositionChangedOnSetText ( ) ;
void textFrameIterator ( ) ;
void markContentsDirty ( ) ;
void clonePreservesMetaInformation ( ) ;
void clonePreservesPageSize ( ) ;
void clonePreservesPageBreakPolicies ( ) ;
void clonePreservesDefaultFont ( ) ;
void clonePreservesRootFrameFormat ( ) ;
void clonePreservesResources ( ) ;
void clonePreservesUserStates ( ) ;
void clonePreservesIndentWidth ( ) ;
void clonePreservesFormatsWhenEmpty ( ) ;
void blockCount ( ) ;
void defaultStyleSheet ( ) ;
void defaultTableStyle_data ( ) ;
void defaultTableStyle ( ) ;
void resolvedFontInEmptyFormat ( ) ;
void defaultRootFrameMargin ( ) ;
void clearResources ( ) ;
void setPlainText ( ) ;
void toPlainText_data ( ) ;
void toPlainText ( ) ;
void toRawText ( ) ;
void deleteTextObjectsOnClear ( ) ;
void maximumBlockCount ( ) ;
void adjustSize ( ) ;
void initialUserData ( ) ;
void html_defaultFont ( ) ;
void blockCountChanged ( ) ;
void nonZeroDocumentLengthOnClear ( ) ;
void setTextPreservesUndoRedoEnabled ( ) ;
void firstLast ( ) ;
void backgroundImage_toHtml ( ) ;
void backgroundImage_toHtml2 ( ) ;
void backgroundImage_clone ( ) ;
void backgroundImage_copy ( ) ;
void documentCleanup ( ) ;
void characterAt ( ) ;
void revisions ( ) ;
void revisionWithUndoCompressionAndUndo ( ) ;
void testUndoCommandAdded ( ) ;
void testUndoBlocks ( ) ;
void receiveCursorPositionChangedAfterContentsChange ( ) ;
void copiedFontSize ( ) ;
void QTBUG25778_pixelSizeFromHtml ( ) ;
void htmlExportImportBlockCount ( ) ;
void QTBUG27354_spaceAndSoftSpace ( ) ;
void baseUrl_data ( ) ;
void baseUrl ( ) ;
void QTBUG28998_linkColor ( ) ;
void textCursorUsageWithinContentsChange ( ) ;
void cssInheritance ( ) ;
void lineHeightType ( ) ;
void cssLineHeightMultiplier ( ) ;
void fontTagFace ( ) ;
void clearUndoRedoStacks ( ) ;
void mergeFontFamilies ( ) ;
void resourceProvider ( ) ;
void contentsChangeIndices_data ( ) ;
void contentsChangeIndices ( ) ;
void insertHtmlWithComments_data ( ) ;
void insertHtmlWithComments ( ) ;
void delayedLayout ( ) ;
private :
void backgroundImage_checkExpectedHtml ( const QTextDocument & doc ) ;
void buildRegExpData ( ) ;
static QString cssFontSizeString ( const QFont & font ) ;
void writeActualAndExpected ( const char * testTag , const QString & actual , const QString & expected ) ;
QTextDocument * doc ;
QTextCursor cursor ;
QFont defaultFont ;
QString htmlHead ;
QString htmlTail ;
} ;
class MyAbstractTextDocumentLayout : public QAbstractTextDocumentLayout
{
public :
MyAbstractTextDocumentLayout ( QTextDocument * doc ) : QAbstractTextDocumentLayout ( doc ) { }
void draw ( QPainter * , const PaintContext & ) override { }
int hitTest ( const QPointF & , Qt : : HitTestAccuracy ) const override { return 0 ; }
int pageCount ( ) const override { return 0 ; }
QSizeF documentSize ( ) const override { return QSizeF ( ) ; }
QRectF frameBoundingRect ( QTextFrame * ) const override { return QRectF ( ) ; }
QRectF blockBoundingRect ( const QTextBlock & ) const override { return QRectF ( ) ; }
void documentChanged ( int , int , int ) override { }
} ;
QString tst_QTextDocument : : cssFontSizeString ( const QFont & font )
{
return font . pointSize ( ) > = 0
? QString : : number ( font . pointSizeF ( ) ) + QStringLiteral ( " pt " )
: QString : : number ( font . pixelSize ( ) ) + QStringLiteral ( " px " ) ;
}
void tst_QTextDocument : : writeActualAndExpected ( const char * testTag , const QString & actual , const QString & expected )
{
# ifdef DEBUG_WRITE_OUTPUT
{
QFile out ( QDir : : temp ( ) . absoluteFilePath ( QLatin1String ( testTag ) + QLatin1String ( " -actual.html " ) ) ) ;
out . open ( QFile : : WriteOnly ) ;
out . write ( actual . toUtf8 ( ) ) ;
out . close ( ) ;
} {
QFile out ( QDir : : temp ( ) . absoluteFilePath ( QLatin1String ( testTag ) + QLatin1String ( " -expected.html " ) ) ) ;
out . open ( QFile : : WriteOnly ) ;
out . write ( expected . toUtf8 ( ) ) ;
out . close ( ) ;
}
# else
Q_UNUSED ( testTag ) ;
Q_UNUSED ( actual ) ;
Q_UNUSED ( expected ) ;
# endif
}
// Testing get/set functions
void tst_QTextDocument : : getSetCheck ( )
{
QTextDocument obj1 ;
// QAbstractTextDocumentLayout * QTextDocument::documentLayout()
// void QTextDocument::setDocumentLayout(QAbstractTextDocumentLayout *)
QPointer < MyAbstractTextDocumentLayout > var1 = new MyAbstractTextDocumentLayout ( 0 ) ;
obj1 . setDocumentLayout ( var1 ) ;
QCOMPARE ( static_cast < QAbstractTextDocumentLayout * > ( var1 ) , obj1 . documentLayout ( ) ) ;
obj1 . setDocumentLayout ( ( QAbstractTextDocumentLayout * ) 0 ) ;
QVERIFY ( var1 . isNull ( ) ) ;
QVERIFY ( obj1 . documentLayout ( ) ) ;
// bool QTextDocument::useDesignMetrics()
// void QTextDocument::setUseDesignMetrics(bool)
obj1 . setUseDesignMetrics ( false ) ;
QCOMPARE ( false , obj1 . useDesignMetrics ( ) ) ;
obj1 . setUseDesignMetrics ( true ) ;
QCOMPARE ( true , obj1 . useDesignMetrics ( ) ) ;
}
tst_QTextDocument : : tst_QTextDocument ( )
{
QImage img ( 16 , 16 , QImage : : Format_ARGB32_Premultiplied ) ;
img . save ( " foo.png " ) ;
}
void tst_QTextDocument : : init ( )
{
doc = new QTextDocument ;
cursor = QTextCursor ( doc ) ;
defaultFont = QFont ( ) ;
htmlHead = QString ( " <!DOCTYPE HTML PUBLIC \" -//W3C//DTD HTML 4.0//EN \" "
" \" http://www.w3.org/TR/REC-html40/strict.dtd \" > \n "
" <html><head><meta name= \" qrichtext \" content= \" 1 \" /><meta charset= \" utf-8 \" /><style type= \" text/css \" > \n "
" p, li { white-space: pre-wrap; } \n "
" hr { height: 1px; border-width: 0; } \n "
" li.unchecked::marker { content: \" \\ 2610 \" ; } \n "
" li.checked::marker { content: \" \\ 2612 \" ; } \n "
" </style></head> "
" <body style= \" font-family:'%1'; font-size:%2; font-weight:%3; font-style:%4; \" > \n " ) ;
htmlHead = htmlHead . arg ( defaultFont . family ( ) )
. arg ( cssFontSizeString ( defaultFont ) )
. arg ( defaultFont . weight ( ) )
. arg ( ( defaultFont . italic ( ) ? " italic " : " normal " ) ) ;
htmlTail = QString ( " </body></html> " ) ;
}
void tst_QTextDocument : : cleanup ( )
{
cursor = QTextCursor ( ) ;
delete doc ;
doc = 0 ;
}
void tst_QTextDocument : : cleanupTestCase ( )
{
QFile : : remove ( QLatin1String ( " foo.png " ) ) ;
}
void tst_QTextDocument : : isEmpty ( )
{
QVERIFY ( doc - > isEmpty ( ) ) ;
}
void tst_QTextDocument : : find_data ( )
{
QTest : : addColumn < QString > ( " haystack " ) ;
QTest : : addColumn < QString > ( " needle " ) ;
QTest : : addColumn < int > ( " flags " ) ;
QTest : : addColumn < int > ( " from " ) ;
QTest : : addColumn < int > ( " anchor " ) ;
QTest : : addColumn < int > ( " position " ) ;
QTest : : newRow ( " 1 " ) < < " Hello World " < < " World " < < int ( QTextDocument : : FindCaseSensitively ) < < 0 < < 6 < < 11 ;
QTest : : newRow ( " 2 " ) < < QString : : fromLatin1 ( " Hello " ) + QString ( QChar : : ParagraphSeparator ) + QString : : fromLatin1 ( " World " )
< < " World " < < int ( QTextDocument : : FindCaseSensitively ) < < 1 < < 6 < < 11 ;
QTest : : newRow ( " 3 " ) < < QString : : fromLatin1 ( " Hello " ) + QString ( QChar : : ParagraphSeparator ) + QString : : fromLatin1 ( " World " )
< < " Hello " < < int ( QTextDocument : : FindCaseSensitively | QTextDocument : : FindBackward ) < < 10 < < 0 < < 5 ;
QTest : : newRow ( " 4wholewords " ) < < QString : : fromLatin1 ( " Hello Blah World " )
< < " Blah " < < int ( QTextDocument : : FindWholeWords ) < < 0 < < 6 < < 10 ;
QTest : : newRow ( " 5wholewords " ) < < QString : : fromLatin1 ( " HelloBlahWorld " )
< < " Blah " < < int ( QTextDocument : : FindWholeWords ) < < 0 < < - 1 < < - 1 ;
QTest : : newRow ( " 6wholewords " ) < < QString : : fromLatin1 ( " HelloBlahWorld Blah Hah " )
< < " Blah " < < int ( QTextDocument : : FindWholeWords ) < < 0 < < 15 < < 19 ;
QTest : : newRow ( " 7wholewords " ) < < QString : : fromLatin1 ( " HelloBlahWorld Blah Hah " )
< < " Blah " < < int ( QTextDocument : : FindWholeWords | QTextDocument : : FindBackward ) < < 23 < < 15 < < 19 ;
QTest : : newRow ( " 8wholewords " ) < < QString : : fromLatin1 ( " Hello: World \n " )
< < " orld " < < int ( QTextDocument : : FindWholeWords ) < < 0 < < - 1 < < - 1 ;
QTest : : newRow ( " across-paragraphs " ) < < QString : : fromLatin1 ( " First Parag \n Second Parag with a lot more text " )
< < " Parag " < < int ( QTextDocument : : FindBackward )
< < 15 < < 6 < < 11 ;
QTest : : newRow ( " nbsp " ) < < " Hello " + QString ( QChar ( QChar : : Nbsp ) ) + " World " < < " " < < int ( QTextDocument : : FindCaseSensitively ) < < 0 < < 5 < < 6 ;
QTest : : newRow ( " from-the-end " ) < < " Hello World " < < " Hello World " < < int ( QTextDocument : : FindCaseSensitively | QTextDocument : : FindBackward ) < < 11 < < 0 < < 11 ;
QTest : : newRow ( " bw-cross-paras-1 " ) < < " a1 \n a2 \n b1 " < < " a " < < int ( QTextDocument : : FindBackward ) < < 7 < < 3 < < 4 ;
QTest : : newRow ( " bw-cross-paras-2 " ) < < " a1 \n a2 \n b1 " < < " a " < < int ( QTextDocument : : FindBackward ) < < 6 < < 3 < < 4 ;
QTest : : newRow ( " bw-cross-paras-3 " ) < < " a1 \n a2 \n b1 " < < " a " < < int ( QTextDocument : : FindBackward ) < < 5 < < 3 < < 4 ;
QTest : : newRow ( " bw-cross-paras-4 " ) < < " a1 \n a2 \n b1 " < < " a " < < int ( QTextDocument : : FindBackward ) < < 3 < < 0 < < 1 ;
QTest : : newRow ( " bw-cross-paras-5 " ) < < " xa \n \n b1 " < < " a " < < int ( QTextDocument : : FindBackward ) < < 5 < < 1 < < 2 ;
QTest : : newRow ( " bw-cross-paras-6 " ) < < " xa \n \n b1 " < < " a " < < int ( QTextDocument : : FindBackward ) < < 4 < < 1 < < 2 ;
QTest : : newRow ( " bw-cross-paras-7 " ) < < " xa \n \n b1 " < < " a " < < int ( QTextDocument : : FindBackward ) < < 3 < < 1 < < 2 ;
QTest : : newRow ( " bw-cross-paras-8 " ) < < " xa \n \n b1 " < < " a " < < int ( QTextDocument : : FindBackward ) < < 2 < < 1 < < 2 ;
}
void tst_QTextDocument : : find ( )
{
QFETCH ( QString , haystack ) ;
QFETCH ( QString , needle ) ;
QFETCH ( int , flags ) ;
QFETCH ( int , from ) ;
QFETCH ( int , anchor ) ;
QFETCH ( int , position ) ;
cursor . insertText ( haystack ) ;
cursor = doc - > find ( needle , from , QTextDocument : : FindFlags ( flags ) ) ;
if ( anchor ! = - 1 ) {
QCOMPARE ( cursor . anchor ( ) , anchor ) ;
QCOMPARE ( cursor . position ( ) , position ) ;
} else {
QVERIFY ( cursor . isNull ( ) ) ;
}
//search using a regular expression
QRegularExpression expr ( QRegularExpression : : escape ( needle ) ) ;
QTextDocument : : FindFlags flg ( flags ) ;
cursor = doc - > find ( expr , from , flg ) ;
if ( anchor ! = - 1 ) {
QCOMPARE ( cursor . anchor ( ) , anchor ) ;
QCOMPARE ( cursor . position ( ) , position ) ;
} else {
QVERIFY ( cursor . isNull ( ) ) ;
}
}
void tst_QTextDocument : : findWithRegularExpression_data ( )
{
buildRegExpData ( ) ;
}
void tst_QTextDocument : : findWithRegularExpression ( )
{
QFETCH ( QString , haystack ) ;
QFETCH ( QString , needle ) ;
QFETCH ( int , flags ) ;
QFETCH ( int , from ) ;
QFETCH ( int , anchor ) ;
QFETCH ( int , position ) ;
cursor . insertText ( haystack ) ;
//search using a regular expression
QRegularExpression expr ( needle ) ;
QTextDocument : : FindFlags flg ( flags ) ;
cursor = doc - > find ( expr , from , flg ) ;
if ( anchor ! = - 1 ) {
QCOMPARE ( cursor . anchor ( ) , anchor ) ;
QCOMPARE ( cursor . position ( ) , position ) ;
} else {
QVERIFY ( cursor . isNull ( ) ) ;
}
}
void tst_QTextDocument : : find2 ( )
{
doc - > setPlainText ( " aaa " ) ;
cursor . movePosition ( QTextCursor : : Start ) ;
cursor . movePosition ( QTextCursor : : NextCharacter , QTextCursor : : KeepAnchor ) ;
QTextCursor hit = doc - > find ( " a " , cursor ) ;
QCOMPARE ( hit . position ( ) , 2 ) ;
QCOMPARE ( hit . anchor ( ) , 1 ) ;
}
void tst_QTextDocument : : findMultiple ( )
{
const QString text ( " foo bar baz foo bar baz " ) ;
doc - > setPlainText ( text ) ;
cursor . movePosition ( QTextCursor : : Start ) ;
cursor = doc - > find ( " bar " , cursor ) ;
QCOMPARE ( cursor . selectionStart ( ) , text . indexOf ( " bar " ) ) ;
QCOMPARE ( cursor . selectionEnd ( ) , cursor . selectionStart ( ) + 3 ) ;
cursor = doc - > find ( " bar " , cursor ) ;
QCOMPARE ( cursor . selectionStart ( ) , text . lastIndexOf ( " bar " ) ) ;
QCOMPARE ( cursor . selectionEnd ( ) , cursor . selectionStart ( ) + 3 ) ;
cursor . movePosition ( QTextCursor : : End ) ;
cursor = doc - > find ( " bar " , cursor , QTextDocument : : FindBackward ) ;
QCOMPARE ( cursor . selectionStart ( ) , text . lastIndexOf ( " bar " ) ) ;
QCOMPARE ( cursor . selectionEnd ( ) , cursor . selectionStart ( ) + 3 ) ;
cursor = doc - > find ( " bar " , cursor , QTextDocument : : FindBackward ) ;
QCOMPARE ( cursor . selectionStart ( ) , text . indexOf ( " bar " ) ) ;
QCOMPARE ( cursor . selectionEnd ( ) , cursor . selectionStart ( ) + 3 ) ;
QRegularExpression regularExpression ( " bar " ) ;
cursor . movePosition ( QTextCursor : : End ) ;
cursor = doc - > find ( regularExpression , cursor , QTextDocument : : FindBackward ) ;
QCOMPARE ( cursor . selectionStart ( ) , text . lastIndexOf ( " bar " ) ) ;
QCOMPARE ( cursor . selectionEnd ( ) , cursor . selectionStart ( ) + 3 ) ;
cursor = doc - > find ( regularExpression , cursor , QTextDocument : : FindBackward ) ;
QCOMPARE ( cursor . selectionStart ( ) , text . indexOf ( " bar " ) ) ;
QCOMPARE ( cursor . selectionEnd ( ) , cursor . selectionStart ( ) + 3 ) ;
cursor . movePosition ( QTextCursor : : Start ) ;
cursor = doc - > find ( regularExpression , cursor ) ;
QCOMPARE ( cursor . selectionStart ( ) , text . indexOf ( " bar " ) ) ;
QCOMPARE ( cursor . selectionEnd ( ) , cursor . selectionStart ( ) + 3 ) ;
cursor = doc - > find ( regularExpression , cursor ) ;
QCOMPARE ( cursor . selectionStart ( ) , text . lastIndexOf ( " bar " ) ) ;
QCOMPARE ( cursor . selectionEnd ( ) , cursor . selectionStart ( ) + 3 ) ;
}
void tst_QTextDocument : : basicIsModifiedChecks ( )
{
QSignalSpy spy ( doc , SIGNAL ( modificationChanged ( bool ) ) ) ;
QVERIFY ( ! doc - > isModified ( ) ) ;
cursor . insertText ( " Hello World " ) ;
QVERIFY ( doc - > isModified ( ) ) ;
QCOMPARE ( spy . size ( ) , 1 ) ;
QVERIFY ( spy . takeFirst ( ) . at ( 0 ) . toBool ( ) ) ;
doc - > undo ( ) ;
QVERIFY ( ! doc - > isModified ( ) ) ;
QCOMPARE ( spy . size ( ) , 1 ) ;
QVERIFY ( ! spy . takeFirst ( ) . at ( 0 ) . toBool ( ) ) ;
doc - > redo ( ) ;
QVERIFY ( doc - > isModified ( ) ) ;
QCOMPARE ( spy . size ( ) , 1 ) ;
QVERIFY ( spy . takeFirst ( ) . at ( 0 ) . toBool ( ) ) ;
}
void tst_QTextDocument : : moreIsModified ( )
{
QVERIFY ( ! doc - > isModified ( ) ) ;
cursor . insertText ( " Hello " ) ;
QVERIFY ( doc - > isModified ( ) ) ;
doc - > undo ( ) ;
QVERIFY ( ! doc - > isModified ( ) ) ;
cursor . insertText ( " Hello " ) ;
doc - > undo ( ) ;
QVERIFY ( ! doc - > isModified ( ) ) ;
}
void tst_QTextDocument : : isModified2 ( )
{
// reported on qt4-preview-feedback
QVERIFY ( ! doc - > isModified ( ) ) ;
cursor . insertText ( " Hello " ) ;
QVERIFY ( doc - > isModified ( ) ) ;
doc - > setModified ( false ) ;
QVERIFY ( ! doc - > isModified ( ) ) ;
cursor . insertText ( " Hello " ) ;
QVERIFY ( doc - > isModified ( ) ) ;
}
void tst_QTextDocument : : isModified3 ( )
{
QVERIFY ( ! doc - > isModified ( ) ) ;
doc - > setUndoRedoEnabled ( false ) ;
doc - > setUndoRedoEnabled ( true ) ;
cursor . insertText ( " Hello " ) ;
QVERIFY ( doc - > isModified ( ) ) ;
doc - > undo ( ) ;
QVERIFY ( ! doc - > isModified ( ) ) ;
}
void tst_QTextDocument : : isModified4 ( )
{
QVERIFY ( ! doc - > isModified ( ) ) ;
cursor . insertText ( " Hello " ) ;
cursor . insertText ( " World " ) ;
doc - > setModified ( false ) ;
QVERIFY ( ! doc - > isModified ( ) ) ;
cursor . insertText ( " Again " ) ;
QVERIFY ( doc - > isModified ( ) ) ;
doc - > undo ( ) ;
QVERIFY ( ! doc - > isModified ( ) ) ;
doc - > undo ( ) ;
QVERIFY ( doc - > isModified ( ) ) ;
doc - > redo ( ) ;
QVERIFY ( ! doc - > isModified ( ) ) ;
doc - > redo ( ) ;
QVERIFY ( doc - > isModified ( ) ) ;
doc - > undo ( ) ;
QVERIFY ( ! doc - > isModified ( ) ) ;
doc - > undo ( ) ;
QVERIFY ( doc - > isModified ( ) ) ;
//task 197769
cursor . insertText ( " Hello " ) ;
QVERIFY ( doc - > isModified ( ) ) ;
}
void tst_QTextDocument : : noundo_basicIsModifiedChecks ( )
{
doc - > setUndoRedoEnabled ( false ) ;
QSignalSpy spy ( doc , SIGNAL ( modificationChanged ( bool ) ) ) ;
QVERIFY ( ! doc - > isModified ( ) ) ;
cursor . insertText ( " Hello World " ) ;
QVERIFY ( doc - > isModified ( ) ) ;
QCOMPARE ( spy . size ( ) , 1 ) ;
QVERIFY ( spy . takeFirst ( ) . at ( 0 ) . toBool ( ) ) ;
doc - > undo ( ) ;
QVERIFY ( doc - > isModified ( ) ) ;
QCOMPARE ( spy . size ( ) , 0 ) ;
doc - > redo ( ) ;
QVERIFY ( doc - > isModified ( ) ) ;
QCOMPARE ( spy . size ( ) , 0 ) ;
}
void tst_QTextDocument : : task240325 ( )
{
doc - > setHtml ( " <html><img width= \" 100 \" height= \" 100 \" align= \" right \" />Foobar Foobar Foobar Foobar</html> " ) ;
QImage img ( 1000 , 7000 , QImage : : Format_ARGB32_Premultiplied ) ;
QPainter p ( & img ) ;
QFontMetrics fm ( p . font ( ) ) ;
// Set page size to contain image and one "Foobar"
doc - > setPageSize ( QSize ( 100 + fm . horizontalAdvance ( " Foobar " ) * 2 , 1000 ) ) ;
// Force layout
doc - > drawContents ( & p ) ;
QCOMPARE ( doc - > blockCount ( ) , 1 ) ;
for ( QTextBlock block = doc - > begin ( ) ; block ! = doc - > end ( ) ; block = block . next ( ) ) {
QTextLayout * layout = block . layout ( ) ;
QCOMPARE ( layout - > lineCount ( ) , 4 ) ;
for ( int lineIdx = 0 ; lineIdx < layout - > lineCount ( ) ; + + lineIdx ) {
QTextLine line = layout - > lineAt ( lineIdx ) ;
QString text = block . text ( ) . mid ( line . textStart ( ) , line . textLength ( ) ) . trimmed ( ) ;
// Remove start token
if ( lineIdx = = 0 )
text = text . mid ( 1 ) ;
QCOMPARE ( text , QString : : fromLatin1 ( " Foobar " ) ) ;
}
}
}
void tst_QTextDocument : : stylesheetFont_data ( )
{
QTest : : addColumn < QString > ( " stylesheet " ) ;
QTest : : addColumn < QFont > ( " font " ) ;
{
QFont font ;
font . setBold ( true ) ;
font . setPixelSize ( 64 ) ;
QTest : : newRow ( " Regular font specification " )
< < " font-size: 64px; font-weight: bold; "
< < font ;
}
{
QFont font ;
font . setBold ( true ) ;
font . setPixelSize ( 64 ) ;
QTest : : newRow ( " Shorthand font specification " )
< < " font: normal bold 64px Arial; "
< < font ;
}
}
void tst_QTextDocument : : stylesheetFont ( )
{
QFETCH ( QString , stylesheet ) ;
QFETCH ( QFont , font ) ;
QString html = QString : : fromLatin1 ( " <html> "
" <body> "
" <div style= \" %1 \" > "
" Foobar "
" </div> "
" </body> "
" </html> " ) . arg ( stylesheet ) ;
qDebug ( ) < < html ;
doc - > setHtml ( html ) ;
QCOMPARE ( doc - > blockCount ( ) , 1 ) ;
// First and only block
QTextBlock block = doc - > firstBlock ( ) ;
QString text = block . text ( ) ;
QCOMPARE ( text , QString : : fromLatin1 ( " Foobar " ) ) ;
QFont actualFont = block . charFormat ( ) . font ( ) ;
QCOMPARE ( actualFont . bold ( ) , font . bold ( ) ) ;
QCOMPARE ( actualFont . pixelSize ( ) , font . pixelSize ( ) ) ;
}
void tst_QTextDocument : : preFont ( )
{
const QFont font = QFontDatabase : : systemFont ( QFontDatabase : : FixedFont ) ;
const QString html = QString : : fromLatin1 ( " <html> "
" <body> "
" <pre> "
" Foobar "
" </pre> "
" </body> "
" </html> " ) ;
doc - > setHtml ( html ) ;
QCOMPARE ( doc - > blockCount ( ) , 1 ) ;
// First and only block
QTextBlock block = doc - > firstBlock ( ) ;
QString text = block . text ( ) ;
QCOMPARE ( text , QString : : fromLatin1 ( " Foobar " ) ) ;
QFont actualFont = block . charFormat ( ) . font ( ) ;
QCOMPARE ( actualFont . family ( ) , font . family ( ) ) ;
}
void tst_QTextDocument : : noundo_moreIsModified ( )
{
doc - > setUndoRedoEnabled ( false ) ;
QVERIFY ( ! doc - > isModified ( ) ) ;
cursor . insertText ( " Hello " ) ;
QVERIFY ( doc - > isModified ( ) ) ;
doc - > undo ( ) ;
QVERIFY ( doc - > isModified ( ) ) ;
cursor . insertText ( " Hello " ) ;
doc - > undo ( ) ;
QVERIFY ( doc - > isModified ( ) ) ;
}
void tst_QTextDocument : : noundo_isModified2 ( )
{
// reported on qt4-preview-feedback
QVERIFY ( ! doc - > isModified ( ) ) ;
cursor . insertText ( " Hello " ) ;
QVERIFY ( doc - > isModified ( ) ) ;
doc - > setModified ( false ) ;
QVERIFY ( ! doc - > isModified ( ) ) ;
cursor . insertText ( " Hello " ) ;
QVERIFY ( doc - > isModified ( ) ) ;
}
void tst_QTextDocument : : noundo_isModified3 ( )
{
doc - > setUndoRedoEnabled ( false ) ;
QVERIFY ( ! doc - > isModified ( ) ) ;
cursor . insertText ( " Hello " ) ;
QVERIFY ( doc - > isModified ( ) ) ;
doc - > undo ( ) ;
QVERIFY ( doc - > isModified ( ) ) ;
}
void tst_QTextDocument : : mightBeRichText_data ( )
{
const char qtDocuHeader [ ] = " <?xml version= \" 1.0 \" encoding= \" iso-8859-1 \" ?> \n "
" <!DOCTYPE html \n "
" PUBLIC " " -//W3C//DTD XHTML 1.0 Strict//EN \" \" DTD/xhtml1-strict.dtd \" > \n "
" <html xmlns= \" http://www.w3.org/1999/xhtml \" xml:lang= \" en \" lang= \" en \" > " ;
QVERIFY ( Qt : : mightBeRichText ( QString : : fromLatin1 ( qtDocuHeader ) ) ) ;
QTest : : addColumn < QString > ( " input " ) ;
QTest : : addColumn < bool > ( " result " ) ;
QTest : : newRow ( " documentation-header " ) < < QString ( " <?xml version= \" 1.0 \" encoding= \" iso-8859-1 \" ?> \n "
" <!DOCTYPE html \n "
" PUBLIC " " -//W3C//DTD XHTML 1.0 Strict//EN \" \" DTD/xhtml1-strict.dtd \" > \n "
" <html xmlns= \" http://www.w3.org/1999/xhtml \" xml:lang= \" en \" lang= \" en \" > " )
< < true ;
QTest : : newRow ( " br-nospace " ) < < QString ( " Test <br/> new line " ) < < true ;
QTest : : newRow ( " br-space " ) < < QString ( " Test <br /> new line " ) < < true ;
QTest : : newRow ( " br-invalidspace " ) < < QString ( " Test <br/ > new line " ) < < false ;
QTest : : newRow ( " invalid closing tag " ) < < QString ( " Test <br/ line " ) < < false ;
}
void tst_QTextDocument : : mightBeRichText ( )
{
QFETCH ( QString , input ) ;
QFETCH ( bool , result ) ;
QCOMPARE ( result , Qt : : mightBeRichText ( input ) ) ;
}
Q_DECLARE_METATYPE ( QTextDocumentFragment )
# define CREATE_DOC_AND_CURSOR() \
QTextDocument doc ; \
doc . setDefaultFont ( defaultFont ) ; \
QTextCursor cursor ( & doc ) ;
void tst_QTextDocument : : toHtml_data ( )
{
QTest : : addColumn < QTextDocumentFragment > ( " input " ) ;
QTest : : addColumn < QString > ( " expectedOutput " ) ;
{
CREATE_DOC_AND_CURSOR ( ) ;
cursor . insertText ( " Blah " ) ;
QTest : : newRow ( " simple " ) < < QTextDocumentFragment ( & doc ) < < QString ( " <p DEFAULTBLOCKSTYLE>Blah</p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
cursor . insertText ( " &<> " ) ;
QTest : : newRow ( " entities " ) < < QTextDocumentFragment ( & doc ) < < QString ( " <p DEFAULTBLOCKSTYLE>&<></p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextCharFormat fmt ;
fmt . setFontFamilies ( { QLatin1String ( " Times " ) } ) ;
cursor . insertText ( " Blah " , fmt ) ;
QTest : : newRow ( " font-family " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <p DEFAULTBLOCKSTYLE><span style= \" font-family:'Times'; \" >Blah</span></p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextCharFormat fmt ;
fmt . setFontFamilies ( { QLatin1String ( " Foo's Family " ) } ) ;
cursor . insertText ( " Blah " , fmt ) ;
QTest : : newRow ( " font-family-with-quotes1 " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <p DEFAULTBLOCKSTYLE><span style= \" font-family:"Foo's Family"; \" >Blah</span></p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextCharFormat fmt ;
fmt . setFontFamilies ( { QLatin1String ( " Foo \" s Family " ) } ) ;
cursor . insertText ( " Blah " , fmt ) ;
QTest : : newRow ( " font-family-with-quotes2 " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <p DEFAULTBLOCKSTYLE><span style= \" font-family:'Foo"s Family'; \" >Blah</span></p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextCharFormat fmt ;
fmt . setFontFamilies ( QStringList { " Times " , " serif " } ) ;
cursor . insertText ( " Blah " , fmt ) ;
QTest : : newRow ( " font-family-with-fallback " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <p DEFAULTBLOCKSTYLE><span style= \" font-family:'Times','serif'; \" >Blah</span></p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextBlockFormat fmt ;
fmt . setNonBreakableLines ( true ) ;
cursor . insertBlock ( fmt ) ;
cursor . insertText ( " Blah " ) ;
QTest : : newRow ( " pre " ) < < QTextDocumentFragment ( & doc )
< <
QString ( " EMPTYBLOCK " ) +
QString ( " <pre DEFAULTBLOCKSTYLE>Blah</pre> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextCharFormat fmt ;
fmt . setFontPointSize ( 40 ) ;
cursor . insertText ( " Blah " , fmt ) ;
QTest : : newRow ( " font-size " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <p DEFAULTBLOCKSTYLE><span style= \" font-size:40pt; \" >Blah</span></p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextCharFormat fmt ;
fmt . setProperty ( QTextFormat : : FontSizeIncrement , 2 ) ;
cursor . insertText ( " Blah " , fmt ) ;
QTest : : newRow ( " logical-font-size " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <p DEFAULTBLOCKSTYLE><span style= \" font-size:x-large; \" >Blah</span></p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
cursor . insertText ( " Foo " ) ;
QTextCharFormat fmt ;
fmt . setFontPointSize ( 40 ) ;
cursor . insertBlock ( QTextBlockFormat ( ) , fmt ) ;
fmt . clearProperty ( QTextFormat : : FontPointSize ) ;
cursor . insertText ( " Blub " , fmt ) ;
QTest : : newRow ( " no-font-size " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <p DEFAULTBLOCKSTYLE>Foo</p> \n <p style= \" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; \" >Blub</p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextBlockFormat fmt ;
fmt . setLayoutDirection ( Qt : : RightToLeft ) ;
cursor . insertBlock ( fmt ) ;
cursor . insertText ( " Blah " ) ;
QTest : : newRow ( " rtl " ) < < QTextDocumentFragment ( & doc )
< <
QString ( " EMPTYBLOCK " ) +
QString ( " <p dir='rtl' DEFAULTBLOCKSTYLE>Blah</p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextBlockFormat fmt ;
fmt . setAlignment ( Qt : : AlignJustify ) ;
cursor . insertBlock ( fmt ) ;
cursor . insertText ( " Blah " ) ;
QTest : : newRow ( " blockalign " ) < < QTextDocumentFragment ( & doc )
< <
QString ( " EMPTYBLOCK " ) +
QString ( " <p align= \" justify \" DEFAULTBLOCKSTYLE>Blah</p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextBlockFormat fmt ;
fmt . setAlignment ( Qt : : AlignCenter ) ;
cursor . insertBlock ( fmt ) ;
cursor . insertText ( " Blah " ) ;
QTest : : newRow ( " blockalign2 " ) < < QTextDocumentFragment ( & doc )
< <
QString ( " EMPTYBLOCK " ) +
QString ( " <p align= \" center \" DEFAULTBLOCKSTYLE>Blah</p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextBlockFormat fmt ;
fmt . setAlignment ( Qt : : AlignRight | Qt : : AlignAbsolute ) ;
cursor . insertBlock ( fmt ) ;
cursor . insertText ( " Blah " ) ;
QTest : : newRow ( " blockalign3 " ) < < QTextDocumentFragment ( & doc )
< <
QString ( " EMPTYBLOCK " ) +
QString ( " <p align= \" right \" DEFAULTBLOCKSTYLE>Blah</p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextBlockFormat fmt ;
fmt . setBackground ( QColor ( " #0000ff " ) ) ;
cursor . insertBlock ( fmt ) ;
cursor . insertText ( " Blah " ) ;
QTest : : newRow ( " bgcolor " ) < < QTextDocumentFragment ( & doc )
< < QString ( " EMPTYBLOCK " ) +
QString ( " <p OPENDEFAULTBLOCKSTYLE background-color:#0000ff; \" >Blah</p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextBlockFormat fmt ;
fmt . setBackground ( QColor ( 255 , 0 , 0 , 51 ) ) ;
cursor . insertBlock ( fmt ) ;
cursor . insertText ( " Blah " ) ;
QTest : : newRow ( " bgcolor-rgba " ) < < QTextDocumentFragment ( & doc )
< < QString ( " EMPTYBLOCK " ) +
QString ( " <p OPENDEFAULTBLOCKSTYLE background-color:rgba(255,0,0,0.2); \" >Blah</p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextBlockFormat fmt ;
fmt . setBackground ( QColor ( 255 , 0 , 0 , 0 ) ) ;
cursor . insertBlock ( fmt ) ;
cursor . insertText ( " Blah " ) ;
QTest : : newRow ( " bgcolor-transparent " ) < < QTextDocumentFragment ( & doc )
< < QString ( " EMPTYBLOCK " ) +
QString ( " <p OPENDEFAULTBLOCKSTYLE background-color:transparent; \" >Blah</p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextCharFormat fmt ;
fmt . setFontWeight ( 320 ) ;
cursor . insertText ( " Blah " , fmt ) ;
QTest : : newRow ( " font-weight " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <p DEFAULTBLOCKSTYLE><span style= \" font-weight:320; \" >Blah</span></p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextCharFormat fmt ;
fmt . setFontItalic ( true ) ;
cursor . insertText ( " Blah " , fmt ) ;
QTest : : newRow ( " font-italic " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <p DEFAULTBLOCKSTYLE><span style= \" font-style:italic; \" >Blah</span></p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextCharFormat fmt ;
fmt . setFontUnderline ( true ) ;
fmt . setFontOverline ( false ) ;
cursor . insertText ( " Blah " , fmt ) ;
QTest : : newRow ( " text-decoration-1 " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <p DEFAULTBLOCKSTYLE><span style= \" text-decoration: underline; \" >Blah</span></p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextCharFormat fmt ;
fmt . setForeground ( QColor ( " #00ff00 " ) ) ;
cursor . insertText ( " Blah " , fmt ) ;
QTest : : newRow ( " color " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <p DEFAULTBLOCKSTYLE><span style= \" color:#00ff00; \" >Blah</span></p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextCharFormat fmt ;
fmt . setForeground ( QColor ( 0 , 255 , 0 , 51 ) ) ;
cursor . insertText ( " Blah " , fmt ) ;
QTest : : newRow ( " color-rgba " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <p DEFAULTBLOCKSTYLE><span style= \" color:rgba(0,255,0,0.2); \" >Blah</span></p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextCharFormat fmt ;
fmt . setForeground ( QColor ( 0 , 255 , 0 , 0 ) ) ;
cursor . insertText ( " Blah " , fmt ) ;
QTest : : newRow ( " color-transparent " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <p DEFAULTBLOCKSTYLE><span style= \" color:transparent; \" >Blah</span></p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextCharFormat fmt ;
fmt . setBackground ( QColor ( " #00ff00 " ) ) ;
cursor . insertText ( " Blah " , fmt ) ;
QTest : : newRow ( " span-bgcolor " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <p DEFAULTBLOCKSTYLE><span style= \" background-color:#00ff00; \" >Blah</span></p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextCharFormat fmt ;
fmt . setBackground ( QColor ( 0 , 255 , 0 , 51 ) ) ;
cursor . insertText ( " Blah " , fmt ) ;
QTest : : newRow ( " span-bgcolor-rgba " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <p DEFAULTBLOCKSTYLE><span style= \" background-color:rgba(0,255,0,0.2); \" >Blah</span></p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextCharFormat fmt ;
fmt . setBackground ( QColor ( 0 , 255 , 0 , 0 ) ) ;
cursor . insertText ( " Blah " , fmt ) ;
QTest : : newRow ( " span-bgcolor-transparent " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <p DEFAULTBLOCKSTYLE><span style= \" background-color:transparent; \" >Blah</span></p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextCharFormat fmt ;
fmt . setVerticalAlignment ( QTextCharFormat : : AlignSubScript ) ;
cursor . insertText ( " Blah " , fmt ) ;
QTest : : newRow ( " valign-sub " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <p DEFAULTBLOCKSTYLE><span style= \" vertical-align:sub; \" >Blah</span></p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextCharFormat fmt ;
fmt . setVerticalAlignment ( QTextCharFormat : : AlignSuperScript ) ;
cursor . insertText ( " Blah " , fmt ) ;
QTest : : newRow ( " valign-super " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <p DEFAULTBLOCKSTYLE><span style= \" vertical-align:super; \" >Blah</span></p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextCharFormat fmt ;
fmt . setAnchor ( true ) ;
fmt . setAnchorNames ( { " blub " } ) ;
cursor . insertText ( " Blah " , fmt ) ;
QTest : : newRow ( " named anchor " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <p DEFAULTBLOCKSTYLE><a name= \" blub \" ></a>Blah</p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextCharFormat fmt ;
fmt . setAnchor ( true ) ;
fmt . setAnchorHref ( " http://www.kde.org/ " ) ;
cursor . insertText ( " Blah " , fmt ) ;
QTest : : newRow ( " href anchor " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <p DEFAULTBLOCKSTYLE><a href= \" http://www.kde.org/ \" >Blah</a></p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextCharFormat fmt ;
fmt . setAnchor ( true ) ;
fmt . setAnchorHref ( " http://www.kde.org/?a=1&b=2 " ) ;
cursor . insertText ( " Blah " , fmt ) ;
QTest : : newRow ( " href anchor with & " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <p DEFAULTBLOCKSTYLE><a href= \" http://www.kde.org/?a=1&b=2 \" >Blah</a></p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextCharFormat fmt ;
fmt . setAnchor ( true ) ;
fmt . setAnchorHref ( " http://www.kde.org/?a='&b= \" " ) ;
cursor . insertText ( " Blah " , fmt ) ;
QTest : : newRow ( " href anchor with ' and \" " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <p DEFAULTBLOCKSTYLE><a href= \" http://www.kde.org/?a='&b=" \" >Blah</a></p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
cursor . insertTable ( 2 , 2 ) ;
QTest : : newRow ( " simpletable " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <table border= \" 1 \" cellspacing= \" 2 \" > "
" \n <tr> \n <td></td> \n <td></td></tr> "
" \n <tr> \n <td></td> \n <td></td></tr> "
" </table> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextTable * table = cursor . insertTable ( 1 , 4 ) ;
table - > mergeCells ( 0 , 0 , 1 , 2 ) ;
table - > mergeCells ( 0 , 2 , 1 , 2 ) ;
QTest : : newRow ( " tablespans " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <table border= \" 1 \" cellspacing= \" 2 \" > "
" \n <tr> \n <td colspan= \" 2 \" ></td> \n <td colspan= \" 2 \" ></td></tr> "
" </table> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextTableFormat fmt ;
fmt . setBorder ( 1 ) ;
fmt . setCellSpacing ( 3 ) ;
fmt . setCellPadding ( 3 ) ;
fmt . setBackground ( QColor ( " #ff00ff " ) ) ;
fmt . setWidth ( QTextLength ( QTextLength : : PercentageLength , 50 ) ) ;
fmt . setAlignment ( Qt : : AlignHCenter ) ;
fmt . setPosition ( QTextFrameFormat : : FloatRight ) ;
cursor . insertTable ( 2 , 2 , fmt ) ;
QTest : : newRow ( " tableattrs " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <table border= \" 1 \" style= \" float: right; \" align= \" center \" width= \" 50% \" cellspacing= \" 3 \" cellpadding= \" 3 \" bgcolor= \" #ff00ff \" > "
" \n <tr> \n <td></td> \n <td></td></tr> "
" \n <tr> \n <td></td> \n <td></td></tr> "
" </table> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextTableFormat fmt ;
fmt . setBorder ( 1 ) ;
fmt . setCellSpacing ( 3 ) ;
fmt . setCellPadding ( 3 ) ;
fmt . setBackground ( QColor ( " #ff00ff " ) ) ;
fmt . setWidth ( QTextLength ( QTextLength : : PercentageLength , 50 ) ) ;
fmt . setAlignment ( Qt : : AlignHCenter ) ;
fmt . setPosition ( QTextFrameFormat : : FloatRight ) ;
fmt . setLeftMargin ( 25 ) ;
fmt . setBottomMargin ( 35 ) ;
cursor . insertTable ( 2 , 2 , fmt ) ;
QTest : : newRow ( " tableattrs2 " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <table border= \" 1 \" style= \" float: right; margin-top:0px; margin-bottom:35px; margin-left:25px; margin-right:0px; \" align= \" center \" width= \" 50% \" cellspacing= \" 3 \" cellpadding= \" 3 \" bgcolor= \" #ff00ff \" > "
" \n <tr> \n <td></td> \n <td></td></tr> "
" \n <tr> \n <td></td> \n <td></td></tr> "
" </table> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextTableFormat fmt ;
fmt . setHeaderRowCount ( 2 ) ;
cursor . insertTable ( 4 , 2 , fmt ) ;
QTest : : newRow ( " tableheader " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <table border= \" 1 \" cellspacing= \" 2 \" > "
" <thead> \n <tr> \n <td></td> \n <td></td></tr> "
" \n <tr> \n <td></td> \n <td></td></tr></thead> "
" \n <tr> \n <td></td> \n <td></td></tr> "
" \n <tr> \n <td></td> \n <td></td></tr> "
" </table> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextTable * table = cursor . insertTable ( 2 , 2 ) ;
QTextTable * subTable = table - > cellAt ( 0 , 1 ) . firstCursorPosition ( ) . insertTable ( 1 , 1 ) ;
subTable - > cellAt ( 0 , 0 ) . firstCursorPosition ( ) . insertText ( " Hey " ) ;
QTest : : newRow ( " nestedtable " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <table border= \" 1 \" cellspacing= \" 2 \" > "
" \n <tr> \n <td></td> \n <td> \n <table border= \" 1 \" cellspacing= \" 2 \" > \n <tr> \n <td> \n <p DEFAULTBLOCKSTYLE>Hey</p></td></tr></table></td></tr> "
" \n <tr> \n <td></td> \n <td></td></tr> "
" </table> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextTableFormat fmt ;
QList < QTextLength > widths ;
widths . append ( QTextLength ( ) ) ;
widths . append ( QTextLength ( QTextLength : : PercentageLength , 30 ) ) ;
widths . append ( QTextLength ( QTextLength : : FixedLength , 40 ) ) ;
fmt . setColumnWidthConstraints ( widths ) ;
cursor . insertTable ( 1 , 3 , fmt ) ;
QTest : : newRow ( " colwidths " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <table border= \" 1 \" cellspacing= \" 2 \" > "
" \n <tr> \n <td></td> \n <td width= \" 30% \" ></td> \n <td width= \" 40 \" ></td></tr> "
" </table> " ) ;
}
// ### rowspan/colspan tests, once texttable api for that is back again
//
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextTable * table = cursor . insertTable ( 1 , 1 ) ;
QTextCursor cellCurs = table - > cellAt ( 0 , 0 ) . firstCursorPosition ( ) ;
QTextCharFormat fmt ;
fmt . setBackground ( QColor ( " #ffffff " ) ) ;
cellCurs . mergeBlockCharFormat ( fmt ) ;
QTest : : newRow ( " cellproperties " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <table border= \" 1 \" cellspacing= \" 2 \" > "
" \n <tr> \n <td bgcolor= \" #ffffff \" ></td></tr> "
" </table> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
// ### fixme: use programmatic api as soon as we can create floats through it
const char html [ ] = " <html><body>Blah<img src= \" image.png \" width= \" 10 \" height= \" 20 \" style= \" float: right; \" />Blubb</body></html> " ;
QTest : : newRow ( " image " ) < < QTextDocumentFragment : : fromHtml ( QString : : fromLatin1 ( html ) )
< < QString ( " <p style= \" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; \" >Blah<img src= \" image.png \" width= \" 10 \" height= \" 20 \" style= \" float: right; \" />Blubb</p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextImageFormat fmt ;
fmt . setName ( " foo " ) ;
fmt . setVerticalAlignment ( QTextCharFormat : : AlignMiddle ) ;
cursor . insertImage ( fmt ) ;
QTest : : newRow ( " image-align-middle " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <p DEFAULTBLOCKSTYLE><img src= \" foo \" style= \" vertical-align: middle; \" /></p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextImageFormat fmt ;
fmt . setName ( " foo " ) ;
fmt . setVerticalAlignment ( QTextCharFormat : : AlignTop ) ;
cursor . insertImage ( fmt ) ;
QTest : : newRow ( " image-align-top " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <p DEFAULTBLOCKSTYLE><img src= \" foo \" style= \" vertical-align: top; \" /></p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextImageFormat fmt ;
fmt . setName ( " foo " ) ;
cursor . insertImage ( fmt ) ;
cursor . insertImage ( fmt ) ;
QTest : : newRow ( " 2images " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <p DEFAULTBLOCKSTYLE><img src= \" foo \" /><img src= \" foo \" /></p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QString txt = QLatin1String ( " Blah " ) ;
txt + = QChar : : LineSeparator ;
txt + = QLatin1String ( " Bar " ) ;
cursor . insertText ( txt ) ;
QTest : : newRow ( " linebreaks " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <p DEFAULTBLOCKSTYLE>Blah<br />Bar</p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextBlockFormat fmt ;
fmt . setTopMargin ( 10 ) ;
fmt . setBottomMargin ( 20 ) ;
fmt . setLeftMargin ( 30 ) ;
fmt . setRightMargin ( 40 ) ;
cursor . insertBlock ( fmt ) ;
cursor . insertText ( " Blah " ) ;
QTest : : newRow ( " blockmargins " ) < < QTextDocumentFragment ( & doc )
< <
QString ( " EMPTYBLOCK " ) +
QString ( " <p style= \" margin-top:10px; margin-bottom:20px; margin-left:30px; margin-right:40px; -qt-block-indent:0; text-indent:0px; \" >Blah</p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextList * list = cursor . insertList ( QTextListFormat : : ListDisc ) ;
cursor . insertText ( " Blubb " ) ;
cursor . insertBlock ( ) ;
cursor . insertText ( " Blah " ) ;
QCOMPARE ( list - > count ( ) , 2 ) ;
QTest : : newRow ( " lists " ) < < QTextDocumentFragment ( & doc )
< <
QString ( " EMPTYBLOCK " ) +
QString ( " <ul style= \" margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1; \" > \n <li DEFAULTBLOCKSTYLE>Blubb</li> \n <li DEFAULTBLOCKSTYLE>Blah</li></ul> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextList * list = cursor . insertList ( QTextListFormat : : ListDisc ) ;
cursor . insertText ( " Blubb " ) ;
cursor . insertBlock ( ) ;
QTextCharFormat blockCharFmt ;
blockCharFmt . setForeground ( QColor ( " #0000ff " ) ) ;
cursor . mergeBlockCharFormat ( blockCharFmt ) ;
QTextCharFormat fmt ;
fmt . setForeground ( QColor ( " #ff0000 " ) ) ;
cursor . insertText ( " Blah " , fmt ) ;
QCOMPARE ( list - > count ( ) , 2 ) ;
QTest : : newRow ( " charfmt-for-list-item " ) < < QTextDocumentFragment ( & doc )
< <
QString ( " EMPTYBLOCK " ) +
QString ( " <ul style= \" margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1; \" > \n <li DEFAULTBLOCKSTYLE>Blubb</li> \n <li style= \" color:#0000ff; \" DEFAULTBLOCKSTYLE><span style= \" color:#ff0000; \" >Blah</span></li></ul> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextBlockFormat fmt ;
fmt . setIndent ( 3 ) ;
fmt . setTextIndent ( 30 ) ;
cursor . insertBlock ( fmt ) ;
cursor . insertText ( " Test " ) ;
QTest : : newRow ( " block-indent " ) < < QTextDocumentFragment ( & doc )
< <
QString ( " EMPTYBLOCK " ) +
QString ( " <p style= \" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:3; text-indent:30px; \" >Test</p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextListFormat fmt ;
fmt . setStyle ( QTextListFormat : : ListDisc ) ;
fmt . setIndent ( 4 ) ;
cursor . insertList ( fmt ) ;
cursor . insertText ( " Blah " ) ;
QTest : : newRow ( " list-indent " ) < < QTextDocumentFragment ( & doc )
< <
QString ( " EMPTYBLOCK " ) +
QString ( " <ul style= \" margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 4; \" > \n <li DEFAULTBLOCKSTYLE>Blah</li></ul> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
cursor . insertBlock ( ) ;
QTest : : newRow ( " emptyblock " ) < < QTextDocumentFragment ( & doc )
// after insertBlock() we /do/ have two blocks in the document, so also expect
// these in the html output
< < QString ( " EMPTYBLOCK " ) + QString ( " EMPTYBLOCK " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
// if you press enter twice in an empty textedit and then insert 'Test'
// you actually get three visible paragraphs, two empty leading ones and
// a third with the actual text. the corresponding html representation
// therefore should also contain three paragraphs.
cursor . insertBlock ( ) ;
QTextCharFormat fmt ;
fmt . setForeground ( QColor ( " #00ff00 " ) ) ;
fmt . setProperty ( QTextFormat : : FontSizeIncrement , 1 ) ;
cursor . mergeBlockCharFormat ( fmt ) ;
fmt . setProperty ( QTextFormat : : FontSizeIncrement , 2 ) ;
cursor . insertText ( " Test " , fmt ) ;
QTest : : newRow ( " blockcharfmt " ) < < QTextDocumentFragment ( & doc )
< < QString ( " EMPTYBLOCK<p style= \" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; \" ><span style= \" font-size:x-large; color:#00ff00; \" >Test</span></p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextCharFormat fmt ;
fmt . setForeground ( QColor ( " #00ff00 " ) ) ;
cursor . setBlockCharFormat ( fmt ) ;
fmt . setForeground ( QColor ( " #0000ff " ) ) ;
cursor . insertText ( " Test " , fmt ) ;
QTest : : newRow ( " blockcharfmt2 " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <p style= \" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; \" ><span style= \" color:#0000ff; \" >Test</span></p> " ) ;
}
{
QTest : : newRow ( " horizontal-ruler " ) < < QTextDocumentFragment : : fromHtml ( " <hr /> " )
< <
QString ( " EMPTYBLOCK " ) +
QString ( " <hr /> " ) ;
}
{
QTest : : newRow ( " horizontal-ruler-with-width " ) < < QTextDocumentFragment : : fromHtml ( " <hr width= \" 50% \" /> " )
< <
QString ( " EMPTYBLOCK " ) +
QString ( " <hr width= \" 50% \" /> " ) ;
}
{
QTest : : newRow ( " horizontal-ruler-with-color " ) < < QTextDocumentFragment : : fromHtml ( " <hr style= \" background-color:green; \" /> " )
< <
QString ( " EMPTYBLOCK " ) +
QString ( " <hr style= \" background-color:#008000; \" /> " ) ;
}
{
QTest : : newRow ( " horizontal-ruler-with-width-and-color " ) < < QTextDocumentFragment : : fromHtml ( " <hr width= \" 50% \" style= \" background-color:green; \" /> " )
< <
QString ( " EMPTYBLOCK " ) +
QString ( " <hr width= \" 50% \" style= \" background-color:#008000; \" /> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextFrame * mainFrame = cursor . currentFrame ( ) ;
QTextFrameFormat ffmt ;
ffmt . setBorder ( 1 ) ;
ffmt . setPosition ( QTextFrameFormat : : FloatRight ) ;
ffmt . setMargin ( 2 ) ;
ffmt . setWidth ( 100 ) ;
ffmt . setHeight ( 50 ) ;
ffmt . setBackground ( QColor ( " #00ff00 " ) ) ;
cursor . insertFrame ( ffmt ) ;
cursor . insertText ( " Hello World " ) ;
cursor = mainFrame - > lastCursorPosition ( ) ;
QTest : : newRow ( " frame " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <table border= \" 1 \" style= \" -qt-table-type: frame; float: right; margin-top:2px; margin-bottom:2px; margin-left:2px; margin-right:2px; \" width= \" 100 \" height= \" 50 \" bgcolor= \" #00ff00 \" > \n <tr> \n <td style= \" border: none; \" > \n <p DEFAULTBLOCKSTYLE>Hello World</p></td></tr></table> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextCharFormat fmt ;
fmt . setForeground ( QColor ( " #00ff00 " ) ) ;
// fmt.setBackground(QColor("#0000ff"));
cursor . setBlockCharFormat ( fmt ) ;
fmt . setForeground ( QBrush ( ) ) ;
// fmt.setBackground(QBrush());
cursor . insertText ( " Test " , fmt ) ;
// QTest::newRow("nostylebrush") << QTextDocumentFragment(&doc) << QString("<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; color:#00ff00; -qt-blockcharfmt-background-color:#0000ff;\">Test</p>");
QTest : : newRow ( " nostylebrush " ) < < QTextDocumentFragment ( & doc ) < < QString ( " <p style= \" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; \" >Test</p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextTable * table = cursor . insertTable ( 2 , 2 ) ;
table - > mergeCells ( 0 , 0 , 1 , 2 ) ;
QTextTableFormat fmt = table - > format ( ) ;
QList < QTextLength > widths ;
widths . append ( QTextLength ( QTextLength : : FixedLength , 20 ) ) ;
widths . append ( QTextLength ( QTextLength : : FixedLength , 40 ) ) ;
fmt . setColumnWidthConstraints ( widths ) ;
table - > setFormat ( fmt ) ;
QTest : : newRow ( " mergedtablecolwidths " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <table border= \" 1 \" cellspacing= \" 2 \" > "
" \n <tr> \n <td colspan= \" 2 \" ></td></tr> "
" \n <tr> \n <td width= \" 20 \" ></td> \n <td width= \" 40 \" ></td></tr> "
" </table> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextCharFormat fmt ;
cursor . insertText ( " Blah \n Green yellow green " ) ;
cursor . setPosition ( 0 ) ;
cursor . setPosition ( 23 , QTextCursor : : KeepAnchor ) ;
fmt . setBackground ( Qt : : green ) ;
cursor . mergeCharFormat ( fmt ) ;
cursor . clearSelection ( ) ;
cursor . setPosition ( 11 ) ;
cursor . setPosition ( 17 , QTextCursor : : KeepAnchor ) ;
fmt . setBackground ( Qt : : yellow ) ;
cursor . mergeCharFormat ( fmt ) ;
cursor . clearSelection ( ) ;
QTest : : newRow ( " multiparagraph-bgcolor " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <p DEFAULTBLOCKSTYLE><span style= \" background-color:#00ff00; \" >Blah</span></p> \n "
" <p DEFAULTBLOCKSTYLE><span style= \" background-color:#00ff00; \" >Green </span> "
" <span style= \" background-color:#ffff00; \" >yellow</span> "
" <span style= \" background-color:#00ff00; \" > green</span></p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextBlockFormat fmt ;
fmt . setBackground ( QColor ( " #0000ff " ) ) ;
cursor . insertBlock ( fmt ) ;
QTextCharFormat charfmt ;
charfmt . setBackground ( QColor ( " #0000ff " ) ) ;
cursor . insertText ( " Blah " , charfmt ) ;
QTest : : newRow ( " nospan-bgcolor " ) < < QTextDocumentFragment ( & doc )
< < QString ( " EMPTYBLOCK " ) +
QString ( " <p OPENDEFAULTBLOCKSTYLE background-color:#0000ff; \" ><span style= \" background-color:#0000ff; \" >Blah</span></p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextTable * table = cursor . insertTable ( 2 , 2 ) ;
QTextCharFormat fmt = table - > cellAt ( 0 , 0 ) . format ( ) ;
fmt . setVerticalAlignment ( QTextCharFormat : : AlignMiddle ) ;
table - > cellAt ( 0 , 0 ) . setFormat ( fmt ) ;
fmt = table - > cellAt ( 0 , 1 ) . format ( ) ;
fmt . setVerticalAlignment ( QTextCharFormat : : AlignTop ) ;
table - > cellAt ( 0 , 1 ) . setFormat ( fmt ) ;
fmt = table - > cellAt ( 1 , 0 ) . format ( ) ;
fmt . setVerticalAlignment ( QTextCharFormat : : AlignBottom ) ;
table - > cellAt ( 1 , 0 ) . setFormat ( fmt ) ;
table - > cellAt ( 0 , 0 ) . firstCursorPosition ( ) . insertText ( " Blah " ) ;
QTest : : newRow ( " table-vertical-alignment " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <table border= \" 1 \" cellspacing= \" 2 \" > "
" \n <tr> \n <td style= \" vertical-align:middle; \" > \n "
" <p DEFAULTBLOCKSTYLE>Blah</p></td> "
" \n <td style= \" vertical-align:top; \" ></td></tr> "
" \n <tr> \n <td style= \" vertical-align:bottom; \" ></td> "
" \n <td></td></tr> "
" </table> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextTable * table = cursor . insertTable ( 2 , 2 ) ;
QTextTableCellFormat fmt = table - > cellAt ( 0 , 0 ) . format ( ) . toTableCellFormat ( ) ;
fmt . setLeftPadding ( 1 ) ;
table - > cellAt ( 0 , 0 ) . setFormat ( fmt ) ;
fmt = table - > cellAt ( 0 , 1 ) . format ( ) . toTableCellFormat ( ) ;
fmt . setRightPadding ( 1 ) ;
table - > cellAt ( 0 , 1 ) . setFormat ( fmt ) ;
fmt = table - > cellAt ( 1 , 0 ) . format ( ) . toTableCellFormat ( ) ;
fmt . setTopPadding ( 1 ) ;
table - > cellAt ( 1 , 0 ) . setFormat ( fmt ) ;
fmt = table - > cellAt ( 1 , 1 ) . format ( ) . toTableCellFormat ( ) ;
fmt . setBottomPadding ( 1 ) ;
table - > cellAt ( 1 , 1 ) . setFormat ( fmt ) ;
table - > cellAt ( 0 , 0 ) . firstCursorPosition ( ) . insertText ( " Blah " ) ;
QTest : : newRow ( " table-cell-paddings " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <table border= \" 1 \" cellspacing= \" 2 \" > "
" \n <tr> \n <td style= \" padding-left:1; \" > \n "
" <p DEFAULTBLOCKSTYLE>Blah</p></td> "
" \n <td style= \" padding-right:1; \" ></td></tr> "
" \n <tr> \n <td style= \" padding-top:1; \" ></td> "
" \n <td style= \" padding-bottom:1; \" ></td></tr> "
" </table> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextTableFormat fmt ;
fmt . setBorderBrush ( QColor ( " #0000ff " ) ) ;
fmt . setBorderStyle ( QTextFrameFormat : : BorderStyle_Solid ) ;
cursor . insertTable ( 2 , 2 , fmt ) ;
QTest : : newRow ( " tableborder " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <table border= \" 1 \" style= \" border-color:#0000ff; border-style:solid; \" cellspacing= \" 2 \" > "
" \n <tr> \n <td></td> \n <td></td></tr> "
" \n <tr> \n <td></td> \n <td></td></tr> "
" </table> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
cursor . insertBlock ( ) ;
cursor . insertText ( " Foo " ) ;
cursor . block ( ) . setUserState ( 42 ) ;
QTest : : newRow ( " userstate " ) < < QTextDocumentFragment ( & doc )
< < QString ( " EMPTYBLOCK " ) +
QString ( " <p OPENDEFAULTBLOCKSTYLE -qt-user-state:42; \" >Foo</p> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextBlockFormat blockFmt ;
blockFmt . setPageBreakPolicy ( QTextFormat : : PageBreak_AlwaysBefore ) ;
cursor . insertBlock ( blockFmt ) ;
cursor . insertText ( " Foo " ) ;
blockFmt . setPageBreakPolicy ( QTextFormat : : PageBreak_AlwaysBefore | QTextFormat : : PageBreak_AlwaysAfter ) ;
cursor . insertBlock ( blockFmt ) ;
cursor . insertText ( " Bar " ) ;
QTextTableFormat tableFmt ;
tableFmt . setPageBreakPolicy ( QTextFormat : : PageBreak_AlwaysAfter ) ;
cursor . insertTable ( 1 , 1 , tableFmt ) ;
QTest : : newRow ( " pagebreak " ) < < QTextDocumentFragment ( & doc )
< < QString ( " EMPTYBLOCK " ) +
QString ( " <p OPENDEFAULTBLOCKSTYLE page-break-before:always; \" >Foo</p> "
" \n <p OPENDEFAULTBLOCKSTYLE page-break-before:always; page-break-after:always; \" >Bar</p> "
" \n <table border= \" 1 \" style= \" page-break-after:always; \" cellspacing= \" 2 \" > \n <tr> \n <td></td></tr></table> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextListFormat listFmt ;
listFmt . setStyle ( QTextListFormat : : ListDisc ) ;
cursor . insertList ( listFmt ) ;
cursor . insertText ( " Blah " ) ;
QTest : : newRow ( " list-ul-margin " ) < < QTextDocumentFragment ( & doc )
< < QString ( " EMPTYBLOCK " ) +
QString ( " <ul style= \" margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1; \" > \n <li DEFAULTBLOCKSTYLE>Blah</li></ul> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
const QString listHtml = " <ul><li>item-1</li><li>item-2<ul><li>item-2.1</li><li>item-2.2 "
" <ul><li>item-2.2.1</li></ul></li><li>item-2.3<ul><li>item-2.3.1 "
" </li></ul></li></ul></li><li>item-3</li></ul> " ;
cursor . insertHtml ( listHtml ) ;
QTest : : newRow ( " nested-lists-one " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <ul DEFAULTULSTYLE 1; \" > \n <li style= \" margin-top:12px; margin-bottom:0px; "
" margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; \" > "
" item-1</li> \n <li DEFAULTBLOCKSTYLE>item-2 \n <ul DEFAULTULSTYLE 2; \" > \n <li "
" DEFAULTBLOCKSTYLE>item-2.1</li> \n <li DEFAULTBLOCKSTYLE>item-2.2 \n <ul "
" DEFAULTULSTYLE 3; \" > \n <li DEFAULTBLOCKSTYLE>item-2.2.1</li></ul></li> \n "
" <li DEFAULTBLOCKSTYLE>item-2.3 \n <ul DEFAULTULSTYLE 3; \" > \n <li DEFAULTBLOCKSTYLE> "
" item-2.3.1</li></ul></li></ul></li> \n <li DEFAULTLASTLISTYLE>item-3</li></ul> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
const QString listHtml = " <ul><li>item-1</li><li>item-2<ul><li>item-2.1</li></ul></li></ul> " ;
cursor . insertHtml ( listHtml ) ;
QTest : : newRow ( " nested-lists-two " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <ul DEFAULTULSTYLE 1; \" > \n <li style= \" margin-top:12px; margin-bottom:0px; "
" margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; \" > "
" item-1</li> \n <li DEFAULTLASTLISTYLE>item-2 \n <ul DEFAULTULSTYLE 2; \" > \n <li "
" DEFAULTBLOCKSTYLE>item-2.1</li></ul></li></ul> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
const QString listHtml = " <ul><li>item-1</li><li>item-2<ul><li>item-2.1</li><li>item-2.2 "
" </li></ul></li></ul> " ;
cursor . insertHtml ( listHtml ) ;
QTest : : newRow ( " nested-lists-three " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <ul DEFAULTULSTYLE 1; \" > \n <li style= \" margin-top:12px; margin-bottom:0px; "
" margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; \" > "
" item-1</li> \n <li DEFAULTLASTLISTYLE>item-2 \n <ul DEFAULTULSTYLE 2; \" > \n <li "
" DEFAULTBLOCKSTYLE>item-2.1</li> \n <li DEFAULTBLOCKSTYLE>item-2.2</li></ul> "
" </li></ul> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
const QString listHtml = " <ul><li>item-1.1</li><li>item-1.2<li></ul> "
" <ul><li>item-2.1</li></ul> " ;
cursor . insertHtml ( listHtml ) ;
QTest : : newRow ( " not-nested-list " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <ul DEFAULTULSTYLE 1; \" > \n <li style= \" margin-top:12px; margin-bottom:0px; "
" margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; \" > "
" item-1.1</li> \n <li DEFAULTBLOCKSTYLE>item-1.2</li></ul> \n <ul DEFAULTULSTYLE 1; \" > \n "
" <li style= \" margin-top:12px; margin-bottom:12px; margin-left:0px; "
" margin-right:0px; -qt-block-indent:0; text-indent:0px; \" >item-2.1</li></ul> " ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
const QString listHtml = " <ul><li>bullet</li><li class= \" unchecked \" >unchecked item</li><li class= \" checked \" >checked item</li></ul> " ;
cursor . insertHtml ( listHtml ) ;
QTest : : newRow ( " list with and without checkboxes " ) < < QTextDocumentFragment ( & doc )
< < QString ( " <ul style= \" margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1; \" > \n "
" <li style= \" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; \" >bullet</li> \n "
" <li class= \" unchecked \" style= \" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; \" >unchecked item</li> \n "
" <li class= \" checked \" style= \" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; \" >checked item</li></ul> " ) ;
}
2023-11-02 05:23:55 +08:00
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextListFormat fmt ;
fmt . setStyle ( QTextListFormat : : ListDecimal ) ;
fmt . setStart ( 4 ) ;
cursor . insertList ( fmt ) ;
cursor . insertText ( " Blah " ) ;
cursor . insertBlock ( ) ;
cursor . insertText ( " Bleh " ) ;
QTest : : newRow ( " ordered list with start " ) < < QTextDocumentFragment ( & doc )
< < QString ( " EMPTYBLOCK " ) +
QString ( " <ol start= \" 4 \" style= \" margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1; \" > \n <li style= \" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; \" >Blah</li> \n <li style= \" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; \" >Bleh</li></ol> " ) ;
}
2023-10-30 06:33:08 +08:00
}
void tst_QTextDocument : : toHtml ( )
{
QFETCH ( QTextDocumentFragment , input ) ;
QFETCH ( QString , expectedOutput ) ;
cursor . insertFragment ( input ) ;
expectedOutput . prepend ( htmlHead ) ;
expectedOutput . replace ( " OPENDEFAULTBLOCKSTYLE " , " style= \" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; " ) ;
expectedOutput . replace ( " DEFAULTBLOCKSTYLE " , " style= \" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; \" " ) ;
expectedOutput . replace ( " EMPTYBLOCK " , " <p style= \" -qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; \" ><br /></p> \n " ) ;
expectedOutput . replace ( " DEFAULTULSTYLE " , " style= \" margin-top: 0px; margin-bottom: 0px; "
" margin-left: 0px; margin-right: 0px; -qt-list-indent: " ) ;
expectedOutput . replace ( " DEFAULTLASTLISTYLE " , " style= \" margin-top:0px; margin-bottom:12px; "
" margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; \" " ) ;
if ( expectedOutput . endsWith ( QLatin1Char ( ' \n ' ) ) )
expectedOutput . chop ( 1 ) ;
expectedOutput . append ( htmlTail ) ;
QString output = doc - > toHtml ( ) ;
writeActualAndExpected ( QTest : : currentDataTag ( ) , output , expectedOutput ) ;
QCOMPARE ( output , expectedOutput ) ;
QDomDocument document ;
QEXPECT_FAIL ( " charfmt-for-list-item " ,
" The attribute \" style \" is redefined in the generated HTML, which is not valid "
" according to XML standard. The new QDomDocument implementation follows the XML "
" standard. " , Continue ) ;
QVERIFY2 ( document . setContent ( output ) , " Output was not valid XML " ) ;
}
void tst_QTextDocument : : toHtml2 ( )
{
QTextDocument doc ;
doc . setHtml ( " <p>text <img src= \" \" > text</p> " ) ; // 4 spaces before the second 'text'
QTextBlock block = doc . firstBlock ( ) ;
QTextBlock : : Iterator iter = block . begin ( ) ;
QTextFragment f = iter . fragment ( ) ;
QVERIFY ( f . isValid ( ) ) ;
QCOMPARE ( f . position ( ) , 0 ) ;
QCOMPARE ( f . length ( ) , 5 ) ;
//qDebug() << block.text().mid(f.position(), f.length());
iter + + ;
f = iter . fragment ( ) ;
QVERIFY ( f . isValid ( ) ) ;
QCOMPARE ( f . position ( ) , 5 ) ;
QCOMPARE ( f . length ( ) , 1 ) ;
//qDebug() << block.text().mid(f.position(), f.length());
iter + + ;
f = iter . fragment ( ) ;
//qDebug() << block.text().mid(f.position(), f.length());
QVERIFY ( f . isValid ( ) ) ;
QCOMPARE ( f . position ( ) , 6 ) ;
QCOMPARE ( f . length ( ) , 5 ) ; // 1 space should be preserved.
QCOMPARE ( block . text ( ) . mid ( f . position ( ) , f . length ( ) ) , QString ( " text " ) ) ;
doc . setHtml ( " <table><tr><td> foo</td></tr></table> text " ) ; // 4 spaces before the second 'text'
block = doc . firstBlock ( ) . next ( ) ;
//qDebug() << block.text();
QCOMPARE ( block . text ( ) , QString ( " foo " ) ) ;
block = block . next ( ) ;
//qDebug() << block.text();
QCOMPARE ( block . text ( ) , QString ( " text " ) ) ;
}
void tst_QTextDocument : : setFragmentMarkersInHtmlExport ( )
{
{
CREATE_DOC_AND_CURSOR ( ) ;
cursor . insertText ( " Leadin " ) ;
const int startPos = cursor . position ( ) ;
cursor . insertText ( " Test " ) ;
QTextCharFormat fmt ;
fmt . setForeground ( QColor ( " #00ff00 " ) ) ;
cursor . insertText ( " Blah " , fmt ) ;
const int endPos = cursor . position ( ) ;
cursor . insertText ( " Leadout " , QTextCharFormat ( ) ) ;
cursor . setPosition ( startPos ) ;
cursor . setPosition ( endPos , QTextCursor : : KeepAnchor ) ;
QTextDocumentFragment fragment ( cursor ) ;
QString expected = htmlHead ;
expected . replace ( QRegularExpression ( " <body.*> " ) , QString ( " <body> " ) ) ;
expected + = QString ( " <p style= \" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; \" ><!--StartFragment-->Test<span style= \" color:#00ff00; \" >Blah</span><!--EndFragment--></p> " ) + htmlTail ;
QCOMPARE ( fragment . toHtml ( ) , expected ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
cursor . insertText ( " Leadin " ) ;
const int startPos = cursor . position ( ) ;
cursor . insertText ( " Test " ) ;
const int endPos = cursor . position ( ) ;
cursor . insertText ( " Leadout " , QTextCharFormat ( ) ) ;
cursor . setPosition ( startPos ) ;
cursor . setPosition ( endPos , QTextCursor : : KeepAnchor ) ;
QTextDocumentFragment fragment ( cursor ) ;
QString expected = htmlHead ;
expected . replace ( QRegularExpression ( " <body.*> " ) , QString ( " <body> " ) ) ;
expected + = QString ( " <p style= \" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; \" ><!--StartFragment-->Test<!--EndFragment--></p> " ) + htmlTail ;
QCOMPARE ( fragment . toHtml ( ) , expected ) ;
}
}
void tst_QTextDocument : : setMediaRule ( )
{
{
CREATE_DOC_AND_CURSOR ( ) ;
doc . setDefaultStyleSheet ( " @media screen { p { background:#000000 } } @media print { p { background:#ffffff } } " ) ;
doc . setHtml ( " <p>Hello World</p> " ) ;
QString expected = htmlHead ;
expected + = QString ( " <p style= \" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#000000; \" ><span style= \" background-color:#000000; \" >Hello World</span></p> " ) + htmlTail ;
QCOMPARE ( doc . toHtml ( ) , expected ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
doc . setDefaultStyleSheet ( " @media screen { p { background:#000000 } } @media print { p { background:#ffffff } } " ) ;
doc . setMetaInformation ( QTextDocument : : CssMedia , " screen " ) ;
doc . setHtml ( " <p>Hello World</p> " ) ;
QString expected = htmlHead ;
expected + = QString ( " <p style= \" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#000000; \" ><span style= \" background-color:#000000; \" >Hello World</span></p> " ) + htmlTail ;
QCOMPARE ( doc . toHtml ( ) , expected ) ;
}
{
CREATE_DOC_AND_CURSOR ( ) ;
doc . setDefaultStyleSheet ( " @media screen { p { background:#000000 } } @media print { p { background:#ffffff } } " ) ;
doc . setMetaInformation ( QTextDocument : : CssMedia , " print " ) ;
doc . setHtml ( " <p>Hello World</p> " ) ;
QString expected = htmlHead ;
expected + = QString ( " <p style= \" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#ffffff; \" ><span style= \" background-color:#ffffff; \" >Hello World</span></p> " ) + htmlTail ;
QCOMPARE ( doc . toHtml ( ) , expected ) ;
}
}
void tst_QTextDocument : : toHtmlBodyBgColor ( )
{
CREATE_DOC_AND_CURSOR ( ) ;
cursor . insertText ( " Blah " ) ;
QTextFrameFormat fmt = doc . rootFrame ( ) - > frameFormat ( ) ;
fmt . setBackground ( QColor ( " #0000ff " ) ) ;
doc . rootFrame ( ) - > setFrameFormat ( fmt ) ;
QString expectedHtml = htmlHead ;
expectedHtml . insert ( htmlHead . size ( ) - 2 , " bgcolor= \" #0000ff \" " ) ;
expectedHtml + = " <p style= \" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; \" >Blah</p> "
+ htmlTail ;
writeActualAndExpected ( QTest : : currentDataTag ( ) , doc . toHtml ( ) , expectedHtml ) ;
QCOMPARE ( doc . toHtml ( ) , expectedHtml ) ;
}
void tst_QTextDocument : : toHtmlBodyBgColorRgba ( )
{
CREATE_DOC_AND_CURSOR ( ) ;
cursor . insertText ( " Blah " ) ;
QTextFrameFormat fmt = doc . rootFrame ( ) - > frameFormat ( ) ;
fmt . setBackground ( QColor ( 255 , 0 , 0 , 51 ) ) ;
doc . rootFrame ( ) - > setFrameFormat ( fmt ) ;
QString expectedHtml = htmlHead ;
expectedHtml . insert ( htmlHead . size ( ) - 2 , " bgcolor= \" rgba(255,0,0,0.2) \" " ) ;
expectedHtml + = " <p style= \" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; \" >Blah</p> "
+ htmlTail ;
writeActualAndExpected ( QTest : : currentDataTag ( ) , doc . toHtml ( ) , expectedHtml ) ;
QCOMPARE ( doc . toHtml ( ) , expectedHtml ) ;
}
void tst_QTextDocument : : toHtmlBodyBgColorTransparent ( )
{
CREATE_DOC_AND_CURSOR ( ) ;
cursor . insertText ( " Blah " ) ;
QTextFrameFormat fmt = doc . rootFrame ( ) - > frameFormat ( ) ;
fmt . setBackground ( QColor ( 255 , 0 , 0 , 0 ) ) ;
doc . rootFrame ( ) - > setFrameFormat ( fmt ) ;
QString expectedHtml = htmlHead ;
expectedHtml . insert ( htmlHead . size ( ) - 2 , " bgcolor= \" transparent \" " ) ;
expectedHtml + = " <p style= \" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; \" >Blah</p> "
+ htmlTail ;
writeActualAndExpected ( QTest : : currentDataTag ( ) , doc . toHtml ( ) , expectedHtml ) ;
QCOMPARE ( doc . toHtml ( ) , expectedHtml ) ;
}
void tst_QTextDocument : : toHtmlRootFrameProperties ( )
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextFrameFormat fmt = doc . rootFrame ( ) - > frameFormat ( ) ;
fmt . setTopMargin ( 10 ) ;
fmt . setLeftMargin ( 10 ) ;
fmt . setBorder ( 2 ) ;
doc . rootFrame ( ) - > setFrameFormat ( fmt ) ;
cursor . insertText ( " Blah " ) ;
QString expectedOutput ( " <table border= \" 2 \" style= \" -qt-table-type: root; margin-top:10px; "
" margin-bottom:4px; margin-left:10px; margin-right:4px; \" > \n "
" <tr> \n <td style= \" border: none; \" > \n "
" <p DEFAULTBLOCKSTYLE>Blah</p></td></tr></table> " ) ;
expectedOutput . prepend ( htmlHead ) ;
expectedOutput . replace ( " DEFAULTBLOCKSTYLE " , " style= \" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; \" " ) ;
expectedOutput . append ( htmlTail ) ;
writeActualAndExpected ( QTest : : currentTestFunction ( ) , doc . toHtml ( ) , expectedOutput ) ;
QCOMPARE ( doc . toHtml ( ) , expectedOutput ) ;
}
void tst_QTextDocument : : toHtmlLineHeightProperties ( )
{
CREATE_DOC_AND_CURSOR ( ) ;
QTextBlock block = doc . firstBlock ( ) ;
QTextBlockFormat blockFormat = block . blockFormat ( ) ;
blockFormat . setLineHeight ( 200 , QTextBlockFormat : : ProportionalHeight ) ;
cursor . setBlockFormat ( blockFormat ) ;
cursor . insertText ( " Blah " ) ;
QString expectedOutput ( " <p DEFAULTBLOCKSTYLE line-height:200%; \" >Blah</p> " ) ;
expectedOutput . prepend ( htmlHead ) ;
expectedOutput . replace ( " DEFAULTBLOCKSTYLE " , " style= \" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; " ) ;
expectedOutput . append ( htmlTail ) ;
QCOMPARE ( doc . toHtml ( ) , expectedOutput ) ;
}
void tst_QTextDocument : : toHtmlDefaultFontSpacingProperties ( )
{
CREATE_DOC_AND_CURSOR ( ) ;
cursor . insertText ( " Blah " ) ;
QFont fnt = doc . defaultFont ( ) ;
fnt . setLetterSpacing ( QFont : : AbsoluteSpacing , 13 ) ;
fnt . setWordSpacing ( 15 ) ;
doc . setDefaultFont ( fnt ) ;
QString expectedOutput = htmlHead ;
expectedOutput . insert ( htmlHead . size ( ) - 3 , " letter-spacing:13px; word-spacing:15px; " ) ;
expectedOutput + =
" <p style= \" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; \" >Blah</p> "
+ htmlTail ;
writeActualAndExpected ( QTest : : currentTestFunction ( ) , doc . toHtml ( ) , expectedOutput ) ;
QCOMPARE ( doc . toHtml ( ) , expectedOutput ) ;
}
void tst_QTextDocument : : toHtmlTextDecorationUnderline ( )
{
CREATE_DOC_AND_CURSOR ( ) ;
cursor . insertText ( " Some text " ) ;
QFont fnt = doc . defaultFont ( ) ;
fnt . setUnderline ( true ) ;
doc . setDefaultFont ( fnt ) ;
QString expectedOutput = htmlHead ;
expectedOutput . insert ( htmlHead . size ( ) - 3 , " text-decoration: underline; " ) ;
expectedOutput + =
" <p style= \" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; \" >Some text</p> "
+ htmlTail ;
writeActualAndExpected ( " toHtmlTextDecorationUnderline1 " , doc . toHtml ( ) , expectedOutput ) ;
QCOMPARE ( doc . toHtml ( ) , expectedOutput ) ;
QTextCharFormat format ;
format . setFontUnderline ( false ) ;
cursor . select ( QTextCursor : : Document ) ;
cursor . mergeCharFormat ( format ) ;
expectedOutput = htmlHead ;
expectedOutput . insert ( htmlHead . size ( ) - 3 , " text-decoration: underline; " ) ;
expectedOutput + =
" <p style= \" margin-top:0px; margin-bottom:0px; margin-left:0px; "
" margin-right:0px; -qt-block-indent:0; text-indent:0px; \" > "
" <span style= \" text-decoration:none; \" >Some text</span></p> "
+ htmlTail ;
writeActualAndExpected ( " toHtmlTextDecorationUnderline2 " , doc . toHtml ( ) , expectedOutput ) ;
QCOMPARE ( doc . toHtml ( ) , expectedOutput ) ;
}
void tst_QTextDocument : : capitalizationHtmlInExport ( )
{
doc - > setPlainText ( " Test " ) ;
QRegularExpression re ( " .*span style= \" (.*) \ " >Test.* " ) ;
QCOMPARE ( re . captureCount ( ) , 1 ) ;
QVERIFY ( ! re . match ( doc - > toHtml ( ) ) . hasMatch ( ) ) ; // no span
QTextCursor cursor ( doc ) ;
cursor . setPosition ( 4 , QTextCursor : : KeepAnchor ) ;
QTextCharFormat cf ;
cf . setFontCapitalization ( QFont : : SmallCaps ) ;
cursor . mergeCharFormat ( cf ) ;
const QString smallcaps = doc - > toHtml ( ) ;
auto match = re . match ( doc - > toHtml ( ) ) ;
QVERIFY ( match . hasMatch ( ) ) ;
QCOMPARE ( match . captured ( 1 ) . trimmed ( ) , QString ( " font-variant:small-caps; " ) ) ;
cf . setFontCapitalization ( QFont : : AllUppercase ) ;
cursor . mergeCharFormat ( cf ) ;
const QString uppercase = doc - > toHtml ( ) ;
match = re . match ( doc - > toHtml ( ) ) ;
QVERIFY ( match . hasMatch ( ) ) ;
QCOMPARE ( match . captured ( 1 ) . trimmed ( ) , QString ( " text-transform:uppercase; " ) ) ;
cf . setFontCapitalization ( QFont : : AllLowercase ) ;
cursor . mergeCharFormat ( cf ) ;
const QString lowercase = doc - > toHtml ( ) ;
match = re . match ( doc - > toHtml ( ) ) ;
QVERIFY ( match . hasMatch ( ) ) ;
QCOMPARE ( match . captured ( 1 ) . trimmed ( ) , QString ( " text-transform:lowercase; " ) ) ;
doc - > setHtml ( smallcaps ) ;
cursor . setPosition ( 1 ) ;
QCOMPARE ( cursor . charFormat ( ) . fontCapitalization ( ) , QFont : : SmallCaps ) ;
doc - > setHtml ( uppercase ) ;
QCOMPARE ( cursor . charFormat ( ) . fontCapitalization ( ) , QFont : : AllUppercase ) ;
doc - > setHtml ( lowercase ) ;
QCOMPARE ( cursor . charFormat ( ) . fontCapitalization ( ) , QFont : : AllLowercase ) ;
}
void tst_QTextDocument : : wordspacingHtmlExport ( )
{
doc - > setPlainText ( " Test " ) ;
QRegularExpression re ( " .*span style= \" (.*) \ " >Test.* " ) ;
QCOMPARE ( re . captureCount ( ) , 1 ) ;
QVERIFY ( ! re . match ( doc - > toHtml ( ) ) . hasMatch ( ) ) ; // no span
QTextCursor cursor ( doc ) ;
cursor . setPosition ( 4 , QTextCursor : : KeepAnchor ) ;
QTextCharFormat cf ;
cf . setFontWordSpacing ( 4 ) ;
cursor . mergeCharFormat ( cf ) ;
auto match = re . match ( doc - > toHtml ( ) ) ;
QVERIFY ( match . hasMatch ( ) ) ;
QCOMPARE ( match . captured ( 1 ) . trimmed ( ) , QString ( " word-spacing:4px; " ) ) ;
cf . setFontWordSpacing ( - 8.5 ) ;
cursor . mergeCharFormat ( cf ) ;
match = re . match ( doc - > toHtml ( ) ) ;
QVERIFY ( match . hasMatch ( ) ) ;
QCOMPARE ( match . captured ( 1 ) . trimmed ( ) , QString ( " word-spacing:-8.5px; " ) ) ;
}
class CursorPosSignalSpy : public QObject
{
Q_OBJECT
public :
CursorPosSignalSpy ( QTextDocument * doc )
{
calls = 0 ;
connect ( doc , SIGNAL ( cursorPositionChanged ( QTextCursor ) ) ,
this , SLOT ( cursorPositionChanged ( QTextCursor ) ) ) ;
}
int calls ;
private slots :
void cursorPositionChanged ( const QTextCursor & )
{
+ + calls ;
}
} ;
void tst_QTextDocument : : cursorPositionChanged ( )
{
CursorPosSignalSpy spy ( doc ) ;
cursor . insertText ( " Test " ) ;
QCOMPARE ( spy . calls , 1 ) ;
spy . calls = 0 ;
QTextCursor unrelatedCursor ( doc ) ;
unrelatedCursor . insertText ( " Blah " ) ;
QCOMPARE ( spy . calls , 2 ) ;
spy . calls = 0 ;
cursor . insertText ( " Blah " ) ;
QCOMPARE ( spy . calls , 1 ) ;
spy . calls = 0 ;
cursor . movePosition ( QTextCursor : : PreviousCharacter ) ;
QCOMPARE ( spy . calls , 0 ) ;
}
void tst_QTextDocument : : cursorPositionChangedOnSetText ( )
{
CursorPosSignalSpy spy ( doc ) ;
// doc has one QTextCursor stored in the
// cursor member variable, thus the signal
// gets emitted once.
doc - > setPlainText ( " Foo \n Bar \n Baz \n Blub \n Blah " ) ;
QCOMPARE ( spy . calls , 1 ) ;
spy . calls = 0 ;
doc - > setHtml ( " <p>Foo<p>Bar<p>Baz<p>Blah " ) ;
QCOMPARE ( spy . calls , 1 ) ;
}
void tst_QTextDocument : : textFrameIterator ( )
{
cursor . insertTable ( 1 , 1 ) ;
int blockCount = 0 ;
int frameCount = 0 ;
for ( QTextFrame : : Iterator frameIt = doc - > rootFrame ( ) - > begin ( ) ;
! frameIt . atEnd ( ) ; + + frameIt ) {
if ( frameIt . currentFrame ( ) )
+ + frameCount ;
else if ( frameIt . currentBlock ( ) . isValid ( ) )
+ + blockCount ;
}
QEXPECT_FAIL ( " " , " This is currently worked around in the html export but needs fixing! " , Continue ) ;
QCOMPARE ( blockCount , 0 ) ;
QCOMPARE ( frameCount , 1 ) ;
}
class TestSyntaxHighlighter : public QObject
{
Q_OBJECT
public :
inline TestSyntaxHighlighter ( QTextDocument * doc ) : QObject ( doc ) , ok ( false ) { }
bool ok ;
private slots :
inline void markBlockDirty ( int from , int charsRemoved , int charsAdded )
{
Q_UNUSED ( charsRemoved ) ;
Q_UNUSED ( charsAdded ) ;
QTextDocument * doc = static_cast < QTextDocument * > ( parent ( ) ) ;
QTextBlock block = doc - > findBlock ( from ) ;
QTestDocumentLayout * lout = qobject_cast < QTestDocumentLayout * > ( doc - > documentLayout ( ) ) ;
lout - > called = false ;
doc - > markContentsDirty ( block . position ( ) , block . length ( ) ) ;
ok = ( lout - > called = = false ) ;
}
inline void modifyBlockAgain ( int from , int charsRemoved , int charsAdded )
{
Q_UNUSED ( charsRemoved ) ;
Q_UNUSED ( charsAdded ) ;
QTextDocument * doc = static_cast < QTextDocument * > ( parent ( ) ) ;
QTextBlock block = doc - > findBlock ( from ) ;
QTextCursor cursor ( block ) ;
QTestDocumentLayout * lout = qobject_cast < QTestDocumentLayout * > ( doc - > documentLayout ( ) ) ;
lout - > called = false ;
cursor . insertText ( " Foo " ) ;
ok = ( lout - > called = = true ) ;
}
} ;
void tst_QTextDocument : : markContentsDirty ( )
{
QTestDocumentLayout * lout = new QTestDocumentLayout ( doc ) ;
doc - > setDocumentLayout ( lout ) ;
TestSyntaxHighlighter * highlighter = new TestSyntaxHighlighter ( doc ) ;
connect ( doc , SIGNAL ( contentsChange ( int , int , int ) ) ,
highlighter , SLOT ( markBlockDirty ( int , int , int ) ) ) ;
highlighter - > ok = false ;
cursor . insertText ( " Some dummy text blah blah " ) ;
QVERIFY ( highlighter - > ok ) ;
disconnect ( doc , SIGNAL ( contentsChange ( int , int , int ) ) ,
highlighter , SLOT ( markBlockDirty ( int , int , int ) ) ) ;
connect ( doc , SIGNAL ( contentsChange ( int , int , int ) ) ,
highlighter , SLOT ( modifyBlockAgain ( int , int , int ) ) ) ;
highlighter - > ok = false ;
cursor . insertText ( " FooBar " ) ;
QVERIFY ( highlighter - > ok ) ;
lout - > called = false ;
doc - > markContentsDirty ( 1 , 4 ) ;
QVERIFY ( lout - > called ) ;
}
void tst_QTextDocument : : clonePreservesMetaInformation ( )
{
const QString title ( " Foobar " ) ;
const QString url ( " about:blank " ) ;
const QString media ( " print " ) ;
doc - > setHtml ( " <html><head><title> " + title + " </title></head><body>Hrm</body></html> " ) ;
doc - > setMetaInformation ( QTextDocument : : DocumentUrl , url ) ;
doc - > setMetaInformation ( QTextDocument : : CssMedia , media ) ;
QCOMPARE ( doc - > metaInformation ( QTextDocument : : DocumentTitle ) , title ) ;
QCOMPARE ( doc - > metaInformation ( QTextDocument : : DocumentUrl ) , url ) ;
QCOMPARE ( doc - > metaInformation ( QTextDocument : : CssMedia ) , media ) ;
QTextDocument * clone = doc - > clone ( ) ;
QCOMPARE ( clone - > metaInformation ( QTextDocument : : DocumentTitle ) , title ) ;
QCOMPARE ( clone - > metaInformation ( QTextDocument : : DocumentUrl ) , url ) ;
QCOMPARE ( clone - > metaInformation ( QTextDocument : : CssMedia ) , media ) ;
delete clone ;
}
void tst_QTextDocument : : clonePreservesPageSize ( )
{
QSizeF sz ( 100. , 100. ) ;
doc - > setPageSize ( sz ) ;
QTextDocument * clone = doc - > clone ( ) ;
QCOMPARE ( clone - > pageSize ( ) , sz ) ;
delete clone ;
}
void tst_QTextDocument : : clonePreservesPageBreakPolicies ( )
{
QTextTableFormat tableFmt ;
tableFmt . setPageBreakPolicy ( QTextFormat : : PageBreak_AlwaysAfter ) ;
QTextBlockFormat blockFmt ;
blockFmt . setPageBreakPolicy ( QTextFormat : : PageBreak_AlwaysBefore ) ;
QTextCursor cursor ( doc ) ;
cursor . setBlockFormat ( blockFmt ) ;
cursor . insertText ( " foo " ) ;
cursor . insertTable ( 2 , 2 , tableFmt ) ;
QTextDocument * clone = doc - > clone ( ) ;
QCOMPARE ( clone - > begin ( ) . blockFormat ( ) . pageBreakPolicy ( ) , QTextFormat : : PageBreak_AlwaysBefore ) ;
QVERIFY ( ! clone - > rootFrame ( ) - > childFrames ( ) . isEmpty ( ) ) ;
QCOMPARE ( clone - > rootFrame ( ) - > childFrames ( ) . first ( ) - > frameFormat ( ) . pageBreakPolicy ( ) , QTextFormat : : PageBreak_AlwaysAfter ) ;
delete clone ;
}
void tst_QTextDocument : : clonePreservesDefaultFont ( )
{
QFont f = doc - > defaultFont ( ) ;
QVERIFY ( f . pointSize ( ) ! = 100 ) ;
f . setPointSize ( 100 ) ;
doc - > setDefaultFont ( f ) ;
QTextDocument * clone = doc - > clone ( ) ;
QCOMPARE ( clone - > defaultFont ( ) , f ) ;
delete clone ;
}
void tst_QTextDocument : : clonePreservesResources ( )
{
QUrl testUrl ( " :/foobar " ) ;
QVariant testResource ( " hello world " ) ;
doc - > addResource ( QTextDocument : : ImageResource , testUrl , testResource ) ;
QTextDocument * clone = doc - > clone ( ) ;
QVERIFY ( clone - > resource ( QTextDocument : : ImageResource , testUrl ) = = testResource ) ;
delete clone ;
}
void tst_QTextDocument : : clonePreservesUserStates ( )
{
QTextCursor cursor ( doc ) ;
cursor . insertText ( " bla bla bla " ) ;
cursor . block ( ) . setUserState ( 1 ) ;
cursor . insertBlock ( ) ;
cursor . insertText ( " foo bar " ) ;
cursor . block ( ) . setUserState ( 2 ) ;
cursor . insertBlock ( ) ;
cursor . insertText ( " no user state " ) ;
QTextDocument * clone = doc - > clone ( ) ;
QTextBlock b1 = doc - > begin ( ) , b2 = clone - > begin ( ) ;
while ( b1 ! = doc - > end ( ) ) {
b1 = b1 . next ( ) ;
b2 = b2 . next ( ) ;
QCOMPARE ( b1 . userState ( ) , b2 . userState ( ) ) ;
}
QCOMPARE ( b2 , clone - > end ( ) ) ;
delete clone ;
}
void tst_QTextDocument : : clonePreservesRootFrameFormat ( )
{
doc - > setPlainText ( " Hello " ) ;
QTextFrameFormat fmt = doc - > rootFrame ( ) - > frameFormat ( ) ;
fmt . setMargin ( 200 ) ;
doc - > rootFrame ( ) - > setFrameFormat ( fmt ) ;
QCOMPARE ( doc - > rootFrame ( ) - > frameFormat ( ) . margin ( ) , qreal ( 200 ) ) ;
QTextDocument * copy = doc - > clone ( ) ;
QCOMPARE ( copy - > rootFrame ( ) - > frameFormat ( ) . margin ( ) , qreal ( 200 ) ) ;
delete copy ;
}
void tst_QTextDocument : : clonePreservesIndentWidth ( )
{
doc - > setIndentWidth ( 42 ) ;
QTextDocument * clone = doc - > clone ( ) ;
QCOMPARE ( clone - > indentWidth ( ) , qreal ( 42 ) ) ;
delete clone ;
}
void tst_QTextDocument : : clonePreservesFormatsWhenEmpty ( )
{
QTextDocument document ;
QTextCursor cursor ( & document ) ;
// Change a few char format attributes
QTextCharFormat charFormat ;
charFormat . setFontPointSize ( charFormat . fontPointSize ( ) + 1 ) ;
charFormat . setFontWeight ( charFormat . fontWeight ( ) + 1 ) ;
cursor . setBlockCharFormat ( charFormat ) ;
// Change a few block format attributes
QTextBlockFormat blockFormat ;
blockFormat . setAlignment ( Qt : : AlignRight ) ; // The default is Qt::AlignLeft
blockFormat . setIndent ( blockFormat . indent ( ) + 1 ) ;
cursor . setBlockFormat ( blockFormat ) ;
auto clone = document . clone ( ) ;
QTextCursor cloneCursor ( clone ) ;
QCOMPARE ( cloneCursor . blockCharFormat ( ) . fontPointSize ( ) , charFormat . fontPointSize ( ) ) ;
QCOMPARE ( cloneCursor . blockCharFormat ( ) . fontWeight ( ) , charFormat . fontWeight ( ) ) ;
QCOMPARE ( cloneCursor . blockFormat ( ) . alignment ( ) , blockFormat . alignment ( ) ) ;
QCOMPARE ( cloneCursor . blockFormat ( ) . indent ( ) , blockFormat . indent ( ) ) ;
delete clone ;
}
void tst_QTextDocument : : blockCount ( )
{
QCOMPARE ( doc - > blockCount ( ) , 1 ) ;
cursor . insertBlock ( ) ;
QCOMPARE ( doc - > blockCount ( ) , 2 ) ;
cursor . insertBlock ( ) ;
QCOMPARE ( doc - > blockCount ( ) , 3 ) ;
cursor . insertText ( " blah blah " ) ;
QCOMPARE ( doc - > blockCount ( ) , 3 ) ;
doc - > undo ( ) ;
doc - > undo ( ) ;
QCOMPARE ( doc - > blockCount ( ) , 2 ) ;
doc - > undo ( ) ;
QCOMPARE ( doc - > blockCount ( ) , 1 ) ;
}
void tst_QTextDocument : : resolvedFontInEmptyFormat ( )
{
QFont font ;
font . setPointSize ( 42 ) ;
doc - > setDefaultFont ( font ) ;
QTextCharFormat fmt = doc - > begin ( ) . charFormat ( ) ;
QVERIFY ( fmt . properties ( ) . isEmpty ( ) ) ;
QCOMPARE ( fmt . font ( ) , font ) ;
}
void tst_QTextDocument : : defaultRootFrameMargin ( )
{
QCOMPARE ( doc - > rootFrame ( ) - > frameFormat ( ) . margin ( ) , 4.0 ) ;
}
class TestDocument : public QTextDocument
{
public :
inline TestDocument ( const QUrl & testUrl , const QString & testString )
: url ( testUrl ) , string ( testString ) , resourceLoaded ( false ) { }
bool hasResourceCached ( ) ;
protected :
virtual QVariant loadResource ( int type , const QUrl & name ) override ;
private :
QUrl url ;
QString string ;
bool resourceLoaded ;
} ;
bool TestDocument : : hasResourceCached ( )
{
resourceLoaded = false ;
resource ( QTextDocument : : ImageResource , url ) ;
return ! resourceLoaded ;
}
QVariant TestDocument : : loadResource ( int type , const QUrl & name )
{
if ( type = = QTextDocument : : ImageResource
& & name = = url ) {
resourceLoaded = true ;
return string ;
}
return QTextDocument : : loadResource ( type , name ) ;
}
void tst_QTextDocument : : clearResources ( )
{
// regular resource for QTextDocument
QUrl testUrl ( " :/foobar " ) ;
QVariant testResource ( " hello world " ) ;
// implicitly cached resource, initially loaded through TestDocument::loadResource()
QUrl cacheUrl ( " :/blub " ) ;
QString cacheResource ( " mah " ) ;
TestDocument doc ( cacheUrl , cacheResource ) ;
doc . addResource ( QTextDocument : : ImageResource , testUrl , testResource ) ;
QVERIFY ( doc . resource ( QTextDocument : : ImageResource , testUrl ) = = testResource ) ;
doc . setPlainText ( " Hah " ) ;
QVERIFY ( doc . resource ( QTextDocument : : ImageResource , testUrl ) = = testResource ) ;
doc . setHtml ( " <b>Mooo</b><img src= \" :/blub \" /> " ) ;
QVERIFY ( doc . resource ( QTextDocument : : ImageResource , testUrl ) = = testResource ) ;
QVERIFY ( doc . resource ( QTextDocument : : ImageResource , cacheUrl ) = = cacheResource ) ;
doc . clear ( ) ;
QVERIFY ( ! doc . resource ( QTextDocument : : ImageResource , testUrl ) . isValid ( ) ) ;
QVERIFY ( ! doc . hasResourceCached ( ) ) ;
doc . clear ( ) ;
doc . setHtml ( " <b>Mooo</b><img src= \" :/blub \" /> " ) ;
QVERIFY ( doc . resource ( QTextDocument : : ImageResource , cacheUrl ) = = cacheResource ) ;
doc . setPlainText ( " Foob " ) ;
QVERIFY ( ! doc . hasResourceCached ( ) ) ;
}
void tst_QTextDocument : : setPlainText ( )
{
doc - > setPlainText ( " Hello World " ) ;
QString s ( " " ) ;
doc - > setPlainText ( s ) ;
QCOMPARE ( doc - > toPlainText ( ) , s ) ;
}
void tst_QTextDocument : : toPlainText_data ( )
{
QTest : : addColumn < QString > ( " html " ) ;
QTest : : addColumn < QString > ( " expectedPlainText " ) ;
QTest : : newRow ( " nbsp " ) < < " Hello World " < < " Hello World " ;
QTest : : newRow ( " empty_div " ) < < " <div></div>hello " < < " hello " ;
QTest : : newRow ( " br_and_p " ) < < " <p>first<br></p><p>second<br></p> " < < " first \n \n second \n " ;
QTest : : newRow ( " div " ) < < " first<div>second<br>third</div>fourth " < < " first \n second \n third \n fourth " ; // <div> and </div> become newlines...
QTest : : newRow ( " br_text_end_of_div " ) < < " <div><div>first<br>moretext</div>second<br></div> " < < " first \n moretext \n second \n " ; // ... when there is text before <div>
QTest : : newRow ( " br_end_of_div_like_gmail " ) < < " <div><div><div>first<br></div>second<br></div>third<br></div> " < < " first \n second \n third \n " ; // ... and when there is text before </div>
QTest : : newRow ( " p_and_div " ) < < " <div><div>first<p>second</p></div>third</div> " < < " first \n second \n third " ;
}
void tst_QTextDocument : : toPlainText ( )
{
QFETCH ( QString , html ) ;
QFETCH ( QString , expectedPlainText ) ;
doc - > setHtml ( html ) ;
QCOMPARE ( doc - > toPlainText ( ) , expectedPlainText ) ;
}
void tst_QTextDocument : : toRawText ( )
{
doc - > setHtml ( " " ) ;
QString rawText = doc - > toRawText ( ) ;
QCOMPARE ( rawText . size ( ) , 1 ) ;
QCOMPARE ( rawText . at ( 0 ) . unicode ( ) , ushort ( QChar : : Nbsp ) ) ;
}
void tst_QTextDocument : : deleteTextObjectsOnClear ( )
{
QPointer < QTextTable > table = cursor . insertTable ( 2 , 2 ) ;
QVERIFY ( ! table . isNull ( ) ) ;
doc - > clear ( ) ;
QVERIFY ( table . isNull ( ) ) ;
}
void tst_QTextDocument : : defaultStyleSheet ( )
{
const QColor green ( " green " ) ;
const QString sheet ( " p { background-color: green; } " ) ;
QVERIFY ( doc - > defaultStyleSheet ( ) . isEmpty ( ) ) ;
doc - > setDefaultStyleSheet ( sheet ) ;
QCOMPARE ( doc - > defaultStyleSheet ( ) , sheet ) ;
cursor . insertHtml ( " <p>test " ) ;
QTextBlockFormat fmt = doc - > begin ( ) . blockFormat ( ) ;
QCOMPARE ( fmt . background ( ) . color ( ) , green ) ;
doc - > clear ( ) ;
cursor . insertHtml ( " <p>test " ) ;
fmt = doc - > begin ( ) . blockFormat ( ) ;
QCOMPARE ( fmt . background ( ) . color ( ) , green ) ;
QTextDocument * clone = doc - > clone ( ) ;
QCOMPARE ( clone - > defaultStyleSheet ( ) , sheet ) ;
cursor = QTextCursor ( clone ) ;
cursor . insertHtml ( " <p>test " ) ;
fmt = clone - > begin ( ) . blockFormat ( ) ;
QCOMPARE ( fmt . background ( ) . color ( ) , green ) ;
delete clone ;
cursor = QTextCursor ( doc ) ;
cursor . insertHtml ( " <p>test " ) ;
fmt = doc - > begin ( ) . blockFormat ( ) ;
QCOMPARE ( fmt . background ( ) . color ( ) , green ) ;
doc - > clear ( ) ;
cursor . insertHtml ( " <style>p { background-color: red; }</style><p>test " ) ;
fmt = doc - > begin ( ) . blockFormat ( ) ;
QCOMPARE ( fmt . background ( ) . color ( ) , QColor ( Qt : : red ) ) ;
doc - > clear ( ) ;
doc - > setDefaultStyleSheet ( " invalid style sheet.... " ) ;
cursor . insertHtml ( " <p>test " ) ;
fmt = doc - > begin ( ) . blockFormat ( ) ;
QVERIFY ( fmt . background ( ) . color ( ) ! = QColor ( " green " ) ) ;
}
void tst_QTextDocument : : defaultTableStyle_data ( )
{
QTest : : addColumn < QString > ( " css " ) ;
QTest : : addColumn < QString > ( " html " ) ;
QTest : : addColumn < QList < QBrush > > ( " borderBrushes " ) ;
const QString htmlHeader ( R " (
< tr >
< th > 1 < / th > < th > 2 < / th >
< / tr >
) " );
const QString htmlCells ( R " (
< tr >
< td > A < / td > < td > B < / td >
< / tr >
) " );
const QString cssEachSide = R " ({
border - top - color : red ;
border - bottom - color : blue ;
border - left - color : green ;
border - right - color : yellow ;
} ) " ;
const QString cssOneColor = R " ({ border-color: red; }) " ;
const QString cssFourColors = R " ({ border-color: red blue green yellow; }) " ;
QTest : : addRow ( " td, each side " ) < < QString ( " td " ) + cssEachSide
< < htmlCells
< < QList < QBrush > { Qt : : red , Qt : : blue , QColor ( " green " ) , Qt : : yellow } ;
QTest : : addRow ( " th, each side " ) < < QString ( " th " ) + cssEachSide
< < htmlHeader
< < QList < QBrush > { Qt : : red , Qt : : blue , QColor ( " green " ) , Qt : : yellow } ;
QTest : : addRow ( " th+td, each side " ) < < QString ( " th %1 td %1 " ) . arg ( cssEachSide )
< < htmlHeader + htmlCells
< < QList < QBrush > { Qt : : red , Qt : : blue , QColor ( " green " ) , Qt : : yellow } ;
QTest : : addRow ( " td, one color " ) < < QString ( " td " ) + cssOneColor
< < htmlCells
< < QList < QBrush > { Qt : : red , Qt : : red , Qt : : red , Qt : : red } ;
QTest : : addRow ( " th, one color " ) < < QString ( " th " ) + cssOneColor
< < htmlHeader
< < QList < QBrush > { Qt : : red , Qt : : red , Qt : : red , Qt : : red } ;
QTest : : addRow ( " th+td, one color " ) < < QString ( " th %1 td %1 " ) . arg ( cssOneColor )
< < htmlHeader + htmlCells
< < QList < QBrush > { Qt : : red , Qt : : red , Qt : : red , Qt : : red } ;
// css order is top, right, bottom, left
QTest : : addRow ( " td, four colors " ) < < QString ( " td " ) + cssFourColors
< < htmlCells
< < QList < QBrush > { Qt : : red , QColor ( " green " ) , Qt : : yellow , Qt : : blue } ;
}
void tst_QTextDocument : : defaultTableStyle ( )
{
QFETCH ( QString , css ) ;
QFETCH ( QString , html ) ;
QFETCH ( QList < QBrush > , borderBrushes ) ;
CREATE_DOC_AND_CURSOR ( ) ;
doc . setDefaultStyleSheet ( css ) ;
doc . setHtml ( QString ( " <html><body><table>%1</table></body></html> " ) . arg ( html ) ) ;
const QTextFrame * frame = doc . rootFrame ( ) ;
const QTextTable * table = nullptr ;
for ( auto it = frame - > begin ( ) ; ! table & & ! it . atEnd ( ) ; + + it )
table = qobject_cast < const QTextTable * > ( it . currentFrame ( ) ) ;
QVERIFY ( table ) ;
const QList < QTextFormat : : Property > brushProperties = {
QTextFormat : : TableCellTopBorderBrush ,
QTextFormat : : TableCellBottomBorderBrush ,
QTextFormat : : TableCellLeftBorderBrush ,
QTextFormat : : TableCellRightBorderBrush
} ;
for ( int row = 0 ; row < table - > rows ( ) ; + + row ) {
for ( int column = 0 ; column < table - > columns ( ) ; + + column ) {
auto cellDetails = qScopeGuard ( [ & ] {
qWarning ( " Failure was in cell %d/%d " , row , column ) ;
} ) ;
const QTextTableCell cell = table - > cellAt ( row , column ) ;
const QTextTableCellFormat cellFormat = cell . format ( ) . toTableCellFormat ( ) ;
QList < QBrush > brushes ;
for ( const auto side : brushProperties ) {
QVariant sideProperty = cellFormat . property ( side ) ;
QVERIFY ( sideProperty . isValid ( ) ) ;
QVERIFY ( sideProperty . typeId ( ) = = qMetaTypeId < QBrush > ( ) ) ;
brushes < < sideProperty . value < QBrush > ( ) ;
}
auto errorDetails = qScopeGuard ( [ & ] {
if ( brushes . size ( ) ! = borderBrushes . size ( ) ) {
qWarning ( " Different count: %lld vs %lld " , brushes . size ( ) , borderBrushes . size ( ) ) ;
return ;
}
for ( int i = 0 ; i < brushes . size ( ) ; + + i ) {
QString side ;
QDebug ( & side ) < < QTextFormat : : Property ( QTextFormat : : TableCellTopBorderBrush + i ) ;
QString actual ;
QDebug ( & actual ) < < brushes . at ( i ) ;
QString expected ;
QDebug ( & expected ) < < borderBrushes . at ( i ) ;
if ( expected ! = actual ) {
qWarning ( " \n %s: \n \t Actual: %s \n \t Expected:%s " , qPrintable ( side ) ,
qPrintable ( actual ) , qPrintable ( expected ) ) ;
}
}
} ) ;
QVERIFY2 ( borderBrushes = = brushes , // QCOMPARE doesn't generate helpful output anyway
qPrintable ( QString ( " for cell %1/%2 " ) . arg ( row ) . arg ( column ) ) ) ;
errorDetails . dismiss ( ) ;
cellDetails . dismiss ( ) ;
}
}
}
void tst_QTextDocument : : maximumBlockCount ( )
{
QCOMPARE ( doc - > maximumBlockCount ( ) , 0 ) ;
QVERIFY ( doc - > isUndoRedoEnabled ( ) ) ;
cursor . insertBlock ( ) ;
cursor . insertText ( " Blah " ) ;
cursor . insertBlock ( ) ;
cursor . insertText ( " Foo " ) ;
QCOMPARE ( doc - > blockCount ( ) , 3 ) ;
QCOMPARE ( doc - > toPlainText ( ) , QString ( " \n Blah \n Foo " ) ) ;
doc - > setMaximumBlockCount ( 1 ) ;
QVERIFY ( ! doc - > isUndoRedoEnabled ( ) ) ;
QCOMPARE ( doc - > blockCount ( ) , 1 ) ;
QCOMPARE ( doc - > toPlainText ( ) , QString ( " Foo " ) ) ;
cursor . insertBlock ( ) ;
cursor . insertText ( " Hello " ) ;
doc - > setMaximumBlockCount ( 1 ) ;
QCOMPARE ( doc - > blockCount ( ) , 1 ) ;
QCOMPARE ( doc - > toPlainText ( ) , QString ( " Hello " ) ) ;
doc - > setMaximumBlockCount ( 100 ) ;
for ( int i = 0 ; i < 1000 ; + + i ) {
cursor . insertBlock ( ) ;
cursor . insertText ( " Blah) " ) ;
QVERIFY ( doc - > blockCount ( ) < = 100 ) ;
}
cursor . movePosition ( QTextCursor : : End ) ;
QCOMPARE ( cursor . blockNumber ( ) , 99 ) ;
QTextCharFormat fmt ;
fmt . setFontItalic ( true ) ;
cursor . setBlockCharFormat ( fmt ) ;
cursor . movePosition ( QTextCursor : : Start ) ;
QVERIFY ( ! cursor . blockCharFormat ( ) . fontItalic ( ) ) ;
doc - > setMaximumBlockCount ( 1 ) ;
QVERIFY ( cursor . blockCharFormat ( ) . fontItalic ( ) ) ;
cursor . insertTable ( 2 , 2 ) ;
QCOMPARE ( doc - > blockCount ( ) , 6 ) ;
cursor . insertBlock ( ) ;
QCOMPARE ( doc - > blockCount ( ) , 1 ) ;
}
void tst_QTextDocument : : adjustSize ( )
{
// avoid ugly tooltips like in task 125583
QString text ( " Test Text " ) ;
doc - > setPlainText ( text ) ;
doc - > rootFrame ( ) - > setFrameFormat ( QTextFrameFormat ( ) ) ;
doc - > adjustSize ( ) ;
QCOMPARE ( doc - > size ( ) . width ( ) , doc - > idealWidth ( ) ) ;
}
void tst_QTextDocument : : initialUserData ( )
{
doc - > setPlainText ( " Hello " ) ;
QTextBlock block = doc - > begin ( ) ;
block . setUserData ( new QTextBlockUserData ) ;
QVERIFY ( block . userData ( ) ) ;
doc - > documentLayout ( ) ;
QVERIFY ( block . userData ( ) ) ;
doc - > setDocumentLayout ( new QTestDocumentLayout ( doc ) ) ;
QVERIFY ( ! block . userData ( ) ) ;
}
void tst_QTextDocument : : html_defaultFont ( )
{
QFont f ;
f . setItalic ( true ) ;
f . setWeight ( QFont : : Bold ) ;
doc - > setDefaultFont ( f ) ;
doc - > setPlainText ( " Test " ) ;
QString bodyPart = QString : : fromLatin1 ( " <body style= \" font-family:'%1'; font-size:%2; "
" font-weight:%3; font-style:italic; \" > " )
. arg ( f . family ( ) )
. arg ( cssFontSizeString ( f ) )
. arg ( f . weight ( ) ) ;
QString html = doc - > toHtml ( ) ;
if ( ! html . contains ( bodyPart ) ) {
qDebug ( ) < < " html: " < < html ;
qDebug ( ) < < " expected body: " < < bodyPart ;
QVERIFY ( html . contains ( bodyPart ) ) ;
}
if ( html . contains ( " span " ) )
qDebug ( ) < < " html: " < < html ;
QVERIFY ( ! html . contains ( " <span style " ) ) ;
}
void tst_QTextDocument : : blockCountChanged ( )
{
QSignalSpy spy ( doc , SIGNAL ( blockCountChanged ( int ) ) ) ;
doc - > setPlainText ( " Foo " ) ;
QCOMPARE ( doc - > blockCount ( ) , 1 ) ;
QCOMPARE ( spy . size ( ) , 0 ) ;
spy . clear ( ) ;
doc - > setPlainText ( " Foo \n Bar " ) ;
QCOMPARE ( doc - > blockCount ( ) , 2 ) ;
QCOMPARE ( spy . size ( ) , 1 ) ;
QCOMPARE ( spy . at ( 0 ) . value ( 0 ) . toInt ( ) , 2 ) ;
spy . clear ( ) ;
cursor . movePosition ( QTextCursor : : End ) ;
cursor . insertText ( " Blahblah " ) ;
QCOMPARE ( spy . size ( ) , 0 ) ;
cursor . insertBlock ( ) ;
QCOMPARE ( spy . size ( ) , 1 ) ;
QCOMPARE ( spy . at ( 0 ) . value ( 0 ) . toInt ( ) , 3 ) ;
spy . clear ( ) ;
doc - > undo ( ) ;
QCOMPARE ( spy . size ( ) , 1 ) ;
QCOMPARE ( spy . at ( 0 ) . value ( 0 ) . toInt ( ) , 2 ) ;
}
void tst_QTextDocument : : nonZeroDocumentLengthOnClear ( )
{
QTestDocumentLayout * lout = new QTestDocumentLayout ( doc ) ;
doc - > setDocumentLayout ( lout ) ;
doc - > clear ( ) ;
QVERIFY ( lout - > called ) ;
QVERIFY ( ! lout - > lastDocumentLengths . contains ( 0 ) ) ;
}
void tst_QTextDocument : : setTextPreservesUndoRedoEnabled ( )
{
QVERIFY ( doc - > isUndoRedoEnabled ( ) ) ;
doc - > setPlainText ( " Test " ) ;
QVERIFY ( doc - > isUndoRedoEnabled ( ) ) ;
doc - > setUndoRedoEnabled ( false ) ;
QVERIFY ( ! doc - > isUndoRedoEnabled ( ) ) ;
doc - > setPlainText ( " Test2 " ) ;
QVERIFY ( ! doc - > isUndoRedoEnabled ( ) ) ;
doc - > setHtml ( " <p>hello " ) ;
QVERIFY ( ! doc - > isUndoRedoEnabled ( ) ) ;
}
void tst_QTextDocument : : firstLast ( )
{
QCOMPARE ( doc - > blockCount ( ) , 1 ) ;
QCOMPARE ( doc - > firstBlock ( ) , doc - > lastBlock ( ) ) ;
doc - > setPlainText ( " Hello \n Test \n World " ) ;
QCOMPARE ( doc - > blockCount ( ) , 3 ) ;
QVERIFY ( doc - > firstBlock ( ) ! = doc - > lastBlock ( ) ) ;
QCOMPARE ( doc - > firstBlock ( ) . text ( ) , QString ( " Hello " ) ) ;
QCOMPARE ( doc - > lastBlock ( ) . text ( ) , QString ( " World " ) ) ;
// manual forward loop
QTextBlock block = doc - > firstBlock ( ) ;
QVERIFY ( block . isValid ( ) ) ;
QCOMPARE ( block . text ( ) , QString ( " Hello " ) ) ;
block = block . next ( ) ;
QVERIFY ( block . isValid ( ) ) ;
QCOMPARE ( block . text ( ) , QString ( " Test " ) ) ;
block = block . next ( ) ;
QVERIFY ( block . isValid ( ) ) ;
QCOMPARE ( block . text ( ) , QString ( " World " ) ) ;
block = block . next ( ) ;
QVERIFY ( ! block . isValid ( ) ) ;
// manual backward loop
block = doc - > lastBlock ( ) ;
QVERIFY ( block . isValid ( ) ) ;
QCOMPARE ( block . text ( ) , QString ( " World " ) ) ;
block = block . previous ( ) ;
QVERIFY ( block . isValid ( ) ) ;
QCOMPARE ( block . text ( ) , QString ( " Test " ) ) ;
block = block . previous ( ) ;
QVERIFY ( block . isValid ( ) ) ;
QCOMPARE ( block . text ( ) , QString ( " Hello " ) ) ;
block = block . previous ( ) ;
QVERIFY ( ! block . isValid ( ) ) ;
}
const QString backgroundImage_html ( " <body><table><tr><td background= \" foo.png \" >Blah</td></tr></table></body> " ) ;
void tst_QTextDocument : : backgroundImage_checkExpectedHtml ( const QTextDocument & doc )
{
QString expectedHtml = htmlHead +
" <table border= \" 0 \" style= \" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; \" cellspacing= \" 2 \" cellpadding= \" 0 \" > "
" \n <tr> \n <td background= \" foo.png \" > "
" \n <p style= \" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; \" >Blah</p> "
" </td></tr></table> " + htmlTail ;
writeActualAndExpected ( QTest : : currentTestFunction ( ) , doc . toHtml ( ) , expectedHtml ) ;
QCOMPARE ( doc . toHtml ( ) , expectedHtml ) ;
}
void tst_QTextDocument : : buildRegExpData ( )
{
QTest : : addColumn < QString > ( " haystack " ) ;
QTest : : addColumn < QString > ( " needle " ) ;
QTest : : addColumn < int > ( " flags " ) ;
QTest : : addColumn < int > ( " from " ) ;
QTest : : addColumn < int > ( " anchor " ) ;
QTest : : addColumn < int > ( " position " ) ;
// match integers 0 to 99
QTest : : newRow ( " 1 " ) < < " 23 " < < " ^ \\ d \\ d?$ " < < int ( QTextDocument : : FindCaseSensitively ) < < 0 < < 0 < < 2 ;
// match ampersands but not &
QTest : : newRow ( " 2 " ) < < " His & hers & theirs " < < " &(?!amp;) " < < int ( QTextDocument : : FindCaseSensitively ) < < 0 < < 15 < < 16 ;
//backward search
QTest : : newRow ( " 3 " ) < < QString : : fromLatin1 ( " HelloBlahWorld Blah Hah " )
< < " h " < < int ( QTextDocument : : FindBackward ) < < 18 < < 8 < < 9 ;
}
void tst_QTextDocument : : backgroundImage_toHtml ( )
{
CREATE_DOC_AND_CURSOR ( ) ;
doc . setHtml ( backgroundImage_html ) ;
backgroundImage_checkExpectedHtml ( doc ) ;
}
void tst_QTextDocument : : backgroundImage_toHtml2 ( )
{
CREATE_DOC_AND_CURSOR ( ) ;
cursor . insertHtml ( backgroundImage_html ) ;
backgroundImage_checkExpectedHtml ( doc ) ;
}
void tst_QTextDocument : : backgroundImage_clone ( )
{
CREATE_DOC_AND_CURSOR ( ) ;
doc . setHtml ( backgroundImage_html ) ;
QTextDocument * clone = doc . clone ( ) ;
backgroundImage_checkExpectedHtml ( * clone ) ;
delete clone ;
}
void tst_QTextDocument : : backgroundImage_copy ( )
{
CREATE_DOC_AND_CURSOR ( ) ;
doc . setHtml ( backgroundImage_html ) ;
QTextDocumentFragment fragment ( & doc ) ;
{
CREATE_DOC_AND_CURSOR ( ) ;
cursor . insertFragment ( fragment ) ;
backgroundImage_checkExpectedHtml ( doc ) ;
}
}
void tst_QTextDocument : : documentCleanup ( )
{
QTextDocument doc ;
QTextCursor cursor ( & doc ) ;
cursor . insertText ( " d \n foo \n bar \n " ) ;
doc . documentLayout ( ) ; // forces relayout
// remove char 1
cursor . setPosition ( 0 ) ;
QSizeF size = doc . documentLayout ( ) - > documentSize ( ) ;
cursor . deleteChar ( ) ;
// the size should be unchanged.
QCOMPARE ( doc . documentLayout ( ) - > documentSize ( ) , size ) ;
}
void tst_QTextDocument : : characterAt ( )
{
QTextDocument doc ;
QTextCursor cursor ( & doc ) ;
QString text ( " 12345 \n 67890 " ) ;
cursor . insertText ( text ) ;
int length = doc . characterCount ( ) ;
QCOMPARE ( length , text . size ( ) + 1 ) ;
QCOMPARE ( doc . characterAt ( length - 1 ) , QChar ( QChar : : ParagraphSeparator ) ) ;
QCOMPARE ( doc . characterAt ( - 1 ) , QChar ( ) ) ;
QCOMPARE ( doc . characterAt ( length ) , QChar ( ) ) ;
QCOMPARE ( doc . characterAt ( length + 1 ) , QChar ( ) ) ;
for ( int i = 0 ; i < text . size ( ) ; + + i ) {
QChar c = text . at ( i ) ;
if ( c = = QLatin1Char ( ' \n ' ) )
c = QChar ( QChar : : ParagraphSeparator ) ;
QCOMPARE ( doc . characterAt ( i ) , c ) ;
}
}
void tst_QTextDocument : : revisions ( )
{
QTextDocument doc ;
QTextCursor cursor ( & doc ) ;
QString text ( " Hello World " ) ;
QCOMPARE ( doc . firstBlock ( ) . revision ( ) , 0 ) ;
cursor . insertText ( text ) ;
QCOMPARE ( doc . firstBlock ( ) . revision ( ) , 1 ) ;
cursor . setPosition ( 6 ) ;
cursor . insertBlock ( ) ;
QCOMPARE ( cursor . block ( ) . previous ( ) . revision ( ) , 2 ) ;
QCOMPARE ( cursor . block ( ) . revision ( ) , 2 ) ;
cursor . insertText ( " candle " ) ;
QCOMPARE ( cursor . block ( ) . revision ( ) , 3 ) ;
cursor . movePosition ( QTextCursor : : EndOfBlock ) ;
cursor . insertBlock ( ) ; // we are at the block end
QCOMPARE ( cursor . block ( ) . previous ( ) . revision ( ) , 3 ) ;
QCOMPARE ( cursor . block ( ) . revision ( ) , 4 ) ;
cursor . insertText ( " lightbulb " ) ;
QCOMPARE ( cursor . block ( ) . revision ( ) , 5 ) ;
cursor . movePosition ( QTextCursor : : StartOfBlock ) ;
cursor . insertBlock ( ) ; // we are the block start
QCOMPARE ( cursor . block ( ) . previous ( ) . revision ( ) , 6 ) ;
QCOMPARE ( cursor . block ( ) . revision ( ) , 5 ) ;
}
void tst_QTextDocument : : revisionWithUndoCompressionAndUndo ( )
{
QTextDocument doc ;
QTextCursor cursor ( & doc ) ;
cursor . insertText ( " This is the beginning of it all. " ) ;
QCOMPARE ( doc . firstBlock ( ) . revision ( ) , 1 ) ;
QCOMPARE ( doc . revision ( ) , 1 ) ;
cursor . insertBlock ( ) ;
QCOMPARE ( doc . revision ( ) , 2 ) ;
cursor . insertText ( " this " ) ;
QCOMPARE ( doc . revision ( ) , 3 ) ;
cursor . insertText ( " is " ) ;
QCOMPARE ( doc . revision ( ) , 4 ) ;
cursor . insertText ( " compressed " ) ;
QCOMPARE ( doc . revision ( ) , 5 ) ;
doc . undo ( ) ;
QCOMPARE ( doc . revision ( ) , 6 ) ;
QCOMPARE ( doc . toPlainText ( ) , QString ( " This is the beginning of it all. \n " ) ) ;
cursor . setPosition ( 0 ) ;
QCOMPARE ( doc . firstBlock ( ) . revision ( ) , 1 ) ;
cursor . insertText ( " Very beginnig " ) ;
QCOMPARE ( doc . firstBlock ( ) . revision ( ) , 7 ) ;
doc . undo ( ) ;
QCOMPARE ( doc . revision ( ) , 8 ) ;
QCOMPARE ( doc . firstBlock ( ) . revision ( ) , 1 ) ;
cursor . beginEditBlock ( ) ;
cursor . insertText ( " Hello " ) ;
cursor . insertBlock ( ) ;
cursor . insertText ( " world " ) ;
cursor . endEditBlock ( ) ;
QCOMPARE ( doc . revision ( ) , 9 ) ;
doc . undo ( ) ;
QCOMPARE ( doc . revision ( ) , 10 ) ;
}
void tst_QTextDocument : : testUndoCommandAdded ( )
{
QVERIFY ( doc ) ;
QSignalSpy spy ( doc , SIGNAL ( undoCommandAdded ( ) ) ) ;
QVERIFY ( spy . isValid ( ) ) ;
QVERIFY ( spy . isEmpty ( ) ) ;
cursor . insertText ( " a " ) ;
QCOMPARE ( spy . size ( ) , 1 ) ;
cursor . insertText ( " b " ) ; // should be merged
QCOMPARE ( spy . size ( ) , 1 ) ;
cursor . insertText ( " c " ) ; // should be merged
QCOMPARE ( spy . size ( ) , 1 ) ;
QCOMPARE ( doc - > toPlainText ( ) , QString ( " abc " ) ) ;
doc - > undo ( ) ;
QCOMPARE ( doc - > toPlainText ( ) , QString ( " " ) ) ;
doc - > clear ( ) ;
spy . clear ( ) ;
cursor . insertText ( " aaa " ) ;
QCOMPARE ( spy . size ( ) , 1 ) ;
spy . clear ( ) ;
cursor . insertText ( " aaaa \n bcd " ) ;
QCOMPARE ( spy . size ( ) , 1 ) ;
spy . clear ( ) ;
cursor . beginEditBlock ( ) ;
cursor . insertText ( " aa " ) ;
cursor . insertText ( " bbb \n " ) ;
cursor . setCharFormat ( QTextCharFormat ( ) ) ;
cursor . insertText ( " \n ccc " ) ;
QVERIFY ( spy . isEmpty ( ) ) ;
cursor . endEditBlock ( ) ;
QCOMPARE ( spy . size ( ) , 1 ) ;
spy . clear ( ) ;
cursor . insertBlock ( ) ;
QCOMPARE ( spy . size ( ) , 1 ) ;
spy . clear ( ) ;
cursor . setPosition ( 5 ) ;
QVERIFY ( spy . isEmpty ( ) ) ;
cursor . setCharFormat ( QTextCharFormat ( ) ) ;
QVERIFY ( spy . isEmpty ( ) ) ;
cursor . setPosition ( 10 , QTextCursor : : KeepAnchor ) ;
QVERIFY ( spy . isEmpty ( ) ) ;
QTextCharFormat cf ;
cf . setFontItalic ( true ) ;
cursor . mergeCharFormat ( cf ) ;
QCOMPARE ( spy . size ( ) , 1 ) ;
spy . clear ( ) ;
doc - > undo ( ) ;
QCOMPARE ( spy . size ( ) , 0 ) ;
doc - > undo ( ) ;
QCOMPARE ( spy . size ( ) , 0 ) ;
spy . clear ( ) ;
doc - > redo ( ) ;
QCOMPARE ( spy . size ( ) , 0 ) ;
doc - > redo ( ) ;
QCOMPARE ( spy . size ( ) , 0 ) ;
}
void tst_QTextDocument : : testUndoBlocks ( )
{
QVERIFY ( doc ) ;
cursor . insertText ( " Hello World " ) ;
cursor . insertText ( " period " ) ;
doc - > undo ( ) ;
QCOMPARE ( doc - > toPlainText ( ) , QString ( " " ) ) ;
cursor . insertText ( " Hello World " ) ;
cursor . insertText ( " One \n Two \n Three " ) ;
QCOMPARE ( doc - > toPlainText ( ) , QString ( " Hello WorldOne \n Two \n Three " ) ) ;
doc - > undo ( ) ;
QCOMPARE ( doc - > toPlainText ( ) , QString ( " Hello World " ) ) ;
cursor . insertText ( " One \n Two \n Three " ) ;
cursor . insertText ( " Trailing text " ) ;
doc - > undo ( ) ;
QCOMPARE ( doc - > toPlainText ( ) , QString ( " Hello WorldOne \n Two \n Three " ) ) ;
doc - > undo ( ) ;
QCOMPARE ( doc - > toPlainText ( ) , QString ( " Hello World " ) ) ;
doc - > undo ( ) ;
QCOMPARE ( doc - > toPlainText ( ) , QString ( " " ) ) ;
cursor . insertText ( " town " ) ;
cursor . beginEditBlock ( ) ; // Edit block 1 - Deletion/Insertion
cursor . setPosition ( 0 , QTextCursor : : KeepAnchor ) ;
cursor . insertText ( " r " ) ;
cursor . endEditBlock ( ) ;
cursor . insertText ( " est " ) ; // Merged into edit block 1
QCOMPARE ( doc - > toPlainText ( ) , QString ( " rest " ) ) ;
doc - > undo ( ) ;
QCOMPARE ( doc - > toPlainText ( ) , QString ( " town " ) ) ;
doc - > undo ( ) ;
QCOMPARE ( doc - > toPlainText ( ) , QString ( " " ) ) ;
// This case would not happen in practice. If the user typed out this text, it would all be part of one
// edit block. This would cause the undo to clear all text. But for the purpose of testing the beginEditBlock
// and endEditBlock calls with respect to qtextdocument this is tested.
cursor . insertText ( " quod " ) ;
cursor . beginEditBlock ( ) ; // Edit block 1 - Insertion
cursor . insertText ( " erat " ) ;
cursor . endEditBlock ( ) ;
cursor . insertText ( " demonstrandum " ) ; // Merged into edit block 1
QCOMPARE ( doc - > toPlainText ( ) , QString ( " quod erat demonstrandum " ) ) ;
doc - > undo ( ) ;
QCOMPARE ( doc - > toPlainText ( ) , QString ( " quod " ) ) ;
doc - > undo ( ) ;
QCOMPARE ( doc - > toPlainText ( ) , QString ( " " ) ) ;
}
class Receiver : public QObject
{
Q_OBJECT
public :
QString first ;
public slots :
void cursorPositionChanged ( ) {
if ( first . isEmpty ( ) )
first = QLatin1String ( " cursorPositionChanged " ) ;
}
void contentsChange ( ) {
if ( first . isEmpty ( ) )
first = QLatin1String ( " contentsChanged " ) ;
}
} ;
void tst_QTextDocument : : receiveCursorPositionChangedAfterContentsChange ( )
{
QVERIFY ( doc ) ;
doc - > setDocumentLayout ( new MyAbstractTextDocumentLayout ( doc ) ) ;
Receiver rec ;
connect ( doc , SIGNAL ( cursorPositionChanged ( QTextCursor ) ) ,
& rec , SLOT ( cursorPositionChanged ( ) ) ) ;
connect ( doc , SIGNAL ( contentsChange ( int , int , int ) ) ,
& rec , SLOT ( contentsChange ( ) ) ) ;
cursor . insertText ( " Hello World " ) ;
QCOMPARE ( rec . first , QString ( " contentsChanged " ) ) ;
}
void tst_QTextDocument : : QTBUG25778_pixelSizeFromHtml ( )
{
QTextDocument document1 ;
QTextDocument document2 ;
document1 . setHtml ( " <span style= \" font-size: 24px \" >Foobar</span> " ) ;
document2 . setHtml ( document1 . toHtml ( ) ) ;
QTextCursor cursor ( & document2 ) ;
QCOMPARE ( cursor . charFormat ( ) . font ( ) . pixelSize ( ) , 24 ) ;
}
void tst_QTextDocument : : copiedFontSize ( )
{
QTextDocument documentInput ;
QTextDocument documentOutput ;
QFont fontInput ;
fontInput . setPixelSize ( 24 ) ;
QTextCursor cursorInput ( & documentInput ) ;
QTextCharFormat formatInput = cursorInput . charFormat ( ) ;
formatInput . setFont ( fontInput ) ;
cursorInput . insertText ( " Should be the same font " , formatInput ) ;
cursorInput . select ( QTextCursor : : Document ) ;
QTextDocumentFragment fragmentInput ( cursorInput ) ;
QString html = fragmentInput . toHtml ( ) ;
QTextCursor cursorOutput ( & documentOutput ) ;
QTextDocumentFragment fragmentOutput = QTextDocumentFragment : : fromHtml ( html ) ;
cursorOutput . insertFragment ( fragmentOutput ) ;
QCOMPARE ( cursorOutput . charFormat ( ) . font ( ) . pixelSize ( ) , 24 ) ;
}
void tst_QTextDocument : : htmlExportImportBlockCount ( )
{
QTextDocument document ;
{
QTextCursor cursor ( & document ) ;
cursor . insertText ( " Foo " ) ;
cursor . insertBlock ( ) ;
cursor . insertBlock ( ) ;
cursor . insertBlock ( ) ;
cursor . insertBlock ( ) ;
cursor . insertText ( " Bar " ) ;
}
QCOMPARE ( document . blockCount ( ) , 5 ) ;
QString html = document . toHtml ( ) ;
document . clear ( ) ;
document . setHtml ( html ) ;
QCOMPARE ( document . blockCount ( ) , 5 ) ;
}
void tst_QTextDocument : : QTBUG27354_spaceAndSoftSpace ( )
{
QTextDocument document ;
{
QTextCursor cursor ( & document ) ;
QTextBlockFormat blockFormat ;
blockFormat . setAlignment ( Qt : : AlignJustify ) ;
cursor . mergeBlockFormat ( blockFormat ) ;
cursor . insertText ( " ac " ) ;
cursor . insertBlock ( ) ;
cursor . insertText ( " " ) ;
cursor . insertText ( QChar ( 0x2028 ) ) ;
}
// Trigger justification of text
QImage image ( 1000 , 1000 , QImage : : Format_ARGB32 ) ;
image . fill ( 0 ) ;
{
QPainter p ( & image ) ;
document . drawContents ( & p , image . rect ( ) ) ;
}
{
// If no p tag is specified it should not be inheriting it
QTextDocument td ;
td . setHtml ( " <html><head><style type= \" text/css \" >p { line-height: 200% }</style></head><body>Foo<ul><li>First</li></ul></body></html> " ) ;
QTextBlock block = td . begin ( ) ;
while ( block . isValid ( ) ) {
QTextBlockFormat fmt = block . blockFormat ( ) ;
QCOMPARE ( fmt . lineHeightType ( ) , int ( QTextBlockFormat : : SingleHeight ) ) ;
QCOMPARE ( fmt . lineHeight ( ) , qreal ( 0 ) ) ;
block = block . next ( ) ;
}
}
{
QTextDocument td ;
td . setHtml ( " <html><head></head><body><p>Foo</p><ul><li>First</li></ul></body></html> " ) ;
QList < double > originalMargins ;
QTextBlock block = td . begin ( ) ;
while ( block . isValid ( ) ) {
originalMargins < < block . blockFormat ( ) . topMargin ( ) ;
block = block . next ( ) ;
}
originalMargins [ 0 ] = 85 ;
td . setHtml ( " <html><head><style type= \" text/css \" >body { margin-top: 85px; }</style></head><body><p>Foo</p><ul><li>First</li></ul></body></html> " ) ;
block = td . begin ( ) ;
int count = 0 ;
while ( block . isValid ( ) ) {
QTextBlockFormat fmt = block . blockFormat ( ) ;
QCOMPARE ( fmt . topMargin ( ) , originalMargins . at ( count + + ) ) ;
block = block . next ( ) ;
}
}
}
class BaseDocument : public QTextDocument
{
public :
QUrl loadedResource ( ) const { return resourceUrl ; }
QVariant loadResource ( int type , const QUrl & name ) override
{
resourceUrl = name ;
return QTextDocument : : loadResource ( type , name ) ;
}
private :
QUrl resourceUrl ;
} ;
void tst_QTextDocument : : baseUrl_data ( )
{
QTest : : addColumn < QUrl > ( " base " ) ;
QTest : : addColumn < QUrl > ( " resource " ) ;
QTest : : addColumn < QUrl > ( " loaded " ) ;
QTest : : newRow ( " 1 " ) < < QUrl ( ) < < QUrl ( " images/logo.png " ) < < QUrl ( " images/logo.png " ) ;
QTest : : newRow ( " 2 " ) < < QUrl ( " file:///path/to/content " ) < < QUrl ( " images/logo.png " ) < < QUrl ( " file:///path/to/images/logo.png " ) ;
QTest : : newRow ( " 3 " ) < < QUrl ( " file:///path/to/content/ " ) < < QUrl ( " images/logo.png " ) < < QUrl ( " file:///path/to/content/images/logo.png " ) ;
QTest : : newRow ( " 4 " ) < < QUrl ( " file:///path/to/content/images " ) < < QUrl ( " images/logo.png " ) < < QUrl ( " file:///path/to/content/images/logo.png " ) ;
QTest : : newRow ( " 5 " ) < < QUrl ( " file:///path/to/content/images/ " ) < < QUrl ( " images/logo.png " ) < < QUrl ( " file:///path/to/content/images/images/logo.png " ) ;
QTest : : newRow ( " 6 " ) < < QUrl ( " file:///path/to/content/images " ) < < QUrl ( " ../images/logo.png " ) < < QUrl ( " file:///path/to/images/logo.png " ) ;
QTest : : newRow ( " 7 " ) < < QUrl ( " file:///path/to/content/images/ " ) < < QUrl ( " ../images/logo.png " ) < < QUrl ( " file:///path/to/content/images/logo.png " ) ;
QTest : : newRow ( " 8 " ) < < QUrl ( " file:///path/to/content/index.html " ) < < QUrl ( " images/logo.png " ) < < QUrl ( " file:///path/to/content/images/logo.png " ) ;
}
void tst_QTextDocument : : baseUrl ( )
{
QFETCH ( QUrl , base ) ;
QFETCH ( QUrl , resource ) ;
QFETCH ( QUrl , loaded ) ;
BaseDocument document ;
QVERIFY ( ! document . baseUrl ( ) . isValid ( ) ) ;
document . setBaseUrl ( base ) ;
QCOMPARE ( document . baseUrl ( ) , base ) ;
document . setHtml ( QLatin1String ( " <img src=' " ) + resource . toString ( ) + QLatin1String ( " '/> " ) ) ;
document . resource ( QTextDocument : : ImageResource , resource ) ;
QCOMPARE ( document . loadedResource ( ) , loaded ) ;
}
void tst_QTextDocument : : QTBUG28998_linkColor ( )
{
QPalette pal ;
pal . setColor ( QPalette : : Link , QColor ( " tomato " ) ) ;
QGuiApplication : : setPalette ( pal ) ;
QTextDocument doc ;
doc . setHtml ( " <a href= \" http://www.qt-project.org \" >Qt</a> " ) ;
QCOMPARE ( doc . blockCount ( ) , 1 ) ;
QTextBlock block = doc . firstBlock ( ) ;
QVERIFY ( block . isValid ( ) ) ;
QTextFragment fragment = block . begin ( ) . fragment ( ) ;
QVERIFY ( fragment . isValid ( ) ) ;
QTextCharFormat format = fragment . charFormat ( ) ;
QVERIFY ( format . isValid ( ) ) ;
QVERIFY ( format . isAnchor ( ) ) ;
QCOMPARE ( format . anchorHref ( ) , QStringLiteral ( " http://www.qt-project.org " ) ) ;
QCOMPARE ( format . foreground ( ) , pal . link ( ) ) ;
}
class ContentsChangeHandler : public QObject
{
Q_OBJECT
public :
ContentsChangeHandler ( QTextDocument * doc )
: verticalMovementX ( - 1 )
, doc ( doc )
{
connect ( doc , SIGNAL ( contentsChange ( int , int , int ) ) ,
this , SLOT ( saveModifiedText ( int , int , int ) ) ) ;
}
private slots :
void saveModifiedText ( int from , int /*charsRemoved*/ , int charsAdded )
{
QTextCursor tmp ( doc ) ;
tmp . setPosition ( from ) ;
tmp . setPosition ( from + charsAdded , QTextCursor : : KeepAnchor ) ;
text = tmp . selectedText ( ) ;
verticalMovementX = tmp . verticalMovementX ( ) ;
}
public :
QString text ;
int verticalMovementX ;
private :
QTextDocument * doc ;
} ;
void tst_QTextDocument : : textCursorUsageWithinContentsChange ( )
{
// force creation of layout
doc - > documentLayout ( ) ;
QTextCursor cursor ( doc ) ;
cursor . insertText ( " initial text " ) ;
ContentsChangeHandler handler ( doc ) ;
cursor . insertText ( " new text " ) ;
QCOMPARE ( handler . text , QString ( " new text " ) ) ;
QCOMPARE ( handler . verticalMovementX , - 1 ) ;
}
void tst_QTextDocument : : cssInheritance ( )
{
{
QTextDocument td ;
td . setHtml ( " <html><head><style type= \" text/css \" >body { line-height: 200% }</style></head><body> "
" <p>Foo</p><p>Bar</p><p>Baz</p></body></html> " ) ;
QTextBlock block = td . begin ( ) ;
while ( block . isValid ( ) ) {
QTextBlockFormat fmt = block . blockFormat ( ) ;
QCOMPARE ( fmt . lineHeightType ( ) , int ( QTextBlockFormat : : ProportionalHeight ) ) ;
QCOMPARE ( fmt . lineHeight ( ) , qreal ( 200 ) ) ;
block = block . next ( ) ;
}
}
{
QTextDocument td ;
td . setHtml ( " <html><head><style type= \" text/css \" >body { line-height: 200% } p { line-height: 300% }</style></head><body> "
" <p style= \" line-height: 40px \" >Foo</p><p>Bar</p><p>Baz</p></body></html> " ) ;
QTextBlock block = td . begin ( ) ;
QTextBlockFormat fmt = block . blockFormat ( ) ;
QCOMPARE ( fmt . lineHeightType ( ) , int ( QTextBlockFormat : : MinimumHeight ) ) ;
QCOMPARE ( fmt . lineHeight ( ) , qreal ( 40 ) ) ;
block = block . next ( ) ;
fmt = block . blockFormat ( ) ;
QCOMPARE ( fmt . lineHeightType ( ) , int ( QTextBlockFormat : : ProportionalHeight ) ) ;
QCOMPARE ( fmt . lineHeight ( ) , qreal ( 300 ) ) ;
}
{
QTextDocument td ;
td . setHtml ( " <html><head><style type= \" text/css \" >body { font-weight: bold; background-color: #ff0000 }</style></head><body> "
" <p>Foo</p><p>Bar</p><p>Baz</p></body></html> " ) ;
QTextBlock block = td . begin ( ) ;
while ( block . isValid ( ) ) {
QCOMPARE ( block . blockFormat ( ) . background ( ) , QBrush ( ) ) ;
QVERIFY ( block . charFormat ( ) . font ( ) . bold ( ) ) ;
block = block . next ( ) ;
}
}
{
QTextDocument td ;
td . setHtml ( " <html><head><style type= \" text/css \" >body { font-style: italic; font-weight: normal; }</style></head><body> "
" <table><tr><th>Foo</th></tr><tr><td>Bar</td></tr></table></body></html> " ) ;
QTextBlock block = td . begin ( ) ;
// First is the table
QTextCharFormat fmt = block . charFormat ( ) ;
QVERIFY ( ! fmt . font ( ) . bold ( ) ) ;
QVERIFY ( fmt . font ( ) . italic ( ) ) ;
// Then the th
block = block . next ( ) ;
fmt = block . charFormat ( ) ;
QVERIFY ( fmt . font ( ) . bold ( ) ) ;
QVERIFY ( fmt . font ( ) . italic ( ) ) ;
// Then the td
block = block . next ( ) ;
fmt = block . charFormat ( ) ;
QVERIFY ( ! fmt . font ( ) . bold ( ) ) ;
QVERIFY ( fmt . font ( ) . italic ( ) ) ;
}
{
QTextDocument td ;
td . setHtml ( " <html><head><style type= \" text/css \" >b { font-style: italic; font-weight: normal; }</style></head><body> "
" <p>This should be <b>bold</b></p></body></html> " ) ;
QTextBlock block = td . begin ( ) ;
// First is the p
QTextCharFormat fmt = block . charFormat ( ) ;
QVERIFY ( ! fmt . font ( ) . bold ( ) ) ;
QTextBlock : : iterator it = block . begin ( ) ;
// The non bold text is first
QTextFragment currentFragment = it . fragment ( ) ;
QVERIFY ( currentFragment . isValid ( ) ) ;
fmt = currentFragment . charFormat ( ) ;
QVERIFY ( ! fmt . font ( ) . bold ( ) ) ;
+ + it ;
QVERIFY ( ! it . atEnd ( ) ) ;
// Now check the "bold" text
currentFragment = it . fragment ( ) ;
QVERIFY ( currentFragment . isValid ( ) ) ;
fmt = currentFragment . charFormat ( ) ;
QVERIFY ( ! fmt . font ( ) . bold ( ) ) ;
QVERIFY ( fmt . font ( ) . italic ( ) ) ;
}
{
QTextDocument td ;
td . setHtml ( " <html><head><link rel= \" stylesheet \" type= \" text/css \" href= \" test.css \" ></head><body> "
" <p>This should be <b>bold</b></p></body></html> " ) ;
QTextBlock block = td . begin ( ) ;
// First is the p
QTextCharFormat fmt = block . charFormat ( ) ;
QVERIFY ( ! fmt . font ( ) . bold ( ) ) ;
QTextBlock : : iterator it = block . begin ( ) ;
// The non bold text is first
QTextFragment currentFragment = it . fragment ( ) ;
QVERIFY ( currentFragment . isValid ( ) ) ;
fmt = currentFragment . charFormat ( ) ;
QVERIFY ( ! fmt . font ( ) . bold ( ) ) ;
+ + it ;
QVERIFY ( ! it . atEnd ( ) ) ;
// Now check the bold text
currentFragment = it . fragment ( ) ;
QVERIFY ( currentFragment . isValid ( ) ) ;
fmt = currentFragment . charFormat ( ) ;
QVERIFY ( fmt . font ( ) . bold ( ) ) ;
}
}
void tst_QTextDocument : : lineHeightType ( )
{
{
QTextDocument td ;
td . setHtml ( " <html><body>Foobar</body></html> " ) ;
QTextBlock block = td . begin ( ) ;
QTextBlockFormat format = block . blockFormat ( ) ;
QCOMPARE ( int ( format . lineHeightType ( ) ) , int ( QTextBlockFormat : : SingleHeight ) ) ;
QCOMPARE ( format . lineHeight ( ) , 0.0 ) ;
}
{
QTextDocument td ;
td . setHtml ( " <html><head><style type= \" text/css \" >body { line-height: 40px; }</style></head><body>Foobar</body></html> " ) ;
QTextBlock block = td . begin ( ) ;
QTextBlockFormat format = block . blockFormat ( ) ;
QCOMPARE ( int ( format . lineHeightType ( ) ) , int ( QTextBlockFormat : : MinimumHeight ) ) ;
QCOMPARE ( format . lineHeight ( ) , 40.0 ) ;
}
{
QTextDocument td ;
td . setHtml ( " <html><head><style type= \" text/css \" >body { line-height: 200%; }</style></head><body>Foobar</body></html> " ) ;
QTextBlock block = td . begin ( ) ;
QTextBlockFormat format = block . blockFormat ( ) ;
QCOMPARE ( int ( format . lineHeightType ( ) ) , int ( QTextBlockFormat : : ProportionalHeight ) ) ;
QCOMPARE ( format . lineHeight ( ) , 200.0 ) ;
}
{
QTextDocument td ;
td . setHtml ( " <html><head><style type= \" text/css \" >body { line-height: 200%; -qt-line-height-type: single; }</style></head><body>Foobar</body></html> " ) ;
QTextBlock block = td . begin ( ) ;
QTextBlockFormat format = block . blockFormat ( ) ;
QCOMPARE ( int ( format . lineHeightType ( ) ) , int ( QTextBlockFormat : : SingleHeight ) ) ;
QCOMPARE ( format . lineHeight ( ) , 200.0 ) ;
}
{
QTextDocument td ;
td . setHtml ( " <html><head><style type= \" text/css \" >body { line-height: 40px; -qt-line-height-type: proportional; }</style></head><body>Foobar</body></html> " ) ;
QTextBlock block = td . begin ( ) ;
QTextBlockFormat format = block . blockFormat ( ) ;
QCOMPARE ( int ( format . lineHeightType ( ) ) , int ( QTextBlockFormat : : ProportionalHeight ) ) ;
QCOMPARE ( format . lineHeight ( ) , 40.0 ) ;
}
{
QTextDocument td ;
td . setHtml ( " <html><head><style type= \" text/css \" >body { line-height: 10; -qt-line-height-type: fixed; }</style></head><body>Foobar</body></html> " ) ;
QTextBlock block = td . begin ( ) ;
QTextBlockFormat format = block . blockFormat ( ) ;
QCOMPARE ( int ( format . lineHeightType ( ) ) , int ( QTextBlockFormat : : FixedHeight ) ) ;
QCOMPARE ( format . lineHeight ( ) , 10.0 ) ;
}
{
QTextDocument td ;
td . setHtml ( " <html><head><style type= \" text/css \" >body { -qt-line-height-type: fixed; line-height: 10; -qt-line-height-type: fixed; }</style></head><body>Foobar</body></html> " ) ;
QTextBlock block = td . begin ( ) ;
QTextBlockFormat format = block . blockFormat ( ) ;
QCOMPARE ( int ( format . lineHeightType ( ) ) , int ( QTextBlockFormat : : FixedHeight ) ) ;
QCOMPARE ( format . lineHeight ( ) , 10.0 ) ;
}
{
QTextDocument td ;
td . setHtml ( " <html><head><style type= \" text/css \" >body { -qt-line-height-type: proportional; line-height: 3; }</style></head><body>Foobar</body></html> " ) ;
QTextBlock block = td . begin ( ) ;
QTextBlockFormat format = block . blockFormat ( ) ;
QCOMPARE ( int ( format . lineHeightType ( ) ) , int ( QTextBlockFormat : : ProportionalHeight ) ) ;
QCOMPARE ( format . lineHeight ( ) , 3.0 ) ;
}
{
QTextDocument td ;
td . setHtml ( " <html><head><style type= \" text/css \" >body { line-height: 2.5; -qt-line-height-type: proportional; }</style></head><body>Foobar</body></html> " ) ;
QTextBlock block = td . begin ( ) ;
QTextBlockFormat format = block . blockFormat ( ) ;
QCOMPARE ( int ( format . lineHeightType ( ) ) , int ( QTextBlockFormat : : ProportionalHeight ) ) ;
QCOMPARE ( format . lineHeight ( ) , 2.5 ) ;
}
{
QTextDocument td ;
td . setHtml ( " <html><head><style type= \" text/css \" >body { line-height: 33; -qt-line-height-type: minimum; }</style></head><body>Foobar</body></html> " ) ;
QTextBlock block = td . begin ( ) ;
QTextBlockFormat format = block . blockFormat ( ) ;
QCOMPARE ( int ( format . lineHeightType ( ) ) , int ( QTextBlockFormat : : MinimumHeight ) ) ;
QCOMPARE ( format . lineHeight ( ) , 33.0 ) ;
}
{
QTextDocument td ;
td . setHtml ( " <html><head><style type= \" text/css \" >body { -qt-line-height-type: fixed; line-height: 200%; }</style></head><body>Foobar</body></html> " ) ;
QTextBlock block = td . begin ( ) ;
QTextBlockFormat format = block . blockFormat ( ) ;
QCOMPARE ( int ( format . lineHeightType ( ) ) , int ( QTextBlockFormat : : FixedHeight ) ) ;
QCOMPARE ( format . lineHeight ( ) , 200.0 ) ;
}
{
QTextDocument td ;
td . setHtml ( " <html><head><style type= \" text/css \" >body { -qt-line-height-type: fixed; line-height: 200px; }</style></head><body>Foobar</body></html> " ) ;
QTextBlock block = td . begin ( ) ;
QTextBlockFormat format = block . blockFormat ( ) ;
QCOMPARE ( int ( format . lineHeightType ( ) ) , int ( QTextBlockFormat : : FixedHeight ) ) ;
QCOMPARE ( format . lineHeight ( ) , 200.0 ) ;
}
}
void tst_QTextDocument : : cssLineHeightMultiplier ( )
{
{
QTextDocument td ;
td . setHtml ( " <html><head><style type= \" text/css \" >body { line-height: 10; }</style></head><body>Foobar</body></html> " ) ;
QTextBlock block = td . begin ( ) ;
QTextBlockFormat format = block . blockFormat ( ) ;
QCOMPARE ( int ( format . lineHeightType ( ) ) , int ( QTextBlockFormat : : ProportionalHeight ) ) ;
QCOMPARE ( format . lineHeight ( ) , 1000.0 ) ;
}
{
QTextDocument td ;
td . setHtml ( " <html><head><style type= \" text/css \" >body {line-height: 1.38; }</style></head><body>Foobar</body></html> " ) ;
QTextBlock block = td . begin ( ) ;
QTextBlockFormat format = block . blockFormat ( ) ;
QCOMPARE ( int ( format . lineHeightType ( ) ) , int ( QTextBlockFormat : : ProportionalHeight ) ) ;
QCOMPARE ( format . lineHeight ( ) , 138.0 ) ;
}
}
void tst_QTextDocument : : fontTagFace ( )
{
{
QTextDocument td ;
td . setHtml ( " <html><body><font face='Times'>Foobar</font></body></html> " ) ;
QTextFragment fragment = td . begin ( ) . begin ( ) . fragment ( ) ;
QTextCharFormat format = fragment . charFormat ( ) ;
QCOMPARE ( format . fontFamilies ( ) . toStringList ( ) . value ( 0 , QString ( ) ) , QLatin1String ( " Times " ) ) ;
}
{
QTextDocument td ;
td . setHtml ( " <html><body><font face='Times, serif'>Foobar</font></body></html> " ) ;
QTextFragment fragment = td . begin ( ) . begin ( ) . fragment ( ) ;
QTextCharFormat format = fragment . charFormat ( ) ;
QCOMPARE ( format . fontFamilies ( ) . toStringList ( ) . value ( 0 , QString ( ) ) , QLatin1String ( " Times " ) ) ;
QStringList expectedFamilies = { QLatin1String ( " Times " ) , QLatin1String ( " serif " ) } ;
QCOMPARE ( format . fontFamilies ( ) . toStringList ( ) , expectedFamilies ) ;
}
}
void tst_QTextDocument : : mergeFontFamilies ( )
{
QTextDocument td ;
td . setHtml ( QLatin1String (
" <html><body> "
" <span style= \" font-family:'MS Shell Dlg 2'; \" >Hello world</span> "
" </body></html> " ) ) ;
QTextCharFormat newFormat ;
newFormat . setFontFamilies ( { QLatin1String ( " Jokerman " ) } ) ;
QTextCursor cursor = QTextCursor ( & td ) ;
cursor . setPosition ( 0 ) ;
cursor . setPosition ( QByteArray ( " Hello World " ) . size ( ) , QTextCursor : : KeepAnchor ) ;
cursor . mergeCharFormat ( newFormat ) ;
QVERIFY ( td . toHtml ( ) . contains ( QLatin1String ( " font-family:'Jokerman'; " ) ) ) ;
QTextCharFormat newFormatFamilies ;
newFormatFamilies . setFontFamilies ( { QLatin1String ( " Arial " ) , QLatin1String ( " Helvetica " ) } ) ;
cursor . mergeCharFormat ( newFormatFamilies ) ;
QVERIFY ( td . toHtml ( ) . contains ( QLatin1String ( " font-family:'Arial','Helvetica' " ) ) ) ;
newFormatFamilies . setFontFamilies ( { QLatin1String ( " Arial " ) , QLatin1String ( " Jokerman " ) , QLatin1String ( " Helvetica " ) } ) ;
cursor . mergeCharFormat ( newFormatFamilies ) ;
QVERIFY ( td . toHtml ( ) . contains ( QLatin1String ( " font-family:'Arial','Jokerman','Helvetica' " ) ) ) ;
}
void tst_QTextDocument : : clearUndoRedoStacks ( )
{
QTextDocument doc ;
QTextCursor c ( & doc ) ;
c . insertText ( QStringLiteral ( " lorem ipsum " ) ) ;
QVERIFY ( doc . isUndoAvailable ( ) ) ;
doc . clearUndoRedoStacks ( QTextDocument : : UndoStack ) ; // Don't crash
QVERIFY ( ! doc . isUndoAvailable ( ) ) ;
}
void tst_QTextDocument : : resourceProvider ( )
{
int providerCalled = 0 ;
QUrl providerUrl ;
auto provider = [ & ] ( const QUrl & url ) {
providerUrl = url ;
+ + providerCalled ;
return QVariant ( 42 ) ;
} ;
const QUrl url ( " test://img " ) ;
const QString html = QLatin1String ( " <img src='%1'/> " ) . arg ( url . toString ( ) ) ;
QTextDocument doc ;
QVERIFY ( ! doc . resourceProvider ( ) ) ;
doc . setResourceProvider ( provider ) ;
QVERIFY ( doc . resourceProvider ( ) ) ;
doc . setHtml ( html ) ;
const QVariant res = doc . resource ( QTextDocument : : UserResource , url ) ;
QVERIFY ( res . isValid ( ) ) ;
QCOMPARE ( providerUrl , url ) ;
QCOMPARE ( providerCalled , 1 ) ;
QVERIFY ( ! QTextDocument : : defaultResourceProvider ( ) ) ;
QTextDocument : : setDefaultResourceProvider ( provider ) ;
QVERIFY ( QTextDocument : : defaultResourceProvider ( ) ) ;
QTextDocument doc2 ;
QVERIFY ( ! doc2 . resourceProvider ( ) ) ;
doc2 . setHtml ( html ) ;
QVariant res2 = doc2 . resource ( QTextDocument : : UserResource , url ) ;
QCOMPARE ( res2 , res ) ;
QCOMPARE ( providerCalled , 2 ) ;
}
void tst_QTextDocument : : contentsChangeIndices_data ( )
{
QTest : : addColumn < QString > ( " html " ) ;
// adding list entries change the entire block, so change position is
// not the same as the cursor position if this value is >= 0
QTest : : addColumn < int > ( " expectedBegin " ) ;
QTest : : addRow ( " text " ) < < " Test " < < - 1 ;
QTest : : addRow ( " unnumbered list " ) < < " <ul><li>Test</li></ul> " < < 0 ;
QTest : : addRow ( " numbered list " ) < < " <ol><li>Test</li></ol> " < < 0 ;
QTest : : addRow ( " table " ) < < " <table><tr><td>Test</td></tr></table> " < < - 1 ;
}
void tst_QTextDocument : : contentsChangeIndices ( )
{
QFETCH ( QString , html ) ;
QFETCH ( int , expectedBegin ) ;
QTextDocument doc ;
QTestDocumentLayout * layout = new QTestDocumentLayout ( & doc ) ;
doc . setDocumentLayout ( layout ) ;
doc . setHtml ( QString ( " <html><body>%1</body></html> " ) . arg ( html ) ) ;
int documentLength = 0 ;
int cursorLength = 0 ;
int changeBegin = 0 ;
int changeRemoved = 0 ;
int changeAdded = 0 ;
connect ( & doc , & QTextDocument : : contentsChange , this , [ & ] ( int pos , int removed , int added ) {
documentLength = doc . characterCount ( ) ;
QTextCursor cursor ( & doc ) ;
cursor . movePosition ( QTextCursor : : End ) ;
// includes end-of-paragraph character
cursorLength = cursor . position ( ) + 1 ;
changeBegin = pos ;
changeRemoved = removed ;
changeAdded = added ;
} ) ;
QTextCursor cursor ( & doc ) ;
cursor . movePosition ( QTextCursor : : End ) ;
if ( expectedBegin < 0 )
expectedBegin = cursor . position ( ) ;
cursor . insertBlock ( ) ;
const int changeEnd = changeBegin + changeAdded ;
QVERIFY ( documentLength > 0 ) ;
QCOMPARE ( documentLength , cursorLength ) ;
QVERIFY ( documentLength > = changeEnd ) ;
QCOMPARE ( changeBegin , expectedBegin ) ;
QCOMPARE ( changeAdded - changeRemoved , 1 ) ;
}
void tst_QTextDocument : : insertHtmlWithComments_data ( )
{
QTest : : addColumn < QString > ( " html " ) ;
QTest : : addColumn < QStringList > ( " expectedBlocks " ) ;
QTest : : newRow ( " commentless " ) < < " <p>first</p><p>second</p><p>third</p> "
< < QStringList { " first " , " second " , " third " } ;
QTest : : newRow ( " normal " ) < < " <p>first</p><!--<p>second</p>--><p>third</p> "
< < QStringList { " first " , " third " } ;
QTest : : newRow ( " nonClosing " ) < < " <p>first</p><!--<p>second</p><p>third</p> "
< < QStringList { " first " } ;
QTest : : newRow ( " immediatelyClosing " ) < < " <p>first</p><!----><p>second</p><p>third</p> "
< < QStringList { " first " , " second " , " third " } ;
QTest : : newRow ( " fake " ) < < " <p>first</p><!-<p>second</p><p>third</p> "
< < QStringList { " first " , " second " , " third " } ;
QTest : : newRow ( " endingNonExistant " ) < < " <p>first</p>--><p>second</p><p>third</p> "
< < QStringList { " first " , " --> " , " second " , " third " } ;
}
void tst_QTextDocument : : insertHtmlWithComments ( )
{
QFETCH ( QString , html ) ;
QFETCH ( QStringList , expectedBlocks ) ;
QTextDocument doc ;
doc . setHtml ( html ) ;
QCOMPARE ( doc . blockCount ( ) , expectedBlocks . size ( ) ) ;
QStringList blockContent ;
auto currentBlock = doc . begin ( ) ;
while ( currentBlock ! = doc . end ( ) ) {
blockContent . append ( currentBlock . text ( ) ) ;
currentBlock = currentBlock . next ( ) ;
}
QCOMPARE ( blockContent , expectedBlocks ) ;
}
void tst_QTextDocument : : delayedLayout ( )
{
QTextDocument doc ;
doc . setHtml ( " <html>Foobar</html> " ) ;
QCOMPARE ( doc . blockCount ( ) , 1 ) ;
doc . setLayoutEnabled ( false ) ;
// Force creation of a layout
QVERIFY ( doc . documentLayout ( ) ) ;
QTextBlock block = doc . begin ( ) ;
QTextLayout * layout = block . layout ( ) ;
QCOMPARE ( layout - > lineCount ( ) , 0 ) ; // layout didn't happen yet
doc . setLayoutEnabled ( true ) ;
QCOMPARE ( layout - > lineCount ( ) , 1 ) ; // layout happened
}
QTEST_MAIN ( tst_QTextDocument )
# include "tst_qtextdocument.moc"