1 /***************************************************************************
2 testqgsscalecombobox.cpp
3 ---------------------------
4 begin : September 2012
5 copyright : (C) 2012 by Magnus Homann
6 email : magnus at homann dot se
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18 #include "qgsapplication.h"
19 #include "qgslogger.h"
20 #include "qgsscalecombobox.h"
21 #include <QObject>
22 #include <QLineEdit>
23 #include <QComboBox>
24 #include <QtTest/QSignalSpy>
25 #include "qgstest.h"
26
27 class TestQgsScaleComboBox : public QObject
28 {
29 Q_OBJECT
30 public:
31 TestQgsScaleComboBox() = default;
32
33 private slots:
34 void initTestCase();// will be called before the first testfunction is executed.
35 void cleanupTestCase();// will be called after the last testfunction was executed.
36 void init();// will be called before each testfunction is executed.
37 void cleanup();// will be called after every testfunction.
38 void basic();
39 void slot_test();
40 void min_test();
41 void toString();
42 void toDouble();
43 void allowNull();
44 void testLocale();
45
46 private:
47 void enterScale( const QString &scale );
48 void enterScale( double scale );
49 QgsScaleComboBox *s = nullptr;
50 };
51
initTestCase()52 void TestQgsScaleComboBox::initTestCase()
53 {
54 QgsApplication::init();
55 QgsApplication::initQgis();
56
57 }
58
cleanupTestCase()59 void TestQgsScaleComboBox::cleanupTestCase()
60 {
61 QgsApplication::exitQgis();
62 }
63
init()64 void TestQgsScaleComboBox::init()
65 {
66 // Create a combobox, and init with predefined scales.
67 s = new QgsScaleComboBox();
68 QgsDebugMsg( QStringLiteral( "Initial scale is %1" ).arg( s->scaleString() ) );
69 }
70
basic()71 void TestQgsScaleComboBox::basic()
72 {
73 // Testing conversion from "1:nnn".
74 enterScale( QStringLiteral( "1:2345" ) );
75 QCOMPARE( s->scaleString(), QString( "1:%1" ).arg( QLocale().toString( 2345 ) ) );
76 QCOMPARE( s->scale(), 2345.0 );
77
78 // Testing conversion from number to "1:x"
79 enterScale( 0.02 );
80 QCOMPARE( s->scaleString(), QString( "1:%1" ).arg( QLocale().toString( 50 ) ) );
81 QCOMPARE( s->scale(), 1.0 / 0.02 );
82
83 // Testing conversion from number to "1:x"
84 enterScale( 42 );
85 QCOMPARE( s->scaleString(), QString( "1:%1" ).arg( QLocale().toString( 42 ) ) );
86 QCOMPARE( s->scale(), 42.0 );
87
88 // Testing conversion from number to "1:x,000"
89 QString str = QStringLiteral( "1%01000%01000" ).arg( QLocale().groupSeparator() );
90 enterScale( str );
91 QCOMPARE( s->scaleString(), QString( "1:%1" ).arg( str ) );
92 QCOMPARE( s->scale(), 1000000.0 );
93
94 // Testing conversion from number to "1:x,000" with wonky separators
95 //(e.g., four digits between thousands, which should be fixed automatically)
96 str = QStringLiteral( "1%010000%01000" ).arg( QLocale().groupSeparator() );
97 const QString fixedStr = QStringLiteral( "10%01000%01000" ).arg( QLocale().groupSeparator() );
98 enterScale( str );
99 QCOMPARE( s->scaleString(), QString( "1:%1" ).arg( fixedStr ) );
100 QCOMPARE( s->scale(), 10000000.0 );
101
102 // Testing rounding and conversion from illegal
103
104 enterScale( 0.24 );
105
106 enterScale( QStringLiteral( "1:x:2" ) );
107 QCOMPARE( s->scaleString(), QString( "1:%1" ).arg( QLocale().toString( 4 ) ) );
108 QCOMPARE( s->scale(), 4.0 );
109
110 // Test setting programmatically
111 s->setScale( 1.0 / 0.19 );
112 QCOMPARE( s->scaleString(), QString( "1:%1" ).arg( QLocale().toString( 5 ) ) );
113 QCOMPARE( s->scale(), 5.0 );
114
115 // Test setting programmatically
116 s->setScaleString( QStringLiteral( "1:240" ) );
117 QCOMPARE( s->scaleString(), QString( "1:%1" ).arg( QLocale().toString( 240 ) ) );
118 QCOMPARE( s->scale(), 240.0 );
119
120 // Test setting programmatically illegal string
121 s->setScaleString( QStringLiteral( "1:2" ) + QLocale().decimalPoint() + "4" );
122 QCOMPARE( s->scaleString(), QString( "1:%1" ).arg( QLocale().toString( 240 ) ) );
123 QCOMPARE( s->scale(), 240.0 );
124
125 }
126
slot_test()127 void TestQgsScaleComboBox::slot_test()
128 {
129 QLineEdit *l = s->lineEdit();
130
131 const QSignalSpy spyScaleChanged( s, SIGNAL( scaleChanged( double ) ) );
132 const QSignalSpy spyFixup( l, SIGNAL( editingFinished() ) );
133
134 enterScale( 0.02 );
135 QCOMPARE( spyFixup.count(), 2 ); // Qt emits twice!?
136 QCOMPARE( spyScaleChanged.count(), 1 );
137 }
138
min_test()139 void TestQgsScaleComboBox::min_test()
140 {
141 s->setMinScale( 100.0 );
142
143 enterScale( 0.02 );
144 QCOMPARE( s->scale(), 1.0 / 0.02 );
145
146 enterScale( 0.002 );
147 QCOMPARE( s->scale(), 100.0 );
148
149 s->setMinScale( 1.0 / 0.015 );
150 QCOMPARE( s->scale(), 1.0 / 0.015 );
151
152 s->setScale( 2.0 );
153 QCOMPARE( s->scale(), 2.0 );
154 }
155
toString()156 void TestQgsScaleComboBox::toString()
157 {
158 QCOMPARE( QgsScaleComboBox::toString( 100 ), QStringLiteral( "1:100" ) );
159 QCOMPARE( QgsScaleComboBox::toString( 100.02134234 ), QStringLiteral( "1:100" ) );
160 QCOMPARE( QgsScaleComboBox::toString( 1 ), QStringLiteral( "1:1" ) );
161 QCOMPARE( QgsScaleComboBox::toString( 1.0 / 100 ), QStringLiteral( "100:1" ) );
162 QCOMPARE( QgsScaleComboBox::toString( std::numeric_limits< double >::quiet_NaN() ), QString() );
163 }
164
toDouble()165 void TestQgsScaleComboBox::toDouble()
166 {
167 bool ok = false;
168 QCOMPARE( QgsScaleComboBox::toDouble( QStringLiteral( "1:100" ), &ok ), 100.0 );
169 QVERIFY( ok );
170 QCOMPARE( QgsScaleComboBox::toDouble( QStringLiteral( "1:1" ), &ok ), 1.0 );
171 QVERIFY( ok );
172 QCOMPARE( QgsScaleComboBox::toDouble( QStringLiteral( "100:1" ), &ok ), 1.0 / 100 );
173 QVERIFY( ok );
174 QCOMPARE( QgsScaleComboBox::toDouble( QStringLiteral( "0.01" ), &ok ), 100.0 );
175 QVERIFY( ok );
176 QCOMPARE( QgsScaleComboBox::toDouble( QStringLiteral( "100" ), &ok ), 1.0 / 100.0 );
177 QVERIFY( ok );
178
179 //bad
180 QgsScaleComboBox::toDouble( QStringLiteral( "abc" ), &ok );
181 QVERIFY( !ok );
182 QgsScaleComboBox::toDouble( QString(), &ok );
183 QVERIFY( !ok );
184 QgsScaleComboBox::toDouble( QStringLiteral( "1:" ), &ok );
185 QVERIFY( !ok );
186 QgsScaleComboBox::toDouble( QStringLiteral( "1:a" ), &ok );
187 QVERIFY( !ok );
188 QgsScaleComboBox::toDouble( QStringLiteral( "a:1" ), &ok );
189 QVERIFY( !ok );
190 }
191
allowNull()192 void TestQgsScaleComboBox::allowNull()
193 {
194 s->setScale( 50 );
195 QVERIFY( !s->allowNull() );
196 s->setNull(); // no effect
197 QCOMPARE( s->scale(), 50.0 );
198 QVERIFY( !s->isNull() );
199
200 const QSignalSpy spyScaleChanged( s, &QgsScaleComboBox::scaleChanged );
201 s->setAllowNull( true );
202 QVERIFY( s->allowNull() );
203
204 QVERIFY( s->lineEdit()->isClearButtonEnabled() );
205
206 s->setScaleString( QString() );
207 QCOMPARE( spyScaleChanged.count(), 1 );
208 QVERIFY( std::isnan( s->scale() ) );
209 QVERIFY( s->isNull() );
210 s->setScaleString( QStringLiteral( " " ) );
211 QVERIFY( std::isnan( s->scale() ) );
212 QVERIFY( s->lineEdit()->text().isEmpty() );
213 QCOMPARE( spyScaleChanged.count(), 1 );
214 QVERIFY( s->isNull() );
215
216 enterScale( 0.02 );
217 QCOMPARE( s->scale(), 50.0 );
218 QCOMPARE( spyScaleChanged.count(), 2 );
219 QCOMPARE( s->lineEdit()->text(), QStringLiteral( "1:50" ) );
220 QVERIFY( !s->isNull() );
221
222 enterScale( QString() );
223 QVERIFY( std::isnan( s->scale() ) );
224 QCOMPARE( spyScaleChanged.count(), 3 );
225 QVERIFY( s->lineEdit()->text().isEmpty() );
226 QVERIFY( s->isNull() );
227
228 enterScale( 0.02 );
229 QCOMPARE( s->scale(), 50.0 );
230 QCOMPARE( spyScaleChanged.count(), 4 );
231 s->setNull();
232 QVERIFY( std::isnan( s->scale() ) );
233 QCOMPARE( spyScaleChanged.count(), 5 );
234 QVERIFY( s->lineEdit()->text().isEmpty() );
235 QVERIFY( s->isNull() );
236
237 s->setAllowNull( false );
238 QVERIFY( !s->allowNull() );
239 QVERIFY( !s->lineEdit()->isClearButtonEnabled() );
240 }
241
enterScale(const QString & scale)242 void TestQgsScaleComboBox::enterScale( const QString &scale )
243 {
244 QLineEdit *l = s->lineEdit();
245 l->clear();
246 QTest::keyClicks( l, scale );
247 QTest::keyClick( l, Qt::Key_Return );
248 }
249
enterScale(double scale)250 void TestQgsScaleComboBox::enterScale( double scale )
251 {
252 enterScale( QLocale().toString( scale ) );
253 }
254
cleanup()255 void TestQgsScaleComboBox::cleanup()
256 {
257 delete s;
258 }
259
testLocale()260 void TestQgsScaleComboBox::testLocale()
261 {
262 QLocale::setDefault( QLocale::English );
263 QCOMPARE( s->toString( 1e8 ), QString( "1:100,000,000" ) );
264 QLocale customEnglish( QLocale::English );
265 customEnglish.setNumberOptions( QLocale::NumberOption::OmitGroupSeparator );
266 QLocale::setDefault( customEnglish );
267 QCOMPARE( s->toString( 1e8 ), QString( "1:100000000" ) );
268
269 QLocale::setDefault( QLocale::French );
270 QCOMPARE( s->toString( 1e8 ), QString( "1:100 000 000" ) );
271 QLocale customFrench( QLocale::French );
272 customFrench.setNumberOptions( QLocale::NumberOption::OmitGroupSeparator );
273 QLocale::setDefault( customFrench );
274 QCOMPARE( s->toString( 1e8 ), QString( "1:100000000" ) );
275
276 QLocale::setDefault( QLocale::German );
277 QCOMPARE( s->toString( 1e8 ), QString( "1:100.000.000" ) );
278 const QLocale customGerman( QLocale::German );
279 customFrench.setNumberOptions( QLocale::NumberOption::OmitGroupSeparator );
280 QLocale::setDefault( customFrench );
281 QCOMPARE( s->toString( 1e8 ), QString( "1:100000000" ) );
282 }
283
284 QGSTEST_MAIN( TestQgsScaleComboBox )
285 #include "testqgsscalecombobox.moc"
286