Skip to content

Commit dfb0602

Browse files
author
gsherman
committedJan 25, 2011
Patch for delimited text, ticket #3414. Submitted by ccrook.
git-svn-id: http://svn.osgeo.org/qgis/trunk@15074 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent d80c90d commit dfb0602

10 files changed

+291
-76
lines changed
 

‎python/core/qgscoordinatereferencesystem.sip

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,12 @@ class QgsCoordinateReferenceSystem
2323

2424
~QgsCoordinateReferenceSystem();
2525

26-
/*!
27-
* Constructs a CRS object from a Wkt string
28-
* @param theWkt A String containing a valid Wkt def
26+
/*!
27+
* Constructs a CRS object from a string definition as defined in the createFromString
28+
* member function (by default a WKT definition).
29+
* @param theDefinition A String containing a coordinate reference system definition.
2930
*/
30-
explicit QgsCoordinateReferenceSystem(QString theWkt);
31+
explicit QgsCoordinateReferenceSystem( QString theDefinition );
3132

3233
/*! Use this constructor when you want to create a CRS object using
3334
* a postgis SRID, an Epsg Id id or a QGIS CRS_ID.
@@ -38,7 +39,7 @@ class QgsCoordinateReferenceSystem
3839

3940
// Misc helper functions -----------------------
4041

41-
void createFromId(const long theId, CrsType theType=PostgisCrsId);
42+
bool createFromId(const long theId, CrsType theType=PostgisCrsId);
4243

4344
/**
4445
* \brief Set up this CRS from the given OGC CRS
@@ -70,6 +71,15 @@ class QgsCoordinateReferenceSystem
7071
* @return bool TRUE if sucess else false
7172
*/
7273
bool createFromWkt(const QString theWkt);
74+
75+
/*! Set up this srs from a string definition, by default a WKT definition. Otherwise
76+
* the string defines a authority, followed by a colon, followed by the definition.
77+
* The authority can be one of "epsg", "postgis", "internal" for integer definitions,
78+
* and "wkt" or "proj4" for string definitions. The implementation of each authority
79+
* uses the corresponding createFrom... function.
80+
* @param theDefinition A String containing a coordinate reference system definition.
81+
*/
82+
bool createFromString( const QString theDefinition );
7383

7484
/*! Set up this srs by fetching the appropriate information from the
7585
* sqlite backend. First the system level read only srs.db will be checked

‎src/core/qgscoordinatereferencesystem.cpp

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,13 @@ QgsCoordinateReferenceSystem::QgsCoordinateReferenceSystem()
5151
mCRS = OSRNewSpatialReference( NULL );
5252
}
5353

54-
QgsCoordinateReferenceSystem::QgsCoordinateReferenceSystem( QString theWkt )
54+
QgsCoordinateReferenceSystem::QgsCoordinateReferenceSystem( QString theDefinition )
5555
: mMapUnits( QGis::UnknownUnit )
5656
, mIsValidFlag( 0 )
5757
, mValidationHint( "" )
5858
{
5959
mCRS = OSRNewSpatialReference( NULL );
60-
createFromWkt( theWkt );
60+
createFromString( theDefinition );
6161
}
6262

6363

@@ -75,23 +75,56 @@ QgsCoordinateReferenceSystem::~QgsCoordinateReferenceSystem()
7575
OSRDestroySpatialReference( mCRS );
7676
}
7777

78-
void QgsCoordinateReferenceSystem::createFromId( const long theId, CrsType theType )
78+
bool QgsCoordinateReferenceSystem::createFromId( const long theId, CrsType theType )
7979
{
80+
bool result = false;
8081
switch ( theType )
8182
{
8283
case InternalCrsId:
83-
createFromSrsId( theId );
84+
result = createFromSrsId( theId );
8485
break;
8586
case PostgisCrsId:
86-
createFromSrid( theId );
87+
result = createFromSrid( theId );
8788
break;
8889
case EpsgCrsId:
89-
createFromEpsg( theId );
90+
result = createFromEpsg( theId );
9091
break;
9192
default:
9293
//THIS IS BAD...THIS PART OF CODE SHOULD NEVER BE REACHED...
9394
QgsDebugMsg( "Unexpected case reached!" );
9495
};
96+
return result;
97+
}
98+
99+
bool QgsCoordinateReferenceSystem::createFromString( const QString theDefinition )
100+
{
101+
bool result = false;
102+
QRegExp reCrsId("^(epsg|postgis|internal)\\:(\\d+)$",Qt::CaseInsensitive);
103+
if( reCrsId.indexIn(theDefinition) == 0)
104+
{
105+
QString authName = reCrsId.cap(1).toLower();
106+
CrsType type = InternalCrsId;
107+
if( authName == "epsg" ) type = EpsgCrsId;
108+
if( authName == "postgis" ) type = PostgisCrsId;
109+
long id = reCrsId.cap(2).toLong();
110+
result = createFromId(id,type);
111+
}
112+
else
113+
{
114+
QRegExp reCrsStr("^(?:(wkt|proj4)\\:)?(.+)$",Qt::CaseInsensitive);
115+
if( reCrsStr.indexIn(theDefinition) == 0 )
116+
{
117+
if( reCrsStr.cap(1).toLower() == "proj4" )
118+
{
119+
result = createFromProj4(reCrsStr.cap(2));
120+
}
121+
else
122+
{
123+
result = createFromWkt(reCrsStr.cap(2));
124+
}
125+
}
126+
}
127+
return result;
95128
}
96129

97130
bool QgsCoordinateReferenceSystem::createFromOgcWmsCrs( QString theCrs )

‎src/core/qgscoordinatereferencesystem.h

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,11 @@ class CORE_EXPORT QgsCoordinateReferenceSystem
5757
~QgsCoordinateReferenceSystem();
5858

5959
/*!
60-
* Constructs a CRS object from a Wkt string
61-
* @param theWkt A String containing a valid Wkt def
60+
* Constructs a CRS object from a string definition as defined in the createFromString
61+
* member function (by default a WKT definition).
62+
* @param theDefinition A String containing a coordinate reference system definition.
6263
*/
63-
explicit QgsCoordinateReferenceSystem( QString theWkt );
64+
explicit QgsCoordinateReferenceSystem( QString theDefinition );
6465

6566
/*! Use this constructor when you want to create a CRS object using
6667
* a postgis SRID, an EpsgCrsId id or a QGIS CRS_ID.
@@ -79,7 +80,7 @@ class CORE_EXPORT QgsCoordinateReferenceSystem
7980

8081
// Misc helper functions -----------------------
8182

82-
void createFromId( const long theId, CrsType theType = PostgisCrsId );
83+
bool createFromId( const long theId, CrsType theType = PostgisCrsId );
8384

8485
/**
8586
* \brief Set up this CRS from the given OGC CRS
@@ -161,6 +162,15 @@ class CORE_EXPORT QgsCoordinateReferenceSystem
161162
* @return bool TRUE if sucess else false
162163
*/
163164
bool createFromProj4( const QString theProjString );
165+
166+
/*! Set up this srs from a string definition, by default a WKT definition. Otherwise
167+
* the string defines a authority, followed by a colon, followed by the definition.
168+
* The authority can be one of "epsg", "postgis", "internal" for integer definitions,
169+
* and "wkt" or "proj4" for string definitions. The implementation of each authority
170+
* uses the corresponding createFrom... function.
171+
* @param theDefinition A String containing a coordinate reference system definition.
172+
*/
173+
bool createFromString( const QString theDefinition );
164174

165175
/*! Find out whether this CRS is correctly initialised and usable */
166176
bool isValid() const;

‎src/plugins/delimited_text/qgsdelimitedtextplugingui.cpp

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <QRegExp>
2626
#include <QMessageBox>
2727
#include <QTextStream>
28+
#include <QUrl>
2829
#include "qgslogger.h"
2930

3031
QgsDelimitedTextPluginGui::QgsDelimitedTextPluginGui( QgisInterface * _qI, QWidget * parent, Qt::WFlags fl )
@@ -56,6 +57,13 @@ QgsDelimitedTextPluginGui::QgsDelimitedTextPluginGui( QgisInterface * _qI, QWidg
5657
delimiterRegexp->setChecked( true );
5758
}
5859

60+
QString delimiterChars = settings.value( key + "/delimiterChars", " " ).toString();
61+
cbxDelimSpace->setChecked( delimiterChars.contains(" "));
62+
cbxDelimTab->setChecked( delimiterChars.contains("\\t"));
63+
cbxDelimColon->setChecked( delimiterChars.contains(":"));
64+
cbxDelimSemicolon->setChecked( delimiterChars.contains(":"));
65+
cbxDelimComma->setChecked( delimiterChars.contains(","));
66+
5967
cmbXField->setDisabled( true );
6068
cmbYField->setDisabled( true );
6169
cmbWktField->setDisabled( true );
@@ -99,34 +107,33 @@ void QgsDelimitedTextPluginGui::on_buttonBox_accepted()
99107
else if ( delimiterRegexp->isChecked() )
100108
delimiterType = "regexp";
101109

102-
QString uri = QString( "%1?delimiter=%2&delimiterType=%3" )
103-
.arg( txtFilePath->text() )
104-
.arg( txtDelimiter->text() )
105-
.arg( delimiterType );
110+
QUrl url(txtFilePath->text());
111+
url.addQueryItem("delimiter",txtDelimiter->text());
112+
url.addQueryItem("delimiterType",delimiterType);
106113

107114
if ( geomTypeXY->isChecked() )
108115
{
109116
if ( !cmbXField->currentText().isEmpty() && !cmbYField->currentText().isEmpty() )
110117
{
111-
uri += QString( "&xField=%1&yField=%2" )
112-
.arg( cmbXField->currentText() )
113-
.arg( cmbYField->currentText() );
118+
url.addQueryItem("xField",cmbXField->currentText());
119+
url.addQueryItem("yField",cmbYField->currentText());
114120
}
115121
}
116122
else
117123
{
118124
if ( ! cmbWktField->currentText().isEmpty() )
119125
{
120-
uri += QString( "&wktField=%1" )
121-
.arg( cmbWktField->currentText() );
126+
url.addQueryItem("wktField",cmbWktField->currentText());
122127
}
123128
}
124129

125130
int skipLines = rowCounter->value();
126131
if ( skipLines > 0 )
127-
uri += QString( "&skipLines=%1" ).arg( skipLines );
132+
url.addQueryItem("skipLines",QString( "%1" ).arg( skipLines ));
128133

129134
// add the layer to the map
135+
136+
QString uri(url.toEncoded());
130137
emit drawVectorLayer( uri, txtLayerName->text(), "delimitedtext" );
131138
// store the settings
132139

@@ -138,10 +145,11 @@ void QgsDelimitedTextPluginGui::on_buttonBox_accepted()
138145

139146
if ( delimiterSelection->isChecked() )
140147
settings.setValue( key + "/delimiterType", "selection" );
141-
if ( delimiterPlain->isChecked() )
148+
else if ( delimiterPlain->isChecked() )
142149
settings.setValue( key + "/delimiterType", "plain" );
143150
else
144151
settings.setValue( key + "/delimiterType", "regexp" );
152+
settings.setValue( key + "/delimiterChars", selectedChars());
145153

146154
accept();
147155
}
@@ -156,6 +164,17 @@ void QgsDelimitedTextPluginGui::on_buttonBox_rejected()
156164
reject();
157165
}
158166

167+
QString QgsDelimitedTextPluginGui::selectedChars()
168+
{
169+
QString chars = "";
170+
if ( cbxDelimSpace->isChecked() ) chars += " ";
171+
if ( cbxDelimTab->isChecked() ) chars += "\\t";
172+
if ( cbxDelimSemicolon->isChecked() ) chars += ";";
173+
if ( cbxDelimComma->isChecked() ) chars += ",";
174+
if ( cbxDelimColon->isChecked() ) chars += ":";
175+
return chars;
176+
}
177+
159178
QStringList QgsDelimitedTextPluginGui::splitLine( QString line )
160179
{
161180
QStringList fieldList;
@@ -171,11 +190,7 @@ QStringList QgsDelimitedTextPluginGui::splitLine( QString line )
171190
else if ( delimiterSelection->isChecked() )
172191
{
173192
delimiter = "[";
174-
if ( cbxDelimSpace->isChecked() ) delimiter += " ";
175-
if ( cbxDelimTab->isChecked() ) delimiter += "\t";
176-
if ( cbxDelimSemicolon->isChecked() ) delimiter += ";";
177-
if ( cbxDelimComma->isChecked() ) delimiter += ",";
178-
if ( cbxDelimColon->isChecked() ) delimiter += ":";
193+
delimiter += selectedChars();
179194
delimiter += "]";
180195
txtDelimiter->setText( delimiter );
181196
fieldList = line.split( QRegExp( delimiter ) );

‎src/plugins/delimited_text/qgsdelimitedtextplugingui.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class QgsDelimitedTextPluginGui : public QDialog, private Ui::QgsDelimitedTextPl
3737
bool haveValidFileAndDelimiters();
3838
void updateFieldLists();
3939
void getOpenFileName();
40+
QString selectedChars();
4041

4142
QgisInterface * qI;
4243
QAbstractButton *pbnOK;

‎src/plugins/delimited_text/qgsdelimitedtextpluginguibase.ui

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@
331331
<string>Name of the field containing x values. Choose a field from the list. The list is generated by parsing the header row of the delimited text file.</string>
332332
</property>
333333
<property name="editable">
334-
<bool>true</bool>
334+
<bool>false</bool>
335335
</property>
336336
</widget>
337337
</item>
@@ -366,7 +366,7 @@
366366
<string>Name of the field containing y values. Choose a field from the list. The list is generated by parsing the header row of the delimited text file.</string>
367367
</property>
368368
<property name="editable">
369-
<bool>true</bool>
369+
<bool>false</bool>
370370
</property>
371371
</widget>
372372
</item>
@@ -409,7 +409,7 @@
409409
<string>Name of the field containing y values. Choose a field from the list. The list is generated by parsing the header row of the delimited text file.</string>
410410
</property>
411411
<property name="editable">
412-
<bool>true</bool>
412+
<bool>false</bool>
413413
</property>
414414
</widget>
415415
</item>

‎src/providers/delimitedtext/qgsdelimitedtextprovider.cpp

Lines changed: 26 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
#include "qgsdelimitedtextprovider.h"
2020

21-
2221
#include <QtGlobal>
2322
#include <QFile>
2423
#include <QDataStream>
@@ -135,48 +134,41 @@ QgsDelimitedTextProvider::QgsDelimitedTextProvider( QString uri )
135134
: QgsVectorDataProvider( uri )
136135
, mHasWktField( false )
137136
, mFieldCount( 0 )
138-
, mXFieldIndex( -1 ), mYFieldIndex( -1 )
137+
, mXFieldIndex( -1 )
138+
, mYFieldIndex( -1 )
139139
, mWktFieldIndex( -1 )
140+
, mDelimiterType( "plain" )
141+
, mDelimiter( "," )
142+
, mDelimiterRegexp()
140143
, mWktHasZM( false )
141144
, mWktZMRegexp( "\\s+(?:z|m|zm)(?=\\s*\\()", Qt::CaseInsensitive )
142145
, mWktCrdRegexp( "(\\-?\\d+(?:\\.\\d*)?\\s+\\-?\\d+(?:\\.\\d*)?)\\s[\\s\\d\\.\\-]+" )
146+
, mSkipLines(0)
143147
, mFirstDataLine( 0 )
144148
, mShowInvalidLines( true )
145149
, mWkbType( QGis::WKBNoGeometry )
150+
, mCrs()
146151
{
147-
// Get the file name and mDelimiter out of the uri
148-
mFileName = uri.left( uri.indexOf( "?" ) );
149-
// split the string up on & to get the individual parameters
150-
QStringList parameters = uri.mid( uri.indexOf( "?" ) ).split( "&", QString::SkipEmptyParts );
151-
152-
QgsDebugMsg( "Parameter count after split on &" + QString::number( parameters.size() ) );
153-
154-
// get the individual parameters and assign values
155-
QStringList temp = parameters.filter( "delimiter=" );
156-
mDelimiter = temp.size() ? temp[0].mid( temp[0].indexOf( "=" ) + 1 ) : "";
157-
temp = parameters.filter( "delimiterType=" );
158-
mDelimiterType = temp.size() ? temp[0].mid( temp[0].indexOf( "=" ) + 1 ) : "";
159-
temp = parameters.filter( "wktField=" );
160-
QString wktField = temp.size() ? temp[0].mid( temp[0].indexOf( "=" ) + 1 ) : "";
161-
temp = parameters.filter( "xField=" );
162-
QString xField = temp.size() ? temp[0].mid( temp[0].indexOf( "=" ) + 1 ) : "";
163-
temp = parameters.filter( "yField=" );
164-
QString yField = temp.size() ? temp[0].mid( temp[0].indexOf( "=" ) + 1 ) : "";
165-
temp = parameters.filter( "skipLines=" );
166-
QString skipLines = temp.size() ? temp[0].mid( temp[0].indexOf( "=" ) + 1 ) : "0";
167-
// Decode the parts of the uri. Good if someone entered '=' as a delimiter, for instance.
168-
mFileName = QUrl::fromPercentEncoding( mFileName.toUtf8() );
169-
mDelimiter = QUrl::fromPercentEncoding( mDelimiter.toUtf8() );
170-
mDelimiterType = QUrl::fromPercentEncoding( mDelimiterType.toUtf8() );
171-
wktField = QUrl::fromPercentEncoding( wktField.toUtf8() );
172-
xField = QUrl::fromPercentEncoding( xField.toUtf8() );
173-
yField = QUrl::fromPercentEncoding( yField.toUtf8() );
174152

175-
mHasWktField = wktField != "";
153+
QUrl url = QUrl::fromEncoded(uri.toUtf8());
154+
155+
// Extract the provider definition from the url
176156

177-
skipLines = QUrl::fromPercentEncoding( skipLines.toUtf8() );
157+
mFileName = url.path();
178158

179-
mSkipLines = skipLines.toInt();
159+
QString wktField("");
160+
QString xField("");
161+
QString yField("");
162+
163+
if( url.hasQueryItem("delimiter")) mDelimiter = url.queryItemValue("delimiter");
164+
if( url.hasQueryItem("delimiterType")) mDelimiterType = url.queryItemValue("delimiterType");
165+
if( url.hasQueryItem("wktField")) wktField = url.queryItemValue("wktField");
166+
if( url.hasQueryItem("xField")) xField = url.queryItemValue("xField");
167+
if( url.hasQueryItem("yField")) yField = url.queryItemValue("yField");
168+
if( url.hasQueryItem("skipLines")) mSkipLines = url.queryItemValue("skipLines").toInt();
169+
if( url.hasQueryItem("crs")) mCrs.createFromString( url.queryItemValue("crs"));
170+
171+
mHasWktField = wktField != "";
180172

181173
QgsDebugMsg( "Data source uri is " + uri );
182174
QgsDebugMsg( "Delimited text file is: " + mFileName );
@@ -481,7 +473,7 @@ bool QgsDelimitedTextProvider::nextFeature( QgsFeature& feature )
481473
geom = 0;
482474
}
483475
mFid++;
484-
if ( !boundsCheck( geom ) )
476+
if ( geom && !boundsCheck( geom ) )
485477
{
486478
delete geom;
487479
geom = 0;
@@ -682,8 +674,7 @@ int QgsDelimitedTextProvider::capabilities() const
682674

683675
QgsCoordinateReferenceSystem QgsDelimitedTextProvider::crs()
684676
{
685-
// TODO: make provider projection-aware
686-
return QgsCoordinateReferenceSystem(); // return default CRS
677+
return mCrs;
687678
}
688679

689680

‎src/providers/delimitedtext/qgsdelimitedtextprovider.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,9 @@ class QgsDelimitedTextProvider : public QgsVectorDataProvider
241241
};
242242
wkbPoint mWKBpt;
243243

244+
// Coordinate reference sytem
245+
QgsCoordinateReferenceSystem mCrs;
246+
244247
QGis::WkbType mWkbType;
245248

246249
QString readLine( QTextStream *stream );

‎src/providers/memory/qgsmemoryprovider.cpp

Lines changed: 150 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
#include "qgsspatialindex.h"
2323
#include "qgscoordinatereferencesystem.h"
2424

25+
#include <QUrl>
26+
#include <QRegExp>
27+
2528

2629
static const QString TEXT_PROVIDER_KEY = "memory";
2730
static const QString TEXT_PROVIDER_DESCRIPTION = "Memory provider";
@@ -31,28 +34,105 @@ QgsMemoryProvider::QgsMemoryProvider( QString uri )
3134
mSelectRectGeom( NULL ),
3235
mSpatialIndex( NULL )
3336
{
34-
if ( uri == "Point" )
37+
// Initiallize the geometry with the uri to support old style uri's
38+
// (ie, just 'point', 'line', 'polygon')
39+
QUrl url = QUrl::fromEncoded(uri.toUtf8());
40+
QString geometry;
41+
if( url.hasQueryItem("geometry"))
42+
{
43+
geometry = url.queryItemValue("geometry");
44+
}
45+
else
46+
{
47+
geometry = url.path();
48+
}
49+
50+
geometry = geometry.toLower();
51+
if ( geometry == "point" )
3552
mWkbType = QGis::WKBPoint;
36-
else if ( uri == "LineString" )
53+
else if ( geometry == "linestring" )
3754
mWkbType = QGis::WKBLineString;
38-
else if ( uri == "Polygon" )
55+
else if ( geometry == "polygon" )
3956
mWkbType = QGis::WKBPolygon;
40-
else if ( uri == "MultiPoint" )
57+
else if ( geometry == "multipoint" )
4158
mWkbType = QGis::WKBMultiPoint;
42-
else if ( uri == "MultiLineString" )
59+
else if ( geometry == "multilinestring" )
4360
mWkbType = QGis::WKBMultiLineString;
44-
else if ( uri == "MultiPolygon" )
61+
else if ( geometry == "multipolygon" )
4562
mWkbType = QGis::WKBMultiPolygon;
4663
else
4764
mWkbType = QGis::WKBUnknown;
4865

66+
if( url.hasQueryItem("crs"))
67+
{
68+
QString crsDef = url.queryItemValue("crs");
69+
mCrs.createFromString(crsDef);
70+
}
71+
4972
mNextFeatureId = 1;
5073

5174
mNativeTypes
5275
<< QgsVectorDataProvider::NativeType( tr( "Whole number (integer)" ), "integer", QVariant::Int, 1, 10 )
5376
<< QgsVectorDataProvider::NativeType( tr( "Decimal number (real)" ), "double", QVariant::Double, 1, 20, 0, 5 )
5477
<< QgsVectorDataProvider::NativeType( tr( "Text (string)" ), "string", QVariant::String, 1, 255 )
5578
;
79+
80+
if( url.hasQueryItem("field"))
81+
{
82+
QList<QgsField> attributes;
83+
QRegExp reFieldDef("\\:"
84+
"(int|integer|real|double|string)" // type
85+
"(?:\\((\\d+)" // length
86+
"(?:\\,(\\d+))?" // precision
87+
"\\))?"
88+
"$", Qt::CaseInsensitive);
89+
QStringList fields = url.allQueryItemValues("field");
90+
for( int i = 0; i < fields.size(); i++ )
91+
{
92+
QString name = fields.at(i);
93+
QVariant::Type type = QVariant::String;
94+
QString typeName("string");
95+
int length = 255;
96+
int precision = 0;
97+
98+
int pos = reFieldDef.indexIn(name);
99+
if( pos >= 0 )
100+
{
101+
name = name.mid(0,pos);
102+
typeName = reFieldDef.cap(1).toLower();
103+
if( typeName == "int" || typeName == "integer" )
104+
{
105+
type = QVariant::Int;
106+
typeName = "integer";
107+
length = 10;
108+
}
109+
else if( typeName == "real" || typeName == "double" )
110+
{
111+
type = QVariant::Double;
112+
typeName = "double";
113+
length=20;
114+
precision = 5;
115+
}
116+
117+
if( reFieldDef.cap(2) != "" )
118+
{
119+
length = reFieldDef.cap(2).toInt();
120+
}
121+
if( reFieldDef.cap(3) != "" )
122+
{
123+
precision = reFieldDef.cap(3).toInt();
124+
}
125+
}
126+
if( name != "" ) attributes.append(QgsField(name,type,typeName,length,precision));
127+
}
128+
addAttributes(attributes);
129+
}
130+
131+
if( url.hasQueryItem("index") && url.queryItemValue("index") == "yes" )
132+
{
133+
createSpatialIndex();
134+
}
135+
56136
}
57137

58138
QgsMemoryProvider::~QgsMemoryProvider()
@@ -61,6 +141,69 @@ QgsMemoryProvider::~QgsMemoryProvider()
61141
delete mSelectRectGeom;
62142
}
63143

144+
QString QgsMemoryProvider::dataSourceUri() const
145+
{
146+
QUrl uri("memory");
147+
QString geometry("");
148+
switch(mWkbType)
149+
{
150+
case QGis::WKBPoint :
151+
geometry="Point";
152+
break;
153+
case QGis::WKBLineString :
154+
geometry="LineString";
155+
break;
156+
case QGis::WKBPolygon :
157+
geometry="Polygon";
158+
break;
159+
case QGis::WKBMultiPoint :
160+
geometry="MultiPoint";
161+
break;
162+
case QGis::WKBMultiLineString :
163+
geometry="MultiLineString";
164+
break;
165+
case QGis::WKBMultiPolygon :
166+
geometry="MultiPolygon";
167+
break;
168+
}
169+
uri.addQueryItem("geometry",geometry);
170+
171+
if( mCrs.isValid())
172+
{
173+
QString crsDef("");
174+
long srid = mCrs.epsg();
175+
if( srid )
176+
{
177+
crsDef = QString("epsg:%1").arg(srid);
178+
}
179+
else if( srid=mCrs.postgisSrid() )
180+
{
181+
crsDef = QString("postgis:%1").arg(srid);
182+
}
183+
else
184+
{
185+
crsDef = QString("wkt:%1").arg(mCrs.toWkt());
186+
}
187+
uri.addQueryItem("crs",crsDef);
188+
}
189+
if( mSpatialIndex )
190+
{
191+
uri.addQueryItem("index","yes");
192+
}
193+
194+
QgsAttributeList attrs = const_cast<QgsMemoryProvider *>(this)->attributeIndexes();
195+
for( int i = 0; i < attrs.size(); i++ )
196+
{
197+
QgsField field = mFields[attrs[i]];
198+
QString fieldDef = field.name();
199+
fieldDef.append(QString(":%2(%3,%4)").arg(field.typeName()).arg(field.length()).arg(field.precision()));
200+
uri.addQueryItem("field",fieldDef);
201+
}
202+
203+
return QString(uri.toEncoded());
204+
205+
}
206+
64207
QString QgsMemoryProvider::storageType() const
65208
{
66209
return "Memory storage";
@@ -231,7 +374,7 @@ bool QgsMemoryProvider::isValid()
231374
QgsCoordinateReferenceSystem QgsMemoryProvider::crs()
232375
{
233376
// TODO: make provider projection-aware
234-
return QgsCoordinateReferenceSystem(); // return default CRS
377+
return mCrs; // return default CRS
235378
}
236379

237380

‎src/providers/memory/qgsmemoryprovider.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ class QgsMemoryProvider : public QgsVectorDataProvider
3131

3232
/* Implementation of functions from QgsVectorDataProvider */
3333

34+
/**
35+
* Returns the permanent storage type for this layer as a friendly name.
36+
*/
37+
38+
virtual QString dataSourceUri() const;
39+
3440
/**
3541
* Returns the permanent storage type for this layer as a friendly name.
3642
*/
@@ -185,6 +191,9 @@ class QgsMemoryProvider : public QgsVectorDataProvider
185191
void updateExtent();
186192

187193
private:
194+
// Coordinate reference system
195+
QgsCoordinateReferenceSystem mCrs;
196+
188197
// fields
189198
QgsFieldMap mFields;
190199
QGis::WkbType mWkbType;

0 commit comments

Comments
 (0)
Please sign in to comment.