1
/***************************************************************************
2
qgsprojectproperties.cpp
3
Set various project properties (inherits qgsprojectpropertiesbase)
6
copyright : (C) 2004 by Gary E.Sherman
7
email : sherman at mrcc.com
8
***************************************************************************/
10
/***************************************************************************
12
* This program is free software; you can redistribute it and/or modify *
13
* it under the terms of the GNU General Public License as published by *
14
* the Free Software Foundation; either version 2 of the License, or *
15
* (at your option) any later version. *
17
***************************************************************************/
20
#include "qgsprojectproperties.h"
23
#include "qgsavoidintersectionsdialog.h"
24
#include "qgscontexthelp.h"
25
#include "qgscoordinatetransform.h"
26
#include "qgslogger.h"
27
#include "qgsmapcanvas.h"
28
#include "qgsmaplayer.h"
29
#include "qgsmaplayerregistry.h"
30
#include "qgsmaprenderer.h"
31
#include "qgsproject.h"
32
#include "qgsrenderer.h"
33
#include "qgssnappingdialog.h"
34
#include "qgsrasterlayer.h"
37
#include <QColorDialog>
38
#include <QHeaderView> // Qt 4.4
39
#include "qgslogger.h"
44
QgsProjectProperties::QgsProjectProperties( QgsMapCanvas* mapCanvas, QWidget *parent, Qt::WFlags fl )
45
: QDialog( parent, fl ), mMapCanvas( mapCanvas )
48
connect( buttonBox, SIGNAL( accepted() ), this, SLOT( accept() ) );
49
connect( buttonBox, SIGNAL( rejected() ), this, SLOT( reject() ) );
50
connect( buttonBox->button( QDialogButtonBox::Apply ), SIGNAL( clicked() ), this, SLOT( apply() ) );
51
connect( this, SIGNAL( accepted() ), this, SLOT( apply() ) );
53
///////////////////////////////////////////////////////////
54
// Properties stored in map canvas's QgsMapRenderer
55
// these ones are propagated to QgsProject by a signal
57
QgsMapRenderer* myRender = mMapCanvas->mapRenderer();
58
QGis::UnitType myUnit = myRender->mapUnits();
59
setMapUnits( myUnit );
61
//see if the user wants on the fly projection enabled
62
bool myProjectionEnabled = myRender->hasCrsTransformEnabled();
63
cbxProjectionEnabled->setChecked( myProjectionEnabled );
64
btnGrpMapUnits->setEnabled( !myProjectionEnabled );
66
long myCRSID = myRender->destinationSrs().srsid();
67
QgsDebugMsg( "Read project CRSID: " + QString::number( myCRSID ) );
68
projectionSelector->setSelectedCrsId( myCRSID );
70
///////////////////////////////////////////////////////////
71
// Properties stored in QgsProject
73
title( QgsProject::instance()->title() );
75
// get the manner in which the number of decimal places in the mouse
76
// position display is set (manual or automatic)
77
bool automaticPrecision = QgsProject::instance()->readBoolEntry( "PositionPrecision", "/Automatic" );
78
if ( automaticPrecision )
80
radAutomatic->setChecked( true );
84
radManual->setChecked( true );
87
cbxAbsolutePath->setCurrentIndex( QgsProject::instance()->readBoolEntry( "Paths", "/Absolute", true ) ? 0 : 1 );
89
int dp = QgsProject::instance()->readNumEntry( "PositionPrecision", "/DecimalPlaces" );
90
spinBoxDP->setValue( dp );
92
//get the color selections and set the button color accordingly
93
int myRedInt = QgsProject::instance()->readNumEntry( "Gui", "/SelectionColorRedPart", 255 );
94
int myGreenInt = QgsProject::instance()->readNumEntry( "Gui", "/SelectionColorGreenPart", 255 );
95
int myBlueInt = QgsProject::instance()->readNumEntry( "Gui", "/SelectionColorBluePart", 0 );
96
QColor myColor = QColor( myRedInt, myGreenInt, myBlueInt );
97
pbnSelectionColor->setColor( myColor );
99
//get the color for map canvas background and set button color accordingly (default white)
100
myRedInt = QgsProject::instance()->readNumEntry( "Gui", "/CanvasColorRedPart", 255 );
101
myGreenInt = QgsProject::instance()->readNumEntry( "Gui", "/CanvasColorGreenPart", 255 );
102
myBlueInt = QgsProject::instance()->readNumEntry( "Gui", "/CanvasColorBluePart", 255 );
103
myColor = QColor( myRedInt, myGreenInt, myBlueInt );
104
pbnCanvasColor->setColor( myColor );
106
//read the digitizing settings
107
int topologicalEditing = QgsProject::instance()->readNumEntry( "Digitizing", "/TopologicalEditing", 0 );
108
if ( topologicalEditing != 0 )
110
mEnableTopologicalEditingCheckBox->setCheckState( Qt::Checked );
114
mEnableTopologicalEditingCheckBox->setCheckState( Qt::Unchecked );
117
bool avoidIntersectionListOk;
118
mAvoidIntersectionsSettings.clear();
119
QStringList avoidIntersectionsList = QgsProject::instance()->readListEntry( "Digitizing", "/AvoidIntersectionsList", &avoidIntersectionListOk );
120
if ( avoidIntersectionListOk )
122
QStringList::const_iterator avoidIt = avoidIntersectionsList.constBegin();
123
for ( ; avoidIt != avoidIntersectionsList.constEnd(); ++avoidIt )
125
mAvoidIntersectionsSettings.insert( *avoidIt );
129
bool layerIdListOk, enabledListOk, toleranceListOk, toleranceUnitListOk, snapToListOk;
130
QStringList layerIdList = QgsProject::instance()->readListEntry( "Digitizing", "/LayerSnappingList", &layerIdListOk );
131
QStringList enabledList = QgsProject::instance()->readListEntry( "Digitizing", "/LayerSnappingEnabledList", &enabledListOk );
132
QStringList toleranceList = QgsProject::instance()->readListEntry( "Digitizing", "/LayerSnappingToleranceList", & toleranceListOk );
133
QStringList toleranceUnitList = QgsProject::instance()->readListEntry( "Digitizing", "/LayerSnappingToleranceUnitList", & toleranceUnitListOk );
134
QStringList snapToList = QgsProject::instance()->readListEntry( "Digitizing", "/LayerSnapToList", &snapToListOk );
136
QStringList::const_iterator idIter = layerIdList.constBegin();
137
QStringList::const_iterator enabledIter = enabledList.constBegin();
138
QStringList::const_iterator tolIter = toleranceList.constBegin();
139
QStringList::const_iterator tolUnitIter = toleranceUnitList.constBegin();
140
QStringList::const_iterator snapToIter = snapToList.constBegin();
142
QgsMapLayer* currentLayer = 0;
144
//create the new layer entries
145
for ( ; idIter != layerIdList.constEnd(); ++idIter, ++enabledIter, ++tolIter, ++tolUnitIter, ++snapToIter )
149
currentLayer = QgsMapLayerRegistry::instance()->mapLayer( *idIter );
159
newEntry.layerName = currentLayer->name();
161
newEntry.checked = false;
162
if ( enabledListOk && enabledIter != enabledList.constEnd() )
164
if (( *enabledIter ) == "enabled" )
166
newEntry.checked = true;
170
//snap to vertex / segment / vertex and segment
171
if ( snapToListOk && snapToIter != snapToList.constEnd() )
173
if (( *snapToIter ) == "to_vertex" )
177
else if (( *snapToIter ) == "to_segment" )
181
else //to vertex and segment
192
if ( toleranceListOk && tolIter != toleranceList.constEnd() )
194
newEntry.tolerance = tolIter->toDouble();
198
newEntry.tolerance = 0;
201
//snap tolerance unit
202
if ( toleranceUnitListOk && tolUnitIter != toleranceUnitList.constEnd() )
204
newEntry.toleranceUnit = tolUnitIter->toInt();
208
newEntry.toleranceUnit = 0;
210
mSnappingLayerSettings.insert( *idIter, newEntry );
214
QStringList noIdentifyLayerIdList = QgsProject::instance()->readListEntry( "Identify", "/disabledLayers" );
216
const QMap<QString, QgsMapLayer*> &mapLayers = QgsMapLayerRegistry::instance()->mapLayers();
218
twIdentifyLayers->setColumnCount( 3 );
219
twIdentifyLayers->horizontalHeader()->setVisible( true );
220
twIdentifyLayers->setHorizontalHeaderItem( 0, new QTableWidgetItem( tr( "Layer" ) ) );
221
twIdentifyLayers->setHorizontalHeaderItem( 1, new QTableWidgetItem( tr( "Type" ) ) );
222
twIdentifyLayers->setHorizontalHeaderItem( 2, new QTableWidgetItem( tr( "Identifiable" ) ) );
223
twIdentifyLayers->setRowCount( mapLayers.size() );
224
twIdentifyLayers->verticalHeader()->setResizeMode( QHeaderView::ResizeToContents );
227
for ( QMap<QString, QgsMapLayer*>::const_iterator it = mapLayers.constBegin(); it != mapLayers.constEnd(); it++, i++ )
229
currentLayer = it.value();
231
QTableWidgetItem *twi = new QTableWidgetItem( QString::number( i ) );
232
twi->setData( Qt::UserRole, it.key() );
233
twIdentifyLayers->setVerticalHeaderItem( i, twi );
235
twi = new QTableWidgetItem( currentLayer->name() );
236
twi->setFlags( twi->flags() & ~Qt::ItemIsEditable );
237
twIdentifyLayers->setItem( i, 0, twi );
240
if ( currentLayer->type() == QgsMapLayer::VectorLayer )
242
type = tr( "Vector" );
244
else if ( currentLayer->type() == QgsMapLayer::RasterLayer )
246
QgsRasterLayer *rl = qobject_cast<QgsRasterLayer *>( currentLayer );
248
if ( rl && rl->providerKey() == "wms" )
254
type = tr( "Raster" );
258
twi = new QTableWidgetItem( type );
259
twi->setFlags( twi->flags() & ~Qt::ItemIsEditable );
260
twIdentifyLayers->setItem( i, 1, twi );
262
QCheckBox *cb = new QCheckBox();
263
cb->setChecked( !noIdentifyLayerIdList.contains( currentLayer->getLayerID() ) );
264
twIdentifyLayers->setCellWidget( i, 2, cb );
270
QgsProjectProperties::~QgsProjectProperties()
277
// return the map units
278
QGis::UnitType QgsProjectProperties::mapUnits() const
280
return mMapCanvas->mapRenderer()->mapUnits();
284
void QgsProjectProperties::setMapUnits( QGis::UnitType unit )
287
if ( unit == QGis::UnknownUnit )
291
if ( unit == QGis::Meters )
293
radMeters->setChecked( true );
295
else if ( unit == QGis::Feet )
297
radFeet->setChecked( true );
299
else if ( unit == QGis::DegreesMinutesSeconds )
301
radDMS->setChecked( true );
305
radDecimalDegrees->setChecked( true );
307
mMapCanvas->mapRenderer()->setMapUnits( unit );
311
QString QgsProjectProperties::title() const
313
return titleEdit->text();
314
} // QgsProjectPropertires::title() const
317
void QgsProjectProperties::title( QString const & title )
319
titleEdit->setText( title );
320
QgsProject::instance()->title( title );
321
} // QgsProjectProperties::title( QString const & title )
325
//when user clicks apply button
326
void QgsProjectProperties::apply()
329
// Note. Qt 3.2.3 and greater have a function selectedId() that
330
// can be used instead of the two part technique here
331
QGis::UnitType mapUnit;
332
if ( radMeters->isChecked() )
334
mapUnit = QGis::Meters;
336
else if ( radFeet->isChecked() )
338
mapUnit = QGis::Feet;
340
else if ( radDMS->isChecked() )
342
mapUnit = QGis::DegreesMinutesSeconds;
346
mapUnit = QGis::Degrees;
349
QgsMapRenderer* myRender = mMapCanvas->mapRenderer();
351
myRender->setMapUnits( mapUnit );
353
myRender->setProjectionsEnabled( cbxProjectionEnabled->isChecked() );
355
// Only change the projection if there is a node in the tree
356
// selected that has an srid. This prevents error if the user
357
// selects a top-level node rather than an actual coordinate
359
long myCRSID = projectionSelector->selectedCrsId();
362
QgsCoordinateReferenceSystem srs( myCRSID, QgsCoordinateReferenceSystem::InternalCrsId );
363
myRender->setDestinationSrs( srs );
364
QgsDebugMsg( QString( "Selected CRS " ) + srs.description() );
365
// write the currently selected projections _proj string_ to project settings
366
QgsDebugMsg( QString( "SpatialRefSys/ProjectCRSProj4String: %1" ).arg( projectionSelector->selectedProj4String() ) );
367
QgsProject::instance()->writeEntry( "SpatialRefSys", "/ProjectCRSProj4String", projectionSelector->selectedProj4String() );
369
// Set the map units to the projected coordinates if we are projecting
372
// If we couldn't get the map units, default to the value in the
373
// projectproperties dialog box (set above)
374
if ( srs.mapUnits() != QGis::UnknownUnit )
375
myRender->setMapUnits( srs.mapUnits() );
379
// Set the project title
380
QgsProject::instance()->title( title() );
382
// set the mouse display precision method and the
383
// number of decimal places for the manual option
384
// Note. Qt 3.2.3 and greater have a function selectedId() that
385
// can be used instead of the two part technique here
386
QgsProject::instance()->writeEntry( "PositionPrecision", "/Automatic", radAutomatic->isChecked() );
387
QgsProject::instance()->writeEntry( "PositionPrecision", "/DecimalPlaces", spinBoxDP->value() );
388
// Announce that we may have a new display precision setting
389
emit displayPrecisionChanged();
391
QgsProject::instance()->writeEntry( "Paths", "/Absolute", cbxAbsolutePath->currentIndex() == 0 );
393
//set the color for selections
394
QColor myColor = pbnSelectionColor->color();
395
QgsProject::instance()->writeEntry( "Gui", "/SelectionColorRedPart", myColor.red() );
396
QgsProject::instance()->writeEntry( "Gui", "/SelectionColorGreenPart", myColor.green() );
397
QgsProject::instance()->writeEntry( "Gui", "/SelectionColorBluePart", myColor.blue() );
398
QgsRenderer::setSelectionColor( myColor );
400
//set the color for canvas
401
myColor = pbnCanvasColor->color();
402
QgsProject::instance()->writeEntry( "Gui", "/CanvasColorRedPart", myColor.red() );
403
QgsProject::instance()->writeEntry( "Gui", "/CanvasColorGreenPart", myColor.green() );
404
QgsProject::instance()->writeEntry( "Gui", "/CanvasColorBluePart", myColor.blue() );
406
//write the digitizing settings
407
int topologicalEditingEnabled = ( mEnableTopologicalEditingCheckBox->checkState() == Qt::Checked ) ? 1 : 0;
408
QgsProject::instance()->writeEntry( "Digitizing", "/TopologicalEditing", topologicalEditingEnabled );
410
//store avoid intersection layers
411
QStringList avoidIntersectionList;
412
QSet<QString>::const_iterator avoidIt = mAvoidIntersectionsSettings.constBegin();
413
for ( ; avoidIt != mAvoidIntersectionsSettings.constEnd(); ++avoidIt )
415
avoidIntersectionList.append( *avoidIt );
417
QgsProject::instance()->writeEntry( "Digitizing", "/AvoidIntersectionsList", avoidIntersectionList );
420
QMap<QString, LayerEntry>::const_iterator layerEntryIt;
422
//store the layer snapping settings as string lists
423
QStringList layerIdList;
424
QStringList snapToList;
425
QStringList toleranceList;
426
QStringList enabledList;
427
QStringList toleranceUnitList;
429
for ( layerEntryIt = mSnappingLayerSettings.constBegin(); layerEntryIt != mSnappingLayerSettings.constEnd(); ++layerEntryIt )
431
layerIdList << layerEntryIt.key();
432
toleranceList << QString::number( layerEntryIt->tolerance, 'f' );
433
toleranceUnitList << QString::number(( int )layerEntryIt->toleranceUnit );
434
if ( layerEntryIt->checked )
436
enabledList << "enabled";
440
enabledList << "disabled";
442
if ( layerEntryIt->snapTo == 0 )
444
snapToList << "to_vertex";
446
else if ( layerEntryIt->snapTo == 1 )
448
snapToList << "to_segment";
450
else //to vertex and segment
452
snapToList << "to_vertex_and_segment";
456
if ( mSnappingLayerSettings.size() > 0 )
458
QgsProject::instance()->writeEntry( "Digitizing", "/LayerSnappingList", layerIdList );
459
QgsProject::instance()->writeEntry( "Digitizing", "/LayerSnapToList", snapToList );
460
QgsProject::instance()->writeEntry( "Digitizing", "/LayerSnappingToleranceList", toleranceList );
461
QgsProject::instance()->writeEntry( "Digitizing", "/LayerSnappingToleranceUnitList", toleranceUnitList );
462
QgsProject::instance()->writeEntry( "Digitizing", "/LayerSnappingEnabledList", enabledList );
465
QStringList noIdentifyLayerList;
466
for ( int i = 0; i < twIdentifyLayers->rowCount(); i++ )
468
QCheckBox *cb = qobject_cast<QCheckBox *>( twIdentifyLayers->cellWidget( i, 2 ) );
469
if ( cb && !cb->isChecked() )
471
QString id = twIdentifyLayers->verticalHeaderItem( i )->data( Qt::UserRole ).toString();
472
noIdentifyLayerList << id;
476
QgsProject::instance()->writeEntry( "Identify", "/disabledLayers", noIdentifyLayerList );
478
//todo XXX set canvas color
482
bool QgsProjectProperties::isProjected()
484
return cbxProjectionEnabled->isChecked();
487
void QgsProjectProperties::showProjectionsTab()
489
tabWidget->setCurrentIndex( 1 );
492
void QgsProjectProperties::on_pbnSelectionColor_clicked()
494
QColor color = QColorDialog::getColor( pbnSelectionColor->color(), this );
495
if ( color.isValid() )
497
pbnSelectionColor->setColor( color );
501
void QgsProjectProperties::on_pbnCanvasColor_clicked()
503
QColor color = QColorDialog::getColor( pbnCanvasColor->color(), this );
504
if ( color.isValid() )
506
pbnCanvasColor->setColor( color );
510
void QgsProjectProperties::on_mAvoidIntersectionsPushButton_clicked()
512
QgsAvoidIntersectionsDialog d( mMapCanvas, mAvoidIntersectionsSettings );
513
if ( d.exec() == QDialog::Accepted )
515
d.enabledLayers( mAvoidIntersectionsSettings );
519
void QgsProjectProperties::on_mSnappingOptionsPushButton_clicked()
521
QgsSnappingDialog d( mMapCanvas, mSnappingLayerSettings );
522
if ( d.exec() == QDialog::Accepted )
524
//retrieve the new layer snapping settings from the dialog
525
d.layerSettings( mSnappingLayerSettings );
529
void QgsProjectProperties::on_cbxProjectionEnabled_stateChanged( int state )
531
btnGrpMapUnits->setEnabled( state == Qt::Unchecked );
535
* Function to save dialog window state
537
void QgsProjectProperties::saveState()
540
settings.setValue( "/Windows/ProjectProperties/geometry", saveGeometry() );
541
settings.setValue( "/Windows/ProjectProperties/tab", tabWidget->currentIndex() );
545
* Function to restore dialog window state
547
void QgsProjectProperties::restoreState()
550
restoreGeometry( settings.value( "/Windows/ProjectProperties/geometry" ).toByteArray() );
551
tabWidget->setCurrentIndex( settings.value( "/Windows/ProjectProperties/tab" ).toInt() );