diff

patch to allow addition of raster from multilayer datasources like rasterlite - Jürgen Fischer, 2010-06-27 04:19 PM

Download (16 KB)

 
1
Index: src/app/qgisapp.h
2
===================================================================
3
--- src/app/qgisapp.h	(revision 13817)
4
+++ src/app/qgisapp.h	(working copy)
5
@@ -753,10 +753,10 @@
6
     void composerWillBeRemoved( QgsComposerView* v );
7
 
8
   private:
9
-    /** This method will open a dialog so the user can select the sublayers
10
-    * to load
11
+    /** This method will open a dialog so the user can select the sublayers to load
12
     */
13
-    void askUserForSublayers( QgsVectorLayer *layer );
14
+    void askUserForOGRSublayers( QgsVectorLayer *layer );
15
+    void askUserForGDALSublayers( QgsRasterLayer *layer );
16
     /** Add a raster layer to the map (passed in as a ptr).
17
      * It won't force a refresh.
18
      */
19
Index: src/app/qgisapp.cpp
20
===================================================================
21
--- src/app/qgisapp.cpp	(revision 13817)
22
+++ src/app/qgisapp.cpp	(working copy)
23
@@ -2620,7 +2620,7 @@
24
       // sublayers selection dialog so the user can select the sublayers to actually load.
25
       if ( sublayers.count() > 1 )
26
       {
27
-        askUserForSublayers( layer );
28
+        askUserForOGRSublayers( layer );
29
 
30
         // The first layer loaded is not useful in that case. The user can select it in
31
         // the list if he wants to load it.
32
@@ -2673,18 +2673,49 @@
33
   return true;
34
 } // QgisApp::addVectorLayer()
35
 
36
+void QgisApp::askUserForGDALSublayers( QgsRasterLayer *layer )
37
+{
38
+  if ( !layer )
39
+    return;
40
+
41
+  QStringList sublayers = layer->subLayers();
42
+
43
+  QgsDebugMsg( "sublayers:\n  " + sublayers.join( "  \n" ) + "\n" );
44
+
45
+  // We initialize a selection dialog and display it.
46
+  QgsOGRSublayersDialog chooseSublayersDialog( this );
47
+  chooseSublayersDialog.setWindowTitle( tr( "Select raster layers to add..." ) );
48
+
49
+  QStringList layers;
50
+  for ( int i = 0; i < sublayers.size(); i++ )
51
+  {
52
+    layers << QString( "%1|%2|1|%3" ).arg( i ).arg( sublayers[i] ).arg( tr( "Raster" ) );
53
+  }
54
+
55
+  chooseSublayersDialog.populateLayerTable( layers, "|" );
56
+
57
+  if ( chooseSublayersDialog.exec() )
58
+  {
59
+    foreach( QString layer, chooseSublayersDialog.getSelection() )
60
+    {
61
+      QgsRasterLayer *rlayer = new QgsRasterLayer( layer, layer );
62
+      if ( rlayer && rlayer->isValid() )
63
+      {
64
+        addRasterLayer( rlayer );
65
+      }
66
+    }
67
+  }
68
+}
69
+
70
 // This method is the method that does the real job. If the layer given in
71
 // parameter is NULL, then the method tries to act on the activeLayer.
72
-void QgisApp::askUserForSublayers( QgsVectorLayer *layer )
73
+void QgisApp::askUserForOGRSublayers( QgsVectorLayer *layer )
74
 {
75
   if ( layer == NULL )
76
   {
77
-    if ( activeLayer() == NULL || activeLayer()->type() != QgsMapLayer::VectorLayer )
78
+    layer = qobject_cast<QgsVectorLayer *>( activeLayer() );
79
+    if ( !layer || layer->dataProvider()->name() != "ogr" )
80
       return;
81
-
82
-    layer = ( QgsVectorLayer* ) activeLayer();
83
-    if ( layer->dataProvider()->name() != "ogr" )
84
-      return;
85
   }
86
 
87
   QStringList sublayers = layer->dataProvider()->subLayers();
88
@@ -2692,6 +2723,7 @@
89
 
90
   // We initialize a selection dialog and display it.
91
   QgsOGRSublayersDialog chooseSublayersDialog( this );
92
+  chooseSublayersDialog.setWindowTitle( tr( "Select vector layers to add..." ) );
93
   chooseSublayersDialog.populateLayerTable( sublayers );
94
 
95
   if ( chooseSublayersDialog.exec() )
96
@@ -6332,16 +6364,28 @@
97
 
98
       // create the layer
99
       QgsRasterLayer *layer = new QgsRasterLayer( *myIterator, myBaseNameQString );
100
+      QStringList sublayers = layer->subLayers();
101
 
102
-      addRasterLayer( layer );
103
+      if ( sublayers.size() > 0 )
104
+      {
105
+        askUserForGDALSublayers( layer );
106
 
107
-      //only allow one copy of a ai grid file to be loaded at a
108
-      //time to prevent the user selecting all adfs in 1 dir which
109
-      //actually represent 1 coverate,
110
+        // The first layer loaded is not useful in that case. The user can select it in
111
+        // the list if he wants to load it.
112
+        delete layer;
113
+      }
114
+      else
115
+      {
116
+        addRasterLayer( layer );
117
 
118
-      if ( myBaseNameQString.toLower().endsWith( ".adf" ) )
119
-      {
120
-        break;
121
+        //only allow one copy of a ai grid file to be loaded at a
122
+        //time to prevent the user selecting all adfs in 1 dir which
123
+        //actually represent 1 coverate,
124
+
125
+        if ( myBaseNameQString.toLower().endsWith( ".adf" ) )
126
+        {
127
+          break;
128
+        }
129
       }
130
     }
131
     else
132
Index: src/app/ogr/qgsogrsublayersdialog.h
133
===================================================================
134
--- src/app/ogr/qgsogrsublayersdialog.h	(revision 13817)
135
+++ src/app/ogr/qgsogrsublayersdialog.h	(working copy)
136
@@ -19,18 +19,19 @@
137
 
138
 #include <QDialog>
139
 #include <ui_qgsogrsublayersdialogbase.h>
140
+#include "qgscontexthelp.h"
141
 
142
-
143
-
144
 class QgsOGRSublayersDialog : public QDialog, private Ui::QgsOGRSublayersDialogBase
145
 {
146
     Q_OBJECT
147
   public:
148
     QgsOGRSublayersDialog( QWidget* parent = 0, Qt::WFlags fl = 0 );
149
     ~QgsOGRSublayersDialog();
150
-    void populateLayerTable( QStringList theList );
151
+    void populateLayerTable( QStringList theList, QString delim = ":" );
152
     QStringList getSelection();
153
 
154
+  public slots:
155
+    void on_buttonBox_helpRequested() { QgsContextHelp::run( metaObject()->className() ); }
156
 };
157
 
158
 #endif
159
Index: src/app/ogr/qgsogrsublayersdialog.cpp
160
===================================================================
161
--- src/app/ogr/qgsogrsublayersdialog.cpp	(revision 13817)
162
+++ src/app/ogr/qgsogrsublayersdialog.cpp	(working copy)
163
@@ -42,14 +42,14 @@
164
   return list;
165
 }
166
 
167
-void QgsOGRSublayersDialog::populateLayerTable( QStringList theList )
168
+void QgsOGRSublayersDialog::populateLayerTable( QStringList theList, QString delim )
169
 {
170
   for ( int i = 0; i < theList.size(); i++ )
171
   {
172
-    QString ligne = theList.at( i );
173
-    QStringList elements = ligne.split( ":" );
174
+    QString line = theList.at( i );
175
+    QStringList elements = line.split( delim );
176
     QStringList item = QStringList();
177
     item << elements.at( 0 ) << elements.at( 1 ) << elements.at( 2 ) << elements.at( 3 );
178
-    layersTable -> addTopLevelItem( new QTreeWidgetItem( item ) );
179
+    layersTable->addTopLevelItem( new QTreeWidgetItem( item ) );
180
   }
181
 }
182
Index: src/core/raster/qgsrasterlayer.cpp
183
===================================================================
184
--- src/core/raster/qgsrasterlayer.cpp	(revision 13817)
185
+++ src/core/raster/qgsrasterlayer.cpp	(working copy)
186
@@ -444,10 +444,8 @@
187
 /**
188
  * This helper checks to see whether the file name appears to be a valid raster file name
189
  */
190
-bool QgsRasterLayer::isValidRasterFileName( QString const & theFileNameQString,
191
-    QString & retErrMsg )
192
+bool QgsRasterLayer::isValidRasterFileName( QString const & theFileNameQString, QString & retErrMsg )
193
 {
194
-
195
   GDALDatasetH myDataset;
196
   registerGdalDrivers();
197
 
198
@@ -463,10 +461,15 @@
199
   }
200
   else if ( GDALGetRasterCount( myDataset ) == 0 )
201
   {
202
-    GDALClose( myDataset );
203
-    myDataset = NULL;
204
-    retErrMsg = "This raster file has no bands and is invalid as a raster layer.";
205
-    return false;
206
+    QStringList layers = subLayers( myDataset );
207
+    if ( layers.size() == 0 )
208
+    {
209
+      GDALClose( myDataset );
210
+      myDataset = NULL;
211
+      retErrMsg = tr( "This raster file has no bands and is invalid as a raster layer." );
212
+      return false;
213
+    }
214
+    return true;
215
   }
216
   else
217
   {
218
@@ -476,10 +479,8 @@
219
 }
220
 
221
 bool QgsRasterLayer::isValidRasterFileName( QString const & theFileNameQString )
222
-
223
 {
224
   QString retErrMsg;
225
-
226
   return isValidRasterFileName( theFileNameQString, retErrMsg );
227
 }
228
 
229
@@ -2610,7 +2611,7 @@
230
       }
231
       else
232
       {
233
-        QgsDebugMsg( "band " + QString::number( i ) + "has no metadata" );
234
+        QgsDebugMsg( "band " + QString::number( i ) + " has no metadata" );
235
       }
236
 
237
       char ** GDALcategories = GDALGetRasterCategoryNames( gdalBand );
238
@@ -3565,18 +3566,40 @@
239
   emit statusChanged( theMessage );
240
 }
241
 
242
+QStringList QgsRasterLayer::subLayers( GDALDatasetH dataset )
243
+{
244
+  QStringList subLayers;
245
+
246
+  char **metadata = GDALGetMetadata( dataset, "SUBDATASETS" );
247
+  if ( metadata )
248
+  {
249
+    for ( int i = 0; metadata[i] != NULL; i++ )
250
+    {
251
+      QString layer = QString::fromUtf8( metadata[i] );
252
+
253
+      int pos = layer.indexOf( "_NAME=" );
254
+      if ( pos >= 0 )
255
+      {
256
+        subLayers << layer.mid( pos + 6 );
257
+      }
258
+    }
259
+  }
260
+
261
+  QgsDebugMsg( "sublayers:\n  " + subLayers.join( "\n  " ) );
262
+
263
+  return subLayers;
264
+}
265
+
266
 QStringList QgsRasterLayer::subLayers() const
267
 {
268
-
269
   if ( mDataProvider )
270
   {
271
     return mDataProvider->subLayers();
272
   }
273
   else
274
   {
275
-    return QStringList();   // Empty
276
+    return subLayers( mGdalDataset );
277
   }
278
-
279
 }
280
 
281
 void QgsRasterLayer::thumbnailAsPixmap( QPixmap * theQPixmap )
282
@@ -5219,6 +5242,13 @@
283
     GDALReferenceDataset( mGdalDataset );
284
   }
285
 
286
+  if ( subLayers().size() > 0 )
287
+  {
288
+    // just to get the sublayers
289
+    mValid = false;
290
+    return true;
291
+  }
292
+
293
   //check f this file has pyramids
294
   GDALRasterBandH myGDALBand = GDALGetRasterBand( mGdalDataset, 1 ); //just use the first band
295
   if ( myGDALBand == NULL )
296
@@ -5231,15 +5261,9 @@
297
     mValid = false;
298
     return false;
299
   }
300
-  if ( GDALGetOverviewCount( myGDALBand ) > 0 )
301
-  {
302
-    mHasPyramids = true;
303
-  }
304
-  else
305
-  {
306
-    mHasPyramids = false;
307
-  }
308
 
309
+  mHasPyramids = GDALGetOverviewCount( myGDALBand ) > 0;
310
+
311
   //populate the list of what pyramids exist
312
   buildPyramidList();
313
 
314
Index: src/core/raster/qgsrasterlayer.h
315
===================================================================
316
--- src/core/raster/qgsrasterlayer.h	(revision 13817)
317
+++ src/core/raster/qgsrasterlayer.h	(working copy)
318
@@ -284,9 +284,10 @@
319
      *  returned in retError.
320
      */
321
     static bool isValidRasterFileName( const QString & theFileNameQString, QString &retError );
322
-
323
     static bool isValidRasterFileName( const QString & theFileNameQString );
324
+    static QStringList subLayers( GDALDatasetH dataset );
325
 
326
+
327
     /** Return time stamp for given file name */
328
     static QDateTime lastModified( const QString &  name );
329
 
330
Index: src/ui/qgsogrsublayersdialogbase.ui
331
===================================================================
332
--- src/ui/qgsogrsublayersdialogbase.ui	(revision 13817)
333
+++ src/ui/qgsogrsublayersdialogbase.ui	(working copy)
334
@@ -1,103 +1,45 @@
335
-<ui version="4.0" >
336
+<?xml version="1.0" encoding="UTF-8"?>
337
+<ui version="4.0">
338
  <class>QgsOGRSublayersDialogBase</class>
339
- <widget class="QDialog" name="QgsOGRSublayersDialogBase" >
340
-  <property name="geometry" >
341
+ <widget class="QDialog" name="QgsOGRSublayersDialogBase">
342
+  <property name="geometry">
343
    <rect>
344
     <x>0</x>
345
     <y>0</y>
346
     <width>584</width>
347
-    <height>535</height>
348
+    <height>236</height>
349
    </rect>
350
   </property>
351
-  <property name="windowTitle" >
352
-   <string>Select OGR layers to load</string>
353
+  <property name="windowTitle">
354
+   <string>Select layers to load</string>
355
   </property>
356
-  <property name="windowIcon" >
357
-   <iconset>../../../qgis_1.0.0/src/plugins/ogrsublayers</iconset>
358
-  </property>
359
-  <layout class="QGridLayout" >
360
-   <property name="leftMargin" >
361
+  <layout class="QGridLayout">
362
+   <property name="margin">
363
     <number>9</number>
364
    </property>
365
-   <property name="topMargin" >
366
-    <number>9</number>
367
-   </property>
368
-   <property name="rightMargin" >
369
-    <number>9</number>
370
-   </property>
371
-   <property name="bottomMargin" >
372
-    <number>9</number>
373
-   </property>
374
-   <property name="horizontalSpacing" >
375
+   <property name="spacing">
376
     <number>6</number>
377
    </property>
378
-   <property name="verticalSpacing" >
379
-    <number>6</number>
380
-   </property>
381
-   <item row="0" column="0" >
382
-    <widget class="QLabel" name="txtHeading" >
383
-     <property name="sizePolicy" >
384
-      <sizepolicy vsizetype="Minimum" hsizetype="Preferred" >
385
-       <horstretch>0</horstretch>
386
-       <verstretch>0</verstretch>
387
-      </sizepolicy>
388
-     </property>
389
-     <property name="font" >
390
-      <font>
391
-       <family>Sans Serif</family>
392
-       <pointsize>24</pointsize>
393
-       <weight>75</weight>
394
-       <italic>false</italic>
395
-       <bold>true</bold>
396
-       <underline>false</underline>
397
-       <strikeout>false</strikeout>
398
-      </font>
399
-     </property>
400
-     <property name="text" >
401
-      <string>Sub layers list</string>
402
-     </property>
403
-     <property name="alignment" >
404
-      <set>Qt::AlignCenter</set>
405
-     </property>
406
-    </widget>
407
-   </item>
408
-   <item row="8" column="0" >
409
-    <widget class="QDialogButtonBox" name="buttonBox" >
410
-     <property name="orientation" >
411
+   <item row="6" column="0">
412
+    <widget class="QDialogButtonBox" name="buttonBox">
413
+     <property name="orientation">
414
       <enum>Qt::Horizontal</enum>
415
      </property>
416
-     <property name="standardButtons" >
417
-      <set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
418
+     <property name="standardButtons">
419
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Ok</set>
420
      </property>
421
     </widget>
422
    </item>
423
-   <item row="1" column="0" >
424
-    <widget class="QTextEdit" name="textEdit" >
425
-     <property name="html" >
426
-      <string>&lt;html>&lt;head>&lt;meta name="qrichtext" content="1" />&lt;style type="text/css">
427
-p, li { white-space: pre-wrap; }
428
-&lt;/style>&lt;/head>&lt;body style=" font-family:'DejaVu Sans'; font-size:9pt; font-weight:400; font-style:normal;">
429
-&lt;p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif';">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>
430
-&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; font-family:'Sans Serif';">&lt;/p>
431
-&lt;p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif';">The layer name is format dependent. Consult the OGR documentation or the documentation of your data format to determine the nature of the included information.&lt;/p>
432
-&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; font-family:'Sans Serif';">&lt;/p>
433
-&lt;p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif';">&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>
434
-     </property>
435
-    </widget>
436
-   </item>
437
-   <item row="2" column="0" >
438
-    <widget class="QTreeWidget" name="layersTable" >
439
-     <property name="windowModality" >
440
-      <enum>Qt::NonModal</enum>
441
-     </property>
442
-     <property name="selectionMode" >
443
+   <item row="0" column="0">
444
+    <widget class="QTreeWidget" name="layersTable">
445
+     <property name="selectionMode">
446
       <enum>QAbstractItemView::ExtendedSelection</enum>
447
      </property>
448
-     <property name="selectionBehavior" >
449
+     <property name="selectionBehavior">
450
       <enum>QAbstractItemView::SelectRows</enum>
451
      </property>
452
      <column>
453
-      <property name="text" >
454
+      <property name="text">
455
        <string>1</string>
456
       </property>
457
      </column>
458
@@ -105,7 +47,7 @@
459
    </item>
460
   </layout>
461
  </widget>
462
- <layoutdefault spacing="6" margin="11" />
463
+ <layoutdefault spacing="6" margin="11"/>
464
  <resources/>
465
  <connections>
466
   <connection>
467
@@ -114,11 +56,11 @@
468
    <receiver>QgsOGRSublayersDialogBase</receiver>
469
    <slot>accept()</slot>
470
    <hints>
471
-    <hint type="sourcelabel" >
472
+    <hint type="sourcelabel">
473
      <x>446</x>
474
      <y>508</y>
475
     </hint>
476
-    <hint type="destinationlabel" >
477
+    <hint type="destinationlabel">
478
      <x>351</x>
479
      <y>473</y>
480
     </hint>
481
@@ -130,11 +72,11 @@
482
    <receiver>QgsOGRSublayersDialogBase</receiver>
483
    <slot>reject()</slot>
484
    <hints>
485
-    <hint type="sourcelabel" >
486
+    <hint type="sourcelabel">
487
      <x>541</x>
488
      <y>507</y>
489
     </hint>
490
-    <hint type="destinationlabel" >
491
+    <hint type="destinationlabel">
492
      <x>503</x>
493
      <y>434</y>
494
     </hint>