1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file. Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
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
nativeClipboardWorking()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:
My3TextEdit()139 My3TextEdit() : Q3TextEdit() {}
setDocument(Q3TextDocument * doc)140 void setDocument(Q3TextDocument *doc) { Q3TextEdit::setDocument(doc); }
document()141 Q3TextDocument *document() { return Q3TextEdit::document(); }
142 };
143
144 // Testing get/set functions
getSetCheck()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
tst_Q3TextEdit()194 tst_Q3TextEdit::tst_Q3TextEdit()
195 {
196 }
197
~tst_Q3TextEdit()198 tst_Q3TextEdit::~tst_Q3TextEdit()
199 {
200 }
201
initTestCase()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
cleanupTestCase()211 void tst_Q3TextEdit::cleanupTestCase()
212 {
213 delete textEdit;
214 }
215
doKeyboardAction()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
doKeyboardAction_data()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
cursorPosition_data()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
cursorPosition()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( ¶, &in );
377 QCOMPARE( para, paragraph );
378 QCOMPARE( in, index );
379 }
380
381
text()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
text_data()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
copyPaste_data()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
copyPaste()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
setReadOnly()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 */
find_data()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
find()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, ¶Found, &indexFound ) );
822 } else {
823 for ( pIt = paragraph.begin(); pIt != paragraph.end(); ++pIt ) {
824 QVERIFY( textEdit->find( searchString, caseSensitive, wholeWord, forward, ¶Found, &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
findSC()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(¶Found, &indexFound);
849 QCOMPARE(paraFound, 1);
850 QCOMPARE(indexFound, 6);
851 QVERIFY(textEdit->find("foo", FALSE, FALSE, FALSE));
852 textEdit->getCursorPosition(¶Found, &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(¶Found, &indexFound);
858 QCOMPARE(paraFound, 1);
859 QCOMPARE(indexFound, 6);
860 }
861
862
863
findBackwards()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 }
redoAvailableEmitted(bool t)881 void tst_Q3TextEdit::redoAvailableEmitted( bool t )
882 {
883 redoA = t;
884 }
885
undoAvailableEmitted(bool t)886 void tst_Q3TextEdit::undoAvailableEmitted( bool t )
887 {
888 undoA = t;
889 }
890
copyAvailableEmitted(bool t)891 void tst_Q3TextEdit::copyAvailableEmitted( bool t )
892 {
893 copyA = t;
894 }
895
cut()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
clear()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
insert()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
keyClicks_data()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
keyClicks()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
selectAll()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
setCurrentFont()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
undoRedo()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
length_data()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
length()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
getSelection_data()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
getSelection()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
anchorTest()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"
1116
1117