bug767_090129.diff

Version 3 of the OGR multilayer patch - falahdab -, 2009-01-29 09:49 AM

Download (21.5 KB)

View differences:

src/app/qgisapp.h (copie de travail)
63 63
#include "qgsconfig.h"
64 64
#include "qgspoint.h"
65 65

  
66
#include "../providers/ogr/qgsogrprovider.h"
67

  
66 68
/*! \class QgisApp
67 69
 * \brief Main window for the Qgis application
68 70
 */
......
342 344
     */
343 345
    void editPaste( QgsMapLayer * destinationLayer = 0 );
344 346

  
347
    void loadOGRSublayers( QString uri, QStringList *list );
348

  
345 349
  protected:
346 350

  
347 351
    //! Handle state changes (WindowTitleChange)
......
594 598
    void bookmarkAdded();
595 599

  
596 600
  private:
601
    /** This method will open a dialog so the user can select the sublayers
602
    * to load
603
    */
604
    void askUserForSublayers(QgsVectorLayer *layer);
597 605
    /** Add a raster layer to the map (passed in as a ptr).
598 606
     * It won't force a refresh.
599 607
     */
src/app/qgsogrsublayersdialog.cpp (révision 0)
1
/***************************************************************************
2
 *   Copyright (C) 2003 by Tim Sutton                                      *
3
 *   [email protected]                                                     *
4
 *                                                                         *
5
 *                                                                         *
6
 *   This program is free software; you can redistribute it and/or modify  *
7
 *   it under the terms of the GNU General Public License as published by  *
8
 *   the Free Software Foundation; either version 2 of the License, or     *
9
 *   (at your option) any later version.                                   *
10
 ***************************************************************************/
11
#include "qgsogrsublayersdialog.h"
12
#include "qgscontexthelp.h"
13

  
14
//qt includes
15

  
16
//standard includes
17

  
18
QgsOGRSublayersDialog::QgsOGRSublayersDialog( QWidget* parent, Qt::WFlags fl )
19
    : QDialog( parent, fl )
20
{
21
  setupUi( this );
22
  QStringList labels=QStringList() << "Layer ID" << "Layer name" << "Nb of features" << "Geometry type";
23
	layersTable->setHeaderLabels(labels);
24
}
25

  
26
QgsOGRSublayersDialog::~QgsOGRSublayersDialog()
27
{
28
}
29

  
30
void QgsOGRSublayersDialog::setURI(QString uri)
31
{
32
  if ( uri.contains('&', Qt::CaseSensitive))
33
	{
34
  	// If we get here, there are some options added to the filename.
35
  	// A valid uri is of the form: filename&option1=value1&option2=value2,...
36
    // We want only the filename here, so we get the first part of the split.
37
  	QStringList theURIParts = uri.split("&");
38
	  uri = theURIParts.at( 0 );
39
	}
40
  mURI=QString(uri);
41
}
42

  
43
void QgsOGRSublayersDialog::on_buttonBox_accepted()
44
{
45
  //close the dialog
46
	QStringList list=QStringList();
47
	for (int i = 0; i < layersTable-> selectedItems().size(); i++)
48
	{
49
    QString theItem =layersTable-> selectedItems().at(i)->text(1);
50
  	list.append(theItem);
51
	}
52
	emit updated( mURI , &list );
53
  accept();
54
}
55

  
56
void QgsOGRSublayersDialog::on_buttonBox_rejected()
57
{
58
  reject();
59
}
60

  
61
void QgsOGRSublayersDialog::populateLayerTable (QStringList *theList)
62
{
63
	for (int i =0; i< theList->size(); i++){
64
		QString ligne = theList -> at(i);
65
		QStringList elements = ligne.split(":");
66
    QStringList item=QStringList();
67
    item << elements.at(0) << elements.at(1) << elements.at(2) << elements.at(3);
68
    layersTable -> addTopLevelItem(new QTreeWidgetItem(item));
69
	}	
70
}
src/app/CMakeLists.txt (copie de travail)
39 39
  qgsmeasuretool.cpp
40 40
  qgsnewhttpconnection.cpp
41 41
  qgsnumericsortlistviewitem.cpp
42
  qgsogrsublayersdialog.cpp
42 43
  qgsoptions.cpp
43 44
  qgspastetransformations.cpp
44 45
  qgspluginitem.cpp
......
113 114
  qgsmeasuredialog.h
114 115
  qgsnewhttpconnection.h
115 116
  qgsoptions.h
117
  qgsogrsublayersdialog.h
116 118
  qgspastetransformations.h
117 119
  qgspluginmanager.h
118 120
  qgspythondialog.h
src/app/qgisapp.cpp (copie de travail)
98 98
#include "qgscursors.h"
99 99
#include "qgscustomprojectiondialog.h"
100 100
#include "qgsencodingfiledialog.h"
101
#include "qgsogrsublayersdialog.h"
101 102
#include "qgsexception.h"
102 103
#include "qgsfeature.h"
103 104
#include "qgsgeomtypedialog.h"
......
800 801
  mActionLayerSelectionSaveAs->setStatusTip( tr( "Save the selection as a shapefile" ) );
801 802
  connect( mActionLayerSelectionSaveAs, SIGNAL( triggered() ), this, SLOT( saveSelectionAsShapefile() ) );
802 803
  mActionLayerSelectionSaveAs->setEnabled( false );
803

  
804
  
804 805
  mActionRemoveLayer = new QAction( getThemeIcon( "mActionRemoveLayer.png" ), tr( "Remove Layer" ), this );
805 806
  mActionRemoveLayer->setShortcut( tr( "Ctrl+D", "Remove a Layer" ) );
806 807
  mActionRemoveLayer->setStatusTip( tr( "Remove a Layer" ) );
......
2168 2169
    {
2169 2170
      layer->setProviderEncoding( enc );
2170 2171

  
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
      // The next cast is possible because we know that the provider was ogr and it is 
2173
      // necessary because the QgsMapLayer subLayers method returns an empty QStringList.
2174
      // We have to get down to the actual provider to get the approriate list.
2175
 	  	QgsOgrProvider* theCurrentProvider = ( QgsOgrProvider * )( layer->dataProvider());
2175 2176

  
2177
			QStringList liste = theCurrentProvider->subLayers();
2178

  
2179
      // If the newly created layer has more than 1 layer of data available, we show the
2180
      // sublayers selection dialog so the user can select the sublayers to actually load.
2181
			if ( liste.count() > 1)
2182
			{
2183
        askUserForSublayers(layer);				
2184

  
2185
        // The first layer loaded is not usefull in that case. The user can select it in 
2186
        // the list if he wants to load it.
2187
        delete layer;
2188

  
2189
			}else  // there is 1 layer of data available
2190
      {
2191
        // Register this layer with the layers registry
2192
        QgsMapLayerRegistry::instance()->addMapLayer( layer );
2193
        // notify the project we've made a change
2194
        QgsProject::instance()->dirty( true );
2195
      }
2176 2196
    }
2177 2197
    else
2178 2198
    {
......
2203 2223
  return true;
2204 2224
} // QgisApp::addVectorLayer()
2205 2225

  
2226
// This method is the method that does the real job. If the layer given in
2227
// parameter is NULL, then the method tries to act on the activeLayer. 
2228
void QgisApp::askUserForSublayers(QgsVectorLayer *layer)
2229
{
2230
  if (NULL == layer)
2231
  {
2232
    if (mQgisInterface->activeLayer() && 
2233
        mQgisInterface->activeLayer()->type() == QgsMapLayer::VectorLayer && 
2234
        0 == (( QgsVectorLayer *)mQgisInterface->activeLayer())->dataProvider()->name().compare("ogr"))
2235
    {
2236
      layer=(QgsVectorLayer*)(mQgisInterface->activeLayer());
2237
    }
2238
    else return;
2239
  }
2240
  QgsOgrProvider* theCurrentProvider = ( QgsOgrProvider * )( layer->dataProvider());
2241
  QStringList liste = theCurrentProvider->subLayers();
2242
  QgsOGRSublayersDialog *chooseSublayersDialog;  
2206 2243

  
2244
  // We initialize a selection dialog and display it.
2245
  chooseSublayersDialog = new QgsOGRSublayersDialog(this , QgisGui::ModalDialogFlags );
2246
  chooseSublayersDialog->setURI(layer-> source());
2247
	chooseSublayersDialog->setAttribute( Qt::WA_DeleteOnClose );
2248
	chooseSublayersDialog->show();
2249
	chooseSublayersDialog->populateLayerTable( & liste );
2207 2250

  
2251
  // We want to get the signal from this dialog when the user has done his choice
2252
  connect( chooseSublayersDialog, SIGNAL( updated(QString, QStringList * ) ), this, SLOT( loadOGRSublayers(QString, QStringList *  ) ) );
2253
}
2254

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

  
2208 2272
/** This helper checks to see whether the file name appears to be a valid vector file name */
2209 2273
bool QgisApp::isValidVectorFileName( QString theFileNameQString )
2210 2274
{
src/app/qgsogrsublayersdialog.h (révision 0)
1
/***************************************************************************
2
 *   Copyright (C) 2003 by Tim Sutton                                      *
3
 *   [email protected]                                                     *
4
 *                                                                         *
5
 *   This program is free software; you can redistribute it and/or modify  *
6
 *   it under the terms of the GNU General Public License as published by  *
7
 *   the Free Software Foundation; either version 2 of the License, or     *
8
 *   (at your option) any later version.                                   *
9
 ***************************************************************************/
10
#ifndef QGSOGRSUBLAYERSDIALOG_H
11
#define QGSOGRSUBLAYERSDIALOG_H
12

  
13
#include <QDialog>
14
#include <QTableWidgetItem>
15
#include <ui_qgsogrsublayersdialogbase.h>
16

  
17
#include <qgslogger.h>
18

  
19
/**
20
@author Tim Sutton
21
*/
22
class QgsOGRSublayersDialog : public QDialog, private Ui::QgsOGRSublayersDialogBase
23
{
24
    Q_OBJECT
25
  public:
26
    QgsOGRSublayersDialog( QWidget* parent = 0, Qt::WFlags fl = 0 );
27
    ~QgsOGRSublayersDialog();
28
		void populateLayerTable (QStringList *theList);
29
		QStringList * getSelection ();
30
    void setURI(QString uri);
31

  
32
  private:
33
    static const int context_id = 0;
34
    QString mURI;
35

  
36
  private slots:
37
		void on_buttonBox_accepted();
38
    void on_buttonBox_rejected();
39

  
40
	signals:
41
		void updated(QString uri, QStringList*list);
42

  
43
};
44

  
45
#endif
src/providers/ogr/qgsogrprovider.h (copie de travail)
47 47

  
48 48
    virtual QgsCoordinateReferenceSystem crs();
49 49

  
50
	   /**
51
     * Sub-layers handled by this provider, in order from bottom to top
52
     *
53
     * Sub-layers are used when the provider's source can combine layers
54
     * it knows about in some way before it hands them off to the provider.
55
     */
56
    virtual QStringList subLayers();
50 57

  
51 58
    /**
52 59
     *   Returns the permanent storage type for this layer as a friendly name.
......
181 188
     *  @param index the index of the attribute
182 189
     *  @param values reference to the list of unique values */
183 190
    virtual void uniqueValues( int index, QList<QVariant> &uniqueValues );
184

  
185
  protected:
186
    /** loads fields from input file to member attributeFields */
187
    void loadFields();
188

  
189
    /**Get an attribute associated with a feature*/
190
    void getFeatureAttribute( OGRFeatureH ogrFet, QgsFeature & f, int attindex );
191

  
192 191
    /** return a provider name
193 192

  
194 193
    Essentially just returns the provider key.  Should be used to build file
......
219 218
     */
220 219
    QString description() const;
221 220

  
221
  protected:
222
    /** loads fields from input file to member attributeFields */
223
    void loadFields();
222 224

  
225
    /**Get an attribute associated with a feature*/
226
    void getFeatureAttribute( OGRFeatureH ogrFet, QgsFeature & f, int attindex );
227

  
228

  
229

  
223 230
  private:
224 231
    unsigned char *getGeometryPointer( OGRFeatureH fet );
225 232

  
......
247 254

  
248 255
    //! Selection rectangle
249 256
    OGRGeometryH mSelectionRectangle;
250

  
251 257
    /**Adds one feature*/
252 258
    bool addFeature( QgsFeature& f );
253 259
    /**Deletes one feature*/
src/providers/ogr/qgsogrprovider.cpp (copie de travail)
73 73
  // try to open for update, but disable error messages to avoid a
74 74
  // message if the file is read only, because we cope with that
75 75
  // 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 ( 0 == theInstruction.at( 0 ).compare( QString( "layerid" )))
104
      {
105
        bool ok;
106
        theLayerIndex = theInstruction.at( 1 ).toInt( &ok );
107
        if ( ! ok )
108
        {
109
          theLayerIndex = 0;
110
        }
111
      }
112
      if ( 0 == theInstruction.at( 0 ).compare( QString( "layername" )))
113
      {
114
        theLayerName = theInstruction.at( 1 );
115
      }				
116
    }
117
  }
118

  
119
  QgsLogger::debug("[OGR] mFilePath: " + mFilePath);
120
  QgsLogger::debug("[OGR] theLayerIndex: "+theLayerIndex);
121
  QgsLogger::debug("[OGR] theLayerName: "+theLayerName);
122
	
76 123
  CPLPushErrorHandler( CPLQuietErrorHandler );
77
  ogrDataSource = OGROpen( QFile::encodeName( uri ).constData(), TRUE, &ogrDriver );
124
  ogrDataSource = OGROpen( QFile::encodeName( mFilePath ).constData(), TRUE, &ogrDriver );
78 125
  CPLPopErrorHandler();
79 126

  
80 127
  if ( ogrDataSource == NULL )
81 128
  {
82 129
    // try to open read-only
83
    ogrDataSource = OGROpen( QFile::encodeName( uri ).constData(), FALSE, &ogrDriver );
130
    ogrDataSource = OGROpen( QFile::encodeName( mFilePath ).constData(), FALSE, &ogrDriver );
84 131

  
85 132
    //TODO Need to set a flag or something to indicate that the layer
86 133
    //TODO is in read-only mode, otherwise edit ops will fail
......
95 142
    valid = true;
96 143

  
97 144
    ogrDriverName = OGR_Dr_GetName( ogrDriver );
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 ( NULL == theLayerName )
149
    {
150
      ogrLayer = OGR_DS_GetLayer( ogrDataSource, theLayerIndex );
151
    }else
152
    {
153
      ogrLayer = OGR_DS_GetLayerByName( ogrDataSource, (char*)(theLayerName.toLocal8Bit().data()) );
154
    }
98 155

  
99
    ogrLayer = OGR_DS_GetLayer( ogrDataSource, 0 );
100

  
101 156
    // get the extent_ (envelope) of the layer
102 157

  
103 158
    QgsDebugMsg( "Starting get extent" );
......
145 200
  }
146 201
}
147 202

  
203
QStringList QgsOgrProvider::subLayers()
204
{
205
  QStringList theList = QStringList();
206
  if (! valid )
207
  {
208
    return theList;
209
  }
210
  for ( int i = 0; i < layerCount() ; i++ )
211
  {  
212
    QString theLayerName = QString(OGR_FD_GetName(OGR_L_GetLayerDefn(OGR_DS_GetLayer( ogrDataSource, i ))));
213
    QGis::WkbType layerGeomType = (QGis::WkbType)(OGR_FD_GetGeomType(OGR_L_GetLayerDefn(OGR_DS_GetLayer( ogrDataSource, i ))));
214

  
215
    int theLayerFeatureCount=OGR_L_GetFeatureCount(OGR_DS_GetLayer( ogrDataSource, i ),1) ;
216

  
217
    QString geom;
218
    switch (layerGeomType)
219
    {
220
      case QGis::WKBPoint:
221
        geom="WKBPoint";
222
        break;
223
      case QGis::WKBLineString:
224
        geom="WKBLineString";
225
        break;
226
      case QGis::WKBPolygon:
227
        geom="WKBPolygon";
228
        break;
229
      case QGis::WKBMultiPoint:
230
        geom="WKBMultiPoint";
231
        break;
232
      case QGis::WKBMultiLineString:
233
        geom="WKBMultiLineString";
234
        break;
235
      case QGis::WKBUnknown:
236
        geom="WKBUnknown";
237
        break;
238
      case QGis::WKBPoint25D:
239
        geom="WKBPoint25D";
240
        break;
241
      case QGis::WKBLineString25D:
242
        geom="WKBLineString25D";
243
        break;
244
      case QGis::WKBPolygon25D:
245
        geom="WKBPolygon25D";
246
        break;
247
      case QGis::WKBMultiPoint25D:
248
        geom="WKBMultiPoint25D";
249
        break;
250
      case QGis::WKBMultiLineString25D:
251
        geom="WKBMultiLineString25D";
252
        break;
253
      case QGis::WKBMultiPolygon25D:
254
        geom="WKBMultiPolygon25D";
255
        break;
256
      default:
257
        geom="Unknown OGR geometry ID->" + QString::number(layerGeomType);
258
    }
259
    theList.append(QString::number(i)+":"+ theLayerName+":"+QString::number(theLayerFeatureCount)+":"+geom);
260
  }
261
  return theList;
262
}
263

  
148 264
void QgsOgrProvider::setEncoding( const QString& e )
149 265
{
150 266
  QgsVectorDataProvider::setEncoding( e );
src/ui/qgsogrsublayersdialogbase.ui (révision 0)
1
<ui version="4.0" >
2
 <class>QgsOGRSublayersDialogBase</class>
3
 <widget class="QDialog" name="QgsOGRSublayersDialogBase" >
4
  <property name="geometry" >
5
   <rect>
6
    <x>0</x>
7
    <y>0</y>
8
    <width>584</width>
9
    <height>535</height>
10
   </rect>
11
  </property>
12
  <property name="windowTitle" >
13
   <string>Select OGR layers to load</string>
14
  </property>
15
  <property name="windowIcon" >
16
   <iconset>../../../qgis_1.0.0/src/plugins/ogrsublayers</iconset>
17
  </property>
18
  <layout class="QGridLayout" >
19
   <property name="leftMargin" >
20
    <number>9</number>
21
   </property>
22
   <property name="topMargin" >
23
    <number>9</number>
24
   </property>
25
   <property name="rightMargin" >
26
    <number>9</number>
27
   </property>
28
   <property name="bottomMargin" >
29
    <number>9</number>
30
   </property>
31
   <property name="horizontalSpacing" >
32
    <number>6</number>
33
   </property>
34
   <property name="verticalSpacing" >
35
    <number>6</number>
36
   </property>
37
   <item row="0" column="0" >
38
    <widget class="QLabel" name="txtHeading" >
39
     <property name="sizePolicy" >
40
      <sizepolicy vsizetype="Minimum" hsizetype="Preferred" >
41
       <horstretch>0</horstretch>
42
       <verstretch>0</verstretch>
43
      </sizepolicy>
44
     </property>
45
     <property name="font" >
46
      <font>
47
       <family>Sans Serif</family>
48
       <pointsize>24</pointsize>
49
       <weight>75</weight>
50
       <italic>false</italic>
51
       <bold>true</bold>
52
       <underline>false</underline>
53
       <strikeout>false</strikeout>
54
      </font>
55
     </property>
56
     <property name="text" >
57
      <string>Sub layers list</string>
58
     </property>
59
     <property name="alignment" >
60
      <set>Qt::AlignCenter</set>
61
     </property>
62
    </widget>
63
   </item>
64
   <item row="8" column="0" >
65
    <widget class="QDialogButtonBox" name="buttonBox" >
66
     <property name="orientation" >
67
      <enum>Qt::Horizontal</enum>
68
     </property>
69
     <property name="standardButtons" >
70
      <set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
71
     </property>
72
    </widget>
73
   </item>
74
   <item row="1" column="0" >
75
    <widget class="QTextEdit" name="textEdit" >
76
     <property name="html" >
77
      <string>&lt;html>&lt;head>&lt;meta name="qrichtext" content="1" />&lt;style type="text/css">
78
p, li { white-space: pre-wrap; }
79
&lt;/style>&lt;/head>&lt;body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;">
80
&lt;p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This is the list of all layers available in the datasource of the active layer. You can select the layers to load. The layers will be loaded when you press "OK".&lt;/p>
81
&lt;p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">&lt;/p>
82
&lt;p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The layer name is format dependant. Consult the OGR documentation or the documentation of your data format to determine the nature of the included information.&lt;/p>
83
&lt;p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">&lt;/p>
84
&lt;p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">&lt;span style=" font-weight:600;">Be advised: &lt;/span>selecting an already opened layer will not generate an error message and the layer will end up loaded twice!&lt;/p>&lt;/body>&lt;/html></string>
85
     </property>
86
    </widget>
87
   </item>
88
   <item row="2" column="0" >
89
    <widget class="QTreeWidget" name="layersTable" >
90
     <property name="windowModality" >
91
      <enum>Qt::NonModal</enum>
92
     </property>
93
     <property name="selectionMode" >
94
      <enum>QAbstractItemView::ExtendedSelection</enum>
95
     </property>
96
     <property name="selectionBehavior" >
97
      <enum>QAbstractItemView::SelectRows</enum>
98
     </property>
99
     <column>
100
      <property name="text" >
101
       <string>1</string>
102
      </property>
103
     </column>
104
    </widget>
105
   </item>
106
  </layout>
107
 </widget>
108
 <layoutdefault spacing="6" margin="11" />
109
 <resources/>
110
 <connections/>
111
</ui>