QGIS API Documentation  2.9.0-Master
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 
27 QgsScaleComboBox::QgsScaleComboBox( QWidget* parent ) : QComboBox( parent ), mScale( 1.0 )
28 {
29  updateScales();
30 
31  setEditable( true );
32  setInsertPolicy( QComboBox::NoInsert );
33  setCompleter( 0 );
34  connect( this, SIGNAL( activated( const QString & ) ), this, SLOT( fixupScale() ) );
35  connect( lineEdit(), SIGNAL( editingFinished() ), this, SLOT( fixupScale() ) );
36  fixupScale();
37 }
38 
40 {
41 }
42 
43 void QgsScaleComboBox::updateScales( const QStringList &scales )
44 {
45  QStringList myScalesList;
46  QString oldScale = currentText();
47 
48  if ( scales.isEmpty() )
49  {
50  QSettings settings;
51  QString myScales = settings.value( "Map/scales", PROJECT_SCALES ).toString();
52  if ( !myScales.isEmpty() )
53  {
54  myScalesList = myScales.split( "," );
55  }
56  }
57  else
58  {
59  QStringList::const_iterator scaleIt = scales.constBegin();
60  for ( ; scaleIt != scales.constEnd(); ++scaleIt )
61  {
62  myScalesList.append( *scaleIt );
63  }
64  }
65 
66  QStringList parts;
67  double denominator;
68  bool ok;
69  for ( int i = 0; i < myScalesList.size(); ++i )
70  {
71  parts = myScalesList[ i ] .split( ':' );
72  denominator = QLocale::system().toDouble( parts[1], &ok );
73  if ( ok )
74  {
75  myScalesList[ i ] = toString( 1.0 / denominator );
76  }
77  }
78 
79  blockSignals( true );
80  clear();
81  addItems( myScalesList );
82  setScaleString( oldScale );
83  blockSignals( false );
84 }
85 
87 {
88  QComboBox::showPopup();
89 
90  if ( !currentText().contains( ':' ) )
91  {
92  return;
93  }
94  QStringList parts = currentText().split( ':' );
95  bool ok;
96  int idx = 0;
97  int min = 999999;
98  long currScale = parts.at( 1 ).toLong( &ok );
99  long nextScale, delta;
100  for ( int i = 0; i < count(); i++ )
101  {
102  parts = itemText( i ).split( ':' );
103  nextScale = parts.at( 1 ).toLong( &ok );
104  delta = qAbs( currScale - nextScale );
105  if ( delta < min )
106  {
107  min = delta;
108  idx = i;
109  }
110  }
111 
112  blockSignals( true );
113  view()->setCurrentIndex( model()->index( idx, 0 ) );
114  blockSignals( false );
115 }
116 
119 {
120  return toString( mScale );
121 }
122 
124 bool QgsScaleComboBox::setScaleString( QString scaleTxt )
125 {
126  bool ok;
127  double newScale = toDouble( scaleTxt, &ok );
128  if ( ! ok )
129  {
130  return false;
131  }
132  else
133  {
134  mScale = newScale;
135  setEditText( toString( mScale ) );
136  clearFocus();
137  return true;
138  }
139 }
140 
143 {
144  return mScale;
145 }
146 
148 void QgsScaleComboBox::setScale( double scale )
149 {
150  setScaleString( toString( scale ) );
151 }
152 
154 void QgsScaleComboBox::fixupScale()
155 {
156  double newScale;
157  double oldScale = mScale;
158  bool ok, userSetScale;
159  QStringList txtList = currentText().split( ':' );
160  userSetScale = txtList.size() != 2;
161 
162  // QgsDebugMsg( QString( "entered with oldScale: %1" ).arg( oldScale ) );
163  newScale = toDouble( currentText(), &ok );
164 
165  // Valid string representation
166  if ( ok && ( newScale != oldScale ) )
167  {
168  // if a user types scale = 2345, we transform to 1:2345
169  if ( userSetScale && newScale >= 1.0 )
170  {
171  mScale = 1 / newScale;
172  }
173  else
174  {
175  mScale = newScale;
176  }
177  setScale( mScale );
178  emit scaleChanged();
179  }
180  else
181  {
182  // Invalid string representation or same scale
183  // Reset to the old
184  setScale( mScale );
185  }
186 }
187 
188 QString QgsScaleComboBox::toString( double scale )
189 {
190  if ( scale == 0 )
191  {
192  return "0";
193  }
194  else if ( scale > 1 )
195  {
196  return QString( "%1:1" ).arg( QLocale::system().toString( qRound( scale ) ) );
197  }
198  else
199  {
200  return QString( "1:%1" ).arg( QLocale::system().toString( qRound( 1.0 / scale ) ) );
201  }
202 }
203 
204 double QgsScaleComboBox::toDouble( QString scaleString, bool * returnOk )
205 {
206  bool ok = false;
207  QString scaleTxt( scaleString );
208 
209  double scale = QGis::permissiveToDouble( scaleTxt, ok );
210  if ( ok )
211  {
212  // Create a text version and set that text and rescan
213  // Idea is to get the same rounding.
214  scaleTxt = toString( scale );
215  }
216  else
217  {
218  // It is now either X:Y or not valid
219  QStringList txtList = scaleTxt.split( ':' );
220  if ( 2 == txtList.size() )
221  {
222  bool okX = false;
223  bool okY = false;
224  int x = QGis::permissiveToInt( txtList[ 0 ], okX );
225  int y = QGis::permissiveToInt( txtList[ 1 ], okY );
226  if ( okX && okY )
227  {
228  // Scale is fraction of x and y
229  scale = ( double )x / ( double )y;
230  ok = true;
231  }
232  }
233  }
234 
235  // Set up optional return flag
236  if ( returnOk )
237  {
238  *returnOk = ok;
239  }
240  return scale;
241 }
242 
243 
static unsigned index
static int permissiveToInt(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:195
virtual ~QgsScaleComboBox()
static double permissiveToDouble(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:188
static double toDouble(QString scaleString, bool *ok=NULL)
Helper function to convert a scale string to double.
void setScale(double scale)
Function to set the selected scale from double.
void showPopup() override
double scale()
Function to read the selected scale as double.
int min(int a, int b)
Definition: util.h:93
bool setScaleString(QString scaleTxt)
Function to set the selected scale from text.
static QString toString(double scale)
Helper function to convert a double to scale string.
void scaleChanged()
Signal is emitted when user has finished editing/selecting a new scale.
const QString PROJECT_SCALES
Definition: qgis.cpp:68
QString scaleString()
Function to read the selected scale as text.
QgsScaleComboBox(QWidget *parent=0)
void updateScales(const QStringList &scales=QStringList())