Skip to content

Commit 70bbe63

Browse files
author
wonder
committed
Applied patch from ticket #767 by Florian El Ahdab.
Thanks for the contribution! I've slightly modified the patch to simplify some pieces of code. git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@10065 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent 6f94dbb commit 70bbe63

File tree

9 files changed

+430
-18
lines changed

9 files changed

+430
-18
lines changed

CONTRIBUTORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Carlos Dávila
1111
Christian Ferreira
1212
Faunalia (http://www.faunalia.it)
1313
Fernando Pacheco
14+
Florian El Ahdab
1415
Frank Warmerdam
1516
Hyao (IRC nickname)
1617
Jean-Denis Giguere

src/app/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ SET(QGIS_APP_SRCS
3939
qgsmeasuretool.cpp
4040
qgsnewhttpconnection.cpp
4141
qgsnumericsortlistviewitem.cpp
42+
qgsogrsublayersdialog.cpp
4243
qgsoptions.cpp
4344
qgspastetransformations.cpp
4445
qgspluginitem.cpp
@@ -113,6 +114,7 @@ SET (QGIS_APP_MOC_HDRS
113114
qgsmeasuredialog.h
114115
qgsnewhttpconnection.h
115116
qgsoptions.h
117+
qgsogrsublayersdialog.h
116118
qgspastetransformations.h
117119
qgspluginmanager.h
118120
qgspythondialog.h

src/app/qgisapp.cpp

Lines changed: 72 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@
9898
#include "qgscursors.h"
9999
#include "qgscustomprojectiondialog.h"
100100
#include "qgsencodingfiledialog.h"
101+
#include "qgsogrsublayersdialog.h"
101102
#include "qgsexception.h"
102103
#include "qgsfeature.h"
103104
#include "qgsgeomtypedialog.h"
@@ -800,7 +801,7 @@ void QgisApp::createActions()
800801
mActionLayerSelectionSaveAs->setStatusTip( tr( "Save the selection as a shapefile" ) );
801802
connect( mActionLayerSelectionSaveAs, SIGNAL( triggered() ), this, SLOT( saveSelectionAsShapefile() ) );
802803
mActionLayerSelectionSaveAs->setEnabled( false );
803-
804+
804805
mActionRemoveLayer = new QAction( getThemeIcon( "mActionRemoveLayer.png" ), tr( "Remove Layer" ), this );
805806
mActionRemoveLayer->setShortcut( tr( "Ctrl+D", "Remove a Layer" ) );
806807
mActionRemoveLayer->setStatusTip( tr( "Remove a Layer" ) );
@@ -2168,11 +2169,25 @@ bool QgisApp::addVectorLayers( QStringList const & theLayerQStringList, const QS
21682169
{
21692170
layer->setProviderEncoding( enc );
21702171

2171-
// Register this layer with the layers registry
2172-
QgsMapLayerRegistry::instance()->addMapLayer( layer );
2173-
// notify the project we've made a change
2174-
QgsProject::instance()->dirty( true );
2172+
QStringList sublayers = layer->dataProvider()->subLayers();
2173+
2174+
// If the newly created layer has more than 1 layer of data available, we show the
2175+
// sublayers selection dialog so the user can select the sublayers to actually load.
2176+
if ( sublayers.count() > 1)
2177+
{
2178+
askUserForSublayers(layer);
2179+
2180+
// The first layer loaded is not usefull in that case. The user can select it in
2181+
// the list if he wants to load it.
2182+
delete layer;
21752183

2184+
}else // there is 1 layer of data available
2185+
{
2186+
// Register this layer with the layers registry
2187+
QgsMapLayerRegistry::instance()->addMapLayer( layer );
2188+
// notify the project we've made a change
2189+
QgsProject::instance()->dirty( true );
2190+
}
21762191
}
21772192
else
21782193
{
@@ -2203,7 +2218,59 @@ bool QgisApp::addVectorLayers( QStringList const & theLayerQStringList, const QS
22032218
return true;
22042219
} // QgisApp::addVectorLayer()
22052220

2221+
// This method is the method that does the real job. If the layer given in
2222+
// parameter is NULL, then the method tries to act on the activeLayer.
2223+
void QgisApp::askUserForSublayers(QgsVectorLayer *layer)
2224+
{
2225+
if (layer == NULL)
2226+
{
2227+
if (activeLayer() == NULL || activeLayer()->type() != QgsMapLayer::VectorLayer)
2228+
return;
2229+
2230+
layer = (QgsVectorLayer*) activeLayer();
2231+
if (layer->dataProvider()->name() != "ogr")
2232+
return;
2233+
}
2234+
2235+
QStringList sublayers = layer->dataProvider()->subLayers();
2236+
2237+
// We initialize a selection dialog and display it.
2238+
QgsOGRSublayersDialog chooseSublayersDialog( this );
2239+
chooseSublayersDialog.populateLayerTable( sublayers );
2240+
2241+
if (chooseSublayersDialog.exec())
2242+
{
2243+
QString uri = layer->source();
2244+
if ( uri.contains('&', Qt::CaseSensitive) )
2245+
{
2246+
// If we get here, there are some options added to the filename.
2247+
// A valid uri is of the form: filename&option1=value1&option2=value2,...
2248+
// We want only the filename here, so we get the first part of the split.
2249+
QStringList theURIParts = uri.split("&");
2250+
uri = theURIParts.at( 0 );
2251+
}
2252+
2253+
// the user has done his choice
2254+
loadOGRSublayers(uri, chooseSublayersDialog.getSelection());
2255+
}
2256+
}
22062257

2258+
// This method will load with OGR the layers in parameter.
2259+
// This method has been conceived to use the new URI
2260+
// format of the ogrprovider so as to give precisions about which
2261+
// sublayer to load into QGIS. It is normally triggered by the
2262+
// sublayer selection dialog.
2263+
void QgisApp::loadOGRSublayers( QString uri, QStringList list)
2264+
{
2265+
// The uri must contain the actual uri of the vectorLayer from which we are
2266+
// going to load the sublayers.
2267+
QString fileName = QFileInfo(uri).baseName();
2268+
for (int i = 0; i < list.size(); i++)
2269+
{
2270+
QString composedURI=uri+"&layername="+list.at(i);
2271+
QgsVectorLayer *layer=addVectorLayer(composedURI,fileName+":"+list.at(i),"ogr");
2272+
}
2273+
}
22072274

22082275
/** This helper checks to see whether the file name appears to be a valid vector file name */
22092276
bool QgisApp::isValidVectorFileName( QString theFileNameQString )

src/app/qgisapp.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ class QgsVectorLayer;
6363
#include "qgsconfig.h"
6464
#include "qgspoint.h"
6565

66+
6667
/*! \class QgisApp
6768
* \brief Main window for the Qgis application
6869
*/
@@ -342,6 +343,8 @@ class QgisApp : public QMainWindow
342343
*/
343344
void editPaste( QgsMapLayer * destinationLayer = 0 );
344345

346+
void loadOGRSublayers( QString uri, QStringList list );
347+
345348
protected:
346349

347350
//! Handle state changes (WindowTitleChange)
@@ -594,6 +597,10 @@ class QgisApp : public QMainWindow
594597
void bookmarkAdded();
595598

596599
private:
600+
/** This method will open a dialog so the user can select the sublayers
601+
* to load
602+
*/
603+
void askUserForSublayers(QgsVectorLayer *layer);
597604
/** Add a raster layer to the map (passed in as a ptr).
598605
* It won't force a refresh.
599606
*/

src/app/qgsogrsublayersdialog.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/***************************************************************************
2+
qgsogrsublayersdialog.cpp - dialog for selecting ogr sublayers
3+
---------------------
4+
begin : January 2009
5+
copyright : (C) 2009 by Florian El Ahdab
6+
email : felahdab 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+
/* $Id$ */
16+
17+
#include "qgsogrsublayersdialog.h"
18+
19+
#include <QTableWidgetItem>
20+
21+
22+
QgsOGRSublayersDialog::QgsOGRSublayersDialog( QWidget* parent, Qt::WFlags fl )
23+
: QDialog( parent, fl )
24+
{
25+
setupUi( this );
26+
QStringList labels=QStringList() << "Layer ID" << "Layer name" << "Nb of features" << "Geometry type";
27+
layersTable->setHeaderLabels(labels);
28+
}
29+
30+
QgsOGRSublayersDialog::~QgsOGRSublayersDialog()
31+
{
32+
}
33+
34+
QStringList QgsOGRSublayersDialog::getSelection()
35+
{
36+
QStringList list=QStringList();
37+
for (int i = 0; i < layersTable-> selectedItems().size(); i++)
38+
{
39+
QString theItem =layersTable-> selectedItems().at(i)->text(1);
40+
list.append(theItem);
41+
}
42+
return list;
43+
}
44+
45+
void QgsOGRSublayersDialog::populateLayerTable (QStringList theList)
46+
{
47+
for (int i =0; i< theList.size(); i++){
48+
QString ligne = theList.at(i);
49+
QStringList elements = ligne.split(":");
50+
QStringList item=QStringList();
51+
item << elements.at(0) << elements.at(1) << elements.at(2) << elements.at(3);
52+
layersTable -> addTopLevelItem(new QTreeWidgetItem(item));
53+
}
54+
}

src/app/qgsogrsublayersdialog.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/***************************************************************************
2+
qgsogrsublayersdialog.h - dialog for selecting ogr sublayers
3+
---------------------
4+
begin : January 2009
5+
copyright : (C) 2009 by Florian El Ahdab
6+
email : felahdab 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+
/* $Id$ */
16+
17+
#ifndef QGSOGRSUBLAYERSDIALOG_H
18+
#define QGSOGRSUBLAYERSDIALOG_H
19+
20+
#include <QDialog>
21+
#include <ui_qgsogrsublayersdialogbase.h>
22+
23+
24+
25+
class QgsOGRSublayersDialog : public QDialog, private Ui::QgsOGRSublayersDialogBase
26+
{
27+
Q_OBJECT
28+
public:
29+
QgsOGRSublayersDialog( QWidget* parent = 0, Qt::WFlags fl = 0 );
30+
~QgsOGRSublayersDialog();
31+
void populateLayerTable(QStringList theList);
32+
QStringList getSelection();
33+
34+
};
35+
36+
#endif

src/providers/ogr/qgsogrprovider.cpp

Lines changed: 98 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,61 @@ QgsOgrProvider::QgsOgrProvider( QString const & uri )
7373
// try to open for update, but disable error messages to avoid a
7474
// message if the file is read only, because we cope with that
7575
// ourselves.
76+
77+
// This part of the code parses the uri transmitted to the ogr provider to
78+
// get the options the client wants us to apply
79+
80+
QString mFilePath;
81+
QString theLayerName;
82+
int theLayerIndex=0;
83+
84+
// If there is no & in the uri, then the uri is just the filename. The loaded
85+
// layer will be layer 0.
86+
if ( ! uri.contains('&', Qt::CaseSensitive))
87+
{
88+
mFilePath = uri;
89+
}
90+
else
91+
{
92+
// If we get here, there are some options added to the filename. We must parse
93+
// the different parts separated by &, and among each option, the name and the
94+
// value around the =.
95+
// A valid uri is of the form: filename&option1=value1&option2=value2,...
96+
97+
QStringList theURIParts = uri.split("&");
98+
mFilePath = theURIParts.at( 0 );
99+
100+
for (int i = 1 ; i < theURIParts.size(); i++ )
101+
{
102+
QStringList theInstruction = theURIParts.at( i ).split( "=" );
103+
if ( theInstruction.at( 0 ) == QString( "layerid" ) )
104+
{
105+
bool ok;
106+
theLayerIndex = theInstruction.at( 1 ).toInt( &ok );
107+
if ( ! ok )
108+
{
109+
theLayerIndex = 0;
110+
}
111+
}
112+
if ( theInstruction.at( 0 ) == QString( "layername" ) )
113+
{
114+
theLayerName = theInstruction.at( 1 );
115+
}
116+
}
117+
}
118+
119+
QgsDebugMsg("mFilePath: " + mFilePath);
120+
QgsDebugMsg("theLayerIndex: "+theLayerIndex);
121+
QgsDebugMsg("theLayerName: "+theLayerName);
122+
76123
CPLPushErrorHandler( CPLQuietErrorHandler );
77-
ogrDataSource = OGROpen( QFile::encodeName( uri ).constData(), TRUE, &ogrDriver );
124+
ogrDataSource = OGROpen( QFile::encodeName( mFilePath ).constData(), TRUE, &ogrDriver );
78125
CPLPopErrorHandler();
79126

80127
if ( ogrDataSource == NULL )
81128
{
82129
// try to open read-only
83-
ogrDataSource = OGROpen( QFile::encodeName( uri ).constData(), FALSE, &ogrDriver );
130+
ogrDataSource = OGROpen( QFile::encodeName( mFilePath ).constData(), FALSE, &ogrDriver );
84131

85132
//TODO Need to set a flag or something to indicate that the layer
86133
//TODO is in read-only mode, otherwise edit ops will fail
@@ -95,8 +142,17 @@ QgsOgrProvider::QgsOgrProvider( QString const & uri )
95142
valid = true;
96143

97144
ogrDriverName = OGR_Dr_GetName( ogrDriver );
98-
99-
ogrLayer = OGR_DS_GetLayer( ogrDataSource, 0 );
145+
146+
// We get the layer which was requested by the uri. The layername
147+
// has precedence over the layerid if both are given.
148+
if ( theLayerName.isNull() )
149+
{
150+
ogrLayer = OGR_DS_GetLayer( ogrDataSource, theLayerIndex );
151+
}
152+
else
153+
{
154+
ogrLayer = OGR_DS_GetLayerByName( ogrDataSource, (char*)(theLayerName.toLocal8Bit().data()) );
155+
}
100156

101157
// get the extent_ (envelope) of the layer
102158

@@ -145,6 +201,44 @@ QgsOgrProvider::~QgsOgrProvider()
145201
}
146202
}
147203

204+
QStringList QgsOgrProvider::subLayers() const
205+
{
206+
QStringList theList = QStringList();
207+
if (! valid )
208+
{
209+
return theList;
210+
}
211+
for ( int i = 0; i < layerCount() ; i++ )
212+
{
213+
QString theLayerName = QString(OGR_FD_GetName(OGR_L_GetLayerDefn(OGR_DS_GetLayer( ogrDataSource, i ))));
214+
OGRwkbGeometryType layerGeomType = OGR_FD_GetGeomType(OGR_L_GetLayerDefn(OGR_DS_GetLayer( ogrDataSource, i )));
215+
216+
int theLayerFeatureCount=OGR_L_GetFeatureCount(OGR_DS_GetLayer( ogrDataSource, i ),1) ;
217+
218+
QString geom;
219+
switch (layerGeomType)
220+
{
221+
case wkbUnknown: geom = "Unknown"; break;
222+
case wkbPoint: geom="Point"; break;
223+
case wkbLineString: geom="LineString"; break;
224+
case wkbPolygon: geom="Polygon"; break;
225+
case wkbMultiPoint: geom="MultiPoint"; break;
226+
case wkbMultiLineString: geom="MultiLineString"; break;
227+
case wkbGeometryCollection: geom = "GeometryCollection"; break;
228+
case wkbNone: geom = "None"; break;
229+
case wkbPoint25D: geom="Point25D"; break;
230+
case wkbLineString25D: geom="LineString25D"; break;
231+
case wkbPolygon25D: geom="Polygon25D"; break;
232+
case wkbMultiPoint25D: geom="MultiPoint25D"; break;
233+
case wkbMultiLineString25D: geom="MultiLineString25D"; break;
234+
case wkbMultiPolygon25D: geom="MultiPolygon25D"; break;
235+
default: geom="Unknown WKB: " + QString::number(layerGeomType);
236+
}
237+
theList.append(QString::number(i)+":"+ theLayerName+":"+QString::number(theLayerFeatureCount)+":"+geom);
238+
}
239+
return theList;
240+
}
241+
148242
void QgsOgrProvider::setEncoding( const QString& e )
149243
{
150244
QgsVectorDataProvider::setEncoding( e );

0 commit comments

Comments
 (0)