Skip to content

Commit e6167d2

Browse files
committedJan 3, 2012
fix #4523:
- make geometry validation optional: none, QGIS and GEOS - move internal validation to QgsGeometryValidator thread - cache wkt in QgsCoordinateReferenceSystem - fTools: leave progress of geometry validatation at 100% - move coordinate capture to vector menu
1 parent cc9864e commit e6167d2

22 files changed

+700
-425
lines changed
 

‎python/plugins/fTools/tools/doValidate.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ def run( self ):
211211
self.running = True
212212
output = self.check_geometry( self.vlayer )
213213
self.emit( SIGNAL( "runFinished(PyQt_PyObject)" ), output )
214-
self.emit( SIGNAL( "runStatus(PyQt_PyObject)" ), 0 )
214+
self.emit( SIGNAL( "runStatus(PyQt_PyObject)" ), 100 )
215215

216216
def stop(self):
217217
self.running = False

‎src/app/main.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
#include <QFile>
2222
#include <QFileInfo>
2323
#include <QFont>
24-
#include <QMessageBox>
2524
#include <QPixmap>
2625
#include <QLocale>
2726
#include <QSettings>
@@ -35,6 +34,7 @@
3534

3635
#include "qgscustomization.h"
3736
#include "qgspluginregistry.h"
37+
#include "qgsmessagelog.h"
3838

3939
#include <cstdio>
4040
#include <stdio.h>
@@ -164,11 +164,20 @@ void myMessageOutput( QtMsgType type, const char *msg )
164164
case QtWarningMsg:
165165
fprintf( stderr, "Warning: %s\n", msg );
166166

167+
#ifdef QGISDEBUG
168+
if ( 0 == strncmp( msg, "Object::", 8 )
169+
|| 0 == strncmp( msg, "QWidget::", 9 )
170+
|| 0 == strncmp( msg, "QPainter::", 10 ) )
171+
{
172+
QgsMessageLog::logMessage( msg, "Qt" );
173+
}
174+
#endif
175+
167176
// TODO: Verify this code in action.
168177
if ( 0 == strncmp( msg, "libpng error:", 13 ) )
169178
{
170179
// Let the user know
171-
QMessageBox::warning( 0, "libpng Error", msg );
180+
QgsMessageLog::logMessage( msg, "libpng" );
172181
}
173182

174183
break;

‎src/app/qgsmaptoolcapture.cpp

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "qgsmaprenderer.h"
2424
#include "qgsvectorlayer.h"
2525
#include "qgslogger.h"
26+
#include "qgsgeometryvalidator.h"
2627

2728
#include <QCursor>
2829
#include <QPixmap>
@@ -35,6 +36,7 @@ QgsMapToolCapture::QgsMapToolCapture( QgsMapCanvas* canvas, enum CaptureMode too
3536
: QgsMapToolEdit( canvas )
3637
, mCaptureMode( tool )
3738
, mRubberBand( 0 )
39+
, mValidator( 0 )
3840
{
3941
mCaptureModeFromLayer = tool == CaptureNone;
4042
mCapturing = false;
@@ -52,6 +54,12 @@ QgsMapToolCapture::~QgsMapToolCapture()
5254
delete mSnappingMarkers.takeFirst();
5355

5456
stopCapturing();
57+
58+
if( mValidator )
59+
{
60+
mValidator->deleteLater();
61+
mValidator = 0;
62+
}
5563
}
5664

5765
void QgsMapToolCapture::deactivate()
@@ -271,12 +279,25 @@ void QgsMapToolCapture::closePolygon()
271279

272280
void QgsMapToolCapture::validateGeometry()
273281
{
282+
QSettings settings;
283+
if ( settings.value( "/qgis/digitizing/validate_geometries", 1 ).toInt() == 0 )
284+
return;
285+
286+
if( mValidator )
287+
{
288+
mValidator->deleteLater();
289+
mValidator = 0;
290+
}
291+
292+
mTip = "";
274293
mGeomErrors.clear();
275294
while ( !mGeomErrorMarkers.isEmpty() )
276295
{
277296
delete mGeomErrorMarkers.takeFirst();
278297
}
279298

299+
QgsGeometry *g;
300+
280301
switch ( mCaptureMode )
281302
{
282303
case CaptureNone:
@@ -285,38 +306,59 @@ void QgsMapToolCapture::validateGeometry()
285306
case CaptureLine:
286307
if ( mCaptureList.size() < 2 )
287308
return;
288-
QgsGeometry::validatePolyline( mGeomErrors, 0, mCaptureList.toVector() );
309+
g = QgsGeometry::fromPolyline( mCaptureList.toVector() );
289310
break;
290311
case CapturePolygon:
291312
if ( mCaptureList.size() < 3 )
292313
return;
293-
QgsGeometry::validatePolyline( mGeomErrors, 0, mCaptureList.toVector() << mCaptureList[0], true );
314+
g = QgsGeometry::fromPolygon( QgsPolygon() << ( QgsPolyline () << mCaptureList.toVector() << mCaptureList[0] ) );
294315
break;
295316
}
296317

318+
if ( !g )
319+
return;
320+
321+
mValidator = new QgsGeometryValidator( g );
322+
connect( mValidator, SIGNAL( errorFound( QgsGeometry::Error ) ), this, SLOT( addError( QgsGeometry::Error ) ) );
323+
connect( mValidator, SIGNAL( finished() ), this, SLOT( validationFinished() ) );
324+
mValidator->start();
325+
326+
QStatusBar *sb = QgisApp::instance()->statusBar();
327+
sb->showMessage( tr( "Validation started." ) );
328+
}
329+
330+
void QgsMapToolCapture::addError( QgsGeometry::Error e )
331+
{
332+
mGeomErrors << e;
297333
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() );
298334
if ( !vlayer )
299335
return;
300336

301-
QString tip;
302-
for ( int i = 0; i < mGeomErrors.size(); i++ )
303-
{
304-
tip += mGeomErrors[i].what() + "\n";
305-
if ( !mGeomErrors[i].hasWhere() )
306-
continue;
337+
if ( !mTip.isEmpty() )
338+
mTip += "\n";
339+
340+
mTip += e.what();
307341

342+
if ( e.hasWhere() )
343+
{
308344
QgsVertexMarker *vm = new QgsVertexMarker( mCanvas );
309-
vm->setCenter( mCanvas->mapRenderer()->layerToMapCoordinates( vlayer, mGeomErrors[i].where() ) );
345+
vm->setCenter( mCanvas->mapRenderer()->layerToMapCoordinates( vlayer, e.where() ) );
310346
vm->setIconType( QgsVertexMarker::ICON_X );
311347
vm->setPenWidth( 2 );
312-
vm->setToolTip( mGeomErrors[i].what() );
348+
vm->setToolTip( e.what() );
313349
vm->setColor( Qt::green );
314350
vm->setZValue( vm->zValue() + 1 );
315351
mGeomErrorMarkers << vm;
316352
}
317353

318354
QStatusBar *sb = QgisApp::instance()->statusBar();
319-
sb->showMessage( QObject::tr( "%n geometry error(s) found.", "number of geometry errors", mGeomErrors.size() ) );
320-
if ( !tip.isEmpty() )
321-
sb->setToolTip( tip );
355+
sb->showMessage( e.what() );
356+
if ( !mTip.isEmpty() )
357+
sb->setToolTip( mTip );
358+
}
359+
360+
void QgsMapToolCapture::validationFinished()
361+
{
362+
QStatusBar *sb = QgisApp::instance()->statusBar();
363+
sb->showMessage( tr( "Validation finished." ) );
322364
}

‎src/app/qgsmaptoolcapture.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@
2222
#include "qgsgeometry.h"
2323
#include "qgslegend.h"
2424

25-
class QgsGeometry;
25+
#include <QPoint>
26+
#include <QList>
27+
2628
class QgsRubberBand;
2729
class QgsVertexMarker;
2830
class QgsMapLayer;
29-
30-
#include <QPoint>
31-
#include <QList>
31+
class QgsGeometryValidator;
3232

3333
class QgsMapToolCapture : public QgsMapToolEdit
3434
{
@@ -69,6 +69,8 @@ class QgsMapToolCapture : public QgsMapToolEdit
6969

7070
public slots:
7171
void currentLayerChanged( QgsMapLayer *layer );
72+
void addError( QgsGeometry::Error );
73+
void validationFinished();
7274

7375
protected:
7476
int nextPoint( const QPoint &p, QgsPoint &layerPoint, QgsPoint &mapPoint );
@@ -105,6 +107,8 @@ class QgsMapToolCapture : public QgsMapToolEdit
105107
QList<QgsPoint> mCaptureList;
106108

107109
void validateGeometry();
110+
QString mTip;
111+
QgsGeometryValidator *mValidator;
108112
QList< QgsGeometry::Error > mGeomErrors;
109113
QList< QgsVertexMarker * > mGeomErrorMarkers;
110114

‎src/app/qgsmaptoolnodetool.cpp

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@
2121
#include "qgsvectordataprovider.h"
2222
#include "qgstolerance.h"
2323
#include "qgsgeometry.h"
24-
#include <cmath>
25-
#include <QMouseEvent>
26-
#include <QMessageBox>
2724
#include "qgslogger.h"
2825
#include "qgisapp.h"
2926
#include "qgslegend.h"
3027

28+
#include <cmath>
29+
#include <QMouseEvent>
30+
#include <QMessageBox>
3131
#include <QStatusBar>
3232

3333

@@ -458,7 +458,7 @@ bool QgsMapToolNodeTool::checkCorrectnessOfFeature( QgsVectorLayer *vlayer )
458458
qDebug( "feature doesn't exist any more" );
459459
QMessageBox::warning( NULL,
460460
tr( "Node tool" ),
461-
tr( "Feature was deleted on background.\n" ),
461+
tr( "Feature was deleted on background." ),
462462
QMessageBox::Ok ,
463463
QMessageBox::Ok );
464464
delete mSelectionFeature;
@@ -890,6 +890,7 @@ SelectionFeature::SelectionFeature()
890890
mFeature = new QgsFeature();
891891
mFeatureId = 0;
892892
mFeatureSelected = false;
893+
mValidator = 0;
893894
}
894895

895896
SelectionFeature::~SelectionFeature()
@@ -900,6 +901,12 @@ SelectionFeature::~SelectionFeature()
900901
{
901902
delete mGeomErrorMarkers.takeFirst();
902903
}
904+
905+
if( mValidator )
906+
{
907+
mValidator->deleteLater();
908+
mValidator = 0;
909+
}
903910
}
904911

905912
void SelectionFeature::updateFeature()
@@ -954,43 +961,63 @@ void SelectionFeature::setSelectedFeature( QgsFeatureId featureId,
954961

955962
void SelectionFeature::validateGeometry( QgsGeometry *g )
956963
{
957-
if ( g == NULL )
958-
g = mFeature->geometry();
959-
960-
if ( g->isGeosValid() )
961-
{
962-
QgsDebugMsg( "geometry is valid - not validating." );
964+
QSettings settings;
965+
if ( settings.value( "/qgis/digitizing/validate_geometries", 1 ).toInt() == 0 )
963966
return;
964-
}
967+
968+
if ( !g )
969+
g = mFeature->geometry();
965970

966971
QgsDebugMsg( "validating geometry" );
967972

968-
g->validateGeometry( mGeomErrors );
973+
mTip.clear();
969974

975+
mGeomErrors.clear();
970976
while ( !mGeomErrorMarkers.isEmpty() )
971977
{
972978
delete mGeomErrorMarkers.takeFirst();
973979
}
974980

975-
QString tip;
976-
977-
for ( int i = 0; i < mGeomErrors.size(); i++ )
981+
if( mValidator )
978982
{
979-
tip += mGeomErrors[i].what() + "\n";
980-
if ( !mGeomErrors[i].hasWhere() )
981-
continue;
983+
mValidator->deleteLater();
984+
mValidator = 0;
985+
}
986+
987+
mValidator = new QgsGeometryValidator( g );
988+
connect( mValidator, SIGNAL( errorFound( QgsGeometry::Error ) ), this, SLOT( addError( QgsGeometry::Error ) ) );
989+
connect( mValidator, SIGNAL( finished() ), this, SLOT( validationFinished() ) );
990+
mValidator->start();
991+
992+
QStatusBar *sb = QgisApp::instance()->statusBar();
993+
sb->showMessage( tr( "Validation started." ) );
994+
}
995+
996+
void SelectionFeature::addError( QgsGeometry::Error e )
997+
{
998+
mGeomErrors << e;
999+
if ( !mTip.isEmpty() )
1000+
mTip += "\n";
1001+
mTip += e.what();
9821002

983-
QgsVertexMarker *vm = createVertexMarker( mGeomErrors[i].where(), QgsVertexMarker::ICON_X );
984-
vm->setToolTip( mGeomErrors[i].what() );
1003+
if ( e.hasWhere() )
1004+
{
1005+
QgsVertexMarker *vm = createVertexMarker( e.where(), QgsVertexMarker::ICON_X );
1006+
vm->setToolTip( e.what() );
9851007
vm->setColor( Qt::green );
9861008
vm->setZValue( vm->zValue() + 1 );
9871009
mGeomErrorMarkers << vm;
9881010
}
9891011

9901012
QStatusBar *sb = QgisApp::instance()->statusBar();
991-
sb->showMessage( QObject::tr( "%n geometry error(s) found.", "number of geometry errors", mGeomErrors.size() ) );
992-
if ( !tip.isEmpty() )
993-
sb->setToolTip( tip );
1013+
sb->showMessage( e.what() );
1014+
sb->setToolTip( mTip );
1015+
}
1016+
1017+
void SelectionFeature::validationFinished()
1018+
{
1019+
QStatusBar *sb = QgisApp::instance()->statusBar();
1020+
sb->showMessage( tr( "Validation finished." ) );
9941021
}
9951022

9961023
void SelectionFeature::deleteSelectedVertexes()
@@ -1043,7 +1070,7 @@ void SelectionFeature::deleteSelectedVertexes()
10431070
{
10441071
QMessageBox::warning( NULL,
10451072
tr( "Node tool" ),
1046-
tr( "Result geometry is invalid. Reverting last changes.\n" ),
1073+
tr( "Result geometry is invalid. Reverting last changes." ),
10471074
QMessageBox::Ok ,
10481075
QMessageBox::Ok );
10491076
}
@@ -1061,7 +1088,6 @@ void SelectionFeature::deleteSelectedVertexes()
10611088
updateFromFeature();
10621089
}
10631090

1064-
10651091
void SelectionFeature::moveSelectedVertexes( double changeX, double changeY )
10661092
{
10671093
mVlayer->beginEditCommand( QObject::tr( "Moved vertices" ) );
@@ -1117,7 +1143,7 @@ void SelectionFeature::moveSelectedVertexes( double changeX, double changeY )
11171143
{
11181144
QMessageBox::warning( NULL,
11191145
tr( "Node tool" ),
1120-
tr( "Result geometry is invalid. Reverting last changes.\n" ),
1146+
tr( "Result geometry is invalid. Reverting last changes." ),
11211147
QMessageBox::Ok ,
11221148
QMessageBox::Ok );
11231149
//redo last operations

‎src/app/qgsmaptoolnodetool.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#include "qgsmaptoolvertexedit.h"
2020
#include "qgsfeature.h"
2121
#include "qgsvertexmarker.h"
22+
#include "qgsgeometryvalidator.h"
23+
2224
#include <QRect>
2325
#include <QRubberBand>
2426

@@ -169,6 +171,9 @@ class SelectionFeature: public QObject
169171
*/
170172
QgsVectorLayer* vlayer();
171173

174+
public slots:
175+
void addError( QgsGeometry::Error );
176+
void validationFinished();
172177

173178
private:
174179
/**
@@ -214,6 +219,8 @@ class SelectionFeature: public QObject
214219
QList<VertexEntry> mVertexMap;
215220
QgsMapCanvas* mCanvas;
216221

222+
QgsGeometryValidator *mValidator;
223+
QString mTip;
217224
QList< QgsGeometry::Error > mGeomErrors;
218225
QList< QgsVertexMarker * > mGeomErrorMarkers;
219226
};

‎src/app/qgsoptions.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444

4545
#define CPL_SUPRESS_CPLUSPLUS
4646
#include <gdal.h>
47+
#include <geos_c.h>
48+
4749
/**
4850
* \class QgsOptions - Set user options and preferences
4951
* Constructor
@@ -392,6 +394,14 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WFlags fl ) :
392394
mMarkerStyleComboBox->addItem( tr( "Cross" ) );
393395
mMarkerStyleComboBox->addItem( tr( "None" ) );
394396

397+
mValidateGeometries->clear();
398+
mValidateGeometries->addItem( tr( "Off" ) );
399+
mValidateGeometries->addItem( tr( "QGIS" ) );
400+
#if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \
401+
( (GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR>=3) || GEOS_VERSION_MAJOR>3)
402+
mValidateGeometries->addItem( tr( "GEOS" ) );
403+
#endif
404+
395405
QString markerStyle = settings.value( "/qgis/digitizing/marker_style", "Cross" ).toString();
396406
if ( markerStyle == "SemiTransparentCircle" )
397407
{
@@ -409,6 +419,7 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WFlags fl ) :
409419

410420
chkReuseLastValues->setChecked( settings.value( "/qgis/digitizing/reuseLastValues", false ).toBool() );
411421
chkDisableAttributeValuesDlg->setChecked( settings.value( "/qgis/digitizing/disable_enter_attribute_values_dialog", false ).toBool() );
422+
mValidateGeometries->setCurrentIndex( settings.value( "/qgis/digitizing/validate_geometries", 1 ).toInt() );
412423

413424
#ifdef Q_WS_MAC //MH: disable incremental update on Mac for now to avoid problems with resizing
414425
groupBox_5->setEnabled( false );
@@ -757,6 +768,7 @@ void QgsOptions::saveOptions()
757768

758769
settings.setValue( "/qgis/digitizing/reuseLastValues", chkReuseLastValues->isChecked() );
759770
settings.setValue( "/qgis/digitizing/disable_enter_attribute_values_dialog", chkDisableAttributeValuesDlg->isChecked() );
771+
settings.setValue( "/qgis/digitizing/validate_geometries", mValidateGeometries->currentIndex() );
760772

761773
//
762774
// Locale settings

‎src/core/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ SET(QGIS_CORE_SRCS
6262
qgsfeature.cpp
6363
qgsfield.cpp
6464
qgsgeometry.cpp
65+
qgsgeometryvalidator.cpp
6566
qgshttptransaction.cpp
6667
qgslabel.cpp
6768
qgslabelattributes.cpp
@@ -249,6 +250,7 @@ SET(QGIS_CORE_MOC_HDRS
249250
qgsrasterdataprovider.h
250251
qgsnetworkaccessmanager.h
251252
qgsvectordataprovider.h
253+
qgsgeometryvalidator.h
252254

253255
composer/qgsaddremoveitemcommand.h
254256
composer/qgscomposerlegend.h

‎src/core/qgsapplication.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "qgsmaplayerregistry.h"
1919
#include "qgsproviderregistry.h"
2020
#include "qgsexception.h"
21+
#include "qgsgeometry.h"
2122

2223
#include <QDir>
2324
#include <QFileOpenEvent>
@@ -72,6 +73,8 @@ QgsApplication::QgsApplication( int & argc, char ** argv, bool GUIenabled, QStri
7273
}
7374
void QgsApplication::init( QString customConfigPath )
7475
{
76+
qRegisterMetaType<QgsGeometry::Error>( "QgsGeometry::Error" );
77+
7578
// check if QGIS is run from build directory (not the install directory)
7679
QDir appDir( applicationDirPath() );
7780
if ( appDir.exists( "source_path.txt" ) )

‎src/core/qgscoordinatereferencesystem.cpp

Lines changed: 14 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ QgsCoordinateReferenceSystem& QgsCoordinateReferenceSystem::operator=( const Qgs
171171
mAuthId = srs.mAuthId;
172172
mIsValidFlag = srs.mIsValidFlag;
173173
mValidationHint = srs.mValidationHint;
174+
mWkt = srs.mWkt;
174175
if ( mIsValidFlag )
175176
{
176177
OSRDestroySpatialReference( mCRS );
@@ -217,6 +218,7 @@ bool QgsCoordinateReferenceSystem::loadFromDb( QString db, QString expression, Q
217218
{
218219
QgsDebugMsgLevel( "load CRS from " + db + " where " + expression + " is " + value, 3 );
219220
mIsValidFlag = false;
221+
mWkt.clear();
220222

221223
QFileInfo myInfo( db );
222224
if ( !myInfo.exists() )
@@ -292,6 +294,7 @@ bool QgsCoordinateReferenceSystem::loadFromDb( QString db, QString expression, Q
292294
bool QgsCoordinateReferenceSystem::createFromWkt( QString theWkt )
293295
{
294296
mIsValidFlag = false;
297+
mWkt.clear();
295298

296299
if ( theWkt.isEmpty() )
297300
{
@@ -369,6 +372,7 @@ bool QgsCoordinateReferenceSystem::createFromProj4( const QString theProj4String
369372
//
370373
QgsDebugMsg( "proj4: " + theProj4String );
371374
mIsValidFlag = false;
375+
mWkt.clear();
372376

373377
QRegExp myProjRegExp( "\\+proj=(\\S+)" );
374378
int myStart = myProjRegExp.indexIn( theProj4String );
@@ -565,7 +569,6 @@ bool QgsCoordinateReferenceSystem::createFromProj4( const QString theProj4String
565569
}
566570
}
567571

568-
569572
return mIsValidFlag;
570573
}
571574

@@ -785,6 +788,7 @@ void QgsCoordinateReferenceSystem::setProj4String( QString theProj4String )
785788
OSRDestroySpatialReference( mCRS );
786789
mCRS = OSRNewSpatialReference( NULL );
787790
mIsValidFlag = OSRImportFromProj4( mCRS, theProj4String.toLatin1().constData() ) == OGRERR_NONE;
791+
mWkt.clear();
788792
setMapUnits();
789793

790794
#if defined(QGISDEBUG) && QGISDEBUG>=3
@@ -977,33 +981,7 @@ long QgsCoordinateReferenceSystem::findMatchingProj()
977981

978982
bool QgsCoordinateReferenceSystem::operator==( const QgsCoordinateReferenceSystem &theSrs )
979983
{
980-
if ( !mIsValidFlag || !theSrs.mIsValidFlag )
981-
{
982-
return false;
983-
}
984-
char *thisStr;
985-
char *otherStr;
986-
987-
// OSRIsSame is not relaibel when it comes to comparing +towgs84 parameters
988-
// Use string compare on WKT instead.
989-
if (( OSRExportToWkt( mCRS, &thisStr ) == OGRERR_NONE ) )
990-
{
991-
if ( OSRExportToWkt( theSrs.mCRS, &otherStr ) == OGRERR_NONE )
992-
{
993-
QgsDebugMsgLevel( QString( "Comparing " ) + thisStr, 3 );
994-
QgsDebugMsgLevel( QString( " with " ) + otherStr, 3 );
995-
if ( !strcmp( thisStr, otherStr ) )
996-
{
997-
QgsDebugMsgLevel( QString( "MATCHED!" ) + otherStr, 3 );
998-
CPLFree( thisStr );
999-
CPLFree( otherStr );
1000-
return true;
1001-
}
1002-
CPLFree( otherStr );
1003-
}
1004-
CPLFree( thisStr );
1005-
}
1006-
return false;
984+
return mIsValidFlag && theSrs.mIsValidFlag && toWkt() == theSrs.toWkt();
1007985
}
1008986

1009987
bool QgsCoordinateReferenceSystem::operator!=( const QgsCoordinateReferenceSystem &theSrs )
@@ -1020,15 +998,16 @@ bool QgsCoordinateReferenceSystem::equals( QString theProj4String )
1020998

1021999
QString QgsCoordinateReferenceSystem::toWkt() const
10221000
{
1023-
QString myWkt;
1024-
char* Wkt;
1025-
if ( OSRExportToWkt( mCRS, &Wkt ) == OGRERR_NONE )
1001+
if ( mWkt.isEmpty() )
10261002
{
1027-
myWkt = Wkt;
1028-
OGRFree( Wkt );
1003+
char *wkt;
1004+
if ( OSRExportToWkt( mCRS, &wkt ) == OGRERR_NONE )
1005+
{
1006+
mWkt = wkt;
1007+
OGRFree( wkt );
1008+
}
10291009
}
1030-
1031-
return myWkt;
1010+
return mWkt;
10321011
}
10331012

10341013
bool QgsCoordinateReferenceSystem::readXML( QDomNode & theNode )

‎src/core/qgscoordinatereferencesystem.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,7 @@ class CORE_EXPORT QgsCoordinateReferenceSystem
432432
bool loadFromDb( QString db, QString expression, QString value );
433433

434434
QString mValidationHint;
435+
mutable QString mWkt;
435436

436437
static CUSTOM_CRS_VALIDATION mCustomSrsValidation;
437438
};

‎src/core/qgsgeometry.cpp

Lines changed: 14 additions & 297 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ email : morb at ozemail dot com dot au
2828
#include "qgsmaplayerregistry.h"
2929
#include "qgsvectorlayer.h"
3030
#include "qgsproject.h"
31+
#include "qgsmessagelog.h"
32+
#include "qgsgeometryvalidator.h"
3133

3234
#define DEFAULT_QUADRANT_SEGMENTS 8
3335

@@ -181,19 +183,19 @@ static GEOSGeometry *cloneGeosGeom( const GEOSGeometry *geom )
181183
#endif
182184

183185
QgsGeometry::QgsGeometry()
184-
: mGeometry( 0 ),
185-
mGeometrySize( 0 ),
186-
mGeos( 0 ),
187-
mDirtyWkb( false ),
188-
mDirtyGeos( false )
186+
: mGeometry( 0 )
187+
, mGeometrySize( 0 )
188+
, mGeos( 0 )
189+
, mDirtyWkb( false )
190+
, mDirtyGeos( false )
189191
{
190192
}
191193

192194
QgsGeometry::QgsGeometry( QgsGeometry const & rhs )
193-
: mGeometry( 0 ),
194-
mGeometrySize( rhs.mGeometrySize ),
195-
mDirtyWkb( rhs.mDirtyWkb ),
196-
mDirtyGeos( rhs.mDirtyGeos )
195+
: mGeometry( 0 )
196+
, mGeometrySize( rhs.mGeometrySize )
197+
, mDirtyWkb( rhs.mDirtyWkb )
198+
, mDirtyGeos( rhs.mDirtyGeos )
197199
{
198200
if ( mGeometrySize && rhs.mGeometry )
199201
{
@@ -6399,296 +6401,11 @@ int QgsGeometry::avoidIntersections()
63996401
return returnValue;
64006402
}
64016403

6402-
//
6403-
// distance of point q from line through p in direction v
6404-
// return >0 => q lies left of the line
6405-
// <0 => q lies right of the line
6406-
//
6407-
static double distLine2Point( QgsPoint p, QgsVector v, QgsPoint q )
6408-
{
6409-
if ( v.length() == 0 )
6410-
{
6411-
throw QgsException( QObject::tr( "invalid line" ) );
6412-
}
6413-
6414-
return ( v.x()*( q.y() - p.y() ) - v.y()*( q.x() - p.x() ) ) / v.length();
6415-
}
6416-
6417-
static bool intersectLines( QgsPoint p, QgsVector v, QgsPoint q, QgsVector w, QgsPoint &s )
6418-
{
6419-
double d = v.y() * w.x() - v.x() * w.y();
6420-
6421-
if ( d == 0 )
6422-
return false;
6423-
6424-
double dx = q.x() - p.x();
6425-
double dy = q.y() - p.y();
6426-
double k = ( dy * w.x() - dx * w.y() ) / d;
6427-
6428-
s = p + v * k;
6429-
6430-
return true;
6431-
}
6432-
6433-
bool pointInRing( const QgsPolyline &ring, const QgsPoint &p )
6434-
{
6435-
bool inside = false;
6436-
int j = ring.size() - 1;
6437-
6438-
for ( int i = 0; i < ring.size(); i++ )
6439-
{
6440-
if ( ring[i].x() == p.x() && ring[i].y() == p.y() )
6441-
return true;
6442-
6443-
if (( ring[i].y() < p.y() && ring[j].y() >= p.y() ) ||
6444-
( ring[j].y() < p.y() && ring[i].y() >= p.y() ) )
6445-
{
6446-
if ( ring[i].x() + ( p.y() - ring[i].y() ) / ( ring[j].y() - ring[i].y() )*( ring[j].x() - ring[i].x() ) <= p.x() )
6447-
inside = !inside;
6448-
}
6449-
6450-
j = i;
6451-
}
6452-
6453-
return inside;
6454-
}
6455-
6456-
static bool ringInRing( const QgsPolyline &inside, const QgsPolyline &outside )
6457-
{
6458-
for ( int i = 0; i < inside.size(); i++ )
6459-
{
6460-
if ( !pointInRing( outside, inside[i] ) )
6461-
return false;
6462-
}
6463-
6464-
return true;
6465-
}
6466-
6467-
void QgsGeometry::checkRingIntersections( QList<Error> &errors,
6468-
int p0, int i0, const QgsPolyline &ring0,
6469-
int p1, int i1, const QgsPolyline &ring1 )
6470-
{
6471-
for ( int i = 0; i < ring0.size() - 1; i++ )
6472-
{
6473-
QgsVector v = ring0[i+1] - ring0[i];
6474-
6475-
for ( int j = 0; j < ring1.size() - 1; j++ )
6476-
{
6477-
QgsVector w = ring1[j+1] - ring1[j];
6478-
6479-
QgsPoint s;
6480-
if ( intersectLines( ring0[i], v, ring1[j], w, s ) )
6481-
{
6482-
double d = -distLine2Point( ring0[i], v.perpVector(), s );
6483-
6484-
if ( d >= 0 && d <= v.length() )
6485-
{
6486-
d = -distLine2Point( ring1[j], w.perpVector(), s );
6487-
if ( d >= 0 && d <= w.length() )
6488-
{
6489-
QString msg = QObject::tr( "segment %1 of ring %2 of polygon %3 intersects segment %4 of ring %5 of polygon %6 at %7" )
6490-
.arg( i0 ).arg( i ).arg( p0 )
6491-
.arg( i1 ).arg( j ).arg( p1 )
6492-
.arg( s.toString() );
6493-
QgsDebugMsg( msg );
6494-
errors << Error( msg, s );
6495-
if ( errors.size() > 100 )
6496-
{
6497-
QString msg = QObject::tr( "stopping validation after more than 100 errors" );
6498-
QgsDebugMsg( msg );
6499-
errors << Error( msg );
6500-
return;
6501-
}
6502-
}
6503-
}
6504-
}
6505-
}
6506-
}
6507-
}
6508-
6509-
void QgsGeometry::validatePolyline( QList<Error> &errors, int i, QgsPolyline line, bool ring )
6510-
{
6511-
if ( ring )
6512-
{
6513-
if ( line.size() < 3 )
6514-
{
6515-
QString msg = QObject::tr( "ring %1 with less than three points" ).arg( i );
6516-
QgsDebugMsg( msg );
6517-
errors << Error( msg );
6518-
return;
6519-
}
6520-
6521-
if ( line[0] != line[ line.size()-1 ] )
6522-
{
6523-
QString msg = QObject::tr( "ring %1 not closed" ).arg( i );
6524-
QgsDebugMsg( msg );
6525-
errors << Error( msg );
6526-
return;
6527-
}
6528-
}
6529-
else if ( line.size() < 2 )
6530-
{
6531-
QString msg = QObject::tr( "line %1 with less than two points" ).arg( i );
6532-
QgsDebugMsg( msg );
6533-
errors << Error( msg );
6534-
return;
6535-
}
6536-
6537-
int j = 0;
6538-
while ( j < line.size() - 1 )
6539-
{
6540-
int n = 0;
6541-
while ( j < line.size() - 1 && line[j] == line[j+1] )
6542-
{
6543-
line.remove( j );
6544-
n++;
6545-
}
6546-
6547-
if ( n > 0 )
6548-
{
6549-
QString msg = QObject::tr( "line %1 contains %n duplicate node(s) at %2", "number of duplicate nodes", n ).arg( i ).arg( j );
6550-
QgsDebugMsg( msg );
6551-
errors << Error( msg, line[j] );
6552-
}
6553-
6554-
j++;
6555-
}
6556-
6557-
for ( j = 0; j < line.size() - 3; j++ )
6558-
{
6559-
QgsVector v = line[j+1] - line[j];
6560-
double vl = v.length();
6561-
6562-
int n = ( j == 0 && ring ) ? line.size() - 2 : line.size() - 1;
6563-
6564-
for ( int k = j + 2; k < n; k++ )
6565-
{
6566-
QgsVector w = line[k+1] - line[k];
6567-
6568-
QgsPoint s;
6569-
if ( !intersectLines( line[j], v, line[k], w, s ) )
6570-
continue;
6571-
6572-
double d = -distLine2Point( line[j], v.perpVector(), s );
6573-
if ( d < 0 || d > vl )
6574-
continue;
6575-
6576-
d = -distLine2Point( line[k], w.perpVector(), s );
6577-
if ( d < 0 || d > w.length() )
6578-
continue;
6579-
6580-
QString msg = QObject::tr( "segments %1 and %2 of line %3 intersect at %4" ).arg( j ).arg( k ).arg( i ).arg( s.toString() );
6581-
QgsDebugMsg( msg );
6582-
errors << Error( msg, s );
6583-
if ( errors.size() > 100 )
6584-
{
6585-
QString msg = QObject::tr( "stopping validation after more than 100 errors" );
6586-
QgsDebugMsg( msg );
6587-
errors << Error( msg );
6588-
return;
6589-
}
6590-
}
6591-
}
6592-
}
6593-
6594-
void QgsGeometry::validatePolygon( QList<Error> &errors, int idx, const QgsPolygon &polygon )
6595-
{
6596-
// check if holes are inside polygon
6597-
for ( int i = 1; i < polygon.size(); i++ )
6598-
{
6599-
if ( !ringInRing( polygon[i], polygon[0] ) )
6600-
{
6601-
QString msg = QObject::tr( "ring %1 of polygon %2 not in exterior ring" ).arg( i ).arg( idx );
6602-
QgsDebugMsg( msg );
6603-
errors << Error( msg );
6604-
}
6605-
}
6606-
6607-
// check holes for intersections
6608-
for ( int i = 1; i < polygon.size(); i++ )
6609-
{
6610-
for ( int j = i + 1; j < polygon.size(); j++ )
6611-
{
6612-
checkRingIntersections( errors, idx, i, polygon[i], idx, j, polygon[j] );
6613-
}
6614-
}
6615-
6616-
// check if rings are self-intersecting
6617-
for ( int i = 0; i < polygon.size(); i++ )
6618-
{
6619-
validatePolyline( errors, i, polygon[i], true );
6620-
}
6621-
}
6622-
66236404
void QgsGeometry::validateGeometry( QList<Error> &errors )
66246405
{
6625-
errors.clear();
6626-
6627-
switch ( wkbType() )
6628-
{
6629-
case QGis::WKBPoint:
6630-
case QGis::WKBPoint25D:
6631-
case QGis::WKBMultiPoint:
6632-
case QGis::WKBMultiPoint25D:
6633-
break;
6634-
6635-
case QGis::WKBLineString:
6636-
case QGis::WKBLineString25D:
6637-
validatePolyline( errors, 0, asPolyline() );
6638-
break;
6639-
6640-
case QGis::WKBMultiLineString:
6641-
case QGis::WKBMultiLineString25D:
6642-
{
6643-
QgsMultiPolyline mp = asMultiPolyline();
6644-
for ( int i = 0; i < mp.size(); i++ )
6645-
validatePolyline( errors, i, mp[i] );
6646-
}
6647-
break;
6648-
6649-
case QGis::WKBPolygon:
6650-
case QGis::WKBPolygon25D:
6651-
{
6652-
validatePolygon( errors, 0, asPolygon() );
6653-
}
6654-
break;
6655-
6656-
case QGis::WKBMultiPolygon:
6657-
case QGis::WKBMultiPolygon25D:
6658-
{
6659-
QgsMultiPolygon mp = asMultiPolygon();
6660-
for ( int i = 0; i < mp.size(); i++ )
6661-
{
6662-
validatePolygon( errors, i, mp[i] );
6663-
}
6664-
6665-
for ( int i = 0; i < mp.size(); i++ )
6666-
{
6667-
for ( int j = i + 1; j < mp.size(); j++ )
6668-
{
6669-
if ( ringInRing( mp[i][0], mp[j][0] ) )
6670-
{
6671-
errors << Error( QObject::tr( "polygon %1 inside polygon %2" ).arg( i ).arg( j ) );
6672-
}
6673-
else if ( ringInRing( mp[j][0], mp[i][0] ) )
6674-
{
6675-
errors << Error( QObject::tr( "polygon %1 inside polygon %2" ).arg( j ).arg( i ) );
6676-
}
6677-
else
6678-
{
6679-
checkRingIntersections( errors, i, 0, mp[i][0], j, 0, mp[j][0] );
6680-
}
6681-
}
6682-
}
6683-
}
6684-
break;
6685-
6686-
case QGis::WKBNoGeometry:
6687-
case QGis::WKBUnknown:
6688-
QgsDebugMsg( QObject::tr( "Unknown geometry type" ) );
6689-
errors << Error( QObject::tr( "Unknown geometry type" ) );
6690-
break;
6691-
}
6406+
QgsGeometryValidator *gv = new QgsGeometryValidator( this, &errors );
6407+
gv->start();
6408+
delete gv;
66926409
}
66936410

66946411
bool QgsGeometry::isGeosValid()

‎src/core/qgsgeometry.h

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -415,13 +415,13 @@ class CORE_EXPORT QgsGeometry
415415
*/
416416
int avoidIntersections();
417417

418-
419418
class Error
420419
{
421420
QString message;
422421
QgsPoint location;
423422
bool hasLocation;
424423
public:
424+
Error() : message( "none" ), hasLocation( false ) {}
425425
Error( QString m ) : message( m ), hasLocation( false ) {}
426426
Error( QString m, QgsPoint p ) : message( m ), location( p ), hasLocation( true ) {}
427427

@@ -435,9 +435,6 @@ class CORE_EXPORT QgsGeometry
435435
**/
436436
void validateGeometry( QList<Error> &errors );
437437

438-
static void validatePolyline( QList<Error> &errors, int i, QgsPolyline polyline, bool ring = false );
439-
static void validatePolygon( QList<Error> &errors, int i, const QgsPolygon &polygon );
440-
441438
private:
442439
// Private variables
443440

@@ -566,10 +563,6 @@ class CORE_EXPORT QgsGeometry
566563
/** return polygon from wkb */
567564
QgsPolygon asPolygon( unsigned char*& ptr, bool hasZValue );
568565

569-
static void checkRingIntersections( QList<Error> &errors,
570-
int p0, int i0, const QgsPolyline &ring0,
571-
int p1, int i1, const QgsPolyline &ring1 );
572-
573566
static bool geosRelOp( char( *op )( const GEOSGeometry*, const GEOSGeometry * ),
574567
QgsGeometry *a, QgsGeometry *b );
575568

‎src/core/qgsgeometryvalidator.cpp

Lines changed: 400 additions & 0 deletions
Large diffs are not rendered by default.

‎src/core/qgsgeometryvalidator.h

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/***************************************************************************
2+
qgsgeometryvalidator.h - geometry validation thread
3+
-------------------------------------------------------------------
4+
Date : 03.01.2012
5+
Copyright : (C) 2012 by Juergen E. Fischer
6+
email : jef at norbit dot de
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+
#ifndef QGSGEOMETRYVALIDATOR_H
17+
#define QGSGEOMETRYVALIDATOR_H
18+
19+
#include <QThread>
20+
#include "qgsgeometry.h"
21+
22+
class QgsGeometryValidator : public QThread
23+
{
24+
Q_OBJECT;
25+
26+
public:
27+
//! Constructor
28+
QgsGeometryValidator( QgsGeometry *g, QList<QgsGeometry::Error> *errors = 0 );
29+
~QgsGeometryValidator();
30+
31+
void run();
32+
void stop();
33+
34+
/** Validate geometry and produce a list of geometry errors
35+
* @note added in 1.9
36+
**/
37+
static void validateGeometry( QgsGeometry *g, QList<QgsGeometry::Error> &errors );
38+
39+
signals:
40+
void errorFound( QgsGeometry::Error );
41+
42+
public slots:
43+
void addError( QgsGeometry::Error );
44+
45+
private:
46+
void validatePolyline( int i, QgsPolyline polyline, bool ring = false );
47+
void validatePolygon( int i, const QgsPolygon &polygon );
48+
void checkRingIntersections( int p0, int i0, const QgsPolyline &ring0, int p1, int i1, const QgsPolyline &ring1 );
49+
double distLine2Point( QgsPoint p, QgsVector v, QgsPoint q );
50+
bool intersectLines( QgsPoint p, QgsVector v, QgsPoint q, QgsVector w, QgsPoint &s );
51+
bool ringInRing( const QgsPolyline &inside, const QgsPolyline &outside );
52+
bool pointInRing( const QgsPolyline &ring, const QgsPoint &p );
53+
54+
QgsGeometry mG;
55+
QList<QgsGeometry::Error> *mErrors;
56+
bool mStop;
57+
int mErrorCount;
58+
}; // class QgsGeometryValidator
59+
60+
#endif

‎src/core/qgsmaprenderer.cpp

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ QgsMapRenderer::QgsMapRenderer()
4444
{
4545
mScaleCalculator = new QgsScaleCalculator;
4646
mDistArea = new QgsDistanceArea;
47+
mCachedTrForLayer = 0;
48+
mCachedTr = 0;
4749

4850
mDrawing = false;
4951
mOverview = false;
@@ -67,6 +69,7 @@ QgsMapRenderer::~QgsMapRenderer()
6769
delete mDistArea;
6870
delete mDestCRS;
6971
delete mLabelingEngine;
72+
delete mCachedTr;
7073
}
7174

7275

@@ -702,8 +705,6 @@ bool QgsMapRenderer::splitLayersExtent( QgsMapLayer* layer, QgsRectangle& extent
702705
{
703706
try
704707
{
705-
QgsCoordinateTransform tr( layer->crs(), *mDestCRS );
706-
707708
#ifdef QGISDEBUG
708709
// QgsLogger::debug<QgsRectangle>("Getting extent of canvas in layers CS. Canvas is ", extent, __FILE__, __FUNCTION__, __LINE__);
709710
#endif
@@ -714,17 +715,17 @@ bool QgsMapRenderer::splitLayersExtent( QgsMapLayer* layer, QgsRectangle& extent
714715
// extent separately.
715716
static const double splitCoord = 180.0;
716717

717-
if ( tr.sourceCrs().geographicFlag() )
718+
if ( mCachedTr->sourceCrs().geographicFlag() )
718719
{
719720
// Note: ll = lower left point
720721
// and ur = upper right point
721-
QgsPoint ll = tr.transform( extent.xMinimum(), extent.yMinimum(),
722-
QgsCoordinateTransform::ReverseTransform );
722+
QgsPoint ll = tr( layer )->transform( extent.xMinimum(), extent.yMinimum(),
723+
QgsCoordinateTransform::ReverseTransform );
723724

724-
QgsPoint ur = tr.transform( extent.xMaximum(), extent.yMaximum(),
725-
QgsCoordinateTransform::ReverseTransform );
725+
QgsPoint ur = tr( layer )->transform( extent.xMaximum(), extent.yMaximum(),
726+
QgsCoordinateTransform::ReverseTransform );
726727

727-
extent = tr.transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
728+
extent = tr( layer )->transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
728729

729730
if ( ll.x() > ur.x() )
730731
{
@@ -736,7 +737,7 @@ bool QgsMapRenderer::splitLayersExtent( QgsMapLayer* layer, QgsRectangle& extent
736737
}
737738
else // can't cross 180
738739
{
739-
extent = tr.transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
740+
extent = tr( layer )->transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
740741
}
741742
}
742743
catch ( QgsCsException &cse )
@@ -757,8 +758,7 @@ QgsRectangle QgsMapRenderer::layerExtentToOutputExtent( QgsMapLayer* theLayer, Q
757758
{
758759
try
759760
{
760-
QgsCoordinateTransform tr( theLayer->crs(), *mDestCRS );
761-
extent = tr.transformBoundingBox( extent );
761+
extent = tr( theLayer )->transformBoundingBox( extent );
762762
}
763763
catch ( QgsCsException &cse )
764764
{
@@ -780,8 +780,7 @@ QgsPoint QgsMapRenderer::layerToMapCoordinates( QgsMapLayer* theLayer, QgsPoint
780780
{
781781
try
782782
{
783-
QgsCoordinateTransform tr( theLayer->crs(), *mDestCRS );
784-
point = tr.transform( point, QgsCoordinateTransform::ForwardTransform );
783+
point = tr( theLayer )->transform( point, QgsCoordinateTransform::ForwardTransform );
785784
}
786785
catch ( QgsCsException &cse )
787786
{
@@ -802,8 +801,7 @@ QgsPoint QgsMapRenderer::mapToLayerCoordinates( QgsMapLayer* theLayer, QgsPoint
802801
{
803802
try
804803
{
805-
QgsCoordinateTransform tr( theLayer->crs(), *mDestCRS );
806-
point = tr.transform( point, QgsCoordinateTransform::ReverseTransform );
804+
point = tr( theLayer )->transform( point, QgsCoordinateTransform::ReverseTransform );
807805
}
808806
catch ( QgsCsException &cse )
809807
{
@@ -824,8 +822,7 @@ QgsRectangle QgsMapRenderer::mapToLayerCoordinates( QgsMapLayer* theLayer, QgsRe
824822
{
825823
try
826824
{
827-
QgsCoordinateTransform tr( theLayer->crs(), *mDestCRS );
828-
rect = tr.transform( rect, QgsCoordinateTransform::ReverseTransform );
825+
rect = tr( theLayer )->transform( rect, QgsCoordinateTransform::ReverseTransform );
829826
}
830827
catch ( QgsCsException &cse )
831828
{
@@ -1103,4 +1100,16 @@ void QgsMapRenderer::setLabelingEngine( QgsLabelingEngineInterface* iface )
11031100
mLabelingEngine = iface;
11041101
}
11051102

1103+
QgsCoordinateTransform *QgsMapRenderer::tr( QgsMapLayer *layer )
1104+
{
1105+
if ( mCachedTrForLayer != layer )
1106+
{
1107+
delete mCachedTr;
1108+
mCachedTr = new QgsCoordinateTransform( layer->crs(), *mDestCRS );
1109+
mCachedTrForLayer = layer;
1110+
}
1111+
1112+
return mCachedTr;
1113+
}
1114+
11061115
bool QgsMapRenderer::mDrawing = false;

‎src/core/qgsmaprenderer.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,8 +268,6 @@ class CORE_EXPORT QgsMapRenderer : public QObject
268268
@note this method was added in version 1.1*/
269269
QgsOverlayObjectPositionManager* overlayManagerFromSettings();
270270

271-
protected:
272-
273271
//! indicates drawing in progress
274272
static bool mDrawing;
275273

@@ -323,6 +321,11 @@ class CORE_EXPORT QgsMapRenderer : public QObject
323321

324322
//! Locks rendering loop for concurrent draws
325323
QMutex mRenderMutex;
324+
325+
private:
326+
QgsCoordinateTransform *tr( QgsMapLayer *layer );
327+
QgsCoordinateTransform *mCachedTr;
328+
QgsMapLayer *mCachedTrForLayer;
326329
};
327330

328331
#endif

‎src/core/qgspoint.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,6 @@ QString QgsPoint::toDegreesMinutesSeconds( int thePrecision ) const
159159
return rep;
160160
}
161161

162-
163162
QString QgsPoint::wellKnownText() const
164163
{
165164
return QString( "POINT(%1 %2)" ).arg( QString::number( m_x, 'f', 18 ) ).arg( QString::number( m_y, 'f', 18 ) );

‎src/plugins/coordinate_capture/coordinatecapture.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050

5151
static const QString sName = QObject::tr( "Coordinate Capture" );
5252
static const QString sDescription = QObject::tr( "Capture mouse coordinates in different CRS" );
53-
static const QString sCategory = QObject::tr( "Plugins" );
53+
static const QString sCategory = QObject::tr( "Vector" );
5454
static const QString sPluginVersion = QObject::tr( "Version 0.1" );
5555
static const QString sPluginIcon = ":/coordinate_capture/coordinate_capture.png";
5656
static const QgisPlugin::PLUGINTYPE sPluginType = QgisPlugin::UI;
@@ -66,9 +66,9 @@ static const QgisPlugin::PLUGINTYPE sPluginType = QgisPlugin::UI;
6666
* an interface object that provides access to exposed functions in QGIS.
6767
* @param theQGisInterface - Pointer to the QGIS interface object
6868
*/
69-
CoordinateCapture::CoordinateCapture( QgisInterface * theQgisInterface ):
70-
QgisPlugin( sName, sDescription, sCategory, sPluginVersion, sPluginType ),
71-
mQGisIface( theQgisInterface )
69+
CoordinateCapture::CoordinateCapture( QgisInterface * theQgisInterface )
70+
: QgisPlugin( sName, sDescription, sCategory, sPluginVersion, sPluginType )
71+
, mQGisIface( theQgisInterface )
7272
{
7373
}
7474

@@ -98,7 +98,7 @@ void CoordinateCapture::initGui()
9898
mQActionPointer->setWhatsThis( tr( "Click on the map to view coordinates and capture to clipboard." ) );
9999
// Connect the action to the run
100100
connect( mQActionPointer, SIGNAL( triggered() ), this, SLOT( run() ) );
101-
mQGisIface->addPluginToMenu( tr( "&Coordinate Capture" ), mQActionPointer );
101+
mQGisIface->addPluginToVectorMenu( tr( "&Coordinate Capture" ), mQActionPointer );
102102

103103
// create our map tool
104104
mpMapTool = new CoordinateCaptureMapTool( mQGisIface->mapCanvas() );

‎src/plugins/gps_importer/qgsgpsplugin.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ QgsGPSPlugin::~QgsGPSPlugin()
8686
void QgsGPSPlugin::initGui()
8787
{
8888
// add an action to the toolbar
89-
mQActionPointer = new QAction( QIcon(), tr( "&Gps Tools" ), this );
89+
mQActionPointer = new QAction( QIcon(), tr( "&GPS Tools" ), this );
9090
mCreateGPXAction = new QAction( QIcon(), tr( "&Create new GPX layer" ), this );
9191
setCurrentTheme( "" );
9292

@@ -97,7 +97,7 @@ void QgsGPSPlugin::initGui()
9797

9898
mQGisInterface->layerToolBar()->addAction( mCreateGPXAction );
9999
mQGisInterface->insertAddLayerAction( mCreateGPXAction );
100-
mQGisInterface->addPluginToVectorMenu( tr( "&Gps" ), mQActionPointer );
100+
mQGisInterface->addPluginToVectorMenu( tr( "&GPS" ), mQActionPointer );
101101
mQGisInterface->addVectorToolBarIcon( mQActionPointer );
102102

103103
// this is called when the icon theme is changed
@@ -206,7 +206,7 @@ void QgsGPSPlugin::unload()
206206
// remove the GUI
207207
mQGisInterface->layerToolBar()->removeAction( mCreateGPXAction );
208208
mQGisInterface->removeAddLayerAction( mCreateGPXAction );
209-
mQGisInterface->removePluginVectorMenu( tr( "&Gps" ), mQActionPointer );
209+
mQGisInterface->removePluginVectorMenu( tr( "&GPS" ), mQActionPointer );
210210
mQGisInterface->removeVectorToolBarIcon( mQActionPointer );
211211
delete mQActionPointer;
212212
}

‎src/plugins/gps_importer/qgsgpsplugingui.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ void QgsGPSPluginGui::on_buttonBox_rejected()
236236

237237
void QgsGPSPluginGui::on_pbnGPXSelectFile_clicked()
238238
{
239-
QgsLogger::debug( " Gps File Importer::pbnGPXSelectFile_clicked() " );
239+
QgsLogger::debug( " GPS File Importer::pbnGPXSelectFile_clicked() " );
240240
QString myFileTypeQString;
241241
QString myFilterString = tr( "GPS eXchange format (*.gpx)" );
242242
QSettings settings;

‎src/ui/qgsoptionsbase.ui

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1436,33 +1436,43 @@
14361436
<item row="3" column="0">
14371437
<widget class="QGroupBox" name="mEnterAttributeValuesGroupBox">
14381438
<property name="title">
1439-
<string>Enter attribute values</string>
1439+
<string>Other settings</string>
14401440
</property>
1441-
<layout class="QHBoxLayout">
1442-
<item>
1443-
<widget class="QCheckBox" name="chkReuseLastValues">
1441+
<layout class="QGridLayout" name="gridLayout_26">
1442+
<item row="0" column="0" colspan="2">
1443+
<widget class="QCheckBox" name="chkDisableAttributeValuesDlg">
14441444
<property name="text">
1445-
<string>Reuse last entered attribute values</string>
1445+
<string>Suppress attributes pop-up windows after each created feature</string>
14461446
</property>
14471447
<property name="tristate">
14481448
<bool>false</bool>
14491449
</property>
14501450
</widget>
14511451
</item>
1452-
<item>
1453-
<widget class="QCheckBox" name="chkDisableAttributeValuesDlg">
1452+
<item row="1" column="0" colspan="2">
1453+
<widget class="QCheckBox" name="chkReuseLastValues">
14541454
<property name="text">
1455-
<string>Suppress attributes pop-up windows after each created feature</string>
1455+
<string>Reuse last entered attribute values</string>
14561456
</property>
14571457
<property name="tristate">
14581458
<bool>false</bool>
14591459
</property>
14601460
</widget>
14611461
</item>
1462+
<item row="2" column="1">
1463+
<widget class="QComboBox" name="mValidateGeometries"/>
1464+
</item>
1465+
<item row="2" column="0">
1466+
<widget class="QLabel" name="label_19">
1467+
<property name="text">
1468+
<string>Validate geometries</string>
1469+
</property>
1470+
</widget>
1471+
</item>
14621472
</layout>
14631473
</widget>
14641474
</item>
1465-
<item row="4" column="0">
1475+
<item row="5" column="0">
14661476
<spacer>
14671477
<property name="orientation">
14681478
<enum>Qt::Vertical</enum>
@@ -2067,7 +2077,6 @@
20672077
<tabstop>mMarkerStyleComboBox</tabstop>
20682078
<tabstop>mMarkerSizeSpinBox</tabstop>
20692079
<tabstop>chkReuseLastValues</tabstop>
2070-
<tabstop>chkDisableAttributeValuesDlg</tabstop>
20712080
<tabstop>scrollArea_6</tabstop>
20722081
<tabstop>pbnSelectOtfProjection</tabstop>
20732082
<tabstop>leProjectGlobalCrs</tabstop>

0 commit comments

Comments
 (0)
Please sign in to comment.