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