QGIS API Documentation
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 ), mMinScale( 0.0 )
28 {
29  updateScales();
30 
31  setEditable( true );
32  setInsertPolicy( QComboBox::NoInsert );
33  setCompleter( nullptr );
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  double oldScale = mScale;
130  if ( newScale < mMinScale )
131  {
132  newScale = mMinScale;
133  }
134  if ( ! ok )
135  {
136  return false;
137  }
138  else
139  {
140  mScale = newScale;
141  setEditText( toString( mScale ) );
142  clearFocus();
143  if ( mScale != oldScale )
144  {
145  emit scaleChanged( mScale );
146  }
147  return true;
148  }
149 }
150 
153 {
154  return mScale;
155 }
156 
159 {
160  setScaleString( toString( scale ) );
161 }
162 
164 void QgsScaleComboBox::fixupScale()
165 {
166  QStringList txtList = currentText().split( ':' );
167  bool userSetScale = txtList.size() != 2;
168 
169  bool ok;
170  double newScale = toDouble( currentText(), &ok );
171 
172  // Valid string representation
173  if ( ok )
174  {
175  // if a user types scale = 2345, we transform to 1:2345
176  if ( userSetScale && newScale >= 1.0 )
177  {
178  newScale = 1 / newScale;
179  }
180  setScale( newScale );
181  }
182  else
183  {
184  setScale( mScale );
185  }
186 }
187 
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( const 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 
244 {
245  mMinScale = scale;
246  if ( mScale < scale )
247  {
248  setScale( scale );
249  }
250 }
double scale() const
Function to read the selected scale as double.
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:221
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:214
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)
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