QGIS API Documentation  2.99.0-Master (9f5e33a)
qgsextentgroupbox.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsextentgroupbox.cpp
3  ---------------------
4  begin : March 2014
5  copyright : (C) 2014 by Martin Dobias
6  email : wonder dot sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 #include "qgsextentgroupbox.h"
16 
17 #include "qgscoordinatetransform.h"
18 #include "qgsrasterblock.h"
19 #include "qgsmaplayermodel.h"
20 #include "qgsexception.h"
21 #include "qgsproject.h"
22 #include <QMenu>
23 #include <QAction>
24 
26  : QgsCollapsibleGroupBox( parent )
27  , mTitleBase( tr( "Extent" ) )
28  , mExtentState( OriginalExtent )
29 {
30  setupUi( this );
31 
32  mLayerMenu = new QMenu( this );
33  mButtonCalcFromLayer->setMenu( mLayerMenu );
34  connect( mLayerMenu, &QMenu::aboutToShow, this, &QgsExtentGroupBox::layerMenuAboutToShow );
35  mMapLayerModel = new QgsMapLayerModel( this );
36 
37  mXMinLineEdit->setValidator( new QDoubleValidator( this ) );
38  mXMaxLineEdit->setValidator( new QDoubleValidator( this ) );
39  mYMinLineEdit->setValidator( new QDoubleValidator( this ) );
40  mYMaxLineEdit->setValidator( new QDoubleValidator( this ) );
41 
42  mOriginalExtentButton->setVisible( false );
43 
44  connect( mCurrentExtentButton, &QAbstractButton::clicked, this, &QgsExtentGroupBox::setOutputExtentFromCurrent );
45  connect( mOriginalExtentButton, &QAbstractButton::clicked, this, &QgsExtentGroupBox::setOutputExtentFromOriginal );
46  connect( this, &QGroupBox::clicked, this, &QgsExtentGroupBox::groupBoxClicked );
47 }
48 
49 
51 {
52  mOriginalExtent = originalExtent;
53  mOriginalCrs = originalCrs;
54 
55  mOriginalExtentButton->setVisible( true );
56 }
57 
58 
60 {
61  mCurrentExtent = currentExtent;
62  mCurrentCrs = currentCrs;
63 }
64 
66 {
67  if ( mOutputCrs != outputCrs )
68  {
69  switch ( mExtentState )
70  {
71  case CurrentExtent:
72  mOutputCrs = outputCrs;
74  break;
75 
76  case OriginalExtent:
77  mOutputCrs = outputCrs;
79  break;
80 
81  case ProjectLayerExtent:
82  mOutputCrs = outputCrs;
83  setOutputExtentFromLayer( mExtentLayer.data() );
84  break;
85 
86  case UserExtent:
87  try
88  {
89  QgsCoordinateTransform ct( mOutputCrs, outputCrs );
91  mOutputCrs = outputCrs;
92  setOutputExtentFromUser( extent, outputCrs );
93  }
94  catch ( QgsCsException & )
95  {
96  // can't reproject
97  mOutputCrs = outputCrs;
98  }
99  break;
100  }
101 
102  }
103 
104 }
105 
106 void QgsExtentGroupBox::setOutputExtent( const QgsRectangle &r, const QgsCoordinateReferenceSystem &srcCrs, ExtentState state )
107 {
108  QgsRectangle extent;
109  if ( mOutputCrs == srcCrs )
110  {
111  extent = r;
112  }
113  else
114  {
115  try
116  {
117  QgsCoordinateTransform ct( srcCrs, mOutputCrs );
118  extent = ct.transformBoundingBox( r );
119  }
120  catch ( QgsCsException & )
121  {
122  // can't reproject
123  extent = r;
124  }
125  }
126 
127  mXMinLineEdit->setText( QgsRasterBlock::printValue( extent.xMinimum() ) );
128  mXMaxLineEdit->setText( QgsRasterBlock::printValue( extent.xMaximum() ) );
129  mYMinLineEdit->setText( QgsRasterBlock::printValue( extent.yMinimum() ) );
130  mYMaxLineEdit->setText( QgsRasterBlock::printValue( extent.yMaximum() ) );
131 
132  mExtentState = state;
133 
134  if ( isCheckable() && !isChecked() )
135  setChecked( true );
136 
137  updateTitle();
138 
139  emit extentChanged( extent );
140 }
141 
142 
143 void QgsExtentGroupBox::setOutputExtentFromLineEdit()
144 {
145  mExtentState = UserExtent;
146 
147  updateTitle();
148 
149  emit extentChanged( outputExtent() );
150 }
151 
152 
153 void QgsExtentGroupBox::updateTitle()
154 {
155  QString msg;
156  switch ( mExtentState )
157  {
158  case OriginalExtent:
159  msg = tr( "layer" );
160  break;
161  case CurrentExtent:
162  msg = tr( "map view" );
163  break;
164  case UserExtent:
165  msg = tr( "user defined" );
166  break;
167  case ProjectLayerExtent:
168  msg = mExtentLayerName;
169  break;
170  }
171  if ( isCheckable() && !isChecked() )
172  msg = tr( "none" );
173  msg = tr( "%1 (current: %2)" ).arg( mTitleBase, msg );
174 
175  setTitle( msg );
176 }
177 
178 void QgsExtentGroupBox::layerMenuAboutToShow()
179 {
180  qDeleteAll( mMenuActions );
181  mMenuActions.clear();
182  mLayerMenu->clear();
183  for ( int i = 0; i < mMapLayerModel->rowCount(); ++i )
184  {
185  QModelIndex index = mMapLayerModel->index( i, 0 );
186  QIcon icon = qvariant_cast<QIcon>( mMapLayerModel->data( index, Qt::DecorationRole ) );
187  QString text = mMapLayerModel->data( index, Qt::DisplayRole ).toString();
188  QAction *act = new QAction( icon, text, mLayerMenu );
189  act->setToolTip( mMapLayerModel->data( index, Qt::ToolTipRole ).toString() );
190  QString layerId = mMapLayerModel->data( index, QgsMapLayerModel::LayerIdRole ).toString();
191  if ( mExtentState == ProjectLayerExtent && mExtentLayer && mExtentLayer->id() == layerId )
192  {
193  act->setCheckable( true );
194  act->setChecked( true );
195  }
196  connect( act, &QAction::triggered, this, [this, layerId]
197  {
198  setExtentToLayerExtent( layerId );
199  } );
200  mLayerMenu->addAction( act );
201  mMenuActions << act;
202  }
203 }
204 
205 void QgsExtentGroupBox::setExtentToLayerExtent( const QString &layerId )
206 {
207  QgsMapLayer *layer = QgsProject::instance()->mapLayer( layerId );
208  if ( !layer )
209  return;
210 
211  setOutputExtentFromLayer( layer );
212 }
213 
215 {
216  setOutputExtent( mCurrentExtent, mCurrentCrs, CurrentExtent );
217 }
218 
219 
221 {
222  setOutputExtent( mOriginalExtent, mOriginalCrs, OriginalExtent );
223 }
224 
226 {
227  setOutputExtent( extent, crs, UserExtent );
228 }
229 
231 {
232  if ( !layer )
233  return;
234 
235  mExtentLayer = layer;
236  mExtentLayerName = layer->name();
237 
238  setOutputExtent( layer->extent(), layer->crs(), ProjectLayerExtent );
239 }
240 
241 void QgsExtentGroupBox::groupBoxClicked()
242 {
243  if ( !isCheckable() )
244  return;
245 
246  updateTitle();
247 
248  // output extent just went from null to something (or vice versa)
249  emit extentChanged( outputExtent() );
250 }
251 
252 
254 {
255  if ( isCheckable() && !isChecked() )
256  return QgsRectangle();
257 
258  return QgsRectangle( mXMinLineEdit->text().toDouble(), mYMinLineEdit->text().toDouble(),
259  mXMaxLineEdit->text().toDouble(), mYMaxLineEdit->text().toDouble() );
260 }
261 
262 void QgsExtentGroupBox::setTitleBase( const QString &title )
263 {
264  mTitleBase = title;
265  updateTitle();
266 }
267 
268 QString QgsExtentGroupBox::titleBase() const
269 {
270  return mTitleBase;
271 }
Extent manually entered/modified by the user.
A rectangle specified with double values.
Definition: qgsrectangle.h:38
Base class for all map layer types.
Definition: qgsmaplayer.h:54
QgsRectangle originalExtent() const
Returns the original extent set for the widget.
static QString printValue(double value)
Print double value with all necessary significant digits.
void setOutputExtentFromCurrent()
Sets the output extent to be the same as current extent (may be transformed to output CRS)...
void extentChanged(const QgsRectangle &r)
Emitted when the widget&#39;s extent is changed.
QString titleBase() const
Returns the base part of title of the group box (will be appended with extent state).
A groupbox that collapses/expands when toggled and can save its collapsed and checked states...
void setOutputExtentFromUser(const QgsRectangle &extent, const QgsCoordinateReferenceSystem &crs)
Sets the output extent to a custom extent (may be transformed to output CRS).
Stores the map layer ID.
QgsRectangle transformBoundingBox(const QgsRectangle &rectangle, TransformDirection direction=ForwardTransform, const bool handle180Crossover=false) const
Transforms a rectangle from the source CRS to the destination CRS.
QgsExtentGroupBox(QWidget *parent=0)
Constructor for QgsExtentGroupBox.
virtual QgsRectangle extent() const
Returns the extent of the layer.
ExtentState
Available states for the current extent selection in the widget.
Extent taken from a layer within the project.
The QgsMapLayerModel class is a model to display layers in widgets.
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
QgsCoordinateReferenceSystem crs() const
Returns the layer&#39;s spatial reference system.
void setOutputCrs(const QgsCoordinateReferenceSystem &outputCrs)
Sets the output CRS - may need to be used for transformation from original/current extent...
void setCurrentExtent(const QgsRectangle &currentExtent, const QgsCoordinateReferenceSystem &currentCrs)
Sets the current extent to show in the widget - should be called as part of initialization (or whenev...
QgsRectangle currentExtent() const
Returns the current extent set for the widget.
void setOutputExtentFromLayer(const QgsMapLayer *layer)
Sets the output extent to match a layer&#39;s extent (may be transformed to output CRS).
QgsRectangle outputExtent() const
Returns the extent shown in the widget - in output CRS coordinates.
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:106
double xMaximum() const
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:91
void setTitleBase(const QString &title)
Sets the base part of title of the group box (will be appended with extent state) ...
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:377
This class represents a coordinate reference system (CRS).
QgsCoordinateReferenceSystem originalCrs() const
Returns the original coordinate reference system set for the widget.
Class for doing transforms between two map coordinate systems.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:96
QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
double yMaximum() const
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:101
int rowCount(const QModelIndex &parent=QModelIndex()) const override
QString name
Definition: qgsmaplayer.h:58
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:62
void setOutputExtentFromOriginal()
Sets the output extent to be the same as original extent (may be transformed to output CRS)...
void setOriginalExtent(const QgsRectangle &originalExtent, const QgsCoordinateReferenceSystem &originalCrs)
Sets the original extent and coordinate reference system for the widget.
QgsCoordinateReferenceSystem currentCrs() const
Returns the coordinate reference system for the current extent set for the widget.