Skip to content

Commit ddbdcf8

Browse files
committedFeb 14, 2016
Fix project unit confusion (pt 2): add project distance unit setting
Adds a new option in project properties to set the units used for distance measurements. This setting defaults to the units set in QGIS options, but can then be overridden for specific projects. The setting is respected for length and perimeter calculations in: - Attribute table field update bar - Field calculator calculations - Identify tool derived length and perimeter values - Default unit shown in measure dialog Also adds unit tests to ensure that length and perimeter calculated by attribute table update bar, field calculator and identify tool are consistent wrt ellipsoidal calculations and distance units. (refs #13209, #12939, #2402, #4857, #4252)
1 parent 17a29f9 commit ddbdcf8

20 files changed

+611
-41
lines changed
 

‎python/core/qgsproject.sip

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,11 @@ class QgsProject : QObject
248248
/** Convenience function to query topological editing status */
249249
bool topologicalEditing() const;
250250

251+
/** Convenience function to query default distance measurement units for project.
252+
* @note added in QGIS 2.14
253+
*/
254+
QGis::UnitType distanceUnits() const;
255+
251256
/** Return project's home path
252257
@return home path of project (or QString::null if not set) */
253258
QString homePath() const;

‎python/gui/qgsmaptoolidentify.sip

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,4 +107,17 @@ class QgsMapToolIdentify : QgsMapTool
107107

108108
bool identifyRasterLayer( QList<QgsMapToolIdentify::IdentifyResult> *results, QgsRasterLayer *layer, QgsPoint point, const QgsRectangle& viewExtent, double mapUnitsPerPixel );
109109
bool identifyVectorLayer( QList<QgsMapToolIdentify::IdentifyResult> *results, QgsVectorLayer *layer, const QgsPoint& point );
110+
111+
private:
112+
113+
//! Private helper
114+
virtual void convertMeasurement( QgsDistanceArea &calc, double &measure, QGis::UnitType &u, bool isArea );
115+
116+
/** Transforms the measurements of derived attributes in the desired units*/
117+
virtual QGis::UnitType displayUnits();
118+
119+
/** Desired units for distance display.
120+
* @note added in QGIS 2.14
121+
*/
122+
virtual QGis::UnitType displayDistanceUnits();
110123
};

‎src/app/qgsattributetabledialog.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,7 @@ void QgsAttributeTableDialog::runFieldCalculation( QgsVectorLayer* layer, const
366366

367367
QgsExpression exp( expression );
368368
exp.setGeomCalculator( *myDa );
369+
exp.setDistanceUnits( QgsProject::instance()->distanceUnits() );
369370
bool useGeometry = exp.needsGeometry();
370371

371372
QgsFeatureRequest request( mMainView->masterModel()->request() );
@@ -816,6 +817,7 @@ void QgsAttributeTableDialog::setFilterExpression( const QString& filterString )
816817
QApplication::setOverrideCursor( Qt::WaitCursor );
817818

818819
filterExpression.setGeomCalculator( myDa );
820+
filterExpression.setDistanceUnits( QgsProject::instance()->distanceUnits() );
819821
QgsFeatureRequest request( mMainView->masterModel()->request() );
820822
request.setSubsetOfAttributes( filterExpression.referencedColumns(), mLayer->fields() );
821823
if ( !fetchGeom )

‎src/app/qgsattributetabledialog.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,8 @@ class APP_EXPORT QgsAttributeTableDialog : public QDialog, private Ui::QgsAttrib
223223

224224
QgsRubberBand* mRubberBand;
225225
QgsSearchWidgetWrapper* mCurrentSearchWidgetWrapper;
226+
227+
friend class TestQgsAttributeTable;
226228
};
227229

228230

‎src/app/qgsfieldcalculator.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ void QgsFieldCalculator::accept()
164164
QString calcString = builder->expressionText();
165165
QgsExpression exp( calcString );
166166
exp.setGeomCalculator( myDa );
167+
exp.setDistanceUnits( QgsProject::instance()->distanceUnits() );
167168

168169
QgsExpressionContext expContext;
169170
expContext << QgsExpressionContextUtils::globalScope()

‎src/app/qgsfieldcalculator.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ class APP_EXPORT QgsFieldCalculator: public QDialog, private Ui::QgsFieldCalcula
7171

7272
/** Idx of changed attribute*/
7373
int mAttributeId;
74+
75+
friend class TestQgsFieldCalculator;
7476
};
7577

7678
#endif // QGSFIELDCALCULATOR_H

‎src/app/qgsmaptoolidentifyaction.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,11 @@ QGis::UnitType QgsMapToolIdentifyAction::displayUnits()
193193
return ok ? unit : QGis::Meters;
194194
}
195195

196+
QGis::UnitType QgsMapToolIdentifyAction::displayDistanceUnits()
197+
{
198+
return QgsProject::instance()->distanceUnits();
199+
}
200+
196201
void QgsMapToolIdentifyAction::handleCopyToClipboard( QgsFeatureStore & featureStore )
197202
{
198203
QgsDebugMsg( QString( "features count = %1" ).arg( featureStore.features().size() ) );

‎src/app/qgsmaptoolidentifyaction.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ class APP_EXPORT QgsMapToolIdentifyAction : public QgsMapToolIdentify
8181
QgsIdentifyResultsDialog *resultsDialog();
8282

8383
virtual QGis::UnitType displayUnits() override;
84+
virtual QGis::UnitType displayDistanceUnits() override;
8485

8586
};
8687

‎src/app/qgsmeasuredialog.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,7 @@ QgsMeasureDialog::QgsMeasureDialog( QgsMeasureTool* tool, Qt::WindowFlags f )
5454
mUnitsCombo->addItem( QgsUnitTypes::toString( QGis::Feet ), QGis::Feet );
5555
mUnitsCombo->addItem( QgsUnitTypes::toString( QGis::Degrees ), QGis::Degrees );
5656
mUnitsCombo->addItem( QgsUnitTypes::toString( QGis::NauticalMiles ), QGis::NauticalMiles );
57-
QSettings settings;
58-
QString units = settings.value( "/qgis/measure/displayunits", QgsUnitTypes::encodeUnit( QGis::Meters ) ).toString();
59-
mUnitsCombo->setCurrentIndex( mUnitsCombo->findData( QgsUnitTypes::decodeDistanceUnit( units ) ) );
57+
mUnitsCombo->setCurrentIndex( mUnitsCombo->findData( QgsProject::instance()->distanceUnits() ) );
6058

6159
updateSettings();
6260

@@ -78,7 +76,7 @@ void QgsMeasureDialog::updateSettings()
7876
mDecimalPlaces = settings.value( "/qgis/measure/decimalplaces", "3" ).toInt();
7977
mCanvasUnits = mTool->canvas()->mapUnits();
8078
// Configure QgsDistanceArea
81-
mDisplayUnits = static_cast< QGis::UnitType >( mUnitsCombo->itemData( mUnitsCombo->currentIndex() ).toInt() );
79+
mDisplayUnits = QgsProject::instance()->distanceUnits();
8280
mDa.setSourceCrs( mTool->canvas()->mapSettings().destinationCrs().srsid() );
8381
mDa.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) );
8482
// Only use ellipsoidal calculation when project wide transformation is enabled.

‎src/app/qgsprojectproperties.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#include "qgslayertreegroup.h"
5555
#include "qgslayertreelayer.h"
5656
#include "qgslayertreemodel.h"
57+
#include "qgsunittypes.h"
5758

5859
#include "qgsmessagelog.h"
5960

@@ -84,6 +85,12 @@ QgsProjectProperties::QgsProjectProperties( QgsMapCanvas* mapCanvas, QWidget *pa
8485
mCoordinateDisplayComboBox->addItem( tr( "Degrees, minutes" ), DegreesMinutes );
8586
mCoordinateDisplayComboBox->addItem( tr( "Degrees, minutes, seconds" ), DegreesMinutesSeconds );
8687

88+
mDistanceUnitsCombo->addItem( tr( "Meters" ), QGis::Meters );
89+
mDistanceUnitsCombo->addItem( tr( "Feet" ), QGis::Feet );
90+
mDistanceUnitsCombo->addItem( tr( "Nautical miles" ), QGis::NauticalMiles );
91+
mDistanceUnitsCombo->addItem( tr( "Degrees" ), QGis::Degrees );
92+
mDistanceUnitsCombo->addItem( tr( "Map units" ), QGis::UnknownUnit );
93+
8794
connect( buttonBox->button( QDialogButtonBox::Apply ), SIGNAL( clicked() ), this, SLOT( apply() ) );
8895
connect( this, SIGNAL( accepted() ), this, SLOT( apply() ) );
8996
connect( projectionSelector, SIGNAL( sridSelected( QString ) ), this, SLOT( srIdUpdated() ) );
@@ -157,6 +164,8 @@ QgsProjectProperties::QgsProjectProperties( QgsMapCanvas* mapCanvas, QWidget *pa
157164
else
158165
mCoordinateDisplayComboBox->setCurrentIndex( mCoordinateDisplayComboBox->findData( DecimalDegrees ) );
159166

167+
mDistanceUnitsCombo->setCurrentIndex( mDistanceUnitsCombo->findData( QgsProject::instance()->distanceUnits() ) );
168+
160169
//get the color selections and set the button color accordingly
161170
int myRedInt = QgsProject::instance()->readNumEntry( "Gui", "/SelectionColorRedPart", 255 );
162171
int myGreenInt = QgsProject::instance()->readNumEntry( "Gui", "/SelectionColorGreenPart", 255 );
@@ -779,6 +788,9 @@ void QgsProjectProperties::apply()
779788
// Announce that we may have a new display precision setting
780789
emit displayPrecisionChanged();
781790

791+
QGis::UnitType distanceUnits = static_cast< QGis::UnitType >( mDistanceUnitsCombo->itemData( mDistanceUnitsCombo->currentIndex() ).toInt() );
792+
QgsProject::instance()->writeEntry( "Measurement", "/DistanceUnits", QgsUnitTypes::encodeUnit( distanceUnits ) );
793+
782794
QgsProject::instance()->writeEntry( "Paths", "/Absolute", cbxAbsolutePath->currentIndex() == 0 );
783795

784796
if ( mEllipsoidList.at( mEllipsoidIndex ).acronym.startsWith( "PARAMETER" ) )
@@ -1139,7 +1151,6 @@ void QgsProjectProperties::showProjectionsTab()
11391151

11401152
void QgsProjectProperties::on_cbxProjectionEnabled_toggled( bool onFlyEnabled )
11411153
{
1142-
QString measureOnFlyState = tr( "Measure tool (CRS transformation: %1)" );
11431154
if ( !onFlyEnabled )
11441155
{
11451156
// reset projection to default
@@ -1162,8 +1173,6 @@ void QgsProjectProperties::on_cbxProjectionEnabled_toggled( bool onFlyEnabled )
11621173

11631174
// unset ellipsoid
11641175
mEllipsoidIndex = 0;
1165-
1166-
btnGrpMeasureEllipsoid->setTitle( measureOnFlyState.arg( tr( "OFF" ) ) );
11671176
}
11681177
else
11691178
{
@@ -1172,8 +1181,6 @@ void QgsProjectProperties::on_cbxProjectionEnabled_toggled( bool onFlyEnabled )
11721181
mLayerSrsId = projectionSelector->selectedCrsId();
11731182
}
11741183
projectionSelector->setSelectedCrsId( mProjectSrsId );
1175-
1176-
btnGrpMeasureEllipsoid->setTitle( measureOnFlyState.arg( tr( "ON" ) ) );
11771184
}
11781185

11791186
srIdUpdated();
@@ -1230,7 +1237,7 @@ void QgsProjectProperties::updateGuiForMapUnits( QGis::UnitType units )
12301237
else
12311238
{
12321239
//make sure map units option is shown in coordinate display combo
1233-
QString mapUnitString = tr( "Map units (%1)" ).arg( QGis::tr( units ) );
1240+
QString mapUnitString = tr( "Map units (%1)" ).arg( QgsUnitTypes::toString( units ) );
12341241
if ( idx < 0 )
12351242
{
12361243
mCoordinateDisplayComboBox->insertItem( 0, mapUnitString, MapUnits );

‎src/core/qgsproject.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "qgsvectorlayer.h"
3737
#include "qgsvisibilitypresetcollection.h"
3838
#include "qgslayerdefinition.h"
39+
#include "qgsunittypes.h"
3940

4041
#include <QApplication>
4142
#include <QFileInfo>
@@ -45,6 +46,7 @@
4546
#include <QTemporaryFile>
4647
#include <QDir>
4748
#include <QUrl>
49+
#include <QSettings>
4850

4951
#ifdef Q_OS_UNIX
5052
#include <utime.h>
@@ -452,6 +454,10 @@ void QgsProject::clear()
452454
writeEntry( "PositionPrecision", "/DecimalPlaces", 2 );
453455
writeEntry( "Paths", "/Absolute", false );
454456

457+
//copy default distance units to project
458+
QSettings s;
459+
writeEntry( "Measurement", "/DistanceUnits", s.value( "/qgis/measure/displayunits" ).toString() );
460+
455461
setDirty( false );
456462
}
457463

@@ -2058,6 +2064,19 @@ bool QgsProject::topologicalEditing() const
20582064
return ( QgsProject::instance()->readNumEntry( "Digitizing", "/TopologicalEditing", 0 ) > 0 );
20592065
}
20602066

2067+
QGis::UnitType QgsProject::distanceUnits() const
2068+
{
2069+
QString distanceUnitString = QgsProject::instance()->readEntry( "Measurement", "/DistanceUnits", QString() );
2070+
if ( !distanceUnitString.isEmpty() )
2071+
return QgsUnitTypes::decodeDistanceUnit( distanceUnitString );
2072+
2073+
//fallback to QGIS default measurement unit
2074+
QSettings s;
2075+
bool ok = false;
2076+
QGis::UnitType type = QgsUnitTypes::decodeDistanceUnit( s.value( "/qgis/measure/displayunits" ).toString(), &ok );
2077+
return ok ? type : QGis::Meters;
2078+
}
2079+
20612080
void QgsProjectBadLayerDefaultHandler::handleBadLayers( const QList<QDomNode>& /*layers*/, const QDomDocument& /*projectDom*/ )
20622081
{
20632082
// just ignore any bad layers

‎src/core/qgsproject.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,11 @@ class CORE_EXPORT QgsProject : public QObject
293293
/** Convenience function to query topological editing status */
294294
bool topologicalEditing() const;
295295

296+
/** Convenience function to query default distance measurement units for project.
297+
* @note added in QGIS 2.14
298+
*/
299+
QGis::UnitType distanceUnits() const;
300+
296301
/** Return project's home path
297302
@return home path of project (or QString::null if not set) */
298303
QString homePath() const;

‎src/gui/qgsmaptoolidentify.cpp

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -369,9 +369,8 @@ QMap< QString, QString > QgsMapToolIdentify::featureDerivedAttributes( QgsFeatur
369369
if ( geometryType == QGis::Line )
370370
{
371371
double dist = calc.measureLength( feature->constGeometry() );
372-
QGis::UnitType myDisplayUnits;
373-
convertMeasurement( calc, dist, myDisplayUnits, false );
374-
QString str = calc.textUnit( dist, 3, myDisplayUnits, false ); // dist and myDisplayUnits are out params
372+
dist = calc.convertLengthMeasurement( dist, displayDistanceUnits() );
373+
QString str = formatDistance( dist );
375374
derivedAttributes.insert( tr( "Length" ), str );
376375

377376
const QgsCurveV2* curve = dynamic_cast< const QgsCurveV2* >( feature->constGeometry()->geometry() );
@@ -399,13 +398,15 @@ QMap< QString, QString > QgsMapToolIdentify::featureDerivedAttributes( QgsFeatur
399398
else if ( geometryType == QGis::Polygon )
400399
{
401400
double area = calc.measureArea( feature->constGeometry() );
402-
double perimeter = calc.measurePerimeter( feature->constGeometry() );
401+
403402
QGis::UnitType myDisplayUnits;
404403
convertMeasurement( calc, area, myDisplayUnits, true ); // area and myDisplayUnits are out params
405404
QString str = calc.textUnit( area, 3, myDisplayUnits, true );
406405
derivedAttributes.insert( tr( "Area" ), str );
407-
convertMeasurement( calc, perimeter, myDisplayUnits, false ); // perimeter and myDisplayUnits are out params
408-
str = calc.textUnit( perimeter, 3, myDisplayUnits, false );
406+
407+
double perimeter = calc.measurePerimeter( feature->constGeometry() );
408+
perimeter = calc.convertLengthMeasurement( perimeter, displayDistanceUnits() );
409+
str = formatDistance( perimeter );
409410
derivedAttributes.insert( tr( "Perimeter" ), str );
410411

411412
str = QLocale::system().toString( feature->constGeometry()->geometry()->nCoordinates() );
@@ -640,7 +641,7 @@ bool QgsMapToolIdentify::identifyRasterLayer( QList<IdentifyResult> *results, Qg
640641

641642
void QgsMapToolIdentify::convertMeasurement( QgsDistanceArea &calc, double &measure, QGis::UnitType &u, bool isArea )
642643
{
643-
// Helper for converting between meters and feet
644+
// Helper for converting between units
644645
// The parameter &u is out only...
645646

646647
// Get the canvas units
@@ -655,6 +656,19 @@ QGis::UnitType QgsMapToolIdentify::displayUnits()
655656
return mCanvas->mapUnits();
656657
}
657658

659+
QGis::UnitType QgsMapToolIdentify::displayDistanceUnits()
660+
{
661+
return mCanvas->mapUnits();
662+
}
663+
664+
QString QgsMapToolIdentify::formatDistance( double distance )
665+
{
666+
QSettings settings;
667+
bool baseUnit = settings.value( "/qgis/measure/keepbaseunit", false ).toBool();
668+
669+
return QgsDistanceArea::textUnit( distance, 3, displayDistanceUnits(), false, baseUnit );
670+
}
671+
658672
void QgsMapToolIdentify::formatChanged( QgsRasterLayer *layer )
659673
{
660674
QgsDebugMsg( "Entered" );

‎src/gui/qgsmaptoolidentify.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,16 @@ class GUI_EXPORT QgsMapToolIdentify : public QgsMapTool
163163
/** Transforms the measurements of derived attributes in the desired units*/
164164
virtual QGis::UnitType displayUnits();
165165

166+
/** Desired units for distance display.
167+
* @note added in QGIS 2.14
168+
*/
169+
virtual QGis::UnitType displayDistanceUnits();
170+
171+
/** Format a distance into a suitable string for display to the user
172+
* @note added in QGIS 2.14
173+
*/
174+
QString formatDistance( double distance );
175+
166176
QMap< QString, QString > featureDerivedAttributes( QgsFeature *feature, QgsMapLayer *layer, const QgsPoint& layerPoint = QgsPoint() );
167177

168178
/** Adds details of the closest vertex to derived attributes

‎src/ui/qgsprojectpropertiesbase.ui

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -471,43 +471,53 @@
471471
<item>
472472
<widget class="QgsCollapsibleGroupBox" name="btnGrpMeasureEllipsoid">
473473
<property name="title">
474-
<string>Measure tool</string>
474+
<string>Measurements</string>
475475
</property>
476476
<property name="syncGroup" stdset="0">
477477
<string notr="true">projgeneral</string>
478478
</property>
479479
<layout class="QGridLayout" name="gridLayoutMeasureTool">
480-
<item row="1" column="0">
480+
<item row="0" column="0">
481481
<widget class="QLabel" name="textLabel1_8">
482482
<property name="text">
483483
<string>Ellipsoid
484484
(for distance calculations)</string>
485485
</property>
486486
</widget>
487487
</item>
488-
<item row="2" column="1">
488+
<item row="1" column="4">
489+
<widget class="QLineEdit" name="leSemiMinor"/>
490+
</item>
491+
<item row="2" column="1" colspan="4">
492+
<widget class="QComboBox" name="mDistanceUnitsCombo"/>
493+
</item>
494+
<item row="1" column="2">
495+
<widget class="QLineEdit" name="leSemiMajor"/>
496+
</item>
497+
<item row="0" column="1" colspan="4">
498+
<widget class="QComboBox" name="cmbEllipsoid"/>
499+
</item>
500+
<item row="2" column="0">
501+
<widget class="QLabel" name="label_28">
502+
<property name="text">
503+
<string>Units for distance measurement</string>
504+
</property>
505+
</widget>
506+
</item>
507+
<item row="1" column="1">
489508
<widget class="QLabel" name="label_41">
490509
<property name="text">
491510
<string>Semi-major</string>
492511
</property>
493512
</widget>
494513
</item>
495-
<item row="2" column="2">
496-
<widget class="QLineEdit" name="leSemiMajor"/>
497-
</item>
498-
<item row="2" column="4">
499-
<widget class="QLineEdit" name="leSemiMinor"/>
500-
</item>
501-
<item row="2" column="3">
514+
<item row="1" column="3">
502515
<widget class="QLabel" name="label_42">
503516
<property name="text">
504517
<string>Semi-minor</string>
505518
</property>
506519
</widget>
507520
</item>
508-
<item row="1" column="1" colspan="4">
509-
<widget class="QComboBox" name="cmbEllipsoid"/>
510-
</item>
511521
</layout>
512522
</widget>
513523
</item>
@@ -2528,6 +2538,7 @@
25282538
<tabstop>cmbEllipsoid</tabstop>
25292539
<tabstop>leSemiMajor</tabstop>
25302540
<tabstop>leSemiMinor</tabstop>
2541+
<tabstop>mDistanceUnitsCombo</tabstop>
25312542
<tabstop>mCoordinateDisplayComboBox</tabstop>
25322543
<tabstop>radAutomatic</tabstop>
25332544
<tabstop>radManual</tabstop>

‎tests/src/app/CMakeLists.txt

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,23 @@
33
# the UI file won't be wrapped!
44
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}
55
${CMAKE_CURRENT_BINARY_DIR}
6-
${CMAKE_SOURCE_DIR}/src/core
7-
${CMAKE_SOURCE_DIR}/src/core/auth
8-
${CMAKE_SOURCE_DIR}/src/core/composer
9-
${CMAKE_SOURCE_DIR}/src/core/geometry
10-
${CMAKE_SOURCE_DIR}/src/core/raster
11-
${CMAKE_SOURCE_DIR}/src/core/symbology-ng
12-
${CMAKE_BINARY_DIR}/src/ui
13-
${CMAKE_SOURCE_DIR}/src/gui
14-
${CMAKE_SOURCE_DIR}/src/python
15-
${CMAKE_SOURCE_DIR}/src/app
16-
${CMAKE_SOURCE_DIR}/src/app/pluginmanager
6+
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/core
7+
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/core/auth
8+
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/core/composer
9+
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/core/geometry
10+
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/core/raster
11+
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/core/symbology-ng
12+
${CMAKE_CURRENT_BINARY_DIR}/../../../src/ui
13+
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/gui
14+
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/gui/editorwidgets
15+
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/gui/editorwidgets/core
16+
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/gui/attributetable
17+
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/gui/symbology-ng
18+
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/gui/raster
19+
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/python
20+
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/app
21+
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/app/pluginmanager
22+
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/ui
1723
)
1824
INCLUDE_DIRECTORIES(SYSTEM
1925
${QT_INCLUDE_DIR}
@@ -96,3 +102,6 @@ ENDMACRO (ADD_QGIS_TEST)
96102
# Tests:
97103

98104
ADD_QGIS_TEST(qgisappclipboard testqgisappclipboard.cpp)
105+
ADD_QGIS_TEST(attributetabletest testqgsattributetable.cpp)
106+
ADD_QGIS_TEST(fieldcalculatortest testqgsfieldcalculator.cpp)
107+
ADD_QGIS_TEST(maptoolidentifyaction testqgsmaptoolidentifyaction.cpp)
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/***************************************************************************
2+
testqgsattributetable.cpp
3+
-------------------------
4+
Date : 2016-02-14
5+
Copyright : (C) 2016 by Nyall Dawson
6+
Email : nyall dot dawson 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 <QtTest/QtTest>
16+
#include "qgisapp.h"
17+
#include "qgsapplication.h"
18+
#include "qgsvectorlayer.h"
19+
#include "qgsfeature.h"
20+
#include "qgsgeometry.h"
21+
#include "qgsvectordataprovider.h"
22+
#include "qgsattributetabledialog.h"
23+
#include "qgsproject.h"
24+
#include "qgsmapcanvas.h"
25+
#include "qgsunittypes.h"
26+
27+
/** \ingroup UnitTests
28+
* This is a unit test for the attribute table dialog
29+
*/
30+
class TestQgsAttributeTable : public QObject
31+
{
32+
Q_OBJECT
33+
public:
34+
TestQgsAttributeTable();
35+
36+
private slots:
37+
void initTestCase();// will be called before the first testfunction is executed.
38+
void cleanupTestCase();// will be called after the last testfunction was executed.
39+
void init() {} // will be called before each testfunction is executed.
40+
void cleanup() {} // will be called after every testfunction.
41+
void testFieldCalculation();
42+
43+
private:
44+
QgisApp * mQgisApp;
45+
};
46+
47+
TestQgsAttributeTable::TestQgsAttributeTable()
48+
: mQgisApp( nullptr )
49+
{
50+
51+
}
52+
53+
//runs before all tests
54+
void TestQgsAttributeTable::initTestCase()
55+
{
56+
qDebug() << "TestQgisAppClipboard::initTestCase()";
57+
// init QGIS's paths - true means that all path will be inited from prefix
58+
QgsApplication::init();
59+
QgsApplication::initQgis();
60+
mQgisApp = new QgisApp();
61+
}
62+
63+
//runs after all tests
64+
void TestQgsAttributeTable::cleanupTestCase()
65+
{
66+
QgsApplication::exitQgis();
67+
}
68+
69+
void TestQgsAttributeTable::testFieldCalculation()
70+
{
71+
//test field calculation
72+
73+
//create a temporary layer
74+
QScopedPointer< QgsVectorLayer> tempLayer( new QgsVectorLayer( "LineString?crs=epsg:3111&field=pk:int&field=col1:double", "vl", "memory" ) );
75+
QVERIFY( tempLayer->isValid() );
76+
QgsFeature f1( tempLayer->dataProvider()->fields(), 1 );
77+
f1.setAttribute( "pk", 1 );
78+
f1.setAttribute( "col1", 0.0 );
79+
QgsPolyline line3111;
80+
line3111 << QgsPoint( 2484588, 2425722 ) << QgsPoint( 2482767, 2398853 );
81+
f1.setGeometry( QgsGeometry::fromPolyline( line3111 ) );
82+
tempLayer->dataProvider()->addFeatures( QgsFeatureList() << f1 );
83+
84+
// set project CRS and ellipsoid
85+
QgisApp::instance()->mapCanvas()->setCrsTransformEnabled( true );
86+
QgsCoordinateReferenceSystem srs( 3111, QgsCoordinateReferenceSystem::EpsgCrsId );
87+
QgsProject::instance()->writeEntry( "SpatialRefSys", "/ProjectCRSProj4String", srs.toProj4() );
88+
QgsProject::instance()->writeEntry( "SpatialRefSys", "/ProjectCRSID", ( int ) srs.srsid() );
89+
QgsProject::instance()->writeEntry( "SpatialRefSys", "/ProjectCrs", srs.authid() );
90+
QgsProject::instance()->writeEntry( "Measure", "/Ellipsoid", QString( "WGS84" ) );
91+
QgsProject::instance()->writeEntry( "Measurement", "/DistanceUnits", QgsUnitTypes::encodeUnit( QGis::Meters ) );
92+
93+
// run length calculation
94+
QScopedPointer< QgsAttributeTableDialog > dlg( new QgsAttributeTableDialog( tempLayer.data() ) );
95+
tempLayer->startEditing();
96+
dlg->runFieldCalculation( tempLayer.data(), "col1", "$length" );
97+
tempLayer->commitChanges();
98+
// check result
99+
QgsFeatureIterator fit = tempLayer->dataProvider()->getFeatures();
100+
QgsFeature f;
101+
QVERIFY( fit.nextFeature( f ) );
102+
double expected = 26932.156;
103+
QVERIFY( qgsDoubleNear( f.attribute( "col1" ).toDouble(), expected, 0.001 ) );
104+
105+
// change project length unit, check calculation respects unit
106+
QgsProject::instance()->writeEntry( "Measurement", "/DistanceUnits", QgsUnitTypes::encodeUnit( QGis::Feet ) );
107+
QScopedPointer< QgsAttributeTableDialog > dlg2( new QgsAttributeTableDialog( tempLayer.data() ) );
108+
tempLayer->startEditing();
109+
dlg2->runFieldCalculation( tempLayer.data(), "col1", "$length" );
110+
tempLayer->commitChanges();
111+
// check result
112+
fit = tempLayer->dataProvider()->getFeatures();
113+
QVERIFY( fit.nextFeature( f ) );
114+
expected = 88360.0918635;
115+
QVERIFY( qgsDoubleNear( f.attribute( "col1" ).toDouble(), expected, 0.001 ) );
116+
}
117+
118+
QTEST_MAIN( TestQgsAttributeTable )
119+
#include "testqgsattributetable.moc"
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/***************************************************************************
2+
testqgsfieldcalculator.cpp
3+
--------------------------
4+
Date : 2016-02-14
5+
Copyright : (C) 2016 by Nyall Dawson
6+
Email : nyall dot dawson 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 <QtTest/QtTest>
16+
#include "qgisapp.h"
17+
#include "qgsapplication.h"
18+
#include "qgsvectorlayer.h"
19+
#include "qgsfeature.h"
20+
#include "qgsgeometry.h"
21+
#include "qgsvectordataprovider.h"
22+
#include "qgsfieldcalculator.h"
23+
#include "qgsproject.h"
24+
#include "qgsmapcanvas.h"
25+
#include "qgsunittypes.h"
26+
27+
/** \ingroup UnitTests
28+
* This is a unit test for the field calculator
29+
*/
30+
class TestQgsFieldCalculator : public QObject
31+
{
32+
Q_OBJECT
33+
public:
34+
TestQgsFieldCalculator();
35+
36+
private slots:
37+
void initTestCase();// will be called before the first testfunction is executed.
38+
void cleanupTestCase();// will be called after the last testfunction was executed.
39+
void init() {} // will be called before each testfunction is executed.
40+
void cleanup() {} // will be called after every testfunction.
41+
void testLengthCalculations();
42+
43+
private:
44+
QgisApp * mQgisApp;
45+
};
46+
47+
TestQgsFieldCalculator::TestQgsFieldCalculator()
48+
: mQgisApp( nullptr )
49+
{
50+
51+
}
52+
53+
//runs before all tests
54+
void TestQgsFieldCalculator::initTestCase()
55+
{
56+
qDebug() << "TestQgisAppClipboard::initTestCase()";
57+
// init QGIS's paths - true means that all path will be inited from prefix
58+
QgsApplication::init();
59+
QgsApplication::initQgis();
60+
mQgisApp = new QgisApp();
61+
}
62+
63+
//runs after all tests
64+
void TestQgsFieldCalculator::cleanupTestCase()
65+
{
66+
QgsApplication::exitQgis();
67+
}
68+
69+
void TestQgsFieldCalculator::testLengthCalculations()
70+
{
71+
//test length calculation respects ellipsoid and project distance units
72+
73+
//create a temporary layer
74+
QScopedPointer< QgsVectorLayer> tempLayer( new QgsVectorLayer( "LineString?crs=epsg:3111&field=pk:int&field=col1:double", "vl", "memory" ) );
75+
QVERIFY( tempLayer->isValid() );
76+
QgsFeature f1( tempLayer->dataProvider()->fields(), 1 );
77+
f1.setAttribute( "pk", 1 );
78+
f1.setAttribute( "col1", 0.0 );
79+
QgsPolyline line3111;
80+
line3111 << QgsPoint( 2484588, 2425722 ) << QgsPoint( 2482767, 2398853 );
81+
f1.setGeometry( QgsGeometry::fromPolyline( line3111 ) );
82+
tempLayer->dataProvider()->addFeatures( QgsFeatureList() << f1 );
83+
84+
// set project CRS and ellipsoid
85+
QgisApp::instance()->mapCanvas()->setCrsTransformEnabled( true );
86+
QgsCoordinateReferenceSystem srs( 3111, QgsCoordinateReferenceSystem::EpsgCrsId );
87+
QgsProject::instance()->writeEntry( "SpatialRefSys", "/ProjectCRSProj4String", srs.toProj4() );
88+
QgsProject::instance()->writeEntry( "SpatialRefSys", "/ProjectCRSID", ( int ) srs.srsid() );
89+
QgsProject::instance()->writeEntry( "SpatialRefSys", "/ProjectCrs", srs.authid() );
90+
QgsProject::instance()->writeEntry( "Measure", "/Ellipsoid", QString( "WGS84" ) );
91+
QgsProject::instance()->writeEntry( "Measurement", "/DistanceUnits", QgsUnitTypes::encodeUnit( QGis::Meters ) );
92+
93+
// run length calculation
94+
tempLayer->startEditing();
95+
QScopedPointer< QgsFieldCalculator > calc( new QgsFieldCalculator( tempLayer.data() ) );
96+
97+
// this next part is fragile, and may need to be modified if the dialog changes:
98+
calc->mUpdateExistingGroupBox->setChecked( true );
99+
calc->mExistingFieldComboBox->setCurrentIndex( 1 );
100+
calc->builder->setExpressionText( "$length" );
101+
calc->accept();
102+
103+
tempLayer->commitChanges();
104+
105+
// check result
106+
QgsFeatureIterator fit = tempLayer->dataProvider()->getFeatures();
107+
QgsFeature f;
108+
QVERIFY( fit.nextFeature( f ) );
109+
double expected = 26932.156;
110+
QVERIFY( qgsDoubleNear( f.attribute( "col1" ).toDouble(), expected, 0.001 ) );
111+
112+
// change project length unit, check calculation respects unit
113+
QgsProject::instance()->writeEntry( "Measurement", "/DistanceUnits", QgsUnitTypes::encodeUnit( QGis::Feet ) );
114+
tempLayer->startEditing();
115+
QScopedPointer< QgsFieldCalculator > calc2( new QgsFieldCalculator( tempLayer.data() ) );
116+
calc2->mUpdateExistingGroupBox->setChecked( true );
117+
calc2->mExistingFieldComboBox->setCurrentIndex( 1 );
118+
calc2->builder->setExpressionText( "$length" );
119+
calc2->accept();
120+
tempLayer->commitChanges();
121+
// check result
122+
fit = tempLayer->dataProvider()->getFeatures();
123+
QVERIFY( fit.nextFeature( f ) );
124+
expected = 88360.0918635;
125+
QVERIFY( qgsDoubleNear( f.attribute( "col1" ).toDouble(), expected, 0.001 ) );
126+
127+
}
128+
129+
QTEST_MAIN( TestQgsFieldCalculator )
130+
#include "testqgsfieldcalculator.moc"
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
/***************************************************************************
2+
testqgsmaptoolidentifyaction.cpp
3+
--------------------------------
4+
Date : 2016-02-14
5+
Copyright : (C) 2016 by Nyall Dawson
6+
Email : nyall dot dawson 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+
16+
#include <QtTest/QtTest>
17+
#include "qgsapplication.h"
18+
#include "qgsvectorlayer.h"
19+
#include "qgsfeature.h"
20+
#include "qgsgeometry.h"
21+
#include "qgsvectordataprovider.h"
22+
#include "qgsproject.h"
23+
#include "qgsmapcanvas.h"
24+
#include "qgsunittypes.h"
25+
#include "qgsmaptoolidentifyaction.h"
26+
27+
class TestQgsMapToolIdentifyAction : public QObject
28+
{
29+
Q_OBJECT
30+
public:
31+
TestQgsMapToolIdentifyAction()
32+
: canvas( 0 )
33+
{}
34+
35+
private slots:
36+
void initTestCase(); // will be called before the first testfunction is executed.
37+
void cleanupTestCase(); // will be called after the last testfunction was executed.
38+
void init(); // will be called before each testfunction is executed.
39+
void cleanup(); // will be called after every testfunction.
40+
void lengthCalculation(); //test calculation of derived length attributes
41+
void perimeterCalculation(); //test calculation of derived perimeter attribute
42+
43+
private:
44+
QgsMapCanvas* canvas;
45+
};
46+
47+
void TestQgsMapToolIdentifyAction::initTestCase()
48+
{
49+
QgsApplication::init();
50+
QgsApplication::initQgis();
51+
// Set up the QSettings environment
52+
QCoreApplication::setOrganizationName( "QGIS" );
53+
QCoreApplication::setOrganizationDomain( "qgis.org" );
54+
QCoreApplication::setApplicationName( "QGIS-TEST" );
55+
56+
QgsApplication::showSettings();
57+
}
58+
59+
void TestQgsMapToolIdentifyAction::cleanupTestCase()
60+
{
61+
QgsApplication::exitQgis();
62+
}
63+
64+
void TestQgsMapToolIdentifyAction::init()
65+
{
66+
canvas = new QgsMapCanvas();
67+
}
68+
69+
void TestQgsMapToolIdentifyAction::cleanup()
70+
{
71+
delete canvas;
72+
}
73+
74+
void TestQgsMapToolIdentifyAction::lengthCalculation()
75+
{
76+
QSettings s;
77+
s.setValue( "/qgis/measure/keepbaseunit", true );
78+
79+
//create a temporary layer
80+
QScopedPointer< QgsVectorLayer> tempLayer( new QgsVectorLayer( "LineString?crs=epsg:3111&field=pk:int&field=col1:double", "vl", "memory" ) );
81+
QVERIFY( tempLayer->isValid() );
82+
QgsFeature f1( tempLayer->dataProvider()->fields(), 1 );
83+
f1.setAttribute( "pk", 1 );
84+
f1.setAttribute( "col1", 0.0 );
85+
QgsPolyline line3111;
86+
line3111 << QgsPoint( 2484588, 2425722 ) << QgsPoint( 2482767, 2398853 );
87+
f1.setGeometry( QgsGeometry::fromPolyline( line3111 ) );
88+
tempLayer->dataProvider()->addFeatures( QgsFeatureList() << f1 );
89+
90+
// set project CRS and ellipsoid
91+
QgsCoordinateReferenceSystem srs( 3111, QgsCoordinateReferenceSystem::EpsgCrsId );
92+
canvas->setCrsTransformEnabled( true );
93+
canvas->setDestinationCrs( srs );
94+
canvas->setExtent( f1.geometry()->boundingBox() );
95+
QgsProject::instance()->writeEntry( "SpatialRefSys", "/ProjectCRSProj4String", srs.toProj4() );
96+
QgsProject::instance()->writeEntry( "SpatialRefSys", "/ProjectCRSID", ( int ) srs.srsid() );
97+
QgsProject::instance()->writeEntry( "SpatialRefSys", "/ProjectCrs", srs.authid() );
98+
QgsProject::instance()->writeEntry( "Measure", "/Ellipsoid", QString( "WGS84" ) );
99+
QgsProject::instance()->writeEntry( "Measurement", "/DistanceUnits", QgsUnitTypes::encodeUnit( QGis::Meters ) );
100+
101+
QgsPoint mapPoint = canvas->getCoordinateTransform()->transform( 2484588, 2425722 );
102+
103+
QScopedPointer< QgsMapToolIdentifyAction > action( new QgsMapToolIdentifyAction( canvas ) );
104+
QList<QgsMapToolIdentify::IdentifyResult> result = action->identify( mapPoint.x(), mapPoint.y(), QList<QgsMapLayer*>() << tempLayer.data() );
105+
QCOMPARE( result.length(), 1 );
106+
QString derivedLength = result.at( 0 ).mDerivedAttributes[tr( "Length" )];
107+
double length = derivedLength.remove( ',' ).split( ' ' ).at( 0 ).toDouble();
108+
QVERIFY( qgsDoubleNear( length, 26932.2, 0.1 ) );
109+
110+
//check that project units are respected
111+
QgsProject::instance()->writeEntry( "Measurement", "/DistanceUnits", QgsUnitTypes::encodeUnit( QGis::Feet ) );
112+
result = action->identify( mapPoint.x(), mapPoint.y(), QList<QgsMapLayer*>() << tempLayer.data() );
113+
QCOMPARE( result.length(), 1 );
114+
derivedLength = result.at( 0 ).mDerivedAttributes[tr( "Length" )];
115+
length = derivedLength.remove( ',' ).split( ' ' ).at( 0 ).toDouble();
116+
QVERIFY( qgsDoubleNear( length, 88360.1, 0.1 ) );
117+
118+
//test unchecked "keep base units" setting
119+
s.setValue( "/qgis/measure/keepbaseunit", false );
120+
result = action->identify( mapPoint.x(), mapPoint.y(), QList<QgsMapLayer*>() << tempLayer.data() );
121+
QCOMPARE( result.length(), 1 );
122+
derivedLength = result.at( 0 ).mDerivedAttributes[tr( "Length" )];
123+
length = derivedLength.remove( ',' ).split( ' ' ).at( 0 ).toDouble();
124+
QVERIFY( qgsDoubleNear( length, 16.735, 0.001 ) );
125+
}
126+
127+
void TestQgsMapToolIdentifyAction::perimeterCalculation()
128+
{
129+
QSettings s;
130+
s.setValue( "/qgis/measure/keepbaseunit", true );
131+
132+
//create a temporary layer
133+
QScopedPointer< QgsVectorLayer> tempLayer( new QgsVectorLayer( "Polygon?crs=epsg:3111&field=pk:int&field=col1:double", "vl", "memory" ) );
134+
QVERIFY( tempLayer->isValid() );
135+
QgsFeature f1( tempLayer->dataProvider()->fields(), 1 );
136+
f1.setAttribute( "pk", 1 );
137+
f1.setAttribute( "col1", 0.0 );
138+
QgsPolyline polygonRing3111;
139+
polygonRing3111 << QgsPoint( 2484588, 2425722 ) << QgsPoint( 2482767, 2398853 ) << QgsPoint( 2520109, 2397715 ) << QgsPoint( 2520792, 2425494 ) << QgsPoint( 2484588, 2425722 );
140+
QgsPolygon polygon3111;
141+
polygon3111 << polygonRing3111;
142+
f1.setGeometry( QgsGeometry::fromPolygon( polygon3111 ) );
143+
tempLayer->dataProvider()->addFeatures( QgsFeatureList() << f1 );
144+
145+
// set project CRS and ellipsoid
146+
QgsCoordinateReferenceSystem srs( 3111, QgsCoordinateReferenceSystem::EpsgCrsId );
147+
canvas->setCrsTransformEnabled( true );
148+
canvas->setDestinationCrs( srs );
149+
canvas->setExtent( f1.geometry()->boundingBox() );
150+
QgsProject::instance()->writeEntry( "SpatialRefSys", "/ProjectCRSProj4String", srs.toProj4() );
151+
QgsProject::instance()->writeEntry( "SpatialRefSys", "/ProjectCRSID", ( int ) srs.srsid() );
152+
QgsProject::instance()->writeEntry( "SpatialRefSys", "/ProjectCrs", srs.authid() );
153+
QgsProject::instance()->writeEntry( "Measure", "/Ellipsoid", QString( "WGS84" ) );
154+
QgsProject::instance()->writeEntry( "Measurement", "/DistanceUnits", QgsUnitTypes::encodeUnit( QGis::Meters ) );
155+
156+
QgsPoint mapPoint = canvas->getCoordinateTransform()->transform( 2484588, 2425722 );
157+
158+
QScopedPointer< QgsMapToolIdentifyAction > action( new QgsMapToolIdentifyAction( canvas ) );
159+
QList<QgsMapToolIdentify::IdentifyResult> result = action->identify( mapPoint.x(), mapPoint.y(), QList<QgsMapLayer*>() << tempLayer.data() );
160+
QCOMPARE( result.length(), 1 );
161+
QString derivedPerimeter = result.at( 0 ).mDerivedAttributes[tr( "Perimeter" )];
162+
double perimeter = derivedPerimeter.remove( ',' ).split( ' ' ).at( 0 ).toDouble();
163+
QCOMPARE( perimeter, 128289.074 );
164+
165+
//check that project units are respected
166+
QgsProject::instance()->writeEntry( "Measurement", "/DistanceUnits", QgsUnitTypes::encodeUnit( QGis::Feet ) );
167+
result = action->identify( mapPoint.x(), mapPoint.y(), QList<QgsMapLayer*>() << tempLayer.data() );
168+
QCOMPARE( result.length(), 1 );
169+
derivedPerimeter = result.at( 0 ).mDerivedAttributes[tr( "Perimeter" )];
170+
perimeter = derivedPerimeter.remove( ',' ).split( ' ' ).at( 0 ).toDouble();
171+
QVERIFY( qgsDoubleNear( perimeter, 420896.0, 0.1 ) );
172+
173+
//test unchecked "keep base units" setting
174+
s.setValue( "/qgis/measure/keepbaseunit", false );
175+
result = action->identify( mapPoint.x(), mapPoint.y(), QList<QgsMapLayer*>() << tempLayer.data() );
176+
QCOMPARE( result.length(), 1 );
177+
derivedPerimeter = result.at( 0 ).mDerivedAttributes[tr( "Perimeter" )];
178+
perimeter = derivedPerimeter.remove( ',' ).split( ' ' ).at( 0 ).toDouble();
179+
QVERIFY( qgsDoubleNear( perimeter, 79.715, 0.001 ) );
180+
}
181+
182+
183+
QTEST_MAIN( TestQgsMapToolIdentifyAction )
184+
#include "testqgsmaptoolidentifyaction.moc"
185+
186+
187+
188+

‎tests/src/core/testqgsproject.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include <qgsapplication.h>
1919
#include <qgsproject.h>
20+
#include "qgsunittypes.h"
2021

2122

2223
class TestQgsProject : public QObject
@@ -29,6 +30,7 @@ class TestQgsProject : public QObject
2930
void cleanup();// will be called after every testfunction.
3031

3132
void testReadPath();
33+
void testProjectUnits();
3234
};
3335

3436
void TestQgsProject::init()
@@ -43,6 +45,11 @@ void TestQgsProject::cleanup()
4345
void TestQgsProject::initTestCase()
4446
{
4547
// Runs once before any tests are run
48+
49+
// Set up the QSettings environment
50+
QCoreApplication::setOrganizationName( "QGIS" );
51+
QCoreApplication::setOrganizationDomain( "qgis.org" );
52+
QCoreApplication::setApplicationName( "QGIS-TEST" );
4653
}
4754

4855

@@ -76,6 +83,28 @@ void TestQgsProject::testReadPath()
7683

7784
}
7885

86+
void TestQgsProject::testProjectUnits()
87+
{
88+
//test setting and retrieving project units
89+
90+
//first set a default QGIS distance unit
91+
QSettings s;
92+
s.setValue( "/qgis/measure/displayunits", QgsUnitTypes::encodeUnit( QGis::Feet ) );
93+
94+
QgsProject* prj = QgsProject::instance();
95+
// new project should inherit QGIS default distance unit
96+
prj->clear();
97+
QCOMPARE( prj->distanceUnits(), QGis::Feet );
98+
99+
//changing default QGIS unit should not affect existing project
100+
s.setValue( "/qgis/measure/displayunits", QgsUnitTypes::encodeUnit( QGis::NauticalMiles ) );
101+
QCOMPARE( prj->distanceUnits(), QGis::Feet );
102+
103+
//test setting new units for project
104+
prj->writeEntry( "Measurement", "/DistanceUnits", QgsUnitTypes::encodeUnit( QGis::NauticalMiles ) );
105+
QCOMPARE( prj->distanceUnits(), QGis::NauticalMiles );
106+
}
107+
79108

80109
QTEST_MAIN( TestQgsProject )
81110
#include "testqgsproject.moc"

0 commit comments

Comments
 (0)
Please sign in to comment.