QGIS API Documentation  2.17.0-Master (0497e4a)
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 
47 {
48  QStringList myScalesList;
49  QString oldScale = currentText();
50 
51  if ( scales.isEmpty() )
52  {
53  QSettings settings;
54  QString myScales = settings.value( "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 {
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 
129 {
130  bool ok;
131  double newScale = toDouble( scaleTxt, &ok );
132  double oldScale = mScale;
133  if ( newScale < mMinScale )
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 "0";
196  }
197  else if ( scale > 1 )
198  {
199  return QString( "%1:1" ).arg( QLocale::system().toString( qRound( scale ) ) );
200  }
201  else
202  {
203  return QString( "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 = QGis::permissiveToDouble( 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 = QGis::permissiveToInt( txtList[ 0 ], okX );
228  int y = QGis::permissiveToInt( 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 )
250  {
251  setScale( scale );
252  }
253 }
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:227
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:220
const T & at(int i) const
void clear()
int y() const
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
bool setScaleString(const QString &scaleTxt)
Function to set the selected scale from text.
int size() const
QLocale system()
void showPopup() override
void scaleChanged(double scale)
Signal is emitted when user has finished editing/selecting a new scale.
int count() const
void append(const T &value)
static double toDouble(const QString &scaleString, bool *ok=nullptr)
Helper function to convert a scale string to double.
int x() const
bool isEmpty() const
bool isEmpty() const
void activated(int index)
double scale() const
Function to read the selected scale as double.
void setMinScale(double scale)
Function to set the min scale.
bool blockSignals(bool block)
static QString toString(double scale)
Helper function to convert a double to scale string.
QLineEdit * lineEdit() const
QVariant value(const QString &key, const QVariant &defaultValue) const
void clearFocus()
const QString PROJECT_SCALES
Definition: qgis.cpp:70
QString scaleString()
Function to read the selected scale as text.
void setInsertPolicy(InsertPolicy policy)
void setCompleter(QCompleter *completer)
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
QgsScaleComboBox(QWidget *parent=nullptr)
QAbstractItemView * view() const