|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2010 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 #include <qtest.h> |
|
42 #include "../../../shared/util.h" |
|
43 #include "../shared/testhttpserver.h" |
|
44 #include <math.h> |
|
45 #include <QFile> |
|
46 #include <QTextDocument> |
|
47 #include <QtDeclarative/qdeclarativeengine.h> |
|
48 #include <QtDeclarative/qdeclarativecontext.h> |
|
49 #include <QtDeclarative/qdeclarativeexpression.h> |
|
50 #include <QtDeclarative/qdeclarativecomponent.h> |
|
51 #include <private/qdeclarativetextedit_p.h> |
|
52 #include <QFontMetrics> |
|
53 #include <QDeclarativeView> |
|
54 #include <QStyle> |
|
55 #include <QInputContext> |
|
56 |
|
57 class tst_qdeclarativetextedit : public QObject |
|
58 |
|
59 { |
|
60 Q_OBJECT |
|
61 public: |
|
62 tst_qdeclarativetextedit(); |
|
63 |
|
64 private slots: |
|
65 void text(); |
|
66 void width(); |
|
67 void wrap(); |
|
68 void textFormat(); |
|
69 |
|
70 // ### these tests may be trivial |
|
71 void hAlign(); |
|
72 void vAlign(); |
|
73 void font(); |
|
74 void color(); |
|
75 void textMargin(); |
|
76 void persistentSelection(); |
|
77 void focusOnPress(); |
|
78 void selection(); |
|
79 void mouseSelection_data(); |
|
80 void mouseSelection(); |
|
81 void inputMethodHints(); |
|
82 |
|
83 void cursorDelegate(); |
|
84 void delegateLoading_data(); |
|
85 void delegateLoading(); |
|
86 void navigation(); |
|
87 void readOnly(); |
|
88 void sendRequestSoftwareInputPanelEvent(); |
|
89 void geometrySignals(); |
|
90 private: |
|
91 void simulateKey(QDeclarativeView *, int key); |
|
92 QDeclarativeView *createView(const QString &filename); |
|
93 |
|
94 QStringList standard; |
|
95 QStringList richText; |
|
96 |
|
97 QStringList hAlignmentStrings; |
|
98 QStringList vAlignmentStrings; |
|
99 |
|
100 QList<Qt::Alignment> vAlignments; |
|
101 QList<Qt::Alignment> hAlignments; |
|
102 |
|
103 QStringList colorStrings; |
|
104 |
|
105 QDeclarativeEngine engine; |
|
106 }; |
|
107 |
|
108 tst_qdeclarativetextedit::tst_qdeclarativetextedit() |
|
109 { |
|
110 standard << "the quick brown fox jumped over the lazy dog" |
|
111 << "the quick brown fox\n jumped over the lazy dog"; |
|
112 |
|
113 richText << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a> jumped over the <b>lazy</b> dog</i>" |
|
114 << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a><br>jumped over the <b>lazy</b> dog</i>"; |
|
115 |
|
116 hAlignmentStrings << "AlignLeft" |
|
117 << "AlignRight" |
|
118 << "AlignHCenter"; |
|
119 |
|
120 vAlignmentStrings << "AlignTop" |
|
121 << "AlignBottom" |
|
122 << "AlignVCenter"; |
|
123 |
|
124 hAlignments << Qt::AlignLeft |
|
125 << Qt::AlignRight |
|
126 << Qt::AlignHCenter; |
|
127 |
|
128 vAlignments << Qt::AlignTop |
|
129 << Qt::AlignBottom |
|
130 << Qt::AlignVCenter; |
|
131 |
|
132 colorStrings << "aliceblue" |
|
133 << "antiquewhite" |
|
134 << "aqua" |
|
135 << "darkkhaki" |
|
136 << "darkolivegreen" |
|
137 << "dimgray" |
|
138 << "palevioletred" |
|
139 << "lightsteelblue" |
|
140 << "#000000" |
|
141 << "#AAAAAA" |
|
142 << "#FFFFFF" |
|
143 << "#2AC05F"; |
|
144 // |
|
145 // need a different test to do alpha channel test |
|
146 // << "#AA0011DD" |
|
147 // << "#00F16B11"; |
|
148 // |
|
149 } |
|
150 |
|
151 void tst_qdeclarativetextedit::text() |
|
152 { |
|
153 { |
|
154 QDeclarativeComponent texteditComponent(&engine); |
|
155 texteditComponent.setData("import Qt 4.7\nTextEdit { text: \"\" }", QUrl()); |
|
156 QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create()); |
|
157 |
|
158 QVERIFY(textEditObject != 0); |
|
159 QCOMPARE(textEditObject->text(), QString("")); |
|
160 } |
|
161 |
|
162 for (int i = 0; i < standard.size(); i++) |
|
163 { |
|
164 QString componentStr = "import Qt 4.7\nTextEdit { text: \"" + standard.at(i) + "\" }"; |
|
165 QDeclarativeComponent texteditComponent(&engine); |
|
166 texteditComponent.setData(componentStr.toLatin1(), QUrl()); |
|
167 QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create()); |
|
168 |
|
169 QVERIFY(textEditObject != 0); |
|
170 QCOMPARE(textEditObject->text(), standard.at(i)); |
|
171 } |
|
172 |
|
173 for (int i = 0; i < richText.size(); i++) |
|
174 { |
|
175 QString componentStr = "import Qt 4.7\nTextEdit { text: \"" + richText.at(i) + "\" }"; |
|
176 QDeclarativeComponent texteditComponent(&engine); |
|
177 texteditComponent.setData(componentStr.toLatin1(), QUrl()); |
|
178 QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create()); |
|
179 |
|
180 QVERIFY(textEditObject != 0); |
|
181 QString actual = textEditObject->text(); |
|
182 QString expected = richText.at(i); |
|
183 actual.replace(QRegExp(".*<body[^>]*>"),""); |
|
184 actual.replace(QRegExp("(<[^>]*>)+"),"<>"); |
|
185 expected.replace(QRegExp("(<[^>]*>)+"),"<>"); |
|
186 QCOMPARE(actual.simplified(),expected.simplified()); |
|
187 } |
|
188 } |
|
189 |
|
190 void tst_qdeclarativetextedit::width() |
|
191 { |
|
192 // uses Font metrics to find the width for standard and document to find the width for rich |
|
193 { |
|
194 QDeclarativeComponent texteditComponent(&engine); |
|
195 texteditComponent.setData("import Qt 4.7\nTextEdit { text: \"\" }", QUrl()); |
|
196 QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create()); |
|
197 |
|
198 QVERIFY(textEditObject != 0); |
|
199 QCOMPARE(textEditObject->width(), 1.);//+1 for cursor |
|
200 } |
|
201 |
|
202 for (int i = 0; i < standard.size(); i++) |
|
203 { |
|
204 QFont f; |
|
205 QFontMetricsF fm(f); |
|
206 qreal metricWidth = fm.size(Qt::TextExpandTabs && Qt::TextShowMnemonic, standard.at(i)).width(); |
|
207 metricWidth = ceil(metricWidth); |
|
208 |
|
209 QString componentStr = "import Qt 4.7\nTextEdit { text: \"" + standard.at(i) + "\" }"; |
|
210 QDeclarativeComponent texteditComponent(&engine); |
|
211 texteditComponent.setData(componentStr.toLatin1(), QUrl()); |
|
212 QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create()); |
|
213 |
|
214 QVERIFY(textEditObject != 0); |
|
215 QCOMPARE(textEditObject->width(), qreal(metricWidth + 1 + 3));//+3 is the current way of accounting for space between cursor and last character. |
|
216 } |
|
217 |
|
218 for (int i = 0; i < richText.size(); i++) |
|
219 { |
|
220 QTextDocument document; |
|
221 document.setHtml(richText.at(i)); |
|
222 document.setDocumentMargin(0); |
|
223 |
|
224 int documentWidth = ceil(document.idealWidth()); |
|
225 |
|
226 QString componentStr = "import Qt 4.7\nTextEdit { text: \"" + richText.at(i) + "\" }"; |
|
227 QDeclarativeComponent texteditComponent(&engine); |
|
228 texteditComponent.setData(componentStr.toLatin1(), QUrl()); |
|
229 QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create()); |
|
230 |
|
231 QVERIFY(textEditObject != 0); |
|
232 QCOMPARE(textEditObject->width(), qreal(documentWidth + 1 + 3)); |
|
233 } |
|
234 } |
|
235 |
|
236 void tst_qdeclarativetextedit::wrap() |
|
237 { |
|
238 // for specified width and wrap set true |
|
239 { |
|
240 QDeclarativeComponent texteditComponent(&engine); |
|
241 texteditComponent.setData("import Qt 4.7\nTextEdit { text: \"\"; wrapMode: TextEdit.WordWrap; width: 300 }", QUrl()); |
|
242 QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create()); |
|
243 |
|
244 QVERIFY(textEditObject != 0); |
|
245 QCOMPARE(textEditObject->width(), 300.); |
|
246 } |
|
247 |
|
248 for (int i = 0; i < standard.size(); i++) |
|
249 { |
|
250 QString componentStr = "import Qt 4.7\nTextEdit { wrapMode: TextEdit.WordWrap; width: 300; text: \"" + standard.at(i) + "\" }"; |
|
251 QDeclarativeComponent texteditComponent(&engine); |
|
252 texteditComponent.setData(componentStr.toLatin1(), QUrl()); |
|
253 QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create()); |
|
254 |
|
255 QVERIFY(textEditObject != 0); |
|
256 QCOMPARE(textEditObject->width(), 300.); |
|
257 } |
|
258 |
|
259 for (int i = 0; i < richText.size(); i++) |
|
260 { |
|
261 QString componentStr = "import Qt 4.7\nTextEdit { wrapMode: TextEdit.WordWrap; width: 300; text: \"" + richText.at(i) + "\" }"; |
|
262 QDeclarativeComponent texteditComponent(&engine); |
|
263 texteditComponent.setData(componentStr.toLatin1(), QUrl()); |
|
264 QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create()); |
|
265 |
|
266 QVERIFY(textEditObject != 0); |
|
267 QCOMPARE(textEditObject->width(), 300.); |
|
268 } |
|
269 |
|
270 } |
|
271 |
|
272 void tst_qdeclarativetextedit::textFormat() |
|
273 { |
|
274 { |
|
275 QDeclarativeComponent textComponent(&engine); |
|
276 textComponent.setData("import Qt 4.7\nTextEdit { text: \"Hello\"; textFormat: Text.RichText }", QUrl::fromLocalFile("")); |
|
277 QDeclarativeTextEdit *textObject = qobject_cast<QDeclarativeTextEdit*>(textComponent.create()); |
|
278 |
|
279 QVERIFY(textObject != 0); |
|
280 QVERIFY(textObject->textFormat() == QDeclarativeTextEdit::RichText); |
|
281 } |
|
282 { |
|
283 QDeclarativeComponent textComponent(&engine); |
|
284 textComponent.setData("import Qt 4.7\nTextEdit { text: \"<b>Hello</b>\"; textFormat: Text.PlainText }", QUrl::fromLocalFile("")); |
|
285 QDeclarativeTextEdit *textObject = qobject_cast<QDeclarativeTextEdit*>(textComponent.create()); |
|
286 |
|
287 QVERIFY(textObject != 0); |
|
288 QVERIFY(textObject->textFormat() == QDeclarativeTextEdit::PlainText); |
|
289 } |
|
290 } |
|
291 |
|
292 //the alignment tests may be trivial o.oa |
|
293 void tst_qdeclarativetextedit::hAlign() |
|
294 { |
|
295 //test one align each, and then test if two align fails. |
|
296 |
|
297 for (int i = 0; i < standard.size(); i++) |
|
298 { |
|
299 for (int j=0; j < hAlignmentStrings.size(); j++) |
|
300 { |
|
301 QString componentStr = "import Qt 4.7\nTextEdit { horizontalAlignment: \"" + hAlignmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }"; |
|
302 QDeclarativeComponent texteditComponent(&engine); |
|
303 texteditComponent.setData(componentStr.toLatin1(), QUrl()); |
|
304 QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create()); |
|
305 |
|
306 QVERIFY(textEditObject != 0); |
|
307 QCOMPARE((int)textEditObject->hAlign(), (int)hAlignments.at(j)); |
|
308 } |
|
309 } |
|
310 |
|
311 for (int i = 0; i < richText.size(); i++) |
|
312 { |
|
313 for (int j=0; j < hAlignmentStrings.size(); j++) |
|
314 { |
|
315 QString componentStr = "import Qt 4.7\nTextEdit { horizontalAlignment: \"" + hAlignmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }"; |
|
316 QDeclarativeComponent texteditComponent(&engine); |
|
317 texteditComponent.setData(componentStr.toLatin1(), QUrl()); |
|
318 QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create()); |
|
319 |
|
320 QVERIFY(textEditObject != 0); |
|
321 QCOMPARE((int)textEditObject->hAlign(), (int)hAlignments.at(j)); |
|
322 } |
|
323 } |
|
324 |
|
325 } |
|
326 |
|
327 void tst_qdeclarativetextedit::vAlign() |
|
328 { |
|
329 //test one align each, and then test if two align fails. |
|
330 |
|
331 for (int i = 0; i < standard.size(); i++) |
|
332 { |
|
333 for (int j=0; j < vAlignmentStrings.size(); j++) |
|
334 { |
|
335 QString componentStr = "import Qt 4.7\nTextEdit { verticalAlignment: \"" + vAlignmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }"; |
|
336 QDeclarativeComponent texteditComponent(&engine); |
|
337 texteditComponent.setData(componentStr.toLatin1(), QUrl()); |
|
338 QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create()); |
|
339 |
|
340 QVERIFY(textEditObject != 0); |
|
341 QCOMPARE((int)textEditObject->vAlign(), (int)vAlignments.at(j)); |
|
342 } |
|
343 } |
|
344 |
|
345 for (int i = 0; i < richText.size(); i++) |
|
346 { |
|
347 for (int j=0; j < vAlignmentStrings.size(); j++) |
|
348 { |
|
349 QString componentStr = "import Qt 4.7\nTextEdit { verticalAlignment: \"" + vAlignmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }"; |
|
350 QDeclarativeComponent texteditComponent(&engine); |
|
351 texteditComponent.setData(componentStr.toLatin1(), QUrl()); |
|
352 QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create()); |
|
353 |
|
354 QVERIFY(textEditObject != 0); |
|
355 QCOMPARE((int)textEditObject->vAlign(), (int)vAlignments.at(j)); |
|
356 } |
|
357 } |
|
358 |
|
359 } |
|
360 |
|
361 void tst_qdeclarativetextedit::font() |
|
362 { |
|
363 //test size, then bold, then italic, then family |
|
364 { |
|
365 QString componentStr = "import Qt 4.7\nTextEdit { font.pointSize: 40; text: \"Hello World\" }"; |
|
366 QDeclarativeComponent texteditComponent(&engine); |
|
367 texteditComponent.setData(componentStr.toLatin1(), QUrl()); |
|
368 QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create()); |
|
369 |
|
370 QVERIFY(textEditObject != 0); |
|
371 QCOMPARE(textEditObject->font().pointSize(), 40); |
|
372 QCOMPARE(textEditObject->font().bold(), false); |
|
373 QCOMPARE(textEditObject->font().italic(), false); |
|
374 } |
|
375 |
|
376 { |
|
377 QString componentStr = "import Qt 4.7\nTextEdit { font.bold: true; text: \"Hello World\" }"; |
|
378 QDeclarativeComponent texteditComponent(&engine); |
|
379 texteditComponent.setData(componentStr.toLatin1(), QUrl()); |
|
380 QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create()); |
|
381 |
|
382 QVERIFY(textEditObject != 0); |
|
383 QCOMPARE(textEditObject->font().bold(), true); |
|
384 QCOMPARE(textEditObject->font().italic(), false); |
|
385 } |
|
386 |
|
387 { |
|
388 QString componentStr = "import Qt 4.7\nTextEdit { font.italic: true; text: \"Hello World\" }"; |
|
389 QDeclarativeComponent texteditComponent(&engine); |
|
390 texteditComponent.setData(componentStr.toLatin1(), QUrl()); |
|
391 QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create()); |
|
392 |
|
393 QVERIFY(textEditObject != 0); |
|
394 QCOMPARE(textEditObject->font().italic(), true); |
|
395 QCOMPARE(textEditObject->font().bold(), false); |
|
396 } |
|
397 |
|
398 { |
|
399 QString componentStr = "import Qt 4.7\nTextEdit { font.family: \"Helvetica\"; text: \"Hello World\" }"; |
|
400 QDeclarativeComponent texteditComponent(&engine); |
|
401 texteditComponent.setData(componentStr.toLatin1(), QUrl()); |
|
402 QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create()); |
|
403 |
|
404 QVERIFY(textEditObject != 0); |
|
405 QCOMPARE(textEditObject->font().family(), QString("Helvetica")); |
|
406 QCOMPARE(textEditObject->font().bold(), false); |
|
407 QCOMPARE(textEditObject->font().italic(), false); |
|
408 } |
|
409 |
|
410 { |
|
411 QString componentStr = "import Qt 4.7\nTextEdit { font.family: \"\"; text: \"Hello World\" }"; |
|
412 QDeclarativeComponent texteditComponent(&engine); |
|
413 texteditComponent.setData(componentStr.toLatin1(), QUrl()); |
|
414 QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create()); |
|
415 |
|
416 QVERIFY(textEditObject != 0); |
|
417 QCOMPARE(textEditObject->font().family(), QString("")); |
|
418 } |
|
419 } |
|
420 |
|
421 void tst_qdeclarativetextedit::color() |
|
422 { |
|
423 //test normal |
|
424 for (int i = 0; i < colorStrings.size(); i++) |
|
425 { |
|
426 QString componentStr = "import Qt 4.7\nTextEdit { color: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }"; |
|
427 QDeclarativeComponent texteditComponent(&engine); |
|
428 texteditComponent.setData(componentStr.toLatin1(), QUrl()); |
|
429 QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create()); |
|
430 //qDebug() << "textEditObject: " << textEditObject->color() << "vs. " << QColor(colorStrings.at(i)); |
|
431 QVERIFY(textEditObject != 0); |
|
432 QCOMPARE(textEditObject->color(), QColor(colorStrings.at(i))); |
|
433 } |
|
434 |
|
435 //test selection |
|
436 for (int i = 0; i < colorStrings.size(); i++) |
|
437 { |
|
438 QString componentStr = "import Qt 4.7\nTextEdit { selectionColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }"; |
|
439 QDeclarativeComponent texteditComponent(&engine); |
|
440 texteditComponent.setData(componentStr.toLatin1(), QUrl()); |
|
441 QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create()); |
|
442 QVERIFY(textEditObject != 0); |
|
443 QCOMPARE(textEditObject->selectionColor(), QColor(colorStrings.at(i))); |
|
444 } |
|
445 |
|
446 //test selected text |
|
447 for (int i = 0; i < colorStrings.size(); i++) |
|
448 { |
|
449 QString componentStr = "import Qt 4.7\nTextEdit { selectedTextColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }"; |
|
450 QDeclarativeComponent texteditComponent(&engine); |
|
451 texteditComponent.setData(componentStr.toLatin1(), QUrl()); |
|
452 QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create()); |
|
453 QVERIFY(textEditObject != 0); |
|
454 QCOMPARE(textEditObject->selectedTextColor(), QColor(colorStrings.at(i))); |
|
455 } |
|
456 |
|
457 { |
|
458 QString colorStr = "#AA001234"; |
|
459 QColor testColor("#001234"); |
|
460 testColor.setAlpha(170); |
|
461 |
|
462 QString componentStr = "import Qt 4.7\nTextEdit { color: \"" + colorStr + "\"; text: \"Hello World\" }"; |
|
463 QDeclarativeComponent texteditComponent(&engine); |
|
464 texteditComponent.setData(componentStr.toLatin1(), QUrl()); |
|
465 QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create()); |
|
466 |
|
467 QVERIFY(textEditObject != 0); |
|
468 QCOMPARE(textEditObject->color(), testColor); |
|
469 } |
|
470 } |
|
471 |
|
472 void tst_qdeclarativetextedit::textMargin() |
|
473 { |
|
474 for(qreal i=0; i<=10; i+=0.3){ |
|
475 QString componentStr = "import Qt 4.7\nTextEdit { textMargin: " + QString::number(i) + "; text: \"Hello World\" }"; |
|
476 QDeclarativeComponent texteditComponent(&engine); |
|
477 texteditComponent.setData(componentStr.toLatin1(), QUrl()); |
|
478 QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create()); |
|
479 QVERIFY(textEditObject != 0); |
|
480 QCOMPARE(textEditObject->textMargin(), i); |
|
481 } |
|
482 } |
|
483 |
|
484 void tst_qdeclarativetextedit::persistentSelection() |
|
485 { |
|
486 { |
|
487 QString componentStr = "import Qt 4.7\nTextEdit { persistentSelection: true; text: \"Hello World\" }"; |
|
488 QDeclarativeComponent texteditComponent(&engine); |
|
489 texteditComponent.setData(componentStr.toLatin1(), QUrl()); |
|
490 QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create()); |
|
491 QVERIFY(textEditObject != 0); |
|
492 QCOMPARE(textEditObject->persistentSelection(), true); |
|
493 } |
|
494 |
|
495 { |
|
496 QString componentStr = "import Qt 4.7\nTextEdit { persistentSelection: false; text: \"Hello World\" }"; |
|
497 QDeclarativeComponent texteditComponent(&engine); |
|
498 texteditComponent.setData(componentStr.toLatin1(), QUrl()); |
|
499 QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create()); |
|
500 QVERIFY(textEditObject != 0); |
|
501 QCOMPARE(textEditObject->persistentSelection(), false); |
|
502 } |
|
503 } |
|
504 |
|
505 void tst_qdeclarativetextedit::focusOnPress() |
|
506 { |
|
507 { |
|
508 QString componentStr = "import Qt 4.7\nTextEdit { focusOnPress: true; text: \"Hello World\" }"; |
|
509 QDeclarativeComponent texteditComponent(&engine); |
|
510 texteditComponent.setData(componentStr.toLatin1(), QUrl()); |
|
511 QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create()); |
|
512 QVERIFY(textEditObject != 0); |
|
513 QCOMPARE(textEditObject->focusOnPress(), true); |
|
514 } |
|
515 |
|
516 { |
|
517 QString componentStr = "import Qt 4.7\nTextEdit { focusOnPress: false; text: \"Hello World\" }"; |
|
518 QDeclarativeComponent texteditComponent(&engine); |
|
519 texteditComponent.setData(componentStr.toLatin1(), QUrl()); |
|
520 QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create()); |
|
521 QVERIFY(textEditObject != 0); |
|
522 QCOMPARE(textEditObject->focusOnPress(), false); |
|
523 } |
|
524 } |
|
525 |
|
526 void tst_qdeclarativetextedit::selection() |
|
527 { |
|
528 QString testStr = standard[0];//TODO: What should happen for multiline/rich text? |
|
529 QString componentStr = "import Qt 4.7\nTextEdit { text: \""+ testStr +"\"; }"; |
|
530 QDeclarativeComponent texteditComponent(&engine); |
|
531 texteditComponent.setData(componentStr.toLatin1(), QUrl()); |
|
532 QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create()); |
|
533 QVERIFY(textEditObject != 0); |
|
534 |
|
535 |
|
536 //Test selection follows cursor |
|
537 for(int i=0; i<= testStr.size(); i++) { |
|
538 textEditObject->setCursorPosition(i); |
|
539 QCOMPARE(textEditObject->cursorPosition(), i); |
|
540 QCOMPARE(textEditObject->selectionStart(), i); |
|
541 QCOMPARE(textEditObject->selectionEnd(), i); |
|
542 QVERIFY(textEditObject->selectedText().isNull()); |
|
543 } |
|
544 |
|
545 textEditObject->setCursorPosition(0); |
|
546 QVERIFY(textEditObject->cursorPosition() == 0); |
|
547 QVERIFY(textEditObject->selectionStart() == 0); |
|
548 QVERIFY(textEditObject->selectionEnd() == 0); |
|
549 QVERIFY(textEditObject->selectedText().isNull()); |
|
550 |
|
551 //Test selection |
|
552 for(int i=0; i<= testStr.size(); i++) { |
|
553 textEditObject->setSelectionEnd(i); |
|
554 QCOMPARE(testStr.mid(0,i), textEditObject->selectedText()); |
|
555 } |
|
556 for(int i=0; i<= testStr.size(); i++) { |
|
557 textEditObject->setSelectionStart(i); |
|
558 QCOMPARE(testStr.mid(i,testStr.size()-i), textEditObject->selectedText()); |
|
559 } |
|
560 |
|
561 textEditObject->setCursorPosition(0); |
|
562 QVERIFY(textEditObject->cursorPosition() == 0); |
|
563 QVERIFY(textEditObject->selectionStart() == 0); |
|
564 QVERIFY(textEditObject->selectionEnd() == 0); |
|
565 QVERIFY(textEditObject->selectedText().isNull()); |
|
566 |
|
567 for(int i=0; i< testStr.size(); i++) { |
|
568 textEditObject->setSelectionStart(i); |
|
569 QCOMPARE(textEditObject->selectionEnd(), i); |
|
570 QCOMPARE(testStr.mid(i,0), textEditObject->selectedText()); |
|
571 textEditObject->setSelectionEnd(i+1); |
|
572 QCOMPARE(textEditObject->selectionStart(), i); |
|
573 QCOMPARE(testStr.mid(i,1), textEditObject->selectedText()); |
|
574 } |
|
575 |
|
576 for(int i= testStr.size() - 1; i>0; i--) { |
|
577 textEditObject->setSelectionEnd(i); |
|
578 QCOMPARE(testStr.mid(i,0), textEditObject->selectedText()); |
|
579 textEditObject->setSelectionStart(i-1); |
|
580 QCOMPARE(testStr.mid(i-1,1), textEditObject->selectedText()); |
|
581 } |
|
582 |
|
583 //Test Error Ignoring behaviour |
|
584 textEditObject->setCursorPosition(0); |
|
585 QVERIFY(textEditObject->selectedText().isNull()); |
|
586 textEditObject->setSelectionStart(-10); |
|
587 QVERIFY(textEditObject->selectedText().isNull()); |
|
588 textEditObject->setSelectionStart(100); |
|
589 QVERIFY(textEditObject->selectedText().isNull()); |
|
590 textEditObject->setSelectionEnd(-10); |
|
591 QVERIFY(textEditObject->selectedText().isNull()); |
|
592 textEditObject->setSelectionEnd(100); |
|
593 QVERIFY(textEditObject->selectedText().isNull()); |
|
594 textEditObject->setSelectionStart(0); |
|
595 textEditObject->setSelectionEnd(10); |
|
596 QVERIFY(textEditObject->selectedText().size() == 10); |
|
597 textEditObject->setSelectionStart(-10); |
|
598 QVERIFY(textEditObject->selectedText().size() == 10); |
|
599 textEditObject->setSelectionStart(100); |
|
600 QVERIFY(textEditObject->selectedText().size() == 10); |
|
601 textEditObject->setSelectionEnd(-10); |
|
602 QVERIFY(textEditObject->selectedText().size() == 10); |
|
603 textEditObject->setSelectionEnd(100); |
|
604 QVERIFY(textEditObject->selectedText().size() == 10); |
|
605 } |
|
606 |
|
607 void tst_qdeclarativetextedit::mouseSelection_data() |
|
608 { |
|
609 QTest::addColumn<QString>("qmlfile"); |
|
610 QTest::addColumn<bool>("expectSelection"); |
|
611 |
|
612 // import installed |
|
613 QTest::newRow("on") << SRCDIR "/data/mouseselection_true.qml" << true; |
|
614 QTest::newRow("off") << SRCDIR "/data/mouseselection_false.qml" << false; |
|
615 QTest::newRow("default") << SRCDIR "/data/mouseselection_default.qml" << false; |
|
616 } |
|
617 |
|
618 void tst_qdeclarativetextedit::mouseSelection() |
|
619 { |
|
620 QFETCH(QString, qmlfile); |
|
621 QFETCH(bool, expectSelection); |
|
622 |
|
623 QDeclarativeView *canvas = createView(qmlfile); |
|
624 |
|
625 canvas->show(); |
|
626 QApplication::setActiveWindow(canvas); |
|
627 QTest::qWaitForWindowShown(canvas); |
|
628 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas)); |
|
629 |
|
630 QVERIFY(canvas->rootObject() != 0); |
|
631 QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit *>(canvas->rootObject()); |
|
632 QVERIFY(textEditObject != 0); |
|
633 |
|
634 // press-and-drag-and-release from x1 to x2 |
|
635 int x1 = 10; |
|
636 int x2 = 70; |
|
637 int y = textEditObject->height()/2; |
|
638 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y))); |
|
639 //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work |
|
640 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); |
|
641 QApplication::sendEvent(canvas->viewport(), &mv); |
|
642 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y))); |
|
643 QString str = textEditObject->selectedText(); |
|
644 if (expectSelection) |
|
645 QVERIFY(str.length() > 3); // don't reallly care *what* was selected (and it's too sensitive to platform) |
|
646 else |
|
647 QVERIFY(str.isEmpty()); |
|
648 } |
|
649 |
|
650 void tst_qdeclarativetextedit::inputMethodHints() |
|
651 { |
|
652 QDeclarativeView *canvas = createView(SRCDIR "/data/inputmethodhints.qml"); |
|
653 canvas->show(); |
|
654 canvas->setFocus(); |
|
655 |
|
656 QVERIFY(canvas->rootObject() != 0); |
|
657 QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit *>(canvas->rootObject()); |
|
658 QVERIFY(textEditObject != 0); |
|
659 QVERIFY(textEditObject->inputMethodHints() & Qt::ImhNoPredictiveText); |
|
660 textEditObject->setInputMethodHints(Qt::ImhUppercaseOnly); |
|
661 QVERIFY(textEditObject->inputMethodHints() & Qt::ImhUppercaseOnly); |
|
662 } |
|
663 |
|
664 void tst_qdeclarativetextedit::cursorDelegate() |
|
665 { |
|
666 QDeclarativeView* view = createView(SRCDIR "/data/cursorTest.qml"); |
|
667 view->show(); |
|
668 view->setFocus(); |
|
669 QDeclarativeTextEdit *textEditObject = view->rootObject()->findChild<QDeclarativeTextEdit*>("textEditObject"); |
|
670 QVERIFY(textEditObject != 0); |
|
671 QVERIFY(textEditObject->findChild<QDeclarativeItem*>("cursorInstance")); |
|
672 //Test Delegate gets created |
|
673 textEditObject->setFocus(true); |
|
674 QDeclarativeItem* delegateObject = textEditObject->findChild<QDeclarativeItem*>("cursorInstance"); |
|
675 QVERIFY(delegateObject); |
|
676 //Test Delegate gets moved |
|
677 for(int i=0; i<= textEditObject->text().length(); i++){ |
|
678 textEditObject->setCursorPosition(i); |
|
679 QCOMPARE(textEditObject->cursorRect().x(), qRound(delegateObject->x())); |
|
680 QCOMPARE(textEditObject->cursorRect().y(), qRound(delegateObject->y())); |
|
681 } |
|
682 textEditObject->setCursorPosition(0); |
|
683 QCOMPARE(textEditObject->cursorRect().x(), qRound(delegateObject->x())); |
|
684 QCOMPARE(textEditObject->cursorRect().y(), qRound(delegateObject->y())); |
|
685 //Test Delegate gets deleted |
|
686 textEditObject->setCursorDelegate(0); |
|
687 QVERIFY(!textEditObject->findChild<QDeclarativeItem*>("cursorInstance")); |
|
688 } |
|
689 |
|
690 void tst_qdeclarativetextedit::delegateLoading_data() |
|
691 { |
|
692 QTest::addColumn<QString>("qmlfile"); |
|
693 QTest::addColumn<QString>("error"); |
|
694 |
|
695 // import installed |
|
696 QTest::newRow("pass") << "cursorHttpTestPass.qml" << ""; |
|
697 QTest::newRow("fail1") << "cursorHttpTestFail1.qml" << "<Unknown File>: Network error for URL http://localhost:42332/FailItem.qml "; |
|
698 QTest::newRow("fail2") << "cursorHttpTestFail2.qml" << "http://localhost:42332/ErrItem.qml:4:5: Fungus is not a type "; |
|
699 } |
|
700 |
|
701 void tst_qdeclarativetextedit::delegateLoading() |
|
702 { |
|
703 QFETCH(QString, qmlfile); |
|
704 QFETCH(QString, error); |
|
705 |
|
706 TestHTTPServer server(42332); |
|
707 server.serveDirectory(SRCDIR "/data/httpfail", TestHTTPServer::Disconnect); |
|
708 server.serveDirectory(SRCDIR "/data/httpslow", TestHTTPServer::Delay); |
|
709 server.serveDirectory(SRCDIR "/data/http"); |
|
710 |
|
711 QDeclarativeView* view = new QDeclarativeView(0); |
|
712 |
|
713 view->setSource(QUrl(QLatin1String("http://localhost:42332/") + qmlfile)); |
|
714 view->show(); |
|
715 view->setFocus(); |
|
716 |
|
717 if (!error.isEmpty()) { |
|
718 QTest::ignoreMessage(QtWarningMsg, error.toUtf8()); |
|
719 QTRY_VERIFY(view->status()==QDeclarativeView::Error); |
|
720 QTRY_VERIFY(!view->rootObject()); // there is fail item inside this test |
|
721 } else { |
|
722 QTRY_VERIFY(view->rootObject());//Wait for loading to finish. |
|
723 QDeclarativeTextEdit *textEditObject = view->rootObject()->findChild<QDeclarativeTextEdit*>("textEditObject"); |
|
724 // view->rootObject()->dumpObjectTree(); |
|
725 QVERIFY(textEditObject != 0); |
|
726 textEditObject->setFocus(true); |
|
727 QDeclarativeItem *delegate; |
|
728 delegate = view->rootObject()->findChild<QDeclarativeItem*>("delegateOkay"); |
|
729 QVERIFY(delegate); |
|
730 delegate = view->rootObject()->findChild<QDeclarativeItem*>("delegateSlow"); |
|
731 QVERIFY(delegate); |
|
732 |
|
733 delete delegate; |
|
734 } |
|
735 |
|
736 |
|
737 //A test should be added here with a component which is ready but component.create() returns null |
|
738 //Not sure how to accomplish this with QDeclarativeTextEdits cursor delegate |
|
739 //###This was only needed for code coverage, and could be a case of overzealous defensive programming |
|
740 //delegate = view->rootObject()->findChild<QDeclarativeItem*>("delegateErrorB"); |
|
741 //QVERIFY(!delegate); |
|
742 |
|
743 delete view; |
|
744 } |
|
745 |
|
746 /* |
|
747 TextEdit element should only handle left/right keys until the cursor reaches |
|
748 the extent of the text, then they should ignore the keys. |
|
749 */ |
|
750 void tst_qdeclarativetextedit::navigation() |
|
751 { |
|
752 QDeclarativeView *canvas = createView(SRCDIR "/data/navigation.qml"); |
|
753 canvas->show(); |
|
754 canvas->setFocus(); |
|
755 |
|
756 QVERIFY(canvas->rootObject() != 0); |
|
757 |
|
758 QDeclarativeItem *input = qobject_cast<QDeclarativeItem *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput"))); |
|
759 |
|
760 QVERIFY(input != 0); |
|
761 QTRY_VERIFY(input->hasFocus() == true); |
|
762 simulateKey(canvas, Qt::Key_Left); |
|
763 QVERIFY(input->hasFocus() == false); |
|
764 simulateKey(canvas, Qt::Key_Right); |
|
765 QVERIFY(input->hasFocus() == true); |
|
766 simulateKey(canvas, Qt::Key_Right); |
|
767 QVERIFY(input->hasFocus() == false); |
|
768 simulateKey(canvas, Qt::Key_Left); |
|
769 QVERIFY(input->hasFocus() == true); |
|
770 } |
|
771 |
|
772 void tst_qdeclarativetextedit::readOnly() |
|
773 { |
|
774 QDeclarativeView *canvas = createView(SRCDIR "/data/readOnly.qml"); |
|
775 canvas->show(); |
|
776 canvas->setFocus(); |
|
777 |
|
778 QVERIFY(canvas->rootObject() != 0); |
|
779 |
|
780 QDeclarativeTextEdit *edit = qobject_cast<QDeclarativeTextEdit *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput"))); |
|
781 |
|
782 QVERIFY(edit != 0); |
|
783 QTRY_VERIFY(edit->hasFocus() == true); |
|
784 QVERIFY(edit->isReadOnly() == true); |
|
785 QString initial = edit->text(); |
|
786 for(int k=Qt::Key_0; k<=Qt::Key_Z; k++) |
|
787 simulateKey(canvas, k); |
|
788 simulateKey(canvas, Qt::Key_Return); |
|
789 simulateKey(canvas, Qt::Key_Space); |
|
790 simulateKey(canvas, Qt::Key_Escape); |
|
791 QCOMPARE(edit->text(), initial); |
|
792 } |
|
793 |
|
794 void tst_qdeclarativetextedit::simulateKey(QDeclarativeView *view, int key) |
|
795 { |
|
796 QKeyEvent press(QKeyEvent::KeyPress, key, 0); |
|
797 QKeyEvent release(QKeyEvent::KeyRelease, key, 0); |
|
798 |
|
799 QApplication::sendEvent(view, &press); |
|
800 QApplication::sendEvent(view, &release); |
|
801 } |
|
802 |
|
803 QDeclarativeView *tst_qdeclarativetextedit::createView(const QString &filename) |
|
804 { |
|
805 QDeclarativeView *canvas = new QDeclarativeView(0); |
|
806 |
|
807 canvas->setSource(QUrl::fromLocalFile(filename)); |
|
808 return canvas; |
|
809 } |
|
810 |
|
811 class MyInputContext : public QInputContext |
|
812 { |
|
813 public: |
|
814 MyInputContext() : softwareInputPanelEventReceived(false) {} |
|
815 ~MyInputContext() {} |
|
816 |
|
817 QString identifierName() { return QString(); } |
|
818 QString language() { return QString(); } |
|
819 |
|
820 void reset() {} |
|
821 |
|
822 bool isComposing() const { return false; } |
|
823 |
|
824 bool filterEvent( const QEvent *event ) |
|
825 { |
|
826 if (event->type() == QEvent::RequestSoftwareInputPanel) |
|
827 softwareInputPanelEventReceived = true; |
|
828 return QInputContext::filterEvent(event); |
|
829 } |
|
830 bool softwareInputPanelEventReceived; |
|
831 }; |
|
832 |
|
833 void tst_qdeclarativetextedit::sendRequestSoftwareInputPanelEvent() |
|
834 { |
|
835 QGraphicsScene scene; |
|
836 QGraphicsView view(&scene); |
|
837 MyInputContext ic; |
|
838 view.viewport()->setInputContext(&ic); |
|
839 QStyle::RequestSoftwareInputPanel behavior = QStyle::RequestSoftwareInputPanel( |
|
840 view.style()->styleHint(QStyle::SH_RequestSoftwareInputPanel)); |
|
841 QDeclarativeTextEdit edit; |
|
842 edit.setText("Hello world"); |
|
843 edit.setPos(0, 0); |
|
844 scene.addItem(&edit); |
|
845 view.show(); |
|
846 qApp->setAutoSipEnabled(true); |
|
847 QApplication::setActiveWindow(&view); |
|
848 QTest::qWaitForWindowShown(&view); |
|
849 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view)); |
|
850 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(edit.scenePos())); |
|
851 QApplication::processEvents(); |
|
852 if (behavior == QStyle::RSIP_OnMouseClickAndAlreadyFocused) { |
|
853 QCOMPARE(ic.softwareInputPanelEventReceived, false); |
|
854 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(edit.scenePos())); |
|
855 QApplication::processEvents(); |
|
856 QCOMPARE(ic.softwareInputPanelEventReceived, true); |
|
857 } else if (behavior == QStyle::RSIP_OnMouseClick) { |
|
858 QCOMPARE(ic.softwareInputPanelEventReceived, true); |
|
859 } |
|
860 } |
|
861 |
|
862 void tst_qdeclarativetextedit::geometrySignals() |
|
863 { |
|
864 QDeclarativeComponent component(&engine, SRCDIR "/data/geometrySignals.qml"); |
|
865 QObject *o = component.create(); |
|
866 QVERIFY(o); |
|
867 QCOMPARE(o->property("bindingWidth").toInt(), 400); |
|
868 QCOMPARE(o->property("bindingHeight").toInt(), 500); |
|
869 delete o; |
|
870 } |
|
871 |
|
872 QTEST_MAIN(tst_qdeclarativetextedit) |
|
873 |
|
874 #include "tst_qdeclarativetextedit.moc" |