tests/auto/q3textedit/tst_q3textedit.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/auto/q3textedit/tst_q3textedit.cpp	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,1116 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <limits.h>
+
+#include <q3textedit.h>
+#include <q3textedit.h>
+#include <qapplication.h>
+#include <qclipboard.h>
+#include <qimage.h>
+#include <private/q3richtext_p.h>
+
+#ifdef Q_WS_MAC
+#include <Carbon/Carbon.h>
+#endif
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_Q3TextEdit : public QObject
+{
+    Q_OBJECT
+public:
+    tst_Q3TextEdit();
+    virtual ~tst_Q3TextEdit();
+
+
+public slots:
+    void initTestCase();
+    void cleanupTestCase();
+private slots:
+    void getSetCheck();
+    void redoAvailableEmitted( bool );
+    void undoAvailableEmitted( bool );
+    void copyAvailableEmitted( bool );
+
+    void cursorPosition_data();
+    void cursorPosition();
+    void doKeyboardAction_data();
+    void doKeyboardAction();
+    void text();
+    void text_data();
+
+    void insert();
+
+    void keyClicks_data();
+    void keyClicks();
+
+    //problem specific tests
+    void copyPaste();
+    void copyPaste_data();
+
+    void setReadOnly();
+
+    void find_data();
+    void find();
+    void findSC();
+    void cut();
+
+    void clear();
+    void selectAll();
+    void getSelection_data();
+    void getSelection();
+
+    void setCurrentFont();
+
+    void undoRedo();
+
+    void length_data();
+    void length();
+    void findBackwards();
+    void anchorTest();
+
+private:
+    bool nativeClipboardWorking();
+    Q3TextEdit *textEdit;
+    bool redoA, undoA, copyA;
+
+};
+
+bool tst_Q3TextEdit::nativeClipboardWorking()
+{
+#ifdef Q_WS_MAC
+    PasteboardRef pasteboard;
+    OSStatus status = PasteboardCreate(0, &pasteboard);
+    if (status == noErr)
+        CFRelease(pasteboard);
+    return status == noErr;
+#endif
+    return true;
+}
+
+
+
+class My3TextEdit : public Q3TextEdit
+{
+public:
+    My3TextEdit() : Q3TextEdit() {}
+    void setDocument(Q3TextDocument *doc) { Q3TextEdit::setDocument(doc); }
+    Q3TextDocument *document() { return Q3TextEdit::document(); }
+};
+
+// Testing get/set functions
+void tst_Q3TextEdit::getSetCheck()
+{
+    My3TextEdit obj1;
+    // int Q3TextEdit::maxLogLines()
+    // void Q3TextEdit::setMaxLogLines(int)
+    obj1.setMaxLogLines(0);
+    QCOMPARE(obj1.maxLogLines(), 0);
+    obj1.setMaxLogLines(INT_MIN);
+    QCOMPARE(obj1.maxLogLines(), -1);
+    obj1.setMaxLogLines(INT_MAX);
+    QCOMPARE(obj1.maxLogLines(), INT_MAX);
+
+    // Q3TextDocument * Q3TextEdit::document()
+    // void Q3TextEdit::setDocument(Q3TextDocument *)
+    Q3TextDocument *var2 = new Q3TextDocument(0);
+    obj1.setDocument(var2);
+    QCOMPARE(obj1.document(), var2);
+    // Should've done as QTextEdit, and created a new document, if you setDocument(0).
+    // Unfortunately it doesn't, and we cannot change it.
+    obj1.setDocument((Q3TextDocument *)0);
+    QCOMPARE(obj1.document(), var2);
+    // delete var2; // No delete, since Q3TextEdit takes ownership
+}
+
+typedef QList<int> IntList;
+Q_DECLARE_METATYPE(IntList)
+Q_DECLARE_METATYPE(Q3TextEdit::KeyboardAction)
+
+static const char *const bullet_xpm[] =
+    {
+        "11 11 5 1",
+        ". c None",
+        "b c #3100c5",
+        "# c #313062",
+        "c c #3189ff",
+        "a c #6265cd",
+        "...........",
+        "...####....",
+        ".a#bbbb#a..",
+        ".#ccbbbb#..",
+        "#bccbbbbb#.",
+        "#bbbbbbbb#.",
+        "#bbbbbbcb#.",
+        "#bbbbbccb#.",
+        ".#bbbccb#..",
+        ".a#bbbb#a..",
+        "...####...."
+    };
+
+tst_Q3TextEdit::tst_Q3TextEdit()
+{
+}
+
+tst_Q3TextEdit::~tst_Q3TextEdit()
+{
+}
+
+void tst_Q3TextEdit::initTestCase()
+{
+    textEdit = new Q3TextEdit( 0, "textEdit" );
+    textEdit->setFixedSize( 200, 200 );
+    textEdit->mimeSourceFactory()->setImage( "bullet", QImage( bullet_xpm ) );
+    qApp->setMainWidget( textEdit );
+    textEdit->show();
+}
+
+void tst_Q3TextEdit::cleanupTestCase()
+{
+    delete textEdit;
+}
+
+void tst_Q3TextEdit::doKeyboardAction()
+{
+    QFETCH( QString, text );
+    QFETCH( int, paragraph );
+    QFETCH( int, index );
+    QFETCH( Q3TextEdit::KeyboardAction, action );
+
+    textEdit->setText( text );
+    textEdit->setCursorPosition( paragraph, index );
+    textEdit->doKeyboardAction( action );
+    QTEST( textEdit->text(), "final" );
+}
+
+void tst_Q3TextEdit::doKeyboardAction_data()
+{
+    QTest::addColumn<QString>("text");
+    QTest::addColumn<int>("paragraph");
+    QTest::addColumn<int>("index");
+    QTest::addColumn<Q3TextEdit::KeyboardAction>("action");
+    QTest::addColumn<QString>("final");
+
+    QTest::newRow( "Bush1" ) <<
+	QString("Republicans understand the importance of bondage between mother and child. - Gov GWB")
+			    << 0
+			    << 49
+			    << Q3TextEdit::ActionWordDelete
+			    <<
+	QString("Republicans understand the importance of bondage mother and child. - Gov GWB");
+
+    QTest::newRow( "Bush2" ) <<
+	QString("If we don't succeed, we run the risk of failure. ...George W. Bush, Jr.")
+			    << 0
+			    << 2
+			    << Q3TextEdit::ActionWordBackspace
+			    <<
+	QString(" we don't succeed, we run the risk of failure. ...George W. Bush, Jr.");
+
+    QTest::newRow( "Bush3" ) <<
+	QString("Welcome to Mrs. Bush, and my fellow astronauts. ...Governor George W. Bush, Jr.")
+			    << 0
+			    << 35
+			    << Q3TextEdit::ActionWordDelete
+			    <<
+	QString("Welcome to Mrs. Bush, and my fellowastronauts. ...Governor George W. Bush, Jr.");
+
+    QTest::newRow( "Bush4" ) <<
+	QString("Mars is essentially in the same orbit... Mars is somewhat the same distance from "
+	"the Sun, which is very important. We have seen pictures where there are canals, we "
+	"believe, and water. If there is water, that means there is oxygen. If oxygen, "
+	"that means we can breathe. ...Gov GW Bush, Jr., 8/11/94")
+			    << 0
+			    << 57
+			    << Q3TextEdit::ActionWordBackspace
+			    <<
+	QString("Mars is essentially in the same orbit... Mars is  the same distance from "
+	"the Sun, which is very important. We have seen pictures where there are canals, we "
+	"believe, and water. If there is water, that means there is oxygen. If oxygen, "
+	"that means we can breathe. ...Gov GW Bush, Jr., 8/11/94");
+
+
+    QTest::newRow( "Bush5" ) <<
+	QString("The Holocaust was an obscene period in our nation's history. I mean in this century's history. But we all lived in this century. I didn't live in this century.   GW Bus, 9/15/95")
+			    << 0
+			    << 139
+			    << Q3TextEdit::ActionWordDelete
+			    <<
+	QString("The Holocaust was an obscene period in our nation's history. I mean in this century's history. But we all lived in this century. I didn't lin this century.   GW Bus, 9/15/95");
+
+    QTest::newRow( "Bush6" ) <<
+	QString("I believe we are on an irreversible trend toward more freedom and democracy, but that could change. GWB 5/22/98")
+			    << 0
+			    << 51
+			    << Q3TextEdit::ActionWordBackspace
+			    <<
+	QString("I believe we are on an irreversible trend toward re freedom and democracy, but that could change. GWB 5/22/98");
+
+    QTest::newRow( "Bush7" ) <<
+	QString("One word sums up probably the responsibility of any Governor, and that one\n\n"
+	"word is 'to be prepared'. ...Governor George W. Bush, Jr., 12/6/93")
+			    << 1
+			    << 0
+			    << Q3TextEdit::ActionWordDelete
+			    <<
+	QString("One word sums up probably the responsibility of any Governor, and that one\n"
+	"word is 'to be prepared'. ...Governor George W. Bush, Jr., 12/6/93");
+
+    QTest::newRow( "Bush8" ) <<
+	QString("Verbosity leads to unclear, inarticulate things.\n\n"
+	"...Governor George W. Bush, Jr., 11/30/96")
+			    << 1
+			    << 0
+			    << Q3TextEdit::ActionWordBackspace
+			    <<
+	QString("Verbosity leads to unclear, inarticulate things.\n"
+	"...Governor George W. Bush, Jr., 11/30/96");
+
+    QTest::newRow( "Bush9" ) <<
+	QString("The future will be better tomorrow. ...Governor George W. Bush, Jr.")
+			    << 0
+			    << 29
+			    << Q3TextEdit::ActionWordDelete
+			    <<
+	QString("The future will be better tomGovernor George W. Bush, Jr.");
+
+    QTest::newRow( "Bush10" ) <<
+	QString("The future will be better tomorrow. ...Governor George W. Bush, Jr.")
+			     << 0
+			     << 36
+			     << Q3TextEdit::ActionWordBackspace
+			     <<
+	QString("The future will be better ...Governor George W. Bush, Jr.");
+
+    QTest::newRow( "Bush11" ) <<
+	QString("The future will be better tomorrow. ...Governor George W. Bush, Jr.")
+			     << 0
+			     << 37
+			     << Q3TextEdit::ActionWordDelete
+			     <<
+	QString("The future will be better tomorrow. .Governor George W. Bush, Jr.");
+
+    QTest::newRow( "Bush12" ) <<
+	QString("The future will be better tomorrow. ...Governor George W. Bush, Jr.")
+			     << 0
+			     << 37
+			     << Q3TextEdit::ActionWordBackspace
+			     <<
+	QString("The future will be better ..Governor George W. Bush, Jr.");
+}
+
+void tst_Q3TextEdit::cursorPosition_data()
+{
+    QTest::addColumn<QString>("text");
+    QTest::addColumn<int>("paragraph");
+    QTest::addColumn<int>("index");
+    QTest::newRow( "curpos1" )
+	<< QString("where to find the icon in the application and the\n"
+	   "application name. Also describe to him what the new icon should\n"
+	   "convey. John will create the icon and send you an email asking if it\n"
+	   "fits your wildest dreams. Iterations are expected to occur.") << 2 << 8;
+}
+
+void tst_Q3TextEdit::cursorPosition()
+{
+    if (!nativeClipboardWorking())
+        QSKIP("Native clipboard and cron-started unit tests do not work", SkipAll);
+
+    QFETCH( QString, text );
+    QFETCH( int, paragraph );
+    QFETCH( int, index );
+
+    int para, in;
+    QApplication::clipboard()->setText( text, QClipboard::Clipboard );
+
+    textEdit->clear();
+    textEdit->paste();
+    textEdit->undo();
+    textEdit->paste();
+    textEdit->setCursorPosition( paragraph, index );
+    textEdit->moveCursor( Q3TextEdit::MoveWordForward, TRUE );
+    textEdit->removeSelectedText();
+    textEdit->getCursorPosition( &para, &in );
+    QCOMPARE( para, paragraph );
+    QCOMPARE( in, index );
+}
+
+
+void tst_Q3TextEdit::text()
+{
+    QFETCH( int, format );
+    QFETCH( QString, text );
+    QFETCH( QString, expectedText );
+
+    textEdit->clear();
+    textEdit->setTextFormat( (Qt::TextFormat) format );
+    QCOMPARE( textEdit->text(), QString("") );
+    textEdit->setText( text );
+
+    QCOMPARE( textEdit->text(), expectedText );
+}
+
+void tst_Q3TextEdit::text_data()
+{
+    QTest::addColumn<int>("format");
+    QTest::addColumn<QString>("text");
+    QTest::addColumn<QString>("expectedText");
+
+    QTest::newRow( "PlainText and nbsp" ) << int(Qt::PlainText)
+				       << QString( "Hello" ) + QChar(0xa0) + "World"
+				       << QString( "Hello" ) + QChar(0xa0) + "World";
+    QTest::newRow( "Empty PlainText" ) << int(Qt::PlainText)
+				   << QString( "" )
+				   << QString( "" );
+
+    QTest::newRow( "Empty RichText" ) << int(Qt::RichText)
+				   << QString( "" )
+				   << QString( "" );
+}
+
+void tst_Q3TextEdit::copyPaste_data()
+{
+    QTest::addColumn<QString>("text");
+    QTest::addColumn<QString>("expectedText");
+
+    QTest::newRow( "0" ) << QString( "Hello" ) << QString( "Hello" );
+    QTest::newRow( "1" ) << QString( "Hello<br>Hello" ) << QString( "Hello\nHello" );
+    QTest::newRow( "2" ) << QString( "<p>Hello</p><p>Hello</p>" ) << QString( "Hello\nHello" );
+    QTest::newRow( "3" ) << QString( "<img src=\"bullet\">Hello" ) << QString( "Hello" );
+    QTest::newRow( "4" ) << QString( "<code>Hello</code>" ) << QString( "Hello" );
+    QTest::newRow( "5" ) << QString( "<p><img src=\"bullet\"></img>Hello</p><p>Hello</p>" ) << QString( "Hello\nHello" );
+    QTest::newRow( "6" ) << QString( "<p><img src=\"bullet\">Hello</p><p>Hello</p>" ) << QString( "Hello\nHello" );
+}
+
+// tests copying richtext and pasting as plain text
+void tst_Q3TextEdit::copyPaste()
+{
+    if (!nativeClipboardWorking())
+        QSKIP("Native clipboard and cron-started unit tests do not work", SkipAll);
+
+    QFETCH( QString, text );
+    QFETCH( QString, expectedText );
+
+    textEdit->clear();
+    textEdit->setTextFormat( Qt::RichText );
+
+    textEdit->setText( text );
+    textEdit->selectAll();
+    textEdit->copy();
+
+    QString pastedText = QApplication::clipboard()->text();
+    QEXPECT_FAIL( "6", "funny behaviour if img tag is not closed", Abort );
+    QCOMPARE( pastedText, expectedText );
+}
+
+void tst_Q3TextEdit::setReadOnly()
+{
+    // Check that text() returns the right thing when
+    // in read-only mode
+
+    textEdit->clear();
+    textEdit->setTextFormat( Qt::PlainText );
+    textEdit->setReadOnly( TRUE );
+    QCOMPARE( textEdit->text(), QString("") );
+    textEdit->setText("This is a test");
+    QCOMPARE( textEdit->text(), QString("This is a test") );
+    textEdit->clear();
+    QCOMPARE( textEdit->text(), QString("")  );
+    textEdit->append( "Foobar test" );
+    QCOMPARE( textEdit->text(), QString("Foobar test") );
+    textEdit->clear();
+    QCOMPARE( textEdit->text(), QString("")  );
+    textEdit->setText( "This is a test" );
+    QCOMPARE( textEdit->text(), QString("This is a test") );
+    textEdit->append( " foobar" );
+    QCOMPARE( textEdit->text(), QString("This is a test\n foobar") );
+
+    // Reset read only state
+    textEdit->setReadOnly( FALSE );
+}
+/*
+typedef QValueList<int> IntList;
+Q_DECLARE_METATYPE(IntList)
+*/
+void tst_Q3TextEdit::find_data()
+{
+    // For the moment, this searches plain text, it should be extended to search
+    // rich text and log text
+
+    QTest::addColumn<QString>("text");
+    QTest::addColumn<QString>("searchString");
+    QTest::addColumn<bool>("caseSensitive");
+    QTest::addColumn<bool>("wholeWord");
+    QTest::addColumn<bool>("forward");
+    QTest::addColumn<IntList>("paragraph");
+    QTest::addColumn<IntList>("index");
+
+    {
+	// Check for t's non case-sensitive not whole word forward
+	QString text = "This is a test\nand this is another test";
+	QString searchString = "t";
+	bool caseSensitive = FALSE;
+	bool wholeWord = FALSE;
+	bool forward = TRUE;
+	IntList paragraph;
+	IntList index;
+	paragraph << 0 << 0 << 0 << 1 << 1 << 1 << 1;
+	index << 0 << 10 << 13 << 4 << 15 << 20 << 23;
+	QTest::newRow( "t-noncs-nonww-forward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
+    }
+
+    {
+	// Check for t's case-sensitive not whole word forward
+	QString text = "This is a test\nand this is another test";
+	QString searchString = "t";
+	bool caseSensitive = TRUE;
+	bool wholeWord = FALSE;
+	bool forward = TRUE;
+	IntList paragraph;
+	IntList index;
+	paragraph << 0 << 0 << 1 << 1 << 1 << 1;
+	index << 10 << 13 << 4 << 15 << 20 << 23;
+	QTest::newRow( "t-cs-nonww-forward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
+    }
+
+    {
+	// Check for t's non case-sensitive whole word forward
+	QString text = "This is a test\nand this is another test";
+	QString searchString = "t";
+	bool caseSensitive = FALSE;
+	bool wholeWord = TRUE;
+	bool forward = TRUE;
+	IntList paragraph;
+	IntList index;
+	QTest::newRow( "t-noncs-ww-forward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
+    }
+
+    {
+	// Check for t's non case-sensitive not whole word backward
+	QString text = "This is a test\nand this is another test";
+	QString searchString = "t";
+	bool caseSensitive = FALSE;
+	bool wholeWord = FALSE;
+	bool forward = FALSE;
+	IntList paragraph;
+	IntList index;
+	paragraph << 1 << 1 << 1 << 1 << 0 << 0 << 0;
+	index << 23 << 20 << 15 << 4 << 13 << 10 << 0;
+	QTest::newRow( "t-noncs-nonww-backward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
+    }
+
+    {
+	// Check for t's case-sensitive not whole word backward
+	QString text = "This is a test\nand this is another test";
+	QString searchString = "t";
+	bool caseSensitive = TRUE;
+	bool wholeWord = FALSE;
+	bool forward = FALSE;
+	IntList paragraph;
+	IntList index;
+	paragraph << 1 << 1 << 1 << 1 << 0 << 0;
+	index << 23 << 20 << 15 << 4 << 13 << 10;
+	QTest::newRow( "t-cs-nonww-backward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
+    }
+
+    {
+	// Check for t's non case-sensitive whole word backward
+	QString text = "This is a test\nand this is another test";
+	QString searchString = "t";
+	bool caseSensitive = FALSE;
+	bool wholeWord = TRUE;
+	bool forward = FALSE;
+	IntList paragraph;
+	IntList index;
+	QTest::newRow( "t-noncs-ww-backward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
+    }
+
+    {
+	// Check for 'this' non case-sensitive not whole word forward
+	QString text = "This is a test\nand this is another test";
+	QString searchString = "this";
+	bool caseSensitive = FALSE;
+	bool wholeWord = FALSE;
+	bool forward = TRUE;
+	IntList paragraph;
+	IntList index;
+	paragraph << 0 << 1;
+	index << 0 << 4;
+	QTest::newRow( "this-noncs-nonww-forward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
+    }
+
+    {
+	// Check for 'this' case-sensitive not whole word forward
+	QString text = "This is a test\nand this is another test";
+	QString searchString = "this";
+	bool caseSensitive = TRUE;
+	bool wholeWord = FALSE;
+	bool forward = TRUE;
+	IntList paragraph;
+	IntList index;
+	paragraph << 1;
+	index << 4;
+	QTest::newRow( "this-cs-nonww-forward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
+    }
+
+    {
+	// Check for 'this' non case-sensitive whole word forward
+	QString text = "This is a test\nand this is another test";
+	QString searchString = "this";
+	bool caseSensitive = FALSE;
+	bool wholeWord = TRUE;
+	bool forward = TRUE;
+	IntList paragraph;
+	IntList index;
+	paragraph << 0 << 1;
+	index << 0 << 4;
+	QTest::newRow( "this-noncs-ww-forward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
+    }
+
+    {
+	// Check for 'this' non case-sensitive not whole word backward
+	QString text = "This is a test\nand this is another test";
+	QString searchString = "this";
+	bool caseSensitive = FALSE;
+	bool wholeWord = FALSE;
+	bool forward = FALSE;
+	IntList paragraph;
+	IntList index;
+	paragraph << 1 << 0;
+	index << 4 << 0;
+	QTest::newRow( "this-noncs-nonww-backward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
+    }
+
+    {
+	// Check for 'this' case-sensitive not whole word backward
+	QString text = "This is a test\nand this is another test";
+	QString searchString = "this";
+	bool caseSensitive = TRUE;
+	bool wholeWord = FALSE;
+	bool forward = FALSE;
+	IntList paragraph;
+	IntList index;
+	paragraph << 1;
+	index << 4;
+	QTest::newRow( "this-cs-nonww-backward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
+    }
+
+    {
+	// Check for 'this' non case-sensitive whole word backward
+	QString text = "This is a test\nand this is another test";
+	QString searchString = "this";
+	bool caseSensitive = FALSE;
+	bool wholeWord = TRUE;
+	bool forward = FALSE;
+	IntList paragraph;
+	IntList index;
+	paragraph << 1 << 0;
+	index << 4 << 0;
+	QTest::newRow( "this-noncs-ww-backward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
+    }
+
+        {
+	// Check for ('s non case-sensitive not whole word forward
+	QString text = "This is (a te)st\nand (this is another test) with ( brackets)";
+	QString searchString = "(";
+	bool caseSensitive = FALSE;
+	bool wholeWord = FALSE;
+	bool forward = TRUE;
+	IntList paragraph;
+	IntList index;
+	paragraph << 0 << 1 << 1;
+	index << 8 << 4 << 32;
+	QTest::newRow( "(-noncs-nonww-forward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
+    }
+
+    {
+	// Check for ('s case-sensitive not whole word forward
+	QString text = "This is (a te)st\nand (this is another test) with ( brackets)";
+	QString searchString = "(";
+	bool caseSensitive = TRUE;
+	bool wholeWord = FALSE;
+	bool forward = TRUE;
+	IntList paragraph;
+	IntList index;
+	paragraph << 0 << 1 << 1;
+	index << 8 << 4 << 32;
+	QTest::newRow( "(-cs-nonww-forward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
+    }
+
+    {
+	// Check for ('s non case-sensitive whole word forward
+	QString text = "This is (a te)st\nand (this is another test) with ( brackets)";
+	QString searchString = "(";
+	bool caseSensitive = FALSE;
+	bool wholeWord = TRUE;
+	bool forward = TRUE;
+	IntList paragraph;
+	IntList index;
+	paragraph << 1;
+	index << 32;
+	QTest::newRow( "(-noncs-ww-forward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
+    }
+
+    {
+	// Check for ('s non case-sensitive not whole word backward
+	QString text = "This is (a te)st\nand (this is another test) with ( brackets)";
+	QString searchString = "(";
+	bool caseSensitive = FALSE;
+	bool wholeWord = FALSE;
+	bool forward = FALSE;
+	IntList paragraph;
+	IntList index;
+	paragraph << 1 << 1 << 0;
+	index << 32 << 4 << 8;
+	QTest::newRow( "(-noncs-nonww-backward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
+    }
+
+    {
+	// Check for ('s case-sensitive not whole word backward
+	QString text = "This is (a te)st\nand (this is another test) with ( brackets)";
+	QString searchString = "(";
+	bool caseSensitive = TRUE;
+	bool wholeWord = FALSE;
+	bool forward = FALSE;
+	IntList paragraph;
+	IntList index;
+	paragraph << 1 << 1 << 0;
+	index << 32 << 4 << 8;
+	QTest::newRow( "(-cs-nonww-backward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
+    }
+
+    {
+	// Check for ('s non case-sensitive whole word backward
+	QString text = "This is (a te)st\nand (this is another test) with ( brackets)";
+	QString searchString = "(";
+	bool caseSensitive = FALSE;
+	bool wholeWord = TRUE;
+	bool forward = FALSE;
+	IntList paragraph;
+	IntList index;
+	paragraph << 1;
+	index << 32;
+	QTest::newRow( "(-noncs-ww-backward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
+    }
+
+    {
+	// Check for (this's non case-sensitive whole word backward
+	QString text = "This is (a te)st\nand (this is another test) with (brackets)";
+	QString searchString = "(this";
+	bool caseSensitive = FALSE;
+	bool wholeWord = TRUE;
+	bool forward = FALSE;
+	IntList paragraph;
+	IntList index;
+	paragraph << 1;
+	index << 4;
+	QTest::newRow( "(this-noncs-ww-backward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
+    }
+
+    {
+	// Check for (this's non case-sensitive whole word forward
+	QString text = "This is (a te)st\nand (this is another test) with (brackets)";
+	QString searchString = "(this";
+	bool caseSensitive = FALSE;
+	bool wholeWord = TRUE;
+	bool forward = TRUE;
+	IntList paragraph;
+	IntList index;
+	paragraph << 1;
+	index << 4;
+	QTest::newRow( "(this-noncs-ww-forward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
+    }
+
+    {
+	// Check for " "'s non case-sensitive non whole word forward
+	QString text = "foo";
+	QString searchString = " ";
+	bool caseSensitive = false;
+	bool wholeWord = false;
+	bool forward = true;
+	IntList paragraph;
+	IntList index;
+// 	paragraph << 0 << 1 << 1 << 1;
+//         index << 3 << 0 << 6 << 12;
+	QTest::newRow( " -noncs-nonww-forward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
+    }
+
+    {
+	// Check for " "'s non case-sensitive non whole word backward
+	QString text = "foo ";
+	QString searchString = " ";
+	bool caseSensitive = false;
+	bool wholeWord = false;
+	bool forward = false;
+	IntList paragraph;
+	IntList index;
+	paragraph << 0;
+        index << 3;
+	QTest::newRow( " -noncs-nonww-backward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
+    }
+}
+
+
+void tst_Q3TextEdit::find()
+{
+    QFETCH( QString, text );
+    QFETCH( QString, searchString );
+    QFETCH( bool, caseSensitive );
+    QFETCH( bool, wholeWord );
+    QFETCH( bool, forward );
+    QFETCH( IntList, paragraph );
+    QFETCH( IntList, index );
+
+    textEdit->clear();
+    textEdit->setTextFormat( Qt::PlainText );
+    textEdit->setText( text );
+
+    IntList::Iterator pIt;
+    IntList::Iterator iIt = index.begin();
+    int paraFound = forward ? 0 : INT_MAX;
+    int indexFound = forward ? 0 : INT_MAX;
+
+    QEXPECT_FAIL(" -noncs-nonww-forward", "Searching for space is broken in Q3TextEdit because of the extra space added at the end of all paragraphs", Abort );
+    QEXPECT_FAIL(" -noncs-nonww-backward", "Searching for space is broken in Q3TextEdit because of the extra space added at the end of all paragraphs", Abort );
+
+    // It should not find anything
+    if ( !paragraph.count() ) {
+	QVERIFY( !textEdit->find( searchString, caseSensitive, wholeWord, forward, &paraFound, &indexFound ) );
+    } else {
+	for ( pIt = paragraph.begin(); pIt != paragraph.end(); ++pIt ) {
+	    QVERIFY( textEdit->find( searchString, caseSensitive, wholeWord, forward, &paraFound, &indexFound ) );
+	    QCOMPARE( paraFound, (*pIt) );
+	    QCOMPARE( indexFound, (*iIt) );
+
+	    // This sounds dubious to me, it should search from the next character specified by indexFound
+	    if ( forward )
+		indexFound++;
+	    else
+		indexFound--;
+
+	    ++iIt;
+	}
+    }
+}
+
+void tst_Q3TextEdit::findSC()
+{
+    // Special bug case #29649 test
+    textEdit->clear();
+    textEdit->setTextFormat(Qt::PlainText);
+    textEdit->setText("foo do soo boo arg\ndf df foo a;ls lkdf lsdkjf");
+    textEdit->setCursorPosition(1, 16);
+    int paraFound, indexFound;
+    QVERIFY(textEdit->find("foo", FALSE, FALSE, FALSE));
+    textEdit->getCursorPosition(&paraFound, &indexFound);
+    QCOMPARE(paraFound, 1);
+    QCOMPARE(indexFound, 6);
+    QVERIFY(textEdit->find("foo", FALSE, FALSE, FALSE));
+    textEdit->getCursorPosition(&paraFound, &indexFound);
+    QCOMPARE(paraFound, 0);
+    QCOMPARE(indexFound, 0);
+    QVERIFY(!textEdit->find("foo", FALSE, FALSE, FALSE));
+    QVERIFY(textEdit->find("foo", FALSE, FALSE, FALSE));
+    textEdit->getCursorPosition(&paraFound, &indexFound);
+    QCOMPARE(paraFound, 1);
+    QCOMPARE(indexFound, 6);
+}
+
+
+
+void tst_Q3TextEdit::findBackwards()
+{
+    textEdit->clear();
+    textEdit->setTextFormat(Qt::PlainText);
+    textEdit->setText("ABCABCABCABC");
+    textEdit->setCursorPosition(0, 3);
+    QVERIFY(textEdit->find("ABC", FALSE, FALSE, FALSE));
+    QCOMPARE(textEdit->selectedText(), QString("ABC"));
+    int pFrom, pTo, iFrom, iTo;
+    QString qw;
+
+    textEdit->getSelection(&pFrom, &iFrom, &pTo, &iTo);
+    QCOMPARE(pFrom, 0);
+    QCOMPARE(iFrom, 0);
+    QCOMPARE(pTo, 0);
+    QCOMPARE(iTo, 3);
+}
+void tst_Q3TextEdit::redoAvailableEmitted( bool t )
+{
+    redoA = t;
+}
+
+void tst_Q3TextEdit::undoAvailableEmitted( bool t )
+{
+    undoA = t;
+}
+
+void tst_Q3TextEdit::copyAvailableEmitted( bool t )
+{
+    copyA = t;
+}
+
+void tst_Q3TextEdit::cut()
+{
+    connect( textEdit, SIGNAL( copyAvailable(bool) ), this, SLOT( copyAvailableEmitted(bool) ) );
+    copyA = FALSE;
+    textEdit->setText( "I believe that people who are going to commit crimes shouldn't have guns" );
+    textEdit->selectAll();
+    QTest::qWait( 2000 );
+    QVERIFY( copyA );
+    textEdit->cut();
+    QTest::qWait( 2000 );
+    QVERIFY( !copyA );
+}
+
+void tst_Q3TextEdit::clear()
+{
+    // Clear is actually tested all over the place, this is
+    // really just to test for task 21355
+    textEdit->clear();
+    textEdit->setTextFormat( Qt::RichText );
+    textEdit->setText( "<table align=right></table>" );
+    textEdit->clear();
+    // If it got here, then it didn't crash
+    QVERIFY( TRUE );
+}
+
+void tst_Q3TextEdit::insert()
+{
+    Qt::TextFormat fmt = textEdit->textFormat();
+    textEdit->setTextFormat(Qt::LogText);
+    textEdit->setText("<blue>The<red> following: </red><b>fooooooooooooooooooff</b>\nLine <green>Number 2\nLine</green> Number 3");
+    textEdit->insertParagraph("<orange>#orange#</orange>", 1);
+    textEdit->insertAt(" #\nper\nka<blue>ar<yellow>e\nreo</yellow>le</blue># \n", 2, 3 );
+    textEdit->insertAt("\n#<b>o</b><i>l</i><u>e</u>#\n\n", 100, 100);
+    textEdit->insertAt("<u>#o\nle#</u>", 0, 10);
+    QString result = "<blue>The<red> follow<u>#o\nle#</u>ing: </red><b>fooooooooooooooooooff</b>\n<orange>#orange#</orange>\n"
+		     "Lin #\nper\nka<blue>ar<yellow>e\nreo</yellow>le</blue># \ne <green>Number 2\nLine</green> Number 3\n"
+		     "#<b>o</b><i>l</i><u>e</u>#\n\n\n";
+    QCOMPARE(textEdit->text(), result);
+    textEdit->setTextFormat(fmt);
+}
+
+void tst_Q3TextEdit::keyClicks_data()
+{
+    QTest::addColumn<QString>("inputString");
+
+    QTest::newRow("English") << "This is not a sentence.";
+    QTest::newRow("Norwegian") << "\x0e6\x0f8\x0e5\x0c6\x0d8\x0c5 er norske bokstaver.";
+}
+
+void tst_Q3TextEdit::keyClicks()
+{
+    QFETCH(QString, inputString);
+
+    textEdit->clear();
+    textEdit->setTextFormat(Qt::PlainText);
+    textEdit->setReadOnly(false);
+
+    QVERIFY(textEdit->text().isEmpty());
+    QTest::keyClicks(textEdit, inputString);
+    QCOMPARE(textEdit->text(), inputString);
+}
+
+
+
+void tst_Q3TextEdit::selectAll()
+{
+    QString testString = "This is test for task #24092";
+    textEdit->setText( testString );
+
+    textEdit->setTextFormat(Qt::PlainText);
+    textEdit->selectAll(TRUE);
+    QVERIFY( textEdit->hasSelectedText() );
+    textEdit->selectAll(FALSE);
+    QVERIFY( !textEdit->hasSelectedText() );
+
+    textEdit->setTextFormat(Qt::RichText);
+    textEdit->selectAll(TRUE);
+    QVERIFY( textEdit->hasSelectedText() );
+    textEdit->selectAll(FALSE);
+    QVERIFY( !textEdit->hasSelectedText() );
+    textEdit->setTextFormat(Qt::LogText);
+    textEdit->selectAll(TRUE);
+    QVERIFY( textEdit->hasSelectedText() );
+    textEdit->selectAll(FALSE);
+    QVERIFY( !textEdit->hasSelectedText() );
+}
+
+void tst_Q3TextEdit::setCurrentFont()
+{
+    textEdit->clear();
+    textEdit->setTextFormat(Qt::LogText);
+    textEdit->setCurrentFont(QFont("Courier New", 9));
+    textEdit->setText("Just some dummy text");
+    QCOMPARE(textEdit->text(), QString("Just some dummy text\n"));
+}
+
+void tst_Q3TextEdit::undoRedo()
+{
+    Q3TextEdit edit;
+    edit.setTextFormat(Qt::PlainText);
+
+    QString deftext("Just some text");
+    edit.setText(deftext);
+    edit.insertAt("<tag>",0, 5);
+    QCOMPARE(edit.text(), QString("Just <tag>some text"));
+    edit.undo();
+    QCOMPARE(edit.text(), deftext);
+    edit.insertAt("<tag>",0, 5);
+    edit.insertAt("</tag>",0, 14);
+    QCOMPARE(edit.text(), QString("Just <tag>some</tag> text"));
+    edit.undo();
+    QCOMPARE(edit.text(), QString("Just <tag>some text"));
+    edit.undo();
+    QCOMPARE(edit.text(), QString("Just some text"));
+    edit.insertAt("<tag>",0, 5);
+    edit.insertAt("</tag>",0, 10);
+    QCOMPARE(edit.text(), QString("Just <tag></tag>some text"));
+    edit.undo();
+    QCOMPARE(edit.text(), QString("Just some text"));
+}
+
+void tst_Q3TextEdit::length_data()
+{
+    // The expected length values are based on what is returned in Qt 3.2.1.
+    // We don't want the semantics of this function to change again, no
+    // matter how broken it is, so if this function fails, the test data has to be seen as
+    // correct.  In Qt 4.0, this function will not exist in this form.
+
+    QTest::addColumn<int>("textFormat");
+    QTest::addColumn<QString>("text");
+    QTest::addColumn<int>("expectedLength");
+
+    QTest::newRow("plainText") << int(Qt::PlainText) << "This is a test" << 14;
+    QTest::newRow("plainTextNewLines") << int(Qt::PlainText) << "This is a test\nThis is a test\nThis is a test" << 44;
+    QTest::newRow("logText") << int(Qt::LogText) << "This is a test" << 14;
+    QTest::newRow("logTextNewLines") << int(Qt::LogText) << "This is a test\nThis is a test\nThis is a test" << 42;
+    QTest::newRow("logTextTags") << int(Qt::LogText) << "<b>This is a test</b>" << 14;
+    QTest::newRow("logTextTagsNewLines") << int(Qt::LogText) << "<b>This is a test\nThis is a test\nThis is a test</b>" << 42;
+    QTest::newRow("richText") << int(Qt::RichText) << "This is a test" << 14;
+    QTest::newRow("richTextNewLines") << int(Qt::RichText) << "This is a test\nThis is a test\nThis is a test" << 44;
+    QTest::newRow("richTextTags") << int(Qt::RichText) << "<b>This is a test</b>" << 14;
+}
+
+void tst_Q3TextEdit::length()
+{
+    QFETCH(int, textFormat);
+    QFETCH(QString, text);
+    QFETCH(int, expectedLength);
+
+    textEdit->setTextFormat((Qt::TextFormat)textFormat);
+    textEdit->setText(text);
+    QCOMPARE(textEdit->length(), expectedLength);
+}
+
+void tst_Q3TextEdit::getSelection_data()
+{
+    QTest::addColumn<int>("textFormat");
+    QTest::addColumn<QString>("text");
+
+    QTest::addColumn<int>("paragFrom");
+    QTest::addColumn<int>("indexFrom");
+    QTest::addColumn<int>("paragTo");
+    QTest::addColumn<int>("indexTo");
+
+    QTest::addColumn<int>("selParagFrom");
+    QTest::addColumn<int>("selIndexFrom");
+    QTest::addColumn<int>("selParagTo");
+    QTest::addColumn<int>("selIndexTo");
+
+    QTest::newRow("plainText") << int(Qt::PlainText) << "This is a test" << 0 << 0 << 0 << 2 << 0 << 0 << 0 << 2;
+    QTest::newRow("richText") << int(Qt::RichText) << "This is a test" << 0 << 0 << 0 << 2 << 0 << 0 << 0 << 2;
+    QTest::newRow("logText") << int(Qt::LogText) << "This is a test" << 0 << 0 << 0 << 2 << 0 << 0 << 0 << 2;
+}
+
+void tst_Q3TextEdit::getSelection()
+{
+    QFETCH(int, textFormat);
+    QFETCH(QString, text);
+
+    QFETCH(int, paragFrom);
+    QFETCH(int, indexFrom);
+    QFETCH(int, paragTo);
+    QFETCH(int, indexTo);
+
+    QFETCH(int, selParagFrom);
+    QFETCH(int, selIndexFrom);
+    QFETCH(int, selParagTo);
+    QFETCH(int, selIndexTo);
+
+    int pFr, iFr, pTo, iTo;
+    textEdit->setText(text);
+    textEdit->setTextFormat((Qt::TextFormat)textFormat);
+    textEdit->setSelection(paragFrom, indexFrom, paragTo, indexTo);
+    textEdit->getSelection(&pFr, &iFr, &pTo, &iTo);
+
+    QCOMPARE(pFr, selParagFrom);
+    QCOMPARE(iFr, selIndexFrom);
+    QCOMPARE(pTo, selParagTo);
+    QCOMPARE(iTo, selIndexTo);
+}
+
+void tst_Q3TextEdit::anchorTest()
+{
+    // This is from task 57709
+    Q3TextEdit edit;
+    QString richText = "<p dir=\"ltr\"><a name=\"Gold\"></a>something</p>\n"
+                       "<p dir=\"ltr\"><a name=\"Silver\"></a>more"
+                       "<a name=\"Bronze\"></a>stuff</p>\n";
+    edit.setText(richText);
+
+    QString expected = "<html><head><meta name=\"qrichtext\" content=\"1\" /></head>"
+                    "<body style=\"font-size:%1pt;font-family:%2\">\n"
+                       + richText + "</body></html>\n";
+    QFont f = edit.font();
+    expected = expected.arg(f.pointSize()).arg(f.family());
+    QCOMPARE(edit.text(),expected);
+}
+
+QTEST_MAIN(tst_Q3TextEdit)
+#include "tst_q3textedit.moc"
+