QGIS API Documentation  2.0.1-Dufour
 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  blockSignals( true );
67  clear();
68  addItems( myScalesList );
69  setScaleString( oldScale );
70  blockSignals( false );
71 }
72 
74 {
76 
77  if ( !currentText().contains( ':' ) )
78  {
79  return;
80  }
81  QStringList parts = currentText().split( ':' );
82  bool ok;
83  int idx = 0;
84  int min = 999999;
85  long currScale = parts.at( 1 ).toLong( &ok );
86  long nextScale, delta;
87  for ( int i = 0; i < count(); i++ )
88  {
89  parts = itemText( i ).split( ':' );
90  nextScale = parts.at( 1 ).toLong( &ok );
91  delta = qAbs( currScale - nextScale );
92  if ( delta < min )
93  {
94  min = delta;
95  idx = i;
96  }
97  }
98 
99  blockSignals( true );
100  view()->setCurrentIndex( model()->index( idx, 0 ) );
101  blockSignals( false );
102 }
103 
105 // @note added in 2.0
107 {
108  return toString( mScale );
109 }
110 
112 // @note added in 2.0
113 bool QgsScaleComboBox::setScaleString( QString scaleTxt )
114 {
115  bool ok;
116  double newScale = toDouble( scaleTxt, &ok );
117  if ( ! ok )
118  {
119  return false;
120  }
121  else
122  {
123  mScale = newScale;
124  setEditText( toString( mScale ) );
125  clearFocus();
126  return true;
127  }
128 }
129 
131 // @note added in 2.0
133 {
134  return mScale;
135 }
136 
138 // @note added in 2.0
139 void QgsScaleComboBox::setScale( double scale )
140 {
141  setScaleString( toString( scale ) );
142 }
143 
146 {
147  double newScale;
148  double oldScale = mScale;
149  bool ok, userSetScale;
150  QStringList txtList = currentText().split( ':' );
151  txtList.size() == 2 ? userSetScale = false : userSetScale = true ;
152 
153  // QgsDebugMsg( QString( "entered with oldScale: %1" ).arg( oldScale ) );
154  newScale = toDouble( currentText(), &ok );
155 
156  // Valid string representation
157  if ( ok && ( newScale != oldScale ) )
158  {
159  // if a user types scale = 2345, we transform to 1:2345
160  if ( userSetScale && newScale >= 1.0 )
161  {
162  mScale = 1 / newScale;
163  }
164  else
165  {
166  mScale = newScale;
167  }
168  setScale( mScale );
169  emit scaleChanged();
170  }
171  else
172  {
173  // Invalid string representation or same scale
174  // Reset to the old
175  setScale( mScale );
176  }
177 }
178 
179 QString QgsScaleComboBox::toString( double scale )
180 {
181  if ( scale > 1 )
182  {
183  return QString( "%1:1" ).arg( qRound( scale ) );
184  }
185  else
186  {
187  return QString( "1:%1" ).arg( qRound( 1.0 / scale ) );
188  }
189 }
190 
191 double QgsScaleComboBox::toDouble( QString scaleString, bool * returnOk )
192 {
193  bool ok = false;
194  QString scaleTxt( scaleString );
195 
196  double scale = QLocale::system().toDouble( scaleTxt, &ok );
197  if ( ok )
198  {
199  // Create a text version and set that text and rescan
200  // Idea is to get the same rounding.
201  scaleTxt = toString( scale );
202  }
203  // It is now either X:Y or not valid
204  ok = false;
205  QStringList txtList = scaleTxt.split( ':' );
206  if ( 2 == txtList.size() )
207  {
208  bool okX = false;
209  bool okY = false;
210  int x = QLocale::system().toInt( txtList[ 0 ], &okX );
211  int y = QLocale::system().toInt( txtList[ 1 ], &okY );
212  if ( okX && okY )
213  {
214  // Scale is fraction of x and y
215  scale = ( double )x / ( double )y;
216  ok = true;
217  }
218  }
219 
220  // Set up optional return flag
221  if ( returnOk )
222  {
223  *returnOk = ok;
224  }
225  return scale;
226 }