1
/****************************************************************************
2
**
3
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4
** All rights reserved.
5
** Contact: Nokia Corporation (qt-info@nokia.com)
6
**
7
** This file is part of the test suite of the Qt Toolkit.
8
**
9
** $QT_BEGIN_LICENSE:LGPL$
10
** GNU Lesser General Public License Usage
11
** This file may be used under the terms of the GNU Lesser General Public
12
** License version 2.1 as published by the Free Software Foundation and
13
** appearing in the file LICENSE.LGPL included in the packaging of this
14
** file. Please review the following information to ensure the GNU Lesser
15
** General Public License version 2.1 requirements will be met:
16
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17
**
18
** In addition, as a special exception, Nokia gives you certain additional
19
** rights. These rights are described in the Nokia Qt LGPL Exception
20
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21
**
22
** GNU General Public License Usage
23
** Alternatively, this file may be used under the terms of the GNU General
24
** Public License version 3.0 as published by the Free Software Foundation
25
** and appearing in the file LICENSE.GPL included in the packaging of this
26
** file. Please review the following information to ensure the GNU General
27
** Public License version 3.0 requirements will be met:
28
** http://www.gnu.org/copyleft/gpl.html.
29
**
30
** Other Usage
31
** Alternatively, this file may be used in accordance with the terms and
32
** conditions contained in a signed written agreement between you and Nokia.
33
**
34
**
35
**
36
**
37
**
38
** $QT_END_LICENSE$
39
**
40
****************************************************************************/
41
42
43
#include <QtTest/QtTest>
44
45
#include <limits.h>
46
47
#include <q3textedit.h>
48
#include <q3textedit.h>
49
#include <qapplication.h>
50
#include <qclipboard.h>
51
#include <qimage.h>
52
#include <private/q3richtext_p.h>
53
54
#ifdef Q_WS_MAC
55
#include <Carbon/Carbon.h>
56
#endif
57
58
//TESTED_CLASS=
59
//TESTED_FILES=
60
61
class tst_Q3TextEdit : public QObject
62
{
63
    Q_OBJECT
64
public:
65
    tst_Q3TextEdit();
66
    virtual ~tst_Q3TextEdit();
67
68
69
public slots:
70
    void initTestCase();
71
    void cleanupTestCase();
72
private slots:
73
    void getSetCheck();
74
    void redoAvailableEmitted( bool );
75
    void undoAvailableEmitted( bool );
76
    void copyAvailableEmitted( bool );
77
78
    void cursorPosition_data();
79
    void cursorPosition();
80
    void doKeyboardAction_data();
81
    void doKeyboardAction();
82
    void text();
83
    void text_data();
84
85
    void insert();
86
87
    void keyClicks_data();
88
    void keyClicks();
89
90
    //problem specific tests
91
    void copyPaste();
92
    void copyPaste_data();
93
94
    void setReadOnly();
95
96
    void find_data();
97
    void find();
98
    void findSC();
99
    void cut();
100
101
    void clear();
102
    void selectAll();
103
    void getSelection_data();
104
    void getSelection();
105
106
    void setCurrentFont();
107
108
    void undoRedo();
109
110
    void length_data();
111
    void length();
112
    void findBackwards();
113
    void anchorTest();
114
115
private:
116
    bool nativeClipboardWorking();
117
    Q3TextEdit *textEdit;
118
    bool redoA, undoA, copyA;
119
120
};
121
122
bool tst_Q3TextEdit::nativeClipboardWorking()
123
{
124
#ifdef Q_WS_MAC
125
    PasteboardRef pasteboard;
126
    OSStatus status = PasteboardCreate(0, &pasteboard);
127
    if (status == noErr)
128
        CFRelease(pasteboard);
129
    return status == noErr;
130
#endif
131
    return true;
132
}
133
134
135
136
class My3TextEdit : public Q3TextEdit
137
{
138
public:
139
    My3TextEdit() : Q3TextEdit() {}
140
    void setDocument(Q3TextDocument *doc) { Q3TextEdit::setDocument(doc); }
141
    Q3TextDocument *document() { return Q3TextEdit::document(); }
142
};
143
144
// Testing get/set functions
145
void tst_Q3TextEdit::getSetCheck()
146
{
147
    My3TextEdit obj1;
148
    // int Q3TextEdit::maxLogLines()
149
    // void Q3TextEdit::setMaxLogLines(int)
150
    obj1.setMaxLogLines(0);
151
    QCOMPARE(obj1.maxLogLines(), 0);
152
    obj1.setMaxLogLines(INT_MIN);
153
    QCOMPARE(obj1.maxLogLines(), -1);
154
    obj1.setMaxLogLines(INT_MAX);
155
    QCOMPARE(obj1.maxLogLines(), INT_MAX);
156
157
    // Q3TextDocument * Q3TextEdit::document()
158
    // void Q3TextEdit::setDocument(Q3TextDocument *)
159
    Q3TextDocument *var2 = new Q3TextDocument(0);
160
    obj1.setDocument(var2);
161
    QCOMPARE(obj1.document(), var2);
162
    // Should've done as QTextEdit, and created a new document, if you setDocument(0).
163
    // Unfortunately it doesn't, and we cannot change it.
164
    obj1.setDocument((Q3TextDocument *)0);
165
    QCOMPARE(obj1.document(), var2);
166
    // delete var2; // No delete, since Q3TextEdit takes ownership
167
}
168
169
typedef QList<int> IntList;
170
Q_DECLARE_METATYPE(IntList)
171
Q_DECLARE_METATYPE(Q3TextEdit::KeyboardAction)
172
173
static const char *const bullet_xpm[] =
174
    {
175
        "11 11 5 1",
176
        ". c None",
177
        "b c #3100c5",
178
        "# c #313062",
179
        "c c #3189ff",
180
        "a c #6265cd",
181
        "...........",
182
        "...####....",
183
        ".a#bbbb#a..",
184
        ".#ccbbbb#..",
185
        "#bccbbbbb#.",
186
        "#bbbbbbbb#.",
187
        "#bbbbbbcb#.",
188
        "#bbbbbccb#.",
189
        ".#bbbccb#..",
190
        ".a#bbbb#a..",
191
        "...####...."
192
    };
193
194
tst_Q3TextEdit::tst_Q3TextEdit()
195
{
196
}
197
198
tst_Q3TextEdit::~tst_Q3TextEdit()
199
{
200
}
201
202
void tst_Q3TextEdit::initTestCase()
203
{
204
    textEdit = new Q3TextEdit( 0, "textEdit" );
205
    textEdit->setFixedSize( 200, 200 );
206
    textEdit->mimeSourceFactory()->setImage( "bullet", QImage( bullet_xpm ) );
207
    qApp->setMainWidget( textEdit );
208
    textEdit->show();
209
}
210
211
void tst_Q3TextEdit::cleanupTestCase()
212
{
213
    delete textEdit;
214
}
215
216
void tst_Q3TextEdit::doKeyboardAction()
217
{
218
    QFETCH( QString, text );
219
    QFETCH( int, paragraph );
220
    QFETCH( int, index );
221
    QFETCH( Q3TextEdit::KeyboardAction, action );
222
223
    textEdit->setText( text );
224
    textEdit->setCursorPosition( paragraph, index );
225
    textEdit->doKeyboardAction( action );
226
    QTEST( textEdit->text(), "final" );
227
}
228
229
void tst_Q3TextEdit::doKeyboardAction_data()
230
{
231
    QTest::addColumn<QString>("text");
232
    QTest::addColumn<int>("paragraph");
233
    QTest::addColumn<int>("index");
234
    QTest::addColumn<Q3TextEdit::KeyboardAction>("action");
235
    QTest::addColumn<QString>("final");
236
237
    QTest::newRow( "Bush1" ) <<
238
	QString("Republicans understand the importance of bondage between mother and child. - Gov GWB")
239
			    << 0
240
			    << 49
241
			    << Q3TextEdit::ActionWordDelete
242
			    <<
243
	QString("Republicans understand the importance of bondage mother and child. - Gov GWB");
244
245
    QTest::newRow( "Bush2" ) <<
246
	QString("If we don't succeed, we run the risk of failure. ...George W. Bush, Jr.")
247
			    << 0
248
			    << 2
249
			    << Q3TextEdit::ActionWordBackspace
250
			    <<
251
	QString(" we don't succeed, we run the risk of failure. ...George W. Bush, Jr.");
252
253
    QTest::newRow( "Bush3" ) <<
254
	QString("Welcome to Mrs. Bush, and my fellow astronauts. ...Governor George W. Bush, Jr.")
255
			    << 0
256
			    << 35
257
			    << Q3TextEdit::ActionWordDelete
258
			    <<
259
	QString("Welcome to Mrs. Bush, and my fellowastronauts. ...Governor George W. Bush, Jr.");
260
261
    QTest::newRow( "Bush4" ) <<
262
	QString("Mars is essentially in the same orbit... Mars is somewhat the same distance from "
263
	"the Sun, which is very important. We have seen pictures where there are canals, we "
264
	"believe, and water. If there is water, that means there is oxygen. If oxygen, "
265
	"that means we can breathe. ...Gov GW Bush, Jr., 8/11/94")
266
			    << 0
267
			    << 57
268
			    << Q3TextEdit::ActionWordBackspace
269
			    <<
270
	QString("Mars is essentially in the same orbit... Mars is  the same distance from "
271
	"the Sun, which is very important. We have seen pictures where there are canals, we "
272
	"believe, and water. If there is water, that means there is oxygen. If oxygen, "
273
	"that means we can breathe. ...Gov GW Bush, Jr., 8/11/94");
274
275
276
    QTest::newRow( "Bush5" ) <<
277
	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")
278
			    << 0
279
			    << 139
280
			    << Q3TextEdit::ActionWordDelete
281
			    <<
282
	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");
283
284
    QTest::newRow( "Bush6" ) <<
285
	QString("I believe we are on an irreversible trend toward more freedom and democracy, but that could change. GWB 5/22/98")
286
			    << 0
287
			    << 51
288
			    << Q3TextEdit::ActionWordBackspace
289
			    <<
290
	QString("I believe we are on an irreversible trend toward re freedom and democracy, but that could change. GWB 5/22/98");
291
292
    QTest::newRow( "Bush7" ) <<
293
	QString("One word sums up probably the responsibility of any Governor, and that one\n\n"
294
	"word is 'to be prepared'. ...Governor George W. Bush, Jr., 12/6/93")
295
			    << 1
296
			    << 0
297
			    << Q3TextEdit::ActionWordDelete
298
			    <<
299
	QString("One word sums up probably the responsibility of any Governor, and that one\n"
300
	"word is 'to be prepared'. ...Governor George W. Bush, Jr., 12/6/93");
301
302
    QTest::newRow( "Bush8" ) <<
303
	QString("Verbosity leads to unclear, inarticulate things.\n\n"
304
	"...Governor George W. Bush, Jr., 11/30/96")
305
			    << 1
306
			    << 0
307
			    << Q3TextEdit::ActionWordBackspace
308
			    <<
309
	QString("Verbosity leads to unclear, inarticulate things.\n"
310
	"...Governor George W. Bush, Jr., 11/30/96");
311
312
    QTest::newRow( "Bush9" ) <<
313
	QString("The future will be better tomorrow. ...Governor George W. Bush, Jr.")
314
			    << 0
315
			    << 29
316
			    << Q3TextEdit::ActionWordDelete
317
			    <<
318
	QString("The future will be better tomGovernor George W. Bush, Jr.");
319
320
    QTest::newRow( "Bush10" ) <<
321
	QString("The future will be better tomorrow. ...Governor George W. Bush, Jr.")
322
			     << 0
323
			     << 36
324
			     << Q3TextEdit::ActionWordBackspace
325
			     <<
326
	QString("The future will be better ...Governor George W. Bush, Jr.");
327
328
    QTest::newRow( "Bush11" ) <<
329
	QString("The future will be better tomorrow. ...Governor George W. Bush, Jr.")
330
			     << 0
331
			     << 37
332
			     << Q3TextEdit::ActionWordDelete
333
			     <<
334
	QString("The future will be better tomorrow. .Governor George W. Bush, Jr.");
335
336
    QTest::newRow( "Bush12" ) <<
337
	QString("The future will be better tomorrow. ...Governor George W. Bush, Jr.")
338
			     << 0
339
			     << 37
340
			     << Q3TextEdit::ActionWordBackspace
341
			     <<
342
	QString("The future will be better ..Governor George W. Bush, Jr.");
343
}
344
345
void tst_Q3TextEdit::cursorPosition_data()
346
{
347
    QTest::addColumn<QString>("text");
348
    QTest::addColumn<int>("paragraph");
349
    QTest::addColumn<int>("index");
350
    QTest::newRow( "curpos1" )
351
	<< QString("where to find the icon in the application and the\n"
352
	   "application name. Also describe to him what the new icon should\n"
353
	   "convey. John will create the icon and send you an email asking if it\n"
354
	   "fits your wildest dreams. Iterations are expected to occur.") << 2 << 8;
355
}
356
357
void tst_Q3TextEdit::cursorPosition()
358
{
359
    if (!nativeClipboardWorking())
360
        QSKIP("Native clipboard and cron-started unit tests do not work", SkipAll);
361
362
    QFETCH( QString, text );
363
    QFETCH( int, paragraph );
364
    QFETCH( int, index );
365
366
    int para, in;
367
    QApplication::clipboard()->setText( text, QClipboard::Clipboard );
368
369
    textEdit->clear();
370
    textEdit->paste();
371
    textEdit->undo();
372
    textEdit->paste();
373
    textEdit->setCursorPosition( paragraph, index );
374
    textEdit->moveCursor( Q3TextEdit::MoveWordForward, TRUE );
375
    textEdit->removeSelectedText();
376
    textEdit->getCursorPosition( &para, &in );
377
    QCOMPARE( para, paragraph );
378
    QCOMPARE( in, index );
379
}
380
381
382
void tst_Q3TextEdit::text()
383
{
384
    QFETCH( int, format );
385
    QFETCH( QString, text );
386
    QFETCH( QString, expectedText );
387
388
    textEdit->clear();
389
    textEdit->setTextFormat( (Qt::TextFormat) format );
390
    QCOMPARE( textEdit->text(), QString("") );
391
    textEdit->setText( text );
392
393
    QCOMPARE( textEdit->text(), expectedText );
394
}
395
396
void tst_Q3TextEdit::text_data()
397
{
398
    QTest::addColumn<int>("format");
399
    QTest::addColumn<QString>("text");
400
    QTest::addColumn<QString>("expectedText");
401
402
    QTest::newRow( "PlainText and nbsp" ) << int(Qt::PlainText)
403
				       << QString( "Hello" ) + QChar(0xa0) + "World"
404
				       << QString( "Hello" ) + QChar(0xa0) + "World";
405
    QTest::newRow( "Empty PlainText" ) << int(Qt::PlainText)
406
				   << QString( "" )
407
				   << QString( "" );
408
409
    QTest::newRow( "Empty RichText" ) << int(Qt::RichText)
410
				   << QString( "" )
411
				   << QString( "" );
412
}
413
414
void tst_Q3TextEdit::copyPaste_data()
415
{
416
    QTest::addColumn<QString>("text");
417
    QTest::addColumn<QString>("expectedText");
418
419
    QTest::newRow( "0" ) << QString( "Hello" ) << QString( "Hello" );
420
    QTest::newRow( "1" ) << QString( "Hello<br>Hello" ) << QString( "Hello\nHello" );
421
    QTest::newRow( "2" ) << QString( "<p>Hello</p><p>Hello</p>" ) << QString( "Hello\nHello" );
422
    QTest::newRow( "3" ) << QString( "<img src=\"bullet\">Hello" ) << QString( "Hello" );
423
    QTest::newRow( "4" ) << QString( "<code>Hello</code>" ) << QString( "Hello" );
424
    QTest::newRow( "5" ) << QString( "<p><img src=\"bullet\"></img>Hello</p><p>Hello</p>" ) << QString( "Hello\nHello" );
425
    QTest::newRow( "6" ) << QString( "<p><img src=\"bullet\">Hello</p><p>Hello</p>" ) << QString( "Hello\nHello" );
426
}
427
428
// tests copying richtext and pasting as plain text
429
void tst_Q3TextEdit::copyPaste()
430
{
431
    if (!nativeClipboardWorking())
432
        QSKIP("Native clipboard and cron-started unit tests do not work", SkipAll);
433
434
    QFETCH( QString, text );
435
    QFETCH( QString, expectedText );
436
437
    textEdit->clear();
438
    textEdit->setTextFormat( Qt::RichText );
439
440
    textEdit->setText( text );
441
    textEdit->selectAll();
442
    textEdit->copy();
443
444
    QString pastedText = QApplication::clipboard()->text();
445
    QEXPECT_FAIL( "6", "funny behaviour if img tag is not closed", Abort );
446
    QCOMPARE( pastedText, expectedText );
447
}
448
449
void tst_Q3TextEdit::setReadOnly()
450
{
451
    // Check that text() returns the right thing when
452
    // in read-only mode
453
454
    textEdit->clear();
455
    textEdit->setTextFormat( Qt::PlainText );
456
    textEdit->setReadOnly( TRUE );
457
    QCOMPARE( textEdit->text(), QString("") );
458
    textEdit->setText("This is a test");
459
    QCOMPARE( textEdit->text(), QString("This is a test") );
460
    textEdit->clear();
461
    QCOMPARE( textEdit->text(), QString("")  );
462
    textEdit->append( "Foobar test" );
463
    QCOMPARE( textEdit->text(), QString("Foobar test") );
464
    textEdit->clear();
465
    QCOMPARE( textEdit->text(), QString("")  );
466
    textEdit->setText( "This is a test" );
467
    QCOMPARE( textEdit->text(), QString("This is a test") );
468
    textEdit->append( " foobar" );
469
    QCOMPARE( textEdit->text(), QString("This is a test\n foobar") );
470
471
    // Reset read only state
472
    textEdit->setReadOnly( FALSE );
473
}
474
/*
475
typedef QValueList<int> IntList;
476
Q_DECLARE_METATYPE(IntList)
477
*/
478
void tst_Q3TextEdit::find_data()
479
{
480
    // For the moment, this searches plain text, it should be extended to search
481
    // rich text and log text
482
483
    QTest::addColumn<QString>("text");
484
    QTest::addColumn<QString>("searchString");
485
    QTest::addColumn<bool>("caseSensitive");
486
    QTest::addColumn<bool>("wholeWord");
487
    QTest::addColumn<bool>("forward");
488
    QTest::addColumn<IntList>("paragraph");
489
    QTest::addColumn<IntList>("index");
490
491
    {
492
	// Check for t's non case-sensitive not whole word forward
493
	QString text = "This is a test\nand this is another test";
494
	QString searchString = "t";
495
	bool caseSensitive = FALSE;
496
	bool wholeWord = FALSE;
497
	bool forward = TRUE;
498
	IntList paragraph;
499
	IntList index;
500
	paragraph << 0 << 0 << 0 << 1 << 1 << 1 << 1;
501
	index << 0 << 10 << 13 << 4 << 15 << 20 << 23;
502
	QTest::newRow( "t-noncs-nonww-forward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
503
    }
504
505
    {
506
	// Check for t's case-sensitive not whole word forward
507
	QString text = "This is a test\nand this is another test";
508
	QString searchString = "t";
509
	bool caseSensitive = TRUE;
510
	bool wholeWord = FALSE;
511
	bool forward = TRUE;
512
	IntList paragraph;
513
	IntList index;
514
	paragraph << 0 << 0 << 1 << 1 << 1 << 1;
515
	index << 10 << 13 << 4 << 15 << 20 << 23;
516
	QTest::newRow( "t-cs-nonww-forward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
517
    }
518
519
    {
520
	// Check for t's non case-sensitive whole word forward
521
	QString text = "This is a test\nand this is another test";
522
	QString searchString = "t";
523
	bool caseSensitive = FALSE;
524
	bool wholeWord = TRUE;
525
	bool forward = TRUE;
526
	IntList paragraph;
527
	IntList index;
528
	QTest::newRow( "t-noncs-ww-forward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
529
    }
530
531
    {
532
	// Check for t's non case-sensitive not whole word backward
533
	QString text = "This is a test\nand this is another test";
534
	QString searchString = "t";
535
	bool caseSensitive = FALSE;
536
	bool wholeWord = FALSE;
537
	bool forward = FALSE;
538
	IntList paragraph;
539
	IntList index;
540
	paragraph << 1 << 1 << 1 << 1 << 0 << 0 << 0;
541
	index << 23 << 20 << 15 << 4 << 13 << 10 << 0;
542
	QTest::newRow( "t-noncs-nonww-backward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
543
    }
544
545
    {
546
	// Check for t's case-sensitive not whole word backward
547
	QString text = "This is a test\nand this is another test";
548
	QString searchString = "t";
549
	bool caseSensitive = TRUE;
550
	bool wholeWord = FALSE;
551
	bool forward = FALSE;
552
	IntList paragraph;
553
	IntList index;
554
	paragraph << 1 << 1 << 1 << 1 << 0 << 0;
555
	index << 23 << 20 << 15 << 4 << 13 << 10;
556
	QTest::newRow( "t-cs-nonww-backward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
557
    }
558
559
    {
560
	// Check for t's non case-sensitive whole word backward
561
	QString text = "This is a test\nand this is another test";
562
	QString searchString = "t";
563
	bool caseSensitive = FALSE;
564
	bool wholeWord = TRUE;
565
	bool forward = FALSE;
566
	IntList paragraph;
567
	IntList index;
568
	QTest::newRow( "t-noncs-ww-backward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
569
    }
570
571
    {
572
	// Check for 'this' non case-sensitive not whole word forward
573
	QString text = "This is a test\nand this is another test";
574
	QString searchString = "this";
575
	bool caseSensitive = FALSE;
576
	bool wholeWord = FALSE;
577
	bool forward = TRUE;
578
	IntList paragraph;
579
	IntList index;
580
	paragraph << 0 << 1;
581
	index << 0 << 4;
582
	QTest::newRow( "this-noncs-nonww-forward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
583
    }
584
585
    {
586
	// Check for 'this' case-sensitive not whole word forward
587
	QString text = "This is a test\nand this is another test";
588
	QString searchString = "this";
589
	bool caseSensitive = TRUE;
590
	bool wholeWord = FALSE;
591
	bool forward = TRUE;
592
	IntList paragraph;
593
	IntList index;
594
	paragraph << 1;
595
	index << 4;
596
	QTest::newRow( "this-cs-nonww-forward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
597
    }
598
599
    {
600
	// Check for 'this' non case-sensitive whole word forward
601
	QString text = "This is a test\nand this is another test";
602
	QString searchString = "this";
603
	bool caseSensitive = FALSE;
604
	bool wholeWord = TRUE;
605
	bool forward = TRUE;
606
	IntList paragraph;
607
	IntList index;
608
	paragraph << 0 << 1;
609
	index << 0 << 4;
610
	QTest::newRow( "this-noncs-ww-forward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
611
    }
612
613
    {
614
	// Check for 'this' non case-sensitive not whole word backward
615
	QString text = "This is a test\nand this is another test";
616
	QString searchString = "this";
617
	bool caseSensitive = FALSE;
618
	bool wholeWord = FALSE;
619
	bool forward = FALSE;
620
	IntList paragraph;
621
	IntList index;
622
	paragraph << 1 << 0;
623
	index << 4 << 0;
624
	QTest::newRow( "this-noncs-nonww-backward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
625
    }
626
627
    {
628
	// Check for 'this' case-sensitive not whole word backward
629
	QString text = "This is a test\nand this is another test";
630
	QString searchString = "this";
631
	bool caseSensitive = TRUE;
632
	bool wholeWord = FALSE;
633
	bool forward = FALSE;
634
	IntList paragraph;
635
	IntList index;
636
	paragraph << 1;
637
	index << 4;
638
	QTest::newRow( "this-cs-nonww-backward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
639
    }
640
641
    {
642
	// Check for 'this' non case-sensitive whole word backward
643
	QString text = "This is a test\nand this is another test";
644
	QString searchString = "this";
645
	bool caseSensitive = FALSE;
646
	bool wholeWord = TRUE;
647
	bool forward = FALSE;
648
	IntList paragraph;
649
	IntList index;
650
	paragraph << 1 << 0;
651
	index << 4 << 0;
652
	QTest::newRow( "this-noncs-ww-backward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
653
    }
654
655
        {
656
	// Check for ('s non case-sensitive not whole word forward
657
	QString text = "This is (a te)st\nand (this is another test) with ( brackets)";
658
	QString searchString = "(";
659
	bool caseSensitive = FALSE;
660
	bool wholeWord = FALSE;
661
	bool forward = TRUE;
662
	IntList paragraph;
663
	IntList index;
664
	paragraph << 0 << 1 << 1;
665
	index << 8 << 4 << 32;
666
	QTest::newRow( "(-noncs-nonww-forward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
667
    }
668
669
    {
670
	// Check for ('s case-sensitive not whole word forward
671
	QString text = "This is (a te)st\nand (this is another test) with ( brackets)";
672
	QString searchString = "(";
673
	bool caseSensitive = TRUE;
674
	bool wholeWord = FALSE;
675
	bool forward = TRUE;
676
	IntList paragraph;
677
	IntList index;
678
	paragraph << 0 << 1 << 1;
679
	index << 8 << 4 << 32;
680
	QTest::newRow( "(-cs-nonww-forward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
681
    }
682
683
    {
684
	// Check for ('s non case-sensitive whole word forward
685
	QString text = "This is (a te)st\nand (this is another test) with ( brackets)";
686
	QString searchString = "(";
687
	bool caseSensitive = FALSE;
688
	bool wholeWord = TRUE;
689
	bool forward = TRUE;
690
	IntList paragraph;
691
	IntList index;
692
	paragraph << 1;
693
	index << 32;
694
	QTest::newRow( "(-noncs-ww-forward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
695
    }
696
697
    {
698
	// Check for ('s non case-sensitive not whole word backward
699
	QString text = "This is (a te)st\nand (this is another test) with ( brackets)";
700
	QString searchString = "(";
701
	bool caseSensitive = FALSE;
702
	bool wholeWord = FALSE;
703
	bool forward = FALSE;
704
	IntList paragraph;
705
	IntList index;
706
	paragraph << 1 << 1 << 0;
707
	index << 32 << 4 << 8;
708
	QTest::newRow( "(-noncs-nonww-backward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
709
    }
710
711
    {
712
	// Check for ('s case-sensitive not whole word backward
713
	QString text = "This is (a te)st\nand (this is another test) with ( brackets)";
714
	QString searchString = "(";
715
	bool caseSensitive = TRUE;
716
	bool wholeWord = FALSE;
717
	bool forward = FALSE;
718
	IntList paragraph;
719
	IntList index;
720
	paragraph << 1 << 1 << 0;
721
	index << 32 << 4 << 8;
722
	QTest::newRow( "(-cs-nonww-backward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
723
    }
724
725
    {
726
	// Check for ('s non case-sensitive whole word backward
727
	QString text = "This is (a te)st\nand (this is another test) with ( brackets)";
728
	QString searchString = "(";
729
	bool caseSensitive = FALSE;
730
	bool wholeWord = TRUE;
731
	bool forward = FALSE;
732
	IntList paragraph;
733
	IntList index;
734
	paragraph << 1;
735
	index << 32;
736
	QTest::newRow( "(-noncs-ww-backward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
737
    }
738
739
    {
740
	// Check for (this's non case-sensitive whole word backward
741
	QString text = "This is (a te)st\nand (this is another test) with (brackets)";
742
	QString searchString = "(this";
743
	bool caseSensitive = FALSE;
744
	bool wholeWord = TRUE;
745
	bool forward = FALSE;
746
	IntList paragraph;
747
	IntList index;
748
	paragraph << 1;
749
	index << 4;
750
	QTest::newRow( "(this-noncs-ww-backward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
751
    }
752
753
    {
754
	// Check for (this's non case-sensitive whole word forward
755
	QString text = "This is (a te)st\nand (this is another test) with (brackets)";
756
	QString searchString = "(this";
757
	bool caseSensitive = FALSE;
758
	bool wholeWord = TRUE;
759
	bool forward = TRUE;
760
	IntList paragraph;
761
	IntList index;
762
	paragraph << 1;
763
	index << 4;
764
	QTest::newRow( "(this-noncs-ww-forward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
765
    }
766
767
    {
768
	// Check for " "'s non case-sensitive non whole word forward
769
	QString text = "foo";
770
	QString searchString = " ";
771
	bool caseSensitive = false;
772
	bool wholeWord = false;
773
	bool forward = true;
774
	IntList paragraph;
775
	IntList index;
776
// 	paragraph << 0 << 1 << 1 << 1;
777
//         index << 3 << 0 << 6 << 12;
778
	QTest::newRow( " -noncs-nonww-forward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
779
    }
780
781
    {
782
	// Check for " "'s non case-sensitive non whole word backward
783
	QString text = "foo ";
784
	QString searchString = " ";
785
	bool caseSensitive = false;
786
	bool wholeWord = false;
787
	bool forward = false;
788
	IntList paragraph;
789
	IntList index;
790
	paragraph << 0;
791
        index << 3;
792
	QTest::newRow( " -noncs-nonww-backward" ) << text << searchString << caseSensitive << wholeWord << forward << paragraph << index;
793
    }
794
}
795
796
797
void tst_Q3TextEdit::find()
798
{
799
    QFETCH( QString, text );
800
    QFETCH( QString, searchString );
801
    QFETCH( bool, caseSensitive );
802
    QFETCH( bool, wholeWord );
803
    QFETCH( bool, forward );
804
    QFETCH( IntList, paragraph );
805
    QFETCH( IntList, index );
806
807
    textEdit->clear();
808
    textEdit->setTextFormat( Qt::PlainText );
809
    textEdit->setText( text );
810
811
    IntList::Iterator pIt;
812
    IntList::Iterator iIt = index.begin();
813
    int paraFound = forward ? 0 : INT_MAX;
814
    int indexFound = forward ? 0 : INT_MAX;
815
816
    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 );
817
    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 );
818
819
    // It should not find anything
820
    if ( !paragraph.count() ) {
821
	QVERIFY( !textEdit->find( searchString, caseSensitive, wholeWord, forward, &paraFound, &indexFound ) );
822
    } else {
823
	for ( pIt = paragraph.begin(); pIt != paragraph.end(); ++pIt ) {
824
	    QVERIFY( textEdit->find( searchString, caseSensitive, wholeWord, forward, &paraFound, &indexFound ) );
825
	    QCOMPARE( paraFound, (*pIt) );
826
	    QCOMPARE( indexFound, (*iIt) );
827
828
	    // This sounds dubious to me, it should search from the next character specified by indexFound
829
	    if ( forward )
830
		indexFound++;
831
	    else
832
		indexFound--;
833
834
	    ++iIt;
835
	}
836
    }
837
}
838
839
void tst_Q3TextEdit::findSC()
840
{
841
    // Special bug case #29649 test
842
    textEdit->clear();
843
    textEdit->setTextFormat(Qt::PlainText);
844
    textEdit->setText("foo do soo boo arg\ndf df foo a;ls lkdf lsdkjf");
845
    textEdit->setCursorPosition(1, 16);
846
    int paraFound, indexFound;
847
    QVERIFY(textEdit->find("foo", FALSE, FALSE, FALSE));
848
    textEdit->getCursorPosition(&paraFound, &indexFound);
849
    QCOMPARE(paraFound, 1);
850
    QCOMPARE(indexFound, 6);
851
    QVERIFY(textEdit->find("foo", FALSE, FALSE, FALSE));
852
    textEdit->getCursorPosition(&paraFound, &indexFound);
853
    QCOMPARE(paraFound, 0);
854
    QCOMPARE(indexFound, 0);
855
    QVERIFY(!textEdit->find("foo", FALSE, FALSE, FALSE));
856
    QVERIFY(textEdit->find("foo", FALSE, FALSE, FALSE));
857
    textEdit->getCursorPosition(&paraFound, &indexFound);
858
    QCOMPARE(paraFound, 1);
859
    QCOMPARE(indexFound, 6);
860
}
861
862
863
864
void tst_Q3TextEdit::findBackwards()
865
{
866
    textEdit->clear();
867
    textEdit->setTextFormat(Qt::PlainText);
868
    textEdit->setText("ABCABCABCABC");
869
    textEdit->setCursorPosition(0, 3);
870
    QVERIFY(textEdit->find("ABC", FALSE, FALSE, FALSE));
871
    QCOMPARE(textEdit->selectedText(), QString("ABC"));
872
    int pFrom, pTo, iFrom, iTo;
873
    QString qw;
874
875
    textEdit->getSelection(&pFrom, &iFrom, &pTo, &iTo);
876
    QCOMPARE(pFrom, 0);
877
    QCOMPARE(iFrom, 0);
878
    QCOMPARE(pTo, 0);
879
    QCOMPARE(iTo, 3);
880
}
881
void tst_Q3TextEdit::redoAvailableEmitted( bool t )
882
{
883
    redoA = t;
884
}
885
886
void tst_Q3TextEdit::undoAvailableEmitted( bool t )
887
{
888
    undoA = t;
889
}
890
891
void tst_Q3TextEdit::copyAvailableEmitted( bool t )
892
{
893
    copyA = t;
894
}
895
896
void tst_Q3TextEdit::cut()
897
{
898
    connect( textEdit, SIGNAL( copyAvailable(bool) ), this, SLOT( copyAvailableEmitted(bool) ) );
899
    copyA = FALSE;
900
    textEdit->setText( "I believe that people who are going to commit crimes shouldn't have guns" );
901
    textEdit->selectAll();
902
    QTest::qWait( 2000 );
903
    QVERIFY( copyA );
904
    textEdit->cut();
905
    QTest::qWait( 2000 );
906
    QVERIFY( !copyA );
907
}
908
909
void tst_Q3TextEdit::clear()
910
{
911
    // Clear is actually tested all over the place, this is
912
    // really just to test for task 21355
913
    textEdit->clear();
914
    textEdit->setTextFormat( Qt::RichText );
915
    textEdit->setText( "<table align=right></table>" );
916
    textEdit->clear();
917
    // If it got here, then it didn't crash
918
    QVERIFY( TRUE );
919
}
920
921
void tst_Q3TextEdit::insert()
922
{
923
    Qt::TextFormat fmt = textEdit->textFormat();
924
    textEdit->setTextFormat(Qt::LogText);
925
    textEdit->setText("<blue>The<red> following: </red><b>fooooooooooooooooooff</b>\nLine <green>Number 2\nLine</green> Number 3");
926
    textEdit->insertParagraph("<orange>#orange#</orange>", 1);
927
    textEdit->insertAt(" #\nper\nka<blue>ar<yellow>e\nreo</yellow>le</blue># \n", 2, 3 );
928
    textEdit->insertAt("\n#<b>o</b><i>l</i><u>e</u>#\n\n", 100, 100);
929
    textEdit->insertAt("<u>#o\nle#</u>", 0, 10);
930
    QString result = "<blue>The<red> follow<u>#o\nle#</u>ing: </red><b>fooooooooooooooooooff</b>\n<orange>#orange#</orange>\n"
931
		     "Lin #\nper\nka<blue>ar<yellow>e\nreo</yellow>le</blue># \ne <green>Number 2\nLine</green> Number 3\n"
932
		     "#<b>o</b><i>l</i><u>e</u>#\n\n\n";
933
    QCOMPARE(textEdit->text(), result);
934
    textEdit->setTextFormat(fmt);
935
}
936
937
void tst_Q3TextEdit::keyClicks_data()
938
{
939
    QTest::addColumn<QString>("inputString");
940
941
    QTest::newRow("English") << "This is not a sentence.";
942
    QTest::newRow("Norwegian") << "\x0e6\x0f8\x0e5\x0c6\x0d8\x0c5 er norske bokstaver.";
943
}
944
945
void tst_Q3TextEdit::keyClicks()
946
{
947
    QFETCH(QString, inputString);
948
949
    textEdit->clear();
950
    textEdit->setTextFormat(Qt::PlainText);
951
    textEdit->setReadOnly(false);
952
953
    QVERIFY(textEdit->text().isEmpty());
954
    QTest::keyClicks(textEdit, inputString);
955
    QCOMPARE(textEdit->text(), inputString);
956
}
957
958
959
960
void tst_Q3TextEdit::selectAll()
961
{
962
    QString testString = "This is test for task #24092";
963
    textEdit->setText( testString );
964
965
    textEdit->setTextFormat(Qt::PlainText);
966
    textEdit->selectAll(TRUE);
967
    QVERIFY( textEdit->hasSelectedText() );
968
    textEdit->selectAll(FALSE);
969
    QVERIFY( !textEdit->hasSelectedText() );
970
971
    textEdit->setTextFormat(Qt::RichText);
972
    textEdit->selectAll(TRUE);
973
    QVERIFY( textEdit->hasSelectedText() );
974
    textEdit->selectAll(FALSE);
975
    QVERIFY( !textEdit->hasSelectedText() );
976
    textEdit->setTextFormat(Qt::LogText);
977
    textEdit->selectAll(TRUE);
978
    QVERIFY( textEdit->hasSelectedText() );
979
    textEdit->selectAll(FALSE);
980
    QVERIFY( !textEdit->hasSelectedText() );
981
}
982
983
void tst_Q3TextEdit::setCurrentFont()
984
{
985
    textEdit->clear();
986
    textEdit->setTextFormat(Qt::LogText);
987
    textEdit->setCurrentFont(QFont("Courier New", 9));
988
    textEdit->setText("Just some dummy text");
989
    QCOMPARE(textEdit->text(), QString("Just some dummy text\n"));
990
}
991
992
void tst_Q3TextEdit::undoRedo()
993
{
994
    Q3TextEdit edit;
995
    edit.setTextFormat(Qt::PlainText);
996
997
    QString deftext("Just some text");
998
    edit.setText(deftext);
999
    edit.insertAt("<tag>",0, 5);
1000
    QCOMPARE(edit.text(), QString("Just <tag>some text"));
1001
    edit.undo();
1002
    QCOMPARE(edit.text(), deftext);
1003
    edit.insertAt("<tag>",0, 5);
1004
    edit.insertAt("</tag>",0, 14);
1005
    QCOMPARE(edit.text(), QString("Just <tag>some</tag> text"));
1006
    edit.undo();
1007
    QCOMPARE(edit.text(), QString("Just <tag>some text"));
1008
    edit.undo();
1009
    QCOMPARE(edit.text(), QString("Just some text"));
1010
    edit.insertAt("<tag>",0, 5);
1011
    edit.insertAt("</tag>",0, 10);
1012
    QCOMPARE(edit.text(), QString("Just <tag></tag>some text"));
1013
    edit.undo();
1014
    QCOMPARE(edit.text(), QString("Just some text"));
1015
}
1016
1017
void tst_Q3TextEdit::length_data()
1018
{
1019
    // The expected length values are based on what is returned in Qt 3.2.1.
1020
    // We don't want the semantics of this function to change again, no
1021
    // matter how broken it is, so if this function fails, the test data has to be seen as
1022
    // correct.  In Qt 4.0, this function will not exist in this form.
1023
1024
    QTest::addColumn<int>("textFormat");
1025
    QTest::addColumn<QString>("text");
1026
    QTest::addColumn<int>("expectedLength");
1027
1028
    QTest::newRow("plainText") << int(Qt::PlainText) << "This is a test" << 14;
1029
    QTest::newRow("plainTextNewLines") << int(Qt::PlainText) << "This is a test\nThis is a test\nThis is a test" << 44;
1030
    QTest::newRow("logText") << int(Qt::LogText) << "This is a test" << 14;
1031
    QTest::newRow("logTextNewLines") << int(Qt::LogText) << "This is a test\nThis is a test\nThis is a test" << 42;
1032
    QTest::newRow("logTextTags") << int(Qt::LogText) << "<b>This is a test</b>" << 14;
1033
    QTest::newRow("logTextTagsNewLines") << int(Qt::LogText) << "<b>This is a test\nThis is a test\nThis is a test</b>" << 42;
1034
    QTest::newRow("richText") << int(Qt::RichText) << "This is a test" << 14;
1035
    QTest::newRow("richTextNewLines") << int(Qt::RichText) << "This is a test\nThis is a test\nThis is a test" << 44;
1036
    QTest::newRow("richTextTags") << int(Qt::RichText) << "<b>This is a test</b>" << 14;
1037
}
1038
1039
void tst_Q3TextEdit::length()
1040
{
1041
    QFETCH(int, textFormat);
1042
    QFETCH(QString, text);
1043
    QFETCH(int, expectedLength);
1044
1045
    textEdit->setTextFormat((Qt::TextFormat)textFormat);
1046
    textEdit->setText(text);
1047
    QCOMPARE(textEdit->length(), expectedLength);
1048
}
1049
1050
void tst_Q3TextEdit::getSelection_data()
1051
{
1052
    QTest::addColumn<int>("textFormat");
1053
    QTest::addColumn<QString>("text");
1054
1055
    QTest::addColumn<int>("paragFrom");
1056
    QTest::addColumn<int>("indexFrom");
1057
    QTest::addColumn<int>("paragTo");
1058
    QTest::addColumn<int>("indexTo");
1059
1060
    QTest::addColumn<int>("selParagFrom");
1061
    QTest::addColumn<int>("selIndexFrom");
1062
    QTest::addColumn<int>("selParagTo");
1063
    QTest::addColumn<int>("selIndexTo");
1064
1065
    QTest::newRow("plainText") << int(Qt::PlainText) << "This is a test" << 0 << 0 << 0 << 2 << 0 << 0 << 0 << 2;
1066
    QTest::newRow("richText") << int(Qt::RichText) << "This is a test" << 0 << 0 << 0 << 2 << 0 << 0 << 0 << 2;
1067
    QTest::newRow("logText") << int(Qt::LogText) << "This is a test" << 0 << 0 << 0 << 2 << 0 << 0 << 0 << 2;
1068
}
1069
1070
void tst_Q3TextEdit::getSelection()
1071
{
1072
    QFETCH(int, textFormat);
1073
    QFETCH(QString, text);
1074
1075
    QFETCH(int, paragFrom);
1076
    QFETCH(int, indexFrom);
1077
    QFETCH(int, paragTo);
1078
    QFETCH(int, indexTo);
1079
1080
    QFETCH(int, selParagFrom);
1081
    QFETCH(int, selIndexFrom);
1082
    QFETCH(int, selParagTo);
1083
    QFETCH(int, selIndexTo);
1084
1085
    int pFr, iFr, pTo, iTo;
1086
    textEdit->setText(text);
1087
    textEdit->setTextFormat((Qt::TextFormat)textFormat);
1088
    textEdit->setSelection(paragFrom, indexFrom, paragTo, indexTo);
1089
    textEdit->getSelection(&pFr, &iFr, &pTo, &iTo);
1090
1091
    QCOMPARE(pFr, selParagFrom);
1092
    QCOMPARE(iFr, selIndexFrom);
1093
    QCOMPARE(pTo, selParagTo);
1094
    QCOMPARE(iTo, selIndexTo);
1095
}
1096
1097
void tst_Q3TextEdit::anchorTest()
1098
{
1099
    // This is from task 57709
1100
    Q3TextEdit edit;
1101
    QString richText = "<p dir=\"ltr\"><a name=\"Gold\"></a>something</p>\n"
1102
                       "<p dir=\"ltr\"><a name=\"Silver\"></a>more"
1103
                       "<a name=\"Bronze\"></a>stuff</p>\n";
1104
    edit.setText(richText);
1105
1106
    QString expected = "<html><head><meta name=\"qrichtext\" content=\"1\" /></head>"
1107
                    "<body style=\"font-size:%1pt;font-family:%2\">\n"
1108
                       + richText + "</body></html>\n";
1109
    QFont f = edit.font();
1110
    expected = expected.arg(f.pointSize()).arg(f.family());
1111
    QCOMPARE(edit.text(),expected);
1112
}
1113
1114
QTEST_MAIN(tst_Q3TextEdit)
1115
#include "tst_q3textedit.moc"