1 /***************************************************************************
2 testqgsdatetimeedit.cpp
3 --------------------------------------
4 Date : September 2019
5 Copyright : (C) 2019 Etienne Trimaille
6 Email : etienne dot trimaille at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16
17 #include "qgstest.h"
18 #include "qdatetime.h"
19
20 #include <qgsdatetimeedit.h>
21 #include <qgsdatetimeeditwrapper.h>
22 #include <qgsdatetimefieldformatter.h>
23
24 class TestQgsDateTimeEdit: public QObject
25 {
26 Q_OBJECT
27 private slots:
28 void initTestCase(); // will be called before the first testfunction is executed.
29 void cleanupTestCase(); // will be called after the last testfunction was executed.
30 void init(); // will be called before each testfunction is executed.
31 void cleanup(); // will be called after every testfunction.
32
33 void nullValues();
34 void focus();
35 void testDateTime();
36
37 private:
38 std::unique_ptr<QgsDateTimeEditWrapper> widget1; // For field 0
39 std::unique_ptr<QgsDateTimeEditWrapper> widget2; // For field 1
40 std::unique_ptr<QgsDateTimeEditWrapper> widget3; // For field 2
41 std::unique_ptr<QgsDateTimeEditWrapper> widget4; // For field 3
42 std::unique_ptr<QgsDateTimeEditWrapper> widget5; // For field 4
43 std::unique_ptr<QgsDateTimeEditWrapper> widget6; // For field 5
44 std::unique_ptr<QgsDateTimeEditWrapper> widget7; // For field 6
45 std::unique_ptr<QgsVectorLayer> vl;
46
47 };
48
initTestCase()49 void TestQgsDateTimeEdit::initTestCase()
50 {
51 }
52
cleanupTestCase()53 void TestQgsDateTimeEdit::cleanupTestCase()
54 {
55 }
56
init()57 void TestQgsDateTimeEdit::init()
58 {
59
60 vl = std::make_unique<QgsVectorLayer>( QStringLiteral( "Point?crs=epsg:4326" ),
61 QStringLiteral( "myvl" ),
62 QLatin1String( "memory" ) );
63
64 // add fields
65 QList<QgsField> fields;
66 fields.append( QgsField( "date1", QVariant::Date ) );
67 fields.append( QgsField( "date2", QVariant::Date ) );
68 fields.append( QgsField( "date3", QVariant::Date ) );
69 fields.append( QgsField( "time", QVariant::Time ) );
70 fields.append( QgsField( "datetime1", QVariant::DateTime ) );
71 fields.append( QgsField( "datetime2", QVariant::DateTime ) );
72 fields.append( QgsField( "text", QVariant::String ) );
73 vl->dataProvider()->addAttributes( fields );
74 vl->updateFields();
75 QVERIFY( vl.get() );
76 QVERIFY( vl->isValid() );
77
78 widget1 = std::make_unique<QgsDateTimeEditWrapper>( vl.get(), 0, nullptr, nullptr );
79 widget2 = std::make_unique<QgsDateTimeEditWrapper>( vl.get(), 1, nullptr, nullptr );
80 widget3 = std::make_unique<QgsDateTimeEditWrapper>( vl.get(), 2, nullptr, nullptr );
81 widget4 = std::make_unique<QgsDateTimeEditWrapper>( vl.get(), 3, nullptr, nullptr );
82 widget5 = std::make_unique<QgsDateTimeEditWrapper>( vl.get(), 4, nullptr, nullptr );
83 widget6 = std::make_unique<QgsDateTimeEditWrapper>( vl.get(), 5, nullptr, nullptr );
84 widget7 = std::make_unique<QgsDateTimeEditWrapper>( vl.get(), 6, nullptr, nullptr );
85 QVERIFY( widget1.get() );
86 QVERIFY( widget2.get() );
87 QVERIFY( widget3.get() );
88 QVERIFY( widget4.get() );
89 QVERIFY( widget5.get() );
90 QVERIFY( widget6.get() );
91 QVERIFY( widget7.get() );
92 }
93
cleanup()94 void TestQgsDateTimeEdit::cleanup()
95 {
96 }
97
nullValues()98 void TestQgsDateTimeEdit::nullValues()
99 {
100 QgsDateTimeEdit *timeEdit = new QgsDateTimeEdit();
101
102 // Allow null with a null datetime
103 QVERIFY( timeEdit->allowNull() );
104 timeEdit->setDateTime( QDateTime() );
105 QCOMPARE( timeEdit->dateTime(), QDateTime() );
106 QCOMPARE( timeEdit->time(), QTime() );
107 QCOMPARE( timeEdit->date(), QDate() );
108
109 // Not null with not null datetime
110 const QDateTime date( QDate( 2019, 7, 6 ), QTime( 8, 30, 0 ) );
111 timeEdit->setAllowNull( false );
112 QVERIFY( !timeEdit->allowNull() );
113 timeEdit->setDateTime( date );
114 QCOMPARE( timeEdit->dateTime(), date );
115 QCOMPARE( timeEdit->time(), date.time() );
116 QCOMPARE( timeEdit->date(), date.date() );
117
118 // Not null with null date
119 timeEdit->setAllowNull( false );
120 QVERIFY( !timeEdit->allowNull() );
121 timeEdit->setDateTime( QDateTime() );
122 QCOMPARE( timeEdit->dateTime(), date );
123 QCOMPARE( timeEdit->time(), date.time() );
124 QCOMPARE( timeEdit->date(), date.date() );
125
126 delete timeEdit;
127
128 // QgsDateEdit
129
130 QgsDateEdit *dateEdit = new QgsDateEdit();
131
132 // Allow null with a null datetime
133 QVERIFY( dateEdit->allowNull() );
134 dateEdit->setDate( QDate() );
135 QCOMPARE( dateEdit->date(), QDate() );
136
137 // Not null with not null datetime
138 const QDate dt( 2019, 7, 6 );
139 dateEdit->setAllowNull( false );
140 QVERIFY( !dateEdit->allowNull() );
141 dateEdit->setDate( dt );
142 QCOMPARE( dateEdit->date(), dt );
143
144 // Not null with null date
145 dateEdit->setAllowNull( false );
146 QVERIFY( !dateEdit->allowNull() );
147 dateEdit->setDate( QDate() );
148 QCOMPARE( dateEdit->date(), dt );
149
150 delete dateEdit;
151
152 // QgsTimeEdit
153
154 QgsTimeEdit *tEdit = new QgsTimeEdit();
155
156 // Allow null with a null datetime
157 QVERIFY( tEdit->allowNull() );
158 tEdit->setTime( QTime() );
159 QCOMPARE( tEdit->time(), QTime() );
160
161 // Not null with not null datetime
162 const QTime t( 8, 30, 0 );
163 tEdit->setAllowNull( false );
164 QVERIFY( !tEdit->allowNull() );
165 tEdit->setTime( t );
166 QCOMPARE( tEdit->time(), t );
167
168 // Not null with null date
169 tEdit->setAllowNull( false );
170 QVERIFY( !tEdit->allowNull() );
171 tEdit->setTime( QTime() );
172 QCOMPARE( tEdit->time(), t );
173
174 delete tEdit;
175 }
176
focus()177 void TestQgsDateTimeEdit::focus()
178 {
179 QgsApplication::setNullRepresentation( QString( "nope" ) );
180 QWidget w; //required for focus events
181 QApplication::setActiveWindow( &w );
182
183 QVariantMap cfg;
184 cfg.insert( QStringLiteral( "AllowNull" ), true );
185
186 widget1->setConfig( cfg );
187 QgsDateTimeEdit *dateedit1 = qobject_cast<QgsDateTimeEdit *>( widget1->createWidget( &w ) );
188 QVERIFY( dateedit1 );
189 widget1->initWidget( dateedit1 );
190 widget1->setValue( QVariant::Date );
191
192 widget2->setConfig( cfg );
193 QgsDateTimeEdit *dateedit2 = qobject_cast<QgsDateTimeEdit *>( widget2->createWidget( &w ) );
194 QVERIFY( dateedit2 );
195 widget2->initWidget( dateedit2 );
196 widget2->setValue( QVariant::Date );
197
198 widget3->setConfig( cfg );
199 QgsDateTimeEdit *dateedit3 = qobject_cast<QgsDateTimeEdit *>( widget3->createWidget( &w ) );
200 QVERIFY( dateedit3 );
201 widget3->initWidget( dateedit3 );
202 widget3->setValue( QVariant::Date );
203
204 QVERIFY( widget1->value().isNull() );
205 QVERIFY( widget2->value().isNull() );
206 QVERIFY( widget3->value().isNull() );
207 QVERIFY( !dateedit1->hasFocus() );
208 QVERIFY( !dateedit2->hasFocus() );
209 QVERIFY( !dateedit3->hasFocus() );
210 QCOMPARE( dateedit1->text(), QStringLiteral( "nope" ) );
211 QCOMPARE( dateedit2->text(), QStringLiteral( "nope" ) );
212 QCOMPARE( dateedit3->text(), QStringLiteral( "nope" ) );
213
214 dateedit1->setFocus();
215 QVERIFY( widget1->value().isNull() );
216 QVERIFY( widget2->value().isNull() );
217 QVERIFY( widget3->value().isNull() );
218 QVERIFY( dateedit1->hasFocus() );
219 QVERIFY( !dateedit2->hasFocus() );
220 QVERIFY( !dateedit3->hasFocus() );
221 QCOMPARE( dateedit1->text(), QDateTime::currentDateTime().toString( QgsDateTimeFieldFormatter::DATE_FORMAT ) );
222 QCOMPARE( dateedit2->text(), QStringLiteral( "nope" ) );
223 QCOMPARE( dateedit3->text(), QStringLiteral( "nope" ) );
224
225 dateedit2->setFocus();
226 QVERIFY( widget1->value().isNull() );
227 QVERIFY( widget2->value().isNull() );
228 QVERIFY( widget3->value().isNull() );
229 QVERIFY( !dateedit1->hasFocus() );
230 QVERIFY( dateedit2->hasFocus() );
231 QVERIFY( !dateedit3->hasFocus() );
232 QCOMPARE( dateedit1->text(), QStringLiteral( "nope" ) );
233 QCOMPARE( dateedit2->text(), QDateTime::currentDateTime().toString( QgsDateTimeFieldFormatter::DATE_FORMAT ) );
234 QCOMPARE( dateedit3->text(), QStringLiteral( "nope" ) );
235
236 dateedit3->setFocus();
237 QVERIFY( widget1->value().isNull() );
238 QVERIFY( widget2->value().isNull() );
239 QVERIFY( widget3->value().isNull() );
240 QVERIFY( !dateedit1->hasFocus() );
241 QVERIFY( !dateedit2->hasFocus() );
242 QVERIFY( dateedit3->hasFocus() );
243 QCOMPARE( dateedit1->text(), QStringLiteral( "nope" ) );
244 QCOMPARE( dateedit2->text(), QStringLiteral( "nope" ) );
245 QCOMPARE( dateedit3->text(), QDateTime::currentDateTime().toString( QgsDateTimeFieldFormatter::DATE_FORMAT ) );
246
247 dateedit1->setFocus();
248 dateedit1->setDateTime( QDateTime::fromString( QStringLiteral( "1955-11-12" ), QgsDateTimeFieldFormatter::DATE_FORMAT ) );
249 QVERIFY( !widget1->value().isNull() );
250 QVERIFY( widget2->value().isNull() );
251 QVERIFY( widget3->value().isNull() );
252 QVERIFY( dateedit1->hasFocus() );
253 QVERIFY( !dateedit2->hasFocus() );
254 QVERIFY( !dateedit3->hasFocus() );
255 QCOMPARE( dateedit1->text(), QStringLiteral( "1955-11-12" ) );
256 QCOMPARE( dateedit2->text(), QStringLiteral( "nope" ) );
257 QCOMPARE( dateedit3->text(), QStringLiteral( "nope" ) );
258
259 dateedit2->setFocus();
260 QVERIFY( !widget1->value().isNull() );
261 QVERIFY( widget2->value().isNull() );
262 QVERIFY( widget3->value().isNull() );
263 QVERIFY( !dateedit1->hasFocus() );
264 QVERIFY( dateedit2->hasFocus() );
265 QVERIFY( !dateedit3->hasFocus() );
266 QCOMPARE( dateedit1->text(), QStringLiteral( "1955-11-12" ) );
267 QCOMPARE( dateedit2->text(), QDateTime::currentDateTime().toString( QgsDateTimeFieldFormatter::DATE_FORMAT ) );
268 QCOMPARE( dateedit3->text(), QStringLiteral( "nope" ) );
269
270 dateedit1->setFocus();
271 dateedit1->clear();
272 QVERIFY( widget1->value().isNull() );
273 QVERIFY( widget2->value().isNull() );
274 QVERIFY( widget3->value().isNull() );
275 QVERIFY( dateedit1->hasFocus() );
276 QVERIFY( !dateedit2->hasFocus() );
277 QVERIFY( !dateedit3->hasFocus() );
278 QCOMPARE( dateedit1->text(), QDateTime::currentDateTime().toString( QgsDateTimeFieldFormatter::DATE_FORMAT ) );
279 QCOMPARE( dateedit2->text(), QStringLiteral( "nope" ) );
280 QCOMPARE( dateedit3->text(), QStringLiteral( "nope" ) );
281
282 dateedit2->setFocus();
283 QVERIFY( widget1->value().isNull() );
284 QVERIFY( widget2->value().isNull() );
285 QVERIFY( widget3->value().isNull() );
286 QVERIFY( !dateedit1->hasFocus() );
287 QVERIFY( dateedit2->hasFocus() );
288 QVERIFY( !dateedit3->hasFocus() );
289 QCOMPARE( dateedit1->text(), QStringLiteral( "nope" ) );
290 QCOMPARE( dateedit2->text(), QDateTime::currentDateTime().toString( QgsDateTimeFieldFormatter::DATE_FORMAT ) );
291 QCOMPARE( dateedit3->text(), QStringLiteral( "nope" ) );
292 }
293
testDateTime()294 void TestQgsDateTimeEdit::testDateTime()
295 {
296 QgsApplication::setNullRepresentation( QString( "nope" ) );
297 QWidget w;
298 QApplication::setActiveWindow( &w );
299
300 QVariantMap cfg;
301 cfg.insert( QStringLiteral( "AllowNull" ), true );
302
303 widget4->setConfig( cfg );
304 QgsDateTimeEdit *dateedit4 = qobject_cast<QgsDateTimeEdit *>( widget4->createWidget( &w ) );
305 QVERIFY( dateedit4 );
306 widget4->initWidget( dateedit4 );
307 widget4->setValue( QTime( 23, 10, 57 ) );
308 const QTime value { widget4->value().toTime() };
309 QCOMPARE( value, QTime( 23, 10, 57 ) );
310
311 widget5->setConfig( cfg );
312 QgsDateTimeEdit *dateedit5 = qobject_cast<QgsDateTimeEdit *>( widget5->createWidget( &w ) );
313 QVERIFY( dateedit5 );
314 widget5->initWidget( dateedit5 );
315 widget5->setValue( QDate( 1966, 11, 25 ) );
316 const QDate value5 { widget5->value().toDate() };
317 QCOMPARE( value5, QDate( 1966, 11, 25 ) );
318
319 widget6->setConfig( cfg );
320 QgsDateTimeEdit *dateedit6 = qobject_cast<QgsDateTimeEdit *>( widget6->createWidget( &w ) );
321 QVERIFY( dateedit6 );
322 widget6->initWidget( dateedit6 );
323 widget6->setValue( QDate( 1, 1, 1 ) );
324 const QDate value6 { widget6->value().toDate() };
325 QCOMPARE( value6, QDate( 1, 1, 1 ) );
326
327 // Test for issue GH #46542
328 widget7->setConfig( cfg );
329 QgsDateTimeEdit *dateedit7 = qobject_cast<QgsDateTimeEdit *>( widget7->createWidget( &w ) );
330 QVERIFY( dateedit7 );
331 widget7->initWidget( dateedit7 );
332 QgsFeature f { vl->fields() };
333 f.setAttribute( QStringLiteral( "text" ), QgsExpression{ QStringLiteral( "now()" ) }.evaluate() );
334 widget7->setFeature( f );
335 const QDate value7 { widget7->value().toDate() };
336 QCOMPARE( value7, QDate::currentDate() );
337
338 }
339
340 QGSTEST_MAIN( TestQgsDateTimeEdit )
341 #include "testqgsdatetimeedit.moc"
342