1
+ #include " qgslogger.h"
2
+ #include " qgscoordinatetransform.h"
1
3
#include " qgsrasterlayersaveasdialog.h"
2
4
#include " qgsrasterdataprovider.h"
3
5
#include " qgsrasterformatsaveoptionswidget.h"
6
+ #include " qgsgenericprojectionselector.h"
4
7
5
8
#include < QFileDialog>
6
9
#include < QSettings>
7
10
8
11
QgsRasterLayerSaveAsDialog::QgsRasterLayerSaveAsDialog ( QgsRasterDataProvider* sourceProvider, const QgsRectangle& currentExtent,
9
- QWidget* parent, Qt::WindowFlags f ): QDialog( parent, f ),
10
- mDataProvider( sourceProvider ), mCurrentExtent( currentExtent )
11
-
12
+ const QgsCoordinateReferenceSystem& currentCrs,
13
+ QWidget* parent, Qt::WindowFlags f ):
14
+ QDialog( parent, f )
15
+ , mDataProvider( sourceProvider )
16
+ , mCurrentExtent( currentExtent )
17
+ , mCurrentCrs( currentCrs )
18
+ , mExtentState( OriginalExtent )
19
+ , mResolutionState( OriginalResolution )
12
20
{
13
21
setupUi ( this );
14
22
setValidators ();
23
+ // Translated labels + EPSG are updated later
24
+ mCrsComboBox ->addItem ( " Layer" , OriginalCrs );
25
+ mCrsComboBox ->addItem ( " Project" , CurrentCrs );
26
+ mCrsComboBox ->addItem ( " Selected" , UserCrs );
27
+
28
+ toggleResolutionSize ();
29
+ mUserCrs .createFromOgcWmsCrs ( " EPSG:4326" );
15
30
16
31
// only one hardcoded format at the moment
17
32
QStringList myFormats;
@@ -24,12 +39,16 @@ QgsRasterLayerSaveAsDialog::QgsRasterLayerSaveAsDialog( QgsRasterDataProvider* s
24
39
// fill reasonable default values depending on the provider
25
40
if ( mDataProvider )
26
41
{
42
+ // extent
43
+ setOutputExtent ( mDataProvider ->extent (), mDataProvider ->crs (), OriginalExtent );
44
+
27
45
if ( mDataProvider ->capabilities () & QgsRasterDataProvider::ExactResolution )
28
46
{
47
+ setOriginalResolution ();
29
48
int xSize = mDataProvider ->xSize ();
30
49
int ySize = mDataProvider ->ySize ();
31
- mColumnsLineEdit ->setText ( QString::number ( xSize ) );
32
- mRowsLineEdit ->setText ( QString::number ( ySize ) );
50
+ // mColumnsLineEdit->setText( QString::number( xSize ) );
51
+ // mRowsLineEdit->setText( QString::number( ySize ) );
33
52
mMaximumSizeXLineEdit ->setText ( QString::number ( xSize ) );
34
53
mMaximumSizeYLineEdit ->setText ( QString::number ( ySize ) );
35
54
}
@@ -42,9 +61,6 @@ QgsRasterLayerSaveAsDialog::QgsRasterLayerSaveAsDialog( QgsRasterDataProvider* s
42
61
mMaximumSizeYLineEdit ->setText ( QString::number ( 2000 ) );
43
62
}
44
63
45
- // extent
46
- setOutputExtent ( mCurrentExtent );
47
-
48
64
mOptionsWidget ->setProvider ( mDataProvider ->name () );
49
65
if ( mDataProvider ->name () == " gdal" )
50
66
{
@@ -53,6 +69,7 @@ QgsRasterLayerSaveAsDialog::QgsRasterLayerSaveAsDialog( QgsRasterDataProvider* s
53
69
mOptionsWidget ->update ();
54
70
55
71
}
72
+ updateCrsGroup ();
56
73
57
74
QPushButton* okButton = mButtonBox ->button ( QDialogButtonBox::Ok );
58
75
if ( okButton )
@@ -63,6 +80,8 @@ QgsRasterLayerSaveAsDialog::QgsRasterLayerSaveAsDialog( QgsRasterDataProvider* s
63
80
64
81
void QgsRasterLayerSaveAsDialog::setValidators ()
65
82
{
83
+ mXResolutionLineEdit ->setValidator ( new QDoubleValidator ( this ) );
84
+ mYResolutionLineEdit ->setValidator ( new QDoubleValidator ( this ) );
66
85
mColumnsLineEdit ->setValidator ( new QIntValidator ( this ) );
67
86
mRowsLineEdit ->setValidator ( new QIntValidator ( this ) );
68
87
mMaximumSizeXLineEdit ->setValidator ( new QIntValidator ( this ) );
@@ -108,14 +127,14 @@ void QgsRasterLayerSaveAsDialog::on_mSaveAsLineEdit_textChanged( const QString&
108
127
109
128
void QgsRasterLayerSaveAsDialog::on_mCurrentExtentButton_clicked ()
110
129
{
111
- setOutputExtent ( mCurrentExtent );
130
+ setOutputExtent ( mCurrentExtent , mCurrentCrs , CurrentExtent );
112
131
}
113
132
114
- void QgsRasterLayerSaveAsDialog::on_mProviderExtentButton_clicked ()
133
+ void QgsRasterLayerSaveAsDialog::on_mOriginalExtentButton_clicked ()
115
134
{
116
135
if ( mDataProvider )
117
136
{
118
- setOutputExtent ( mDataProvider ->extent () );
137
+ setOutputExtent ( mDataProvider ->extent (), mDataProvider -> crs (), OriginalExtent );
119
138
}
120
139
}
121
140
@@ -139,6 +158,16 @@ int QgsRasterLayerSaveAsDialog::nRows() const
139
158
return mRowsLineEdit ->text ().toInt ();
140
159
}
141
160
161
+ double QgsRasterLayerSaveAsDialog::xResolution () const
162
+ {
163
+ return mXResolutionLineEdit ->text ().toDouble ();
164
+ }
165
+
166
+ double QgsRasterLayerSaveAsDialog::yResolution () const
167
+ {
168
+ return mYResolutionLineEdit ->text ().toDouble ();
169
+ }
170
+
142
171
int QgsRasterLayerSaveAsDialog::maximumTileSizeX () const
143
172
{
144
173
return mMaximumSizeXLineEdit ->text ().toInt ();
@@ -174,12 +203,26 @@ QgsRectangle QgsRasterLayerSaveAsDialog::outputRectangle() const
174
203
return QgsRectangle ( mXMinLineEdit ->text ().toDouble (), mYMinLineEdit ->text ().toDouble (), mXMaxLineEdit ->text ().toDouble (), mYMaxLineEdit ->text ().toDouble () );
175
204
}
176
205
177
- void QgsRasterLayerSaveAsDialog::setOutputExtent ( const QgsRectangle& r )
206
+ void QgsRasterLayerSaveAsDialog::setOutputExtent ( const QgsRectangle& r, const QgsCoordinateReferenceSystem& srcCrs, ExtentState state )
178
207
{
179
- mXMinLineEdit ->setText ( QString::number ( r.xMinimum () ) );
180
- mXMaxLineEdit ->setText ( QString::number ( r.xMaximum () ) );
181
- mYMinLineEdit ->setText ( QString::number ( r.yMinimum () ) );
182
- mYMaxLineEdit ->setText ( QString::number ( r.yMaximum () ) );
208
+ QgsRectangle extent;
209
+ if ( outputCrs () == srcCrs )
210
+ {
211
+ extent = r;
212
+ }
213
+ else
214
+ {
215
+ QgsCoordinateTransform ct ( srcCrs, outputCrs () );
216
+ extent = ct.transformBoundingBox ( r );
217
+ }
218
+
219
+ mXMinLineEdit ->setText ( QString::number ( extent.xMinimum () ) );
220
+ mXMaxLineEdit ->setText ( QString::number ( extent.xMaximum () ) );
221
+ mYMinLineEdit ->setText ( QString::number ( extent.yMinimum () ) );
222
+ mYMaxLineEdit ->setText ( QString::number ( extent.yMaximum () ) );
223
+
224
+ mExtentState = state;
225
+ extentChanged ();
183
226
}
184
227
185
228
void QgsRasterLayerSaveAsDialog::hideFormat ()
@@ -199,3 +242,232 @@ void QgsRasterLayerSaveAsDialog::hideOutput()
199
242
okButton->setEnabled ( true );
200
243
}
201
244
}
245
+
246
+ void QgsRasterLayerSaveAsDialog::toggleResolutionSize ()
247
+ {
248
+ bool on = mResolutionRadioButton ->isChecked ();
249
+ mXResolutionLineEdit ->setEnabled ( on );
250
+ mYResolutionLineEdit ->setEnabled ( on );
251
+ mOriginalResolutionPushButton ->setEnabled ( on );
252
+ mColumnsLineEdit ->setEnabled ( !on );
253
+ mRowsLineEdit ->setEnabled ( !on );
254
+ mOriginalSizePushButton ->setEnabled ( !on );
255
+ }
256
+
257
+ void QgsRasterLayerSaveAsDialog::setOriginalResolution ()
258
+ {
259
+ double xRes = mDataProvider ->extent ().width () / mDataProvider ->xSize ();
260
+ double yRes = mDataProvider ->extent ().height () / mDataProvider ->ySize ();
261
+ setResolution ( xRes, yRes, mDataProvider ->crs () );
262
+ mResolutionState = OriginalResolution;
263
+ recalcSize ();
264
+ }
265
+
266
+ void QgsRasterLayerSaveAsDialog::setResolution ( double xRes, double yRes, const QgsCoordinateReferenceSystem& srcCrs )
267
+ {
268
+ if ( srcCrs != outputCrs () )
269
+ {
270
+ // We reproject pixel rectangle from center of selected extent, of course, it gives
271
+ // bigger xRes,yRes than reprojected edges (envelope), it may also be that
272
+ // close to margins are higher resolutions (even very, too high)
273
+ // TODO: consider more precise resolution calculation
274
+
275
+ QgsPoint center = outputRectangle ().center ();
276
+ QgsCoordinateTransform ct ( srcCrs, outputCrs () );
277
+ QgsPoint srsCenter = ct.transform ( center, QgsCoordinateTransform::ReverseTransform );
278
+
279
+ QgsRectangle srcExtent ( srsCenter.x () - xRes / 2 , srsCenter.y () - yRes / 2 , srsCenter.x () + xRes / 2 , srsCenter.y () + yRes / 2 );
280
+
281
+ QgsRectangle extent = ct.transform ( srcExtent );
282
+ xRes = extent.width ();
283
+ yRes = extent.height ();
284
+ }
285
+ mXResolutionLineEdit ->setText ( QString::number ( xRes ) );
286
+ mYResolutionLineEdit ->setText ( QString::number ( yRes ) );
287
+ }
288
+
289
+ void QgsRasterLayerSaveAsDialog::recalcSize ()
290
+ {
291
+ QgsDebugMsg ( " Entered" );
292
+ QgsRectangle extent = outputRectangle ();
293
+ int xSize = xResolution () != 0 ? static_cast <int >( qRound ( extent.width () / xResolution () ) ) : 0 ;
294
+ int ySize = yResolution () != 0 ? static_cast <int >( qRound ( extent.height () / yResolution () ) ) : 0 ;
295
+ mColumnsLineEdit ->setText ( QString::number ( xSize ) );
296
+ mRowsLineEdit ->setText ( QString::number ( ySize ) );
297
+ updateResolutionStateMsg ();
298
+ }
299
+
300
+ void QgsRasterLayerSaveAsDialog::setOriginalSize ()
301
+ {
302
+ mColumnsLineEdit ->setText ( QString::number ( mDataProvider ->xSize () ) );
303
+ mRowsLineEdit ->setText ( QString::number ( mDataProvider ->ySize () ) );
304
+ recalcResolution ();
305
+ }
306
+
307
+ void QgsRasterLayerSaveAsDialog::recalcResolution ()
308
+ {
309
+ QgsDebugMsg ( " Entered" );
310
+ QgsRectangle extent = outputRectangle ();
311
+ double xRes = nColumns () != 0 ? extent.width () / nColumns () : 0 ;
312
+ double yRes = nRows () != 0 ? extent.height () / nRows () : 0 ;
313
+ mXResolutionLineEdit ->setText ( QString::number ( xRes ) );
314
+ mYResolutionLineEdit ->setText ( QString::number ( yRes ) );
315
+ updateResolutionStateMsg ();
316
+ }
317
+
318
+ void QgsRasterLayerSaveAsDialog::recalcResolutionSize ()
319
+ {
320
+ QgsDebugMsg ( " Entered" );
321
+ if ( mResolutionRadioButton ->isChecked () )
322
+ {
323
+ recalcSize ();
324
+ }
325
+ else
326
+ {
327
+ mResolutionState = UserResolution;
328
+ recalcResolution ();
329
+ }
330
+ }
331
+
332
+ void QgsRasterLayerSaveAsDialog::updateResolutionStateMsg ()
333
+ {
334
+ QString msg;
335
+ switch ( mResolutionState )
336
+ {
337
+ case OriginalResolution:
338
+ msg = tr ( " layer" );
339
+ break ;
340
+ case UserResolution:
341
+ msg = tr ( " user defined" );
342
+ break ;
343
+ default :
344
+ break ;
345
+ }
346
+ msg = tr ( " Resolution" ) + " (" + tr ( " current" ) + " : " + msg + " )" ;
347
+ mResolutionGroupBox ->setTitle ( msg );
348
+ }
349
+
350
+ void QgsRasterLayerSaveAsDialog::extentChanged ()
351
+ {
352
+ updateExtentStateMsg ();
353
+ // Whenever extent changes with fixed size, original resolution is lost
354
+ if ( mSizeRadioButton ->isChecked () )
355
+ {
356
+ mResolutionState = UserResolution;
357
+ }
358
+ recalcResolutionSize ();
359
+ }
360
+
361
+ void QgsRasterLayerSaveAsDialog::updateExtentStateMsg ()
362
+ {
363
+ QString msg;
364
+ switch ( mExtentState )
365
+ {
366
+ case OriginalExtent:
367
+ msg = tr ( " layer" );
368
+ break ;
369
+ case CurrentExtent:
370
+ msg = tr ( " map view" );
371
+ break ;
372
+ case UserExtent:
373
+ msg = tr ( " user defined" );
374
+ break ;
375
+ default :
376
+ break ;
377
+ }
378
+ msg = tr ( " Extent" ) + " (" + tr ( " current" ) + " : " + msg + " )" ;
379
+ mExtentGroupBox ->setTitle ( msg );
380
+ }
381
+
382
+ void QgsRasterLayerSaveAsDialog::on_mChangeCrsPushButton_clicked ()
383
+ {
384
+ QgsGenericProjectionSelector * selector = new QgsGenericProjectionSelector ( this );
385
+ selector->setMessage ();
386
+ selector->setSelectedCrsId ( mUserCrs .srsid () );
387
+ if ( selector->exec () )
388
+ {
389
+ mUserCrs .createFromId ( selector->selectedCrsId (), QgsCoordinateReferenceSystem::InternalCrsId );
390
+ }
391
+ delete selector;
392
+ crsChanged ();
393
+ }
394
+
395
+ void QgsRasterLayerSaveAsDialog::crsChanged ()
396
+ {
397
+ QgsDebugMsg ( " Entered" );
398
+ if ( outputCrs () != mPreviousCrs )
399
+ {
400
+ // Reset extent
401
+ QgsRectangle previousExtent;
402
+ QgsCoordinateReferenceSystem previousCrs;
403
+ // We could reproject previous but that would add additional space also if
404
+ // it is was not necessary or at leas it could decrease accuracy
405
+ if ( mExtentState == OriginalExtent )
406
+ {
407
+ previousExtent = mDataProvider ->extent ();
408
+ previousCrs = mDataProvider ->crs ();
409
+ }
410
+ else if ( mExtentState == CurrentExtent )
411
+ {
412
+ previousExtent = mCurrentExtent ;
413
+ previousCrs = mCurrentCrs ;
414
+ }
415
+ else
416
+ {
417
+ previousExtent = outputRectangle ();
418
+ previousCrs = mPreviousCrs ;
419
+ }
420
+ setOutputExtent ( previousExtent, previousCrs, mExtentState );
421
+
422
+ // Reset resolution
423
+ if ( mResolutionRadioButton ->isChecked () )
424
+ {
425
+ if ( mResolutionState == OriginalResolution )
426
+ {
427
+ setOriginalResolution ();
428
+ }
429
+ else
430
+ {
431
+ // reset from present resolution and present crs
432
+ setResolution ( xResolution (), yResolution (), mPreviousCrs );
433
+ }
434
+ }
435
+ else
436
+ {
437
+ // Size does not change, we just recalc resolution from new extent
438
+ recalcResolution ();
439
+ }
440
+ }
441
+ mPreviousCrs = outputCrs ();
442
+ updateCrsGroup ();
443
+ }
444
+
445
+ void QgsRasterLayerSaveAsDialog::updateCrsGroup ()
446
+ {
447
+ QgsDebugMsg ( " Entered" );
448
+
449
+ mCrsComboBox ->setItemText ( mCrsComboBox ->findData ( OriginalCrs ),
450
+ tr ( " Layer" ) + " (" + mDataProvider ->crs ().description () + " , " + mDataProvider ->crs ().authid () + " )" );
451
+
452
+ mCrsComboBox ->setItemText ( mCrsComboBox ->findData ( CurrentCrs ),
453
+ tr ( " Project" ) + " (" + mCurrentCrs .description () + " , " + mCurrentCrs .authid () + " )" );
454
+
455
+ mCrsComboBox ->setItemText ( mCrsComboBox ->findData ( UserCrs ),
456
+ tr ( " Selected" ) + " (" + mUserCrs .description () + " , " + mUserCrs .authid () + " )" );
457
+
458
+ mChangeCrsPushButton ->setEnabled ( mCrsComboBox ->findData ( UserCrs ) == mCrsComboBox ->currentIndex () );
459
+ }
460
+
461
+ QgsCoordinateReferenceSystem QgsRasterLayerSaveAsDialog::outputCrs ()
462
+ {
463
+ int state = mCrsComboBox ->itemData ( mCrsComboBox ->currentIndex () ).toInt ();
464
+ if ( state == OriginalCrs )
465
+ {
466
+ return mDataProvider ->crs ();
467
+ }
468
+ else if ( state == CurrentCrs )
469
+ {
470
+ return mCurrentCrs ;
471
+ }
472
+ return mUserCrs ;
473
+ }
0 commit comments