QGIS API Documentation  2.99.0-Master (c558d51)
qgsscalecombobox.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsscalecombobox.h
3  ------------------------
4  begin : January 7, 2012
5  copyright : (C) 2012 by Alexander Bruy
6  email : alexander dot bruy at gmail dot com
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 "qgis.h"
19 #include "qgslogger.h"
20 #include "qgsscalecombobox.h"
21 
22 #include <QAbstractItemView>
23 #include <QLocale>
24 #include <QSettings>
25 #include <QLineEdit>
26 
28  : QComboBox( parent )
29  , mScale( 1.0 )
30  , mMinScale( 0.0 )
31 {
32  updateScales();
33 
34  setEditable( true );
35  setInsertPolicy( QComboBox::NoInsert );
36  setCompleter( nullptr );
37  connect( this, SIGNAL( activated( const QString & ) ), this, SLOT( fixupScale() ) );
38  connect( lineEdit(), SIGNAL( editingFinished() ), this, SLOT( fixupScale() ) );
39  fixupScale();
40 }
41 
43 {
44 }
45 
46 void QgsScaleComboBox::updateScales( const QStringList &scales )
47 {
48  QStringList myScalesList;
49  QString oldScale = currentText();
50 
51  if ( scales.isEmpty() )
52  {
53  QSettings settings;
54  QString myScales = settings.value( QStringLiteral( "Map/scales" ), PROJECT_SCALES ).toString();
55  if ( !myScales.isEmpty() )
56  {
57  myScalesList = myScales.split( ',' );
58  }
59  }
60  else
61  {
62  QStringList::const_iterator scaleIt = scales.constBegin();
63  for ( ; scaleIt != scales.constEnd(); ++scaleIt )
64  {
65  myScalesList.append( *scaleIt );
66  }
67  }
68 
69  QStringList parts;
70  double denominator;
71  bool ok;
72  for ( int i = 0; i < myScalesList.size(); ++i )
73  {
74  parts = myScalesList[ i ] .split( ':' );
75  denominator = QLocale::system().toDouble( parts[1], &ok );
76  if ( ok )
77  {
78  myScalesList[ i ] = toString( 1.0 / denominator );
79  }
80  }
81 
82  blockSignals( true );
83  clear();
84  addItems( myScalesList );
85  setScaleString( oldScale );
86  blockSignals( false );
87 }
88 
90 {
91  QComboBox::showPopup();
92 
93  if ( !currentText().contains( ':' ) )
94  {
95  return;
96  }
97  QStringList parts = currentText().split( ':' );
98  bool ok;
99  int idx = 0;
100  int min = 999999;
101  long currScale = parts.at( 1 ).toLong( &ok );
102  long nextScale, delta;
103  for ( int i = 0; i < count(); i++ )
104  {
105  parts = itemText( i ).split( ':' );
106  nextScale = parts.at( 1 ).toLong( &ok );
107  delta = qAbs( currScale - nextScale );
108  if ( delta < min )
109  {
110  min = delta;
111  idx = i;
112  }
113  }
114 
115  blockSignals( true );
116  view()->setCurrentIndex( model()->index( idx, 0 ) );
117  blockSignals( false );
118  view()->setMinimumWidth( view()->sizeHintForColumn( 0 ) );
119 }
120 
123 {
124  return toString( mScale );
125 }
126 
128 bool QgsScaleComboBox::setScaleString( const QString& scaleTxt )
129 {
130  bool ok;
131  double newScale = toDouble( scaleTxt, &ok );
132  double oldScale = mScale;
133  if ( newScale < mMinScale && newScale != 0 )
134  {
135  newScale = mMinScale;
136  }
137  if ( ! ok )
138  {
139  return false;
140  }
141  else
142  {
143  mScale = newScale;
144  setEditText( toString( mScale ) );
145  clearFocus();
146  if ( mScale != oldScale )
147  {
148  emit scaleChanged( mScale );
149  }
150  return true;
151  }
152 }
153 
156 {
157  return mScale;
158 }
159 
162 {
163  setScaleString( toString( scale ) );
164 }
165 
167 void QgsScaleComboBox::fixupScale()
168 {
169  QStringList txtList = currentText().split( ':' );
170  bool userSetScale = txtList.size() != 2;
171 
172  bool ok;
173  double newScale = toDouble( currentText(), &ok );
174 
175  // Valid string representation
176  if ( ok )
177  {
178  // if a user types scale = 2345, we transform to 1:2345
179  if ( userSetScale && newScale >= 1.0 )
180  {
181  newScale = 1 / newScale;
182  }
183  setScale( newScale );
184  }
185  else
186  {
187  setScale( mScale );
188  }
189 }
190 
192 {
193  if ( scale == 0 )
194  {
195  return QStringLiteral( "0" );
196  }
197  else if ( scale > 1 )
198  {
199  return QStringLiteral( "%1:1" ).arg( QLocale::system().toString( qRound( scale ) ) );
200  }
201  else
202  {
203  return QStringLiteral( "1:%1" ).arg( QLocale::system().toString( qRound( 1.0 / scale ) ) );
204  }
205 }
206 
207 double QgsScaleComboBox::toDouble( const QString& scaleString, bool * returnOk )
208 {
209  bool ok = false;
210  QString scaleTxt( scaleString );
211 
212  double scale = qgsPermissiveToDouble( scaleTxt, ok );
213  if ( ok )
214  {
215  // Create a text version and set that text and rescan
216  // Idea is to get the same rounding.
217  scaleTxt = toString( scale );
218  }
219  else
220  {
221  // It is now either X:Y or not valid
222  QStringList txtList = scaleTxt.split( ':' );
223  if ( 2 == txtList.size() )
224  {
225  bool okX = false;
226  bool okY = false;
227  int x = qgsPermissiveToInt( txtList[ 0 ], okX );
228  int y = qgsPermissiveToInt( txtList[ 1 ], okY );
229  if ( okX && okY )
230  {
231  // Scale is fraction of x and y
232  scale = ( double )x / ( double )y;
233  ok = true;
234  }
235  }
236  }
237 
238  // Set up optional return flag
239  if ( returnOk )
240  {
241  *returnOk = ok;
242  }
243  return scale;
244 }
245 
247 {
248  mMinScale = scale;
249  if ( mScale < scale && mScale != 0 )
250  {
251  setScale( scale );
252  }
253 }
double scale() const
Function to read the selected scale as double.
static unsigned index
virtual ~QgsScaleComboBox()
double qgsPermissiveToDouble(QString string, bool &ok)
Converts a string to a double in a permissive way, eg allowing for incorrect numbers of digits betwee...
Definition: qgis.cpp:91
void setScale(double scale)
Function to set the selected scale from double.
int qgsPermissiveToInt(QString string, bool &ok)
Converts a string to an integer in a permissive way, eg allowing for incorrect numbers of digits betw...
Definition: qgis.cpp:98
bool setScaleString(const QString &scaleTxt)
Function to set the selected scale from text.
void showPopup() override
void scaleChanged(double scale)
Signal is emitted when user has finished editing/selecting a new scale.
static double toDouble(const QString &scaleString, bool *ok=nullptr)
Helper function to convert a scale string to double.
void setMinScale(double scale)
Set the minimum allowed scale.
double ANALYSIS_EXPORT min(double x, double y)
Returns the minimum of two doubles or the first argument if both are equal.
Definition: MathUtils.cc:452
static QString toString(double scale)
Helper function to convert a double to scale string.
const QString PROJECT_SCALES
Definition: qgis.cpp:69
QString scaleString()
Function to read the selected scale as text.
void updateScales(const QStringList &scales=QStringList())
QgsScaleComboBox(QWidget *parent=nullptr)