QGIS API Documentation  2.4.0-Chugiak
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 
118 // @note added in 2.0
120 {
121  return toString( mScale );
122 }
123 
125 // @note added in 2.0
126 bool QgsScaleComboBox::setScaleString( QString scaleTxt )
127 {
128  bool ok;
129  double newScale = toDouble( scaleTxt, &ok );
130  if ( ! ok )
131  {
132  return false;
133  }
134  else
135  {
136  mScale = newScale;
137  setEditText( toString( mScale ) );
138  clearFocus();
139  return true;
140  }
141 }
142 
144 // @note added in 2.0
146 {
147  return mScale;
148 }
149 
151 // @note added in 2.0
152 void QgsScaleComboBox::setScale( double scale )
153 {
154  setScaleString( toString( scale ) );
155 }
156 
159 {
160  double newScale;
161  double oldScale = mScale;
162  bool ok, userSetScale;
163  QStringList txtList = currentText().split( ':' );
164  txtList.size() == 2 ? userSetScale = false : userSetScale = true ;
165 
166  // QgsDebugMsg( QString( "entered with oldScale: %1" ).arg( oldScale ) );
167  newScale = toDouble( currentText(), &ok );
168 
169  // Valid string representation
170  if ( ok && ( newScale != oldScale ) )
171  {
172  // if a user types scale = 2345, we transform to 1:2345
173  if ( userSetScale && newScale >= 1.0 )
174  {
175  mScale = 1 / newScale;
176  }
177  else
178  {
179  mScale = newScale;
180  }
181  setScale( mScale );
182  emit scaleChanged();
183  }
184  else
185  {
186  // Invalid string representation or same scale
187  // Reset to the old
188  setScale( mScale );
189  }
190 }
191 
192 QString QgsScaleComboBox::toString( double scale )
193 {
194  if ( scale == 0 )
195  {
196  return "0";
197  }
198  else if ( scale > 1 )
199  {
200  return QString( "%1:1" ).arg( QLocale::system().toString( qRound( scale ) ) );
201  }
202  else
203  {
204  return QString( "1:%1" ).arg( QLocale::system().toString( qRound( 1.0 / scale ) ) );
205  }
206 }
207 
208 double QgsScaleComboBox::toDouble( QString scaleString, bool * returnOk )
209 {
210  bool ok = false;
211  QString scaleTxt( scaleString );
212 
213  double scale = QLocale::system().toDouble( scaleTxt, &ok );
214  if ( ok )
215  {
216  // Create a text version and set that text and rescan
217  // Idea is to get the same rounding.
218  scaleTxt = toString( scale );
219  }
220  // It is now either X:Y or not valid
221  ok = false;
222  QStringList txtList = scaleTxt.split( ':' );
223  if ( 2 == txtList.size() )
224  {
225  bool okX = false;
226  bool okY = false;
227  int x = QLocale::system().toInt( txtList[ 0 ], &okX );
228  int y = QLocale::system().toInt( 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  // Set up optional return flag
238  if ( returnOk )
239  {
240  *returnOk = ok;
241  }
242  return scale;
243 }
244 
245 
static unsigned index
void fixupScale()
Slot called when QComboBox has changed.
virtual ~QgsScaleComboBox()
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.
double scale()
Function to read the selected scale as double.
const CORE_EXPORT QString PROJECT_SCALES
Definition: qgis.cpp:67
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.
QString scaleString()
Function to read the selected scale as text.
QgsScaleComboBox(QWidget *parent=0)
void updateScales(const QStringList &scales=QStringList())
double ANALYSIS_EXPORT min(double x, double y)
returns the minimum of two doubles or the first argument if both are equal