1 /***************************************************************************
2     qgsnumericformatwidget.cpp
3     --------------------------
4     begin                : January 2020
5     copyright            : (C) 2020 by Nyall Dawson
6     email                : nyall dot dawson 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 #include "qgsnumericformatwidget.h"
17 #include "qgsbasicnumericformat.h"
18 #include "qgscurrencynumericformat.h"
19 #include "qgspercentagenumericformat.h"
20 #include "qgsbearingnumericformat.h"
21 #include "qgsscientificnumericformat.h"
22 #include "qgsfractionnumericformat.h"
23 #include "qgsgui.h"
24 #include "qgis.h"
25 #include <QDialogButtonBox>
26 
27 //
28 // QgsBasicNumericFormatWidget
29 //
QgsBasicNumericFormatWidget(const QgsNumericFormat * format,QWidget * parent)30 QgsBasicNumericFormatWidget::QgsBasicNumericFormatWidget( const QgsNumericFormat *format, QWidget *parent )
31   : QgsNumericFormatWidget( parent )
32 {
33   setupUi( this );
34   setFormat( format->clone() );
35 
36   mDecimalsSpinBox->setClearValue( 6 );
37   mThousandsLineEdit->setShowClearButton( true );
38   mDecimalLineEdit->setShowClearButton( true );
39 
40   connect( mShowPlusCheckBox, &QCheckBox::toggled, this, [ = ]( bool checked )
41   {
42     mFormat->setShowPlusSign( checked );
43     if ( !mBlockSignals )
44       emit changed();
45   } );
46 
47   connect( mShowTrailingZerosCheckBox, &QCheckBox::toggled, this, [ = ]( bool checked )
48   {
49     mFormat->setShowTrailingZeros( checked );
50     if ( !mBlockSignals )
51       emit changed();
52   } );
53 
54   connect( mShowThousandsCheckBox, &QCheckBox::toggled, this, [ = ]( bool checked )
55   {
56     mFormat->setShowThousandsSeparator( checked );
57     if ( !mBlockSignals )
58       emit changed();
59   } );
60 
61   connect( mDecimalsSpinBox, qOverload<int>( &QSpinBox::valueChanged ), this, [ = ]( int value )
62   {
63     mFormat->setNumberDecimalPlaces( value );
64     if ( !mBlockSignals )
65       emit changed();
66   } );
67 
68   connect( mRadDecimalPlaces, &QRadioButton::toggled, this, [ = ]( bool checked )
69   {
70     if ( !checked )
71       return;
72 
73     mFormat->setRoundingType( QgsBasicNumericFormat::DecimalPlaces );
74     if ( !mBlockSignals )
75       emit changed();
76   } );
77 
78   connect( mRadSignificantFigures, &QRadioButton::toggled, this, [ = ]( bool checked )
79   {
80     if ( !checked )
81       return;
82 
83     mFormat->setRoundingType( QgsBasicNumericFormat::SignificantFigures );
84     if ( !mBlockSignals )
85       emit changed();
86   } );
87 
88   connect( mThousandsLineEdit, &QLineEdit::textChanged, this, [ = ]( const QString & text )
89   {
90     mFormat->setThousandsSeparator( text.isEmpty() ? QChar() : text.at( 0 ) );
91     if ( !mBlockSignals )
92       emit changed();
93   } );
94 
95   connect( mDecimalLineEdit, &QLineEdit::textChanged, this, [ = ]( const QString & text )
96   {
97     mFormat->setDecimalSeparator( text.isEmpty() ? QChar() : text.at( 0 ) );
98     if ( !mBlockSignals )
99       emit changed();
100   } );
101 }
102 
103 QgsBasicNumericFormatWidget::~QgsBasicNumericFormatWidget() = default;
104 
setFormat(QgsNumericFormat * format)105 void QgsBasicNumericFormatWidget::setFormat( QgsNumericFormat *format )
106 {
107   mFormat.reset( static_cast< QgsBasicNumericFormat * >( format ) );
108 
109   mBlockSignals = true;
110   mDecimalsSpinBox->setValue( mFormat->numberDecimalPlaces() );
111   mShowPlusCheckBox->setChecked( mFormat->showPlusSign() );
112   mShowTrailingZerosCheckBox->setChecked( mFormat->showTrailingZeros() );
113   mShowThousandsCheckBox->setChecked( mFormat->showThousandsSeparator() );
114   mThousandsLineEdit->setText( mFormat->thousandsSeparator().isNull() ? QString() : mFormat->thousandsSeparator() );
115   mDecimalLineEdit->setText( mFormat->decimalSeparator().isNull() ? QString() : mFormat->decimalSeparator() );
116   switch ( mFormat->roundingType() )
117   {
118     case QgsBasicNumericFormat::DecimalPlaces:
119       mRadDecimalPlaces->setChecked( true );
120       break;
121 
122     case QgsBasicNumericFormat::SignificantFigures:
123       mRadSignificantFigures->setChecked( true );
124       break;
125   }
126 
127   mBlockSignals = false;
128 }
129 
format()130 QgsNumericFormat *QgsBasicNumericFormatWidget::format()
131 {
132   return mFormat->clone();
133 }
134 
135 //
136 // QgsBearingNumericFormatWidget
137 //
138 
QgsBearingNumericFormatWidget(const QgsNumericFormat * format,QWidget * parent)139 QgsBearingNumericFormatWidget::QgsBearingNumericFormatWidget( const QgsNumericFormat *format, QWidget *parent )
140   : QgsNumericFormatWidget( parent )
141 {
142   setupUi( this );
143 
144   mDecimalsSpinBox->setClearValue( 6 );
145   mFormatComboBox->addItem( QObject::tr( "0 to 180°, with E/W suffix" ), QgsBearingNumericFormat::UseRange0To180WithEWDirectionalSuffix );
146   mFormatComboBox->addItem( QObject::tr( "-180 to +180°" ), QgsBearingNumericFormat::UseRangeNegative180ToPositive180 );
147   mFormatComboBox->addItem( QObject::tr( "0 to 360°" ), QgsBearingNumericFormat::UseRange0To360 );
148 
149   setFormat( format->clone() );
150 
151   connect( mShowTrailingZerosCheckBox, &QCheckBox::toggled, this, [ = ]( bool checked )
152   {
153     mFormat->setShowTrailingZeros( checked );
154     if ( !mBlockSignals )
155       emit changed();
156   } );
157 
158   connect( mDecimalsSpinBox, qOverload<int>( &QSpinBox::valueChanged ), this, [ = ]( int value )
159   {
160     mFormat->setNumberDecimalPlaces( value );
161     if ( !mBlockSignals )
162       emit changed();
163   } );
164 
165   connect( mFormatComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [ = ]( int )
166   {
167     mFormat->setDirectionFormat( static_cast < QgsBearingNumericFormat::FormatDirectionOption >( mFormatComboBox->currentData().toInt() ) );
168     if ( !mBlockSignals )
169       emit changed();
170   } );
171 }
172 
173 QgsBearingNumericFormatWidget::~QgsBearingNumericFormatWidget() = default;
174 
setFormat(QgsNumericFormat * format)175 void QgsBearingNumericFormatWidget::setFormat( QgsNumericFormat *format )
176 {
177   mFormat.reset( static_cast< QgsBearingNumericFormat * >( format ) );
178 
179   mBlockSignals = true;
180   mDecimalsSpinBox->setValue( mFormat->numberDecimalPlaces() );
181   mShowTrailingZerosCheckBox->setChecked( mFormat->showTrailingZeros() );
182   mFormatComboBox->setCurrentIndex( mFormatComboBox->findData( static_cast< int >( mFormat->directionFormat() ) ) );
183   mBlockSignals = false;
184 }
185 
format()186 QgsNumericFormat *QgsBearingNumericFormatWidget::format()
187 {
188   return mFormat->clone();
189 }
190 
191 //
192 // QgsBearingNumericFormatDialog
193 //
194 
QgsBearingNumericFormatDialog(const QgsNumericFormat * format,QWidget * parent)195 QgsBearingNumericFormatDialog::QgsBearingNumericFormatDialog( const QgsNumericFormat *format, QWidget *parent )
196   : QDialog( parent )
197 {
198   setLayout( new QVBoxLayout() );
199   mWidget = new QgsBearingNumericFormatWidget( format );
200   QDialogButtonBox *buttonBox = new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Ok );
201 
202   connect( buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept );
203   connect( buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject );
204 
205   layout()->addWidget( mWidget );
206   layout()->addWidget( buttonBox );
207 
208   connect( mWidget, &QgsPanelWidget::panelAccepted, this, &QDialog::reject );
209 
210   setObjectName( QStringLiteral( "QgsBearingNumericFormatDialog" ) );
211   QgsGui::instance()->enableAutoGeometryRestore( this );
212 }
213 
format()214 QgsBearingNumericFormat *QgsBearingNumericFormatDialog::format()
215 {
216   return static_cast< QgsBearingNumericFormat * >( mWidget->format() );
217 }
218 
219 
220 
221 //
222 // QgsCurrencyNumericFormatWidget
223 //
QgsCurrencyNumericFormatWidget(const QgsNumericFormat * format,QWidget * parent)224 QgsCurrencyNumericFormatWidget::QgsCurrencyNumericFormatWidget( const QgsNumericFormat *format, QWidget *parent )
225   : QgsNumericFormatWidget( parent )
226 {
227   setupUi( this );
228   mDecimalsSpinBox->setClearValue( 2 );
229   setFormat( format->clone() );
230 
231   connect( mShowPlusCheckBox, &QCheckBox::toggled, this, [ = ]( bool checked )
232   {
233     mFormat->setShowPlusSign( checked );
234     if ( !mBlockSignals )
235       emit changed();
236   } );
237 
238   connect( mShowTrailingZerosCheckBox, &QCheckBox::toggled, this, [ = ]( bool checked )
239   {
240     mFormat->setShowTrailingZeros( checked );
241     if ( !mBlockSignals )
242       emit changed();
243   } );
244 
245   connect( mShowThousandsCheckBox, &QCheckBox::toggled, this, [ = ]( bool checked )
246   {
247     mFormat->setShowThousandsSeparator( checked );
248     if ( !mBlockSignals )
249       emit changed();
250   } );
251 
252   connect( mDecimalsSpinBox, qOverload<int>( &QSpinBox::valueChanged ), this, [ = ]( int value )
253   {
254     mFormat->setNumberDecimalPlaces( value );
255     if ( !mBlockSignals )
256       emit changed();
257   } );
258 
259   connect( mPrefixLineEdit, &QLineEdit::textChanged, this, [ = ]( const QString & text )
260   {
261     mFormat->setPrefix( text );
262     if ( !mBlockSignals )
263       emit changed();
264   } );
265 
266   connect( mSuffixLineEdit, &QLineEdit::textChanged, this, [ = ]( const QString & text )
267   {
268     mFormat->setSuffix( text );
269     if ( !mBlockSignals )
270       emit changed();
271   } );
272 }
273 
274 QgsCurrencyNumericFormatWidget::~QgsCurrencyNumericFormatWidget() = default;
275 
setFormat(QgsNumericFormat * format)276 void QgsCurrencyNumericFormatWidget::setFormat( QgsNumericFormat *format )
277 {
278   mFormat.reset( static_cast< QgsCurrencyNumericFormat * >( format ) );
279 
280   mBlockSignals = true;
281   mDecimalsSpinBox->setValue( mFormat->numberDecimalPlaces() );
282   mShowPlusCheckBox->setChecked( mFormat->showPlusSign() );
283   mShowTrailingZerosCheckBox->setChecked( mFormat->showTrailingZeros() );
284   mShowThousandsCheckBox->setChecked( mFormat->showThousandsSeparator() );
285   mPrefixLineEdit->setText( mFormat->prefix() );
286   mSuffixLineEdit->setText( mFormat->suffix() );
287 
288   mBlockSignals = false;
289 }
290 
format()291 QgsNumericFormat *QgsCurrencyNumericFormatWidget::format()
292 {
293   return mFormat->clone();
294 }
295 
296 
297 //
298 // QgsPercentageNumericFormatWidget
299 //
300 
QgsPercentageNumericFormatWidget(const QgsNumericFormat * format,QWidget * parent)301 QgsPercentageNumericFormatWidget::QgsPercentageNumericFormatWidget( const QgsNumericFormat *format, QWidget *parent )
302   : QgsNumericFormatWidget( parent )
303 {
304   setupUi( this );
305 
306   mDecimalsSpinBox->setClearValue( 6 );
307   mScalingComboBox->addItem( QObject::tr( "Values are Percentages (e.g. 50)" ), QgsPercentageNumericFormat::ValuesArePercentage );
308   mScalingComboBox->addItem( QObject::tr( "Values are Fractions (e.g. 0.5)" ), QgsPercentageNumericFormat::ValuesAreFractions );
309 
310   setFormat( format->clone() );
311 
312   connect( mShowTrailingZerosCheckBox, &QCheckBox::toggled, this, [ = ]( bool checked )
313   {
314     mFormat->setShowTrailingZeros( checked );
315     if ( !mBlockSignals )
316       emit changed();
317   } );
318 
319   connect( mShowPlusCheckBox, &QCheckBox::toggled, this, [ = ]( bool checked )
320   {
321     mFormat->setShowPlusSign( checked );
322     if ( !mBlockSignals )
323       emit changed();
324   } );
325 
326   connect( mShowThousandsCheckBox, &QCheckBox::toggled, this, [ = ]( bool checked )
327   {
328     mFormat->setShowThousandsSeparator( checked );
329     if ( !mBlockSignals )
330       emit changed();
331   } );
332 
333   connect( mDecimalsSpinBox, qOverload<int>( &QSpinBox::valueChanged ), this, [ = ]( int value )
334   {
335     mFormat->setNumberDecimalPlaces( value );
336     if ( !mBlockSignals )
337       emit changed();
338   } );
339 
340   connect( mScalingComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [ = ]( int )
341   {
342     mFormat->setInputValues( static_cast < QgsPercentageNumericFormat::InputValues >( mScalingComboBox->currentData().toInt() ) );
343     if ( !mBlockSignals )
344       emit changed();
345   } );
346 }
347 
348 QgsPercentageNumericFormatWidget::~QgsPercentageNumericFormatWidget() = default;
349 
setFormat(QgsNumericFormat * format)350 void QgsPercentageNumericFormatWidget::setFormat( QgsNumericFormat *format )
351 {
352   mFormat.reset( static_cast< QgsPercentageNumericFormat * >( format ) );
353 
354   mBlockSignals = true;
355   mDecimalsSpinBox->setValue( mFormat->numberDecimalPlaces() );
356   mShowPlusCheckBox->setChecked( mFormat->showPlusSign() );
357   mShowTrailingZerosCheckBox->setChecked( mFormat->showTrailingZeros() );
358   mShowThousandsCheckBox->setChecked( mFormat->showThousandsSeparator() );
359   mScalingComboBox->setCurrentIndex( mScalingComboBox->findData( static_cast< int >( mFormat->inputValues() ) ) );
360   mBlockSignals = false;
361 }
362 
format()363 QgsNumericFormat *QgsPercentageNumericFormatWidget::format()
364 {
365   return mFormat->clone();
366 }
367 
368 //
369 // QgsScientificNumericFormatWidget
370 //
QgsScientificNumericFormatWidget(const QgsNumericFormat * format,QWidget * parent)371 QgsScientificNumericFormatWidget::QgsScientificNumericFormatWidget( const QgsNumericFormat *format, QWidget *parent )
372   : QgsNumericFormatWidget( parent )
373 {
374   setupUi( this );
375   mDecimalsSpinBox->setClearValue( 6 );
376   setFormat( format->clone() );
377 
378   connect( mShowPlusCheckBox, &QCheckBox::toggled, this, [ = ]( bool checked )
379   {
380     mFormat->setShowPlusSign( checked );
381     if ( !mBlockSignals )
382       emit changed();
383   } );
384 
385   connect( mShowTrailingZerosCheckBox, &QCheckBox::toggled, this, [ = ]( bool checked )
386   {
387     mFormat->setShowTrailingZeros( checked );
388     if ( !mBlockSignals )
389       emit changed();
390   } );
391 
392   connect( mDecimalsSpinBox, qOverload<int>( &QSpinBox::valueChanged ), this, [ = ]( int value )
393   {
394     mFormat->setNumberDecimalPlaces( value );
395     if ( !mBlockSignals )
396       emit changed();
397   } );
398 }
399 
400 QgsScientificNumericFormatWidget::~QgsScientificNumericFormatWidget() = default;
401 
setFormat(QgsNumericFormat * format)402 void QgsScientificNumericFormatWidget::setFormat( QgsNumericFormat *format )
403 {
404   mFormat.reset( static_cast< QgsScientificNumericFormat * >( format ) );
405 
406   mBlockSignals = true;
407   mDecimalsSpinBox->setValue( mFormat->numberDecimalPlaces() );
408   mShowPlusCheckBox->setChecked( mFormat->showPlusSign() );
409   mShowTrailingZerosCheckBox->setChecked( mFormat->showTrailingZeros() );
410   mBlockSignals = false;
411 }
412 
format()413 QgsNumericFormat *QgsScientificNumericFormatWidget::format()
414 {
415   return mFormat->clone();
416 }
417 
418 
419 
420 //
421 // QgsFractionNumericFormatWidget
422 //
QgsFractionNumericFormatWidget(const QgsNumericFormat * format,QWidget * parent)423 QgsFractionNumericFormatWidget::QgsFractionNumericFormatWidget( const QgsNumericFormat *format, QWidget *parent )
424   : QgsNumericFormatWidget( parent )
425 {
426   setupUi( this );
427   setFormat( format->clone() );
428 
429   mThousandsLineEdit->setShowClearButton( true );
430 
431   connect( mUseDedicatedUnicodeCheckBox, &QCheckBox::toggled, this, [ = ]( bool checked )
432   {
433     mFormat->setUseDedicatedUnicodeCharacters( checked );
434     if ( !mBlockSignals )
435       emit changed();
436   } );
437 
438   connect( mUseUnicodeSupersubscriptCheckBox, &QCheckBox::toggled, this, [ = ]( bool checked )
439   {
440     mFormat->setUseUnicodeSuperSubscript( checked );
441     if ( !mBlockSignals )
442       emit changed();
443   } );
444 
445   connect( mShowPlusCheckBox, &QCheckBox::toggled, this, [ = ]( bool checked )
446   {
447     mFormat->setShowPlusSign( checked );
448     if ( !mBlockSignals )
449       emit changed();
450   } );
451 
452   connect( mShowThousandsCheckBox, &QCheckBox::toggled, this, [ = ]( bool checked )
453   {
454     mFormat->setShowThousandsSeparator( checked );
455     if ( !mBlockSignals )
456       emit changed();
457   } );
458 
459   connect( mThousandsLineEdit, &QLineEdit::textChanged, this, [ = ]( const QString & text )
460   {
461     mFormat->setThousandsSeparator( text.isEmpty() ? QChar() : text.at( 0 ) );
462     if ( !mBlockSignals )
463       emit changed();
464   } );
465 
466 }
467 
468 QgsFractionNumericFormatWidget::~QgsFractionNumericFormatWidget() = default;
469 
setFormat(QgsNumericFormat * format)470 void QgsFractionNumericFormatWidget::setFormat( QgsNumericFormat *format )
471 {
472   mFormat.reset( static_cast< QgsFractionNumericFormat * >( format ) );
473 
474   mBlockSignals = true;
475   mUseDedicatedUnicodeCheckBox->setChecked( mFormat->useDedicatedUnicodeCharacters() );
476   mUseUnicodeSupersubscriptCheckBox->setChecked( mFormat->useUnicodeSuperSubscript() );
477   mShowPlusCheckBox->setChecked( mFormat->showPlusSign() );
478   mShowThousandsCheckBox->setChecked( mFormat->showThousandsSeparator() );
479   mThousandsLineEdit->setText( mFormat->thousandsSeparator().isNull() ? QString() : mFormat->thousandsSeparator() );
480   mBlockSignals = false;
481 }
482 
format()483 QgsNumericFormat *QgsFractionNumericFormatWidget::format()
484 {
485   return mFormat->clone();
486 }
487