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