QGIS API Documentation  2.11.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 
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 {
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  view()->setMinimumWidth( view()->sizeHintForColumn( 0 ) );
116 }
117 
120 {
121  return toString( mScale );
122 }
123 
126 {
127  bool ok;
128  double newScale = toDouble( scaleTxt, &ok );
129  if ( ! ok )
130  {
131  return false;
132  }
133  else
134  {
135  mScale = newScale;
136  setEditText( toString( mScale ) );
137  clearFocus();
138  return true;
139  }
140 }
141 
144 {
145  return mScale;
146 }
147 
149 void QgsScaleComboBox::setScale( double scale )
150 {
151  setScaleString( toString( scale ) );
152 }
153 
155 void QgsScaleComboBox::fixupScale()
156 {
157  double newScale;
158  double oldScale = mScale;
159  bool ok, userSetScale;
160  QStringList txtList = currentText().split( ':' );
161  userSetScale = txtList.size() != 2;
162 
163  // QgsDebugMsg( QString( "entered with oldScale: %1" ).arg( oldScale ) );
164  newScale = toDouble( currentText(), &ok );
165 
166  // Valid string representation
167  if ( ok && ( newScale != oldScale ) )
168  {
169  // if a user types scale = 2345, we transform to 1:2345
170  if ( userSetScale && newScale >= 1.0 )
171  {
172  mScale = 1 / newScale;
173  }
174  else
175  {
176  mScale = newScale;
177  }
178  setScale( mScale );
179  emit scaleChanged();
180  }
181  else
182  {
183  // Invalid string representation or same scale
184  // Reset to the old
185  setScale( mScale );
186  }
187 }
188 
190 {
191  if ( scale == 0 )
192  {
193  return "0";
194  }
195  else if ( scale > 1 )
196  {
197  return QString( "%1:1" ).arg( QLocale::system().toString( qRound( scale ) ) );
198  }
199  else
200  {
201  return QString( "1:%1" ).arg( QLocale::system().toString( qRound( 1.0 / scale ) ) );
202  }
203 }
204 
205 double QgsScaleComboBox::toDouble( QString scaleString, bool * returnOk )
206 {
207  bool ok = false;
208  QString scaleTxt( scaleString );
209 
210  double scale = QGis::permissiveToDouble( scaleTxt, ok );
211  if ( ok )
212  {
213  // Create a text version and set that text and rescan
214  // Idea is to get the same rounding.
215  scaleTxt = toString( scale );
216  }
217  else
218  {
219  // It is now either X:Y or not valid
220  QStringList txtList = scaleTxt.split( ':' );
221  if ( 2 == txtList.size() )
222  {
223  bool okX = false;
224  bool okY = false;
225  int x = QGis::permissiveToInt( txtList[ 0 ], okX );
226  int y = QGis::permissiveToInt( txtList[ 1 ], okY );
227  if ( okX && okY )
228  {
229  // Scale is fraction of x and y
230  scale = ( double )x / ( double )y;
231  ok = true;
232  }
233  }
234  }
235 
236  // Set up optional return flag
237  if ( returnOk )
238  {
239  *returnOk = ok;
240  }
241  return scale;
242 }
243 
244 
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
QAbstractItemModel * model() const
virtual ~QgsScaleComboBox()
void setCurrentIndex(const QModelIndex &index)
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
void setMinimumWidth(int minw)
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
const T & at(int i) const
void clear()
int y() const
static double toDouble(QString scaleString, bool *ok=NULL)
Helper function to convert a scale string to double.
void setEditText(const QString &text)
QString itemText(int index) const
void setScale(double scale)
Function to set the selected scale from double.
void setEditable(bool editable)
double toDouble(const QString &s, bool *ok) const
int size() const
QLocale system()
void showPopup() override
int count() const
void append(const T &value)
int x() const
bool isEmpty() const
bool isEmpty() const
void activated(int index)
double scale()
Function to read the selected scale as double.
bool blockSignals(bool block)
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.
QLineEdit * lineEdit() const
void scaleChanged()
Signal is emitted when user has finished editing/selecting a new scale.
QVariant value(const QString &key, const QVariant &defaultValue) const
void clearFocus()
const QString PROJECT_SCALES
Definition: qgis.cpp:68
QString scaleString()
Function to read the selected scale as text.
void setInsertPolicy(InsertPolicy policy)
void setCompleter(QCompleter *completer)
QgsScaleComboBox(QWidget *parent=0)
QStringList split(const QString &sep, const QString &str, bool allowEmptyEntries)
void addItems(const QStringList &texts)
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.
const_iterator constEnd() const
const_iterator constBegin() const
QString currentText() const
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
virtual void showPopup()
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QString toString() const
QAbstractItemView * view() const