Skip to content

Commit b28c910

Browse files
committed
Separate OGR data items from provider code
1 parent f15622f commit b28c910

File tree

5 files changed

+344
-282
lines changed

5 files changed

+344
-282
lines changed

src/providers/ogr/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

2-
SET (OGR_SRCS qgsogrprovider.cpp)
2+
SET (OGR_SRCS qgsogrprovider.cpp qgsogrdataitems.cpp)
33

4-
SET(OGR_MOC_HDRS qgsogrprovider.h)
4+
SET(OGR_MOC_HDRS qgsogrprovider.h qgsogrdataitems.h)
55

66
########################################################
77
# Build
Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
/***************************************************************************
2+
qgsogrdataitems.cpp
3+
-------------------
4+
begin : 2011-04-01
5+
copyright : (C) 2011 Radim Blazek
6+
email : radim dot blazek 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 "qgsogrdataitems.h"
17+
18+
#include "qgslogger.h"
19+
20+
#include <QFileInfo>
21+
#include <QTextStream>
22+
23+
#include <ogr_srs_api.h>
24+
#include <cpl_error.h>
25+
#include <cpl_conv.h>
26+
27+
// these are defined in qgsogrprovider.cpp
28+
QGISEXTERN QStringList fileExtensions();
29+
QGISEXTERN QStringList wildcards();
30+
31+
32+
QgsOgrLayerItem::QgsOgrLayerItem( QgsDataItem* parent,
33+
QString name, QString path, QString uri, LayerType layerType )
34+
: QgsLayerItem( parent, name, path, uri, layerType, "ogr" )
35+
{
36+
mToolTip = uri;
37+
mPopulated = true; // children are not expected
38+
}
39+
40+
QgsOgrLayerItem::~QgsOgrLayerItem()
41+
{
42+
}
43+
44+
QgsLayerItem::Capability QgsOgrLayerItem::capabilities()
45+
{
46+
QgsDebugMsg( "mPath = " + mPath );
47+
OGRRegisterAll();
48+
OGRSFDriverH hDriver;
49+
OGRDataSourceH hDataSource = OGROpen( TO8F( mPath ), true, &hDriver );
50+
51+
if ( !hDataSource )
52+
return NoCapabilities;
53+
54+
QString driverName = OGR_Dr_GetName( hDriver );
55+
OGR_DS_Destroy( hDataSource );
56+
57+
if ( driverName == "ESRI Shapefile" )
58+
return SetCrs;
59+
60+
return NoCapabilities;
61+
}
62+
63+
bool QgsOgrLayerItem::setCrs( QgsCoordinateReferenceSystem crs )
64+
{
65+
QgsDebugMsg( "mPath = " + mPath );
66+
OGRRegisterAll();
67+
OGRSFDriverH hDriver;
68+
OGRDataSourceH hDataSource = OGROpen( TO8F( mPath ), true, &hDriver );
69+
70+
if ( !hDataSource )
71+
return false;
72+
73+
QString driverName = OGR_Dr_GetName( hDriver );
74+
OGR_DS_Destroy( hDataSource );
75+
76+
// we are able to assign CRS only to shapefiles :-(
77+
if ( driverName == "ESRI Shapefile" )
78+
{
79+
QString layerName = mPath.left( mPath.indexOf( ".shp", Qt::CaseInsensitive ) );
80+
QString wkt = crs.toWkt();
81+
82+
// save ordinary .prj file
83+
OGRSpatialReferenceH hSRS = OSRNewSpatialReference( wkt.toLocal8Bit().data() );
84+
OSRMorphToESRI( hSRS ); // this is the important stuff for shapefile .prj
85+
char* pszOutWkt = NULL;
86+
OSRExportToWkt( hSRS, &pszOutWkt );
87+
QFile prjFile( layerName + ".prj" );
88+
if ( prjFile.open( QIODevice::WriteOnly ) )
89+
{
90+
QTextStream prjStream( &prjFile );
91+
prjStream << pszOutWkt << endl;
92+
prjFile.close();
93+
}
94+
else
95+
{
96+
QgsDebugMsg( "Couldn't open file " + layerName + ".prj" );
97+
return false;
98+
}
99+
OSRDestroySpatialReference( hSRS );
100+
CPLFree( pszOutWkt );
101+
102+
// save qgis-specific .qpj file (maybe because of better wkt compatibility?)
103+
QFile qpjFile( layerName + ".qpj" );
104+
if ( qpjFile.open( QIODevice::WriteOnly ) )
105+
{
106+
QTextStream qpjStream( &qpjFile );
107+
qpjStream << wkt.toLocal8Bit().data() << endl;
108+
qpjFile.close();
109+
}
110+
else
111+
{
112+
QgsDebugMsg( "Couldn't open file " + layerName + ".qpj" );
113+
return false;
114+
}
115+
116+
return true;
117+
}
118+
119+
// It it is impossible to assign a crs to an existing layer
120+
// No OGR_L_SetSpatialRef : http://trac.osgeo.org/gdal/ticket/4032
121+
return false;
122+
}
123+
124+
// -------
125+
126+
static QgsOgrLayerItem* dataItemForLayer( QgsDataItem* parentItem, QString name, QString path, OGRDataSourceH hDataSource, int layerId )
127+
{
128+
OGRLayerH hLayer = OGR_DS_GetLayer( hDataSource, layerId );
129+
OGRFeatureDefnH hDef = OGR_L_GetLayerDefn( hLayer );
130+
131+
QgsLayerItem::LayerType layerType = QgsLayerItem::Vector;
132+
int ogrType = QgsOgrProvider::getOgrGeomType( hLayer );
133+
switch ( ogrType )
134+
{
135+
case wkbUnknown:
136+
case wkbGeometryCollection:
137+
break;
138+
case wkbNone:
139+
layerType = QgsLayerItem::TableLayer;
140+
break;
141+
case wkbPoint:
142+
case wkbMultiPoint:
143+
case wkbPoint25D:
144+
case wkbMultiPoint25D:
145+
layerType = QgsLayerItem::Point;
146+
break;
147+
case wkbLineString:
148+
case wkbMultiLineString:
149+
case wkbLineString25D:
150+
case wkbMultiLineString25D:
151+
layerType = QgsLayerItem::Line;
152+
break;
153+
case wkbPolygon:
154+
case wkbMultiPolygon:
155+
case wkbPolygon25D:
156+
case wkbMultiPolygon25D:
157+
layerType = QgsLayerItem::Polygon;
158+
break;
159+
default:
160+
break;
161+
}
162+
163+
QgsDebugMsg( QString( "ogrType = %1 layertype = %2" ).arg( ogrType ).arg( layerType ) );
164+
165+
QString layerUri = path;
166+
167+
if ( name.isEmpty() )
168+
{
169+
// we are in a collection
170+
name = FROM8( OGR_FD_GetName( hDef ) );
171+
QgsDebugMsg( "OGR layer name : " + name );
172+
173+
layerUri += "|layerid=" + QString::number( layerId );
174+
175+
path += "/" + name;
176+
}
177+
178+
QgsDebugMsg( "OGR layer uri : " + layerUri );
179+
180+
return new QgsOgrLayerItem( parentItem, name, path, layerUri, layerType );
181+
}
182+
183+
// ----
184+
185+
QgsOgrDataCollectionItem::QgsOgrDataCollectionItem( QgsDataItem* parent, QString name, QString path )
186+
: QgsDataCollectionItem( parent, name, path )
187+
{
188+
}
189+
190+
QgsOgrDataCollectionItem::~QgsOgrDataCollectionItem()
191+
{
192+
}
193+
194+
QVector<QgsDataItem*> QgsOgrDataCollectionItem::createChildren()
195+
{
196+
QVector<QgsDataItem*> children;
197+
198+
OGRSFDriverH hDriver;
199+
OGRDataSourceH hDataSource = OGROpen( TO8F( mPath ), false, &hDriver );
200+
if ( !hDataSource )
201+
return children;
202+
int numLayers = OGR_DS_GetLayerCount( hDataSource );
203+
204+
for ( int i = 0; i < numLayers; i++ )
205+
{
206+
QgsOgrLayerItem* item = dataItemForLayer( this, QString(), mPath, hDataSource, i );
207+
children.append( item );
208+
}
209+
210+
OGR_DS_Destroy( hDataSource );
211+
212+
return children;
213+
}
214+
215+
// ---------------------------------------------------------------------------
216+
217+
QGISEXTERN int dataCapabilities()
218+
{
219+
return QgsDataProvider::File | QgsDataProvider::Dir;
220+
}
221+
222+
QGISEXTERN QgsDataItem * dataItem( QString thePath, QgsDataItem* parentItem )
223+
{
224+
if ( thePath.isEmpty() )
225+
return 0;
226+
227+
QFileInfo info( thePath );
228+
if ( !info.isFile() )
229+
return 0;
230+
231+
// We have to filter by extensions, otherwise e.g. all Shapefile files are displayed
232+
// because OGR drive can open also .dbf, .shx.
233+
QStringList myExtensions = fileExtensions();
234+
if ( myExtensions.indexOf( info.suffix().toLower() ) < 0 )
235+
{
236+
bool matches = false;
237+
foreach( QString wildcard, wildcards() )
238+
{
239+
QRegExp rx( wildcard, Qt::CaseInsensitive, QRegExp::Wildcard );
240+
if ( rx.exactMatch( info.fileName() ) )
241+
{
242+
matches = true;
243+
break;
244+
}
245+
}
246+
if ( !matches )
247+
return 0;
248+
}
249+
250+
// .dbf should probably appear if .shp is not present
251+
if ( info.suffix().toLower() == "dbf" )
252+
{
253+
QString pathShp = thePath.left( thePath.count() - 4 ) + ".shp";
254+
if ( QFileInfo( pathShp ).exists() )
255+
return 0;
256+
}
257+
258+
OGRRegisterAll();
259+
OGRSFDriverH hDriver;
260+
OGRDataSourceH hDataSource = OGROpen( TO8F( thePath ), false, &hDriver );
261+
262+
if ( !hDataSource )
263+
return 0;
264+
265+
QString driverName = OGR_Dr_GetName( hDriver );
266+
QgsDebugMsg( "OGR Driver : " + driverName );
267+
268+
int numLayers = OGR_DS_GetLayerCount( hDataSource );
269+
270+
QgsDataItem* item = 0;
271+
272+
if ( numLayers == 1 )
273+
{
274+
QString name = info.completeBaseName();
275+
item = dataItemForLayer( parentItem, name, thePath, hDataSource, 0 );
276+
}
277+
else if ( numLayers > 1 )
278+
{
279+
item = new QgsOgrDataCollectionItem( parentItem, info.fileName(), thePath );
280+
}
281+
282+
OGR_DS_Destroy( hDataSource );
283+
return item;
284+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/***************************************************************************
2+
qgsogrdataitems.h
3+
-------------------
4+
begin : 2011-04-01
5+
copyright : (C) 2011 Radim Blazek
6+
email : radim dot blazek 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+
#ifndef QGSOGRDATAITEMS_H
17+
#define QGSOGRDATAITEMS_H
18+
19+
#include "qgsdataitem.h"
20+
#include "qgsogrprovider.h"
21+
22+
class QgsOgrLayerItem : public QgsLayerItem
23+
{
24+
Q_OBJECT
25+
public:
26+
QgsOgrLayerItem( QgsDataItem* parent, QString name, QString path, QString uri, LayerType layerType );
27+
~QgsOgrLayerItem();
28+
29+
bool setCrs( QgsCoordinateReferenceSystem crs );
30+
Capability capabilities();
31+
};
32+
33+
class QgsOgrDataCollectionItem : public QgsDataCollectionItem
34+
{
35+
Q_OBJECT
36+
public:
37+
QgsOgrDataCollectionItem( QgsDataItem* parent, QString name, QString path );
38+
~QgsOgrDataCollectionItem();
39+
40+
QVector<QgsDataItem*> createChildren();
41+
};
42+
43+
#endif // QGSOGRDATAITEMS_H

0 commit comments

Comments
 (0)