~ubuntu-branches/ubuntu/quantal/qgis/quantal

« back to all changes in this revision

Viewing changes to src/plugins/grass/qgsgrassselect.cpp

  • Committer: Bazaar Package Importer
  • Author(s): William Grant
  • Date: 2007-05-06 13:42:32 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20070506134232-pyli6t388w5asd8x
Tags: 0.8.0-3ubuntu1
* Merge from Debian unstable. Remaining Ubuntu changes:
  - debian/rules, debian/qgis.install, debian/qgis.dirs debian/qgis.desktop:
    Add and install .desktop.
* debian/qgis.desktop: Remove Applications category; it's not real.
* Modify Maintainer value to match Debian-Maintainer-Field Spec

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
    qgsgrassselect.cpp  -  Select GRASS layer dialog
 
3
                             -------------------
 
4
    begin                : March, 2004
 
5
    copyright            : (C) 2004 by Radim Blazek
 
6
    email                : blazek@itc.it
 
7
 ***************************************************************************/
 
8
/***************************************************************************
 
9
 *                                                                         *
 
10
 *   This program is free software; you can redistribute it and/or modify  *
 
11
 *   it under the terms of the GNU General Public License as published by  *
 
12
 *   the Free Software Foundation; either version 2 of the License, or     *
 
13
 *   (at your option) any later version.                                   *
 
14
 *                                                                         *
 
15
 ***************************************************************************/
 
16
#include <iostream>
 
17
#include <qdir.h>
 
18
#include <qfile.h>
 
19
#include <QFileDialog> 
 
20
#include <qsettings.h>
 
21
#include <qpixmap.h>
 
22
#include <q3listbox.h>
 
23
#include <qstringlist.h>
 
24
#include <qlabel.h>
 
25
#include <QComboBox>
 
26
#include <qmessagebox.h>
 
27
#include <qinputdialog.h>
 
28
#include <qsettings.h>
 
29
 
 
30
extern "C" {
 
31
#include <grass/gis.h>
 
32
#include <grass/Vect.h>
 
33
}
 
34
 
 
35
#include "../../src/providers/grass/qgsgrass.h"
 
36
#include "qgsgrassselect.h"
 
37
 
 
38
QgsGrassSelect::QgsGrassSelect(int type):QgsGrassSelectBase()
 
39
{
 
40
#ifdef QGISDEBUG
 
41
  std::cerr << "QgsGrassSelect() type = " << type << std::endl;
 
42
#endif
 
43
 
 
44
  setupUi(this);
 
45
 
 
46
  if ( first ) {
 
47
    if ( QgsGrass::activeMode() ) {
 
48
      lastGisdbase = QgsGrass::getDefaultGisdbase();
 
49
      lastLocation = QgsGrass::getDefaultLocation();
 
50
      lastMapset = QgsGrass::getDefaultMapset();
 
51
    } else {
 
52
      QSettings settings;
 
53
      lastGisdbase = settings.readEntry("/GRASS/lastGisdbase");
 
54
      //check we got something from qsettings otherwise default to users home dir
 
55
      if (lastGisdbase.isEmpty())
 
56
      {
 
57
        QDir home = QDir::home();
 
58
        lastGisdbase = QString( home.path() );
 
59
      }
 
60
    }
 
61
    first = false;
 
62
  }
 
63
    QgsGrassSelect::type = type;
 
64
 
 
65
    switch ( type ) 
 
66
    {
 
67
        case QgsGrassSelect::VECTOR:
 
68
            setCaption ( tr("Select GRASS Vector Layer") );
 
69
            break;
 
70
 
 
71
        case QgsGrassSelect::RASTER:
 
72
            /* Remove layer combo box */
 
73
            Layer->hide();
 
74
            elayer->hide();
 
75
            setCaption ( tr("Select GRASS Raster Layer") );
 
76
            break;
 
77
 
 
78
        case QgsGrassSelect::MAPCALC:
 
79
            /* Remove layer combo box */
 
80
            Layer->hide();
 
81
            elayer->hide();
 
82
            setCaption ( tr("Select GRASS mapcalc schema") );
 
83
            break;
 
84
            
 
85
        case QgsGrassSelect::MAPSET:
 
86
            Layer->hide();
 
87
            elayer->hide();
 
88
            MapName->hide();
 
89
            emap->hide();
 
90
            setCaption ( tr("Select GRASS Mapset") );
 
91
            break;
 
92
    }
 
93
            
 
94
    egisdbase->setText(lastGisdbase);
 
95
 
 
96
    setLocations();
 
97
 
 
98
    restorePosition();
 
99
}
 
100
 
 
101
QgsGrassSelect::~QgsGrassSelect()
 
102
{
 
103
    saveWindowLocation();
 
104
}
 
105
 
 
106
void QgsGrassSelect::restorePosition()
 
107
{
 
108
  optionsFrame->adjustSize ();
 
109
  adjustSize ();
 
110
  
 
111
  QSettings settings;
 
112
  int ww = settings.readNumEntry("/GRASS/windows/select/w", 500);
 
113
  int wh = settings.readNumEntry("/GRASS/windows/select/h", 100);
 
114
  int wx = settings.readNumEntry("/GRASS/windows/select/x", 100);
 
115
  int wy = settings.readNumEntry("/GRASS/windows/select/y", 100);
 
116
  resize(ww,height());
 
117
  move(wx,wy);
 
118
}
 
119
 
 
120
void QgsGrassSelect::saveWindowLocation()
 
121
{
 
122
  QSettings settings;
 
123
  QPoint p = this->pos();
 
124
  QSize s = this->size();
 
125
  settings.writeEntry("/GRASS/windows/select/x", p.x());
 
126
  settings.writeEntry("/GRASS/windows/select/y", p.y());
 
127
  settings.writeEntry("/GRASS/windows/select/w", s.width());
 
128
  settings.writeEntry("/GRASS/windows/select/h", s.height());
 
129
 
130
 
 
131
bool QgsGrassSelect::first = true;
 
132
QString QgsGrassSelect::lastGisdbase;
 
133
QString QgsGrassSelect::lastLocation;
 
134
QString QgsGrassSelect::lastMapset;
 
135
QString QgsGrassSelect::lastVectorMap;
 
136
QString QgsGrassSelect::lastRasterMap;
 
137
QString QgsGrassSelect::lastLayer;
 
138
QString QgsGrassSelect::lastMapcalc;
 
139
 
 
140
void QgsGrassSelect::setLocations()
 
141
{
 
142
    elocation->clear();
 
143
    emapset->clear();
 
144
    emap->clear();
 
145
    elayer->clear();
 
146
 
 
147
    QDir d = QDir( egisdbase->text() );
 
148
 
 
149
    int idx = 0;
 
150
    int sel = -1;
 
151
    // Add all subdirs containing PERMANENT/DEFAULT_WIND
 
152
    for ( unsigned int i = 0; i < d.count(); i++ ) {
 
153
        if ( d[i] == "." || d[i] == ".." ) continue; 
 
154
 
 
155
        QString ldpath = egisdbase->text() + "/" + d[i];
 
156
 
 
157
        /* TODO: G_is_location() was added to GRASS 6.1 06-05-24,
 
158
           enable its use after some period (others do update) */
 
159
        /*
 
160
        if ( QgsGrass::versionMajor() > 6 || QgsGrass::versionMinor() > 0 )
 
161
        { 
 
162
            if ( !G_is_location( ldpath.toLocal8Bit().constData() ) ) continue;
 
163
        }
 
164
        else
 
165
        {
 
166
        */
 
167
            QString chf = egisdbase->text() + "/" + d[i] + "/PERMANENT/DEFAULT_WIND";
 
168
            if ( !QFile::exists ( chf ) ) continue;
 
169
        //}
 
170
                    
 
171
        // if type is MAPSET check also if at least one mapset owned by user exists
 
172
        if  ( QgsGrassSelect::type == QgsGrassSelect::MAPSET )
 
173
        {
 
174
            bool exists = false;
 
175
            
 
176
            QDir ld = QDir( ldpath );
 
177
         
 
178
            for ( unsigned int j = 0; j < ld.count(); j++ ) 
 
179
            {
 
180
                if ( !QgsGrass::isMapset( ldpath + "/" + ld[j] ) ) continue;
 
181
                
 
182
                QFileInfo info ( ldpath + "/" + ld[j] );
 
183
                if ( !info.isWritable() ) continue;
 
184
 
 
185
                // TODO: check if owner == user: how to get uer name in QT
 
186
                
 
187
                exists = true;
 
188
                break;
 
189
            }
 
190
        
 
191
            if ( !exists ) continue;
 
192
        }
 
193
    
 
194
        elocation->insertItem ( QString ( d[i] ), -1 );
 
195
        if ( QString ( d[i] ) == lastLocation ) {
 
196
            sel = idx;
 
197
        }
 
198
        idx++;
 
199
    }
 
200
    if ( sel >= 0 ) {
 
201
        elocation->setCurrentItem(sel);
 
202
    }
 
203
 
 
204
    setMapsets();
 
205
}
 
206
 
 
207
 
 
208
void QgsGrassSelect::setMapsets()
 
209
{
 
210
    #ifdef QGISDEBUG
 
211
    std::cerr << "setMapsets()" << std::endl;
 
212
    #endif
 
213
    
 
214
    emapset->clear();
 
215
    emap->clear();
 
216
    elayer->clear();
 
217
 
 
218
    if ( elocation->count() < 1 ) return;
 
219
 
 
220
    // Location directory    
 
221
    QString ldpath = egisdbase->text() + "/" + elocation->currentText();
 
222
    QDir ld = QDir( ldpath );
 
223
 
 
224
    int idx = 0;
 
225
    int sel = -1;
 
226
 
 
227
    // Go through all subdirs and add all subdirs from vector/ 
 
228
    for ( unsigned int i = 0; i < ld.count(); i++ ) 
 
229
    {
 
230
        if ( QgsGrass::isMapset( ldpath + "/" + ld[i] ) ) 
 
231
        {
 
232
            emapset->insertItem ( ld[i], -1 );
 
233
            if ( ld[i] == lastMapset ) {
 
234
                sel = idx;
 
235
            }
 
236
            idx++;
 
237
        }
 
238
    }
 
239
    if ( sel >= 0 ) {
 
240
        emapset->setCurrentItem(sel);
 
241
    }
 
242
 
 
243
    setMaps();
 
244
}
 
245
 
 
246
void QgsGrassSelect::setMaps()
 
247
{
 
248
    #ifdef QGISDEBUG
 
249
    std::cerr << "setMaps()" << std::endl;
 
250
    #endif
 
251
 
 
252
    // Replaced by text box to enable wild cards
 
253
    emap->clear();
 
254
    elayer->clear();
 
255
 
 
256
    if ( emapset->count() < 1 ) return;
 
257
 
 
258
    // Mapset directory    
 
259
    QString ldpath = egisdbase->text() + "/" + elocation->currentText() + "/" + emapset->currentText();
 
260
    QDir ld = QDir( ldpath );
 
261
 
 
262
    int idx = 0;
 
263
    int sel = -1;
 
264
 
 
265
    if (type == VECTOR ) // vector
 
266
    {
 
267
        QStringList list = QgsGrass::vectors ( egisdbase->text(), 
 
268
                              elocation->currentText(), emapset->currentText() );
 
269
        
 
270
        for ( int j = 0; j < list.count(); j++ ) 
 
271
        {
 
272
            emap->insertItem ( list[j], -1 );
 
273
            if ( list[j] == lastVectorMap ) sel = idx;
 
274
            idx++;
 
275
        }
 
276
        
 
277
    } 
 
278
    else if ( type == RASTER ) 
 
279
    {
 
280
        /* add cells */
 
281
        QStringList list = QgsGrass::rasters ( egisdbase->text(), 
 
282
                              elocation->currentText(), emapset->currentText() );
 
283
        
 
284
        for ( int j = 0; j < list.count(); j++ ) 
 
285
        {
 
286
            emap->insertItem ( list[j], -1 );
 
287
            if ( list[j] == lastRasterMap ) sel = idx;
 
288
            idx++;
 
289
        }
 
290
 
 
291
        /* add groups */
 
292
        // TODO add QgsGrass::groups ( use G_list( G_ELEMENT_GROUP) )
 
293
        QDir md = QDir( ldpath + "/group/" );
 
294
        md.setFilter (QDir::Dirs);
 
295
        
 
296
        for ( unsigned int j = 0; j < md.count(); j++ ) {
 
297
            if ( md[j] == "." || md[j] == ".." ) continue; 
 
298
 
 
299
            QString m = QString( md[j] + " (GROUP)" );
 
300
            emap->insertItem ( m, -1 );
 
301
            if ( m == lastRasterMap ) {
 
302
                sel = idx;
 
303
            }
 
304
            idx++;
 
305
        }
 
306
    }
 
307
    else if (type == MAPCALC ) 
 
308
    {
 
309
        QDir md = QDir( ldpath + "/mapcalc/" );
 
310
        md.setFilter (QDir::Files);
 
311
        
 
312
        for ( unsigned int j = 0; j < md.count(); j++ ) {
 
313
            QString m = QString( md[j] );
 
314
            emap->insertItem ( m, -1 );
 
315
            if ( m == lastMapcalc ) {
 
316
                sel = idx;
 
317
            }
 
318
            idx++;
 
319
        }
 
320
    }
 
321
    if ( sel >= 0 ) {
 
322
        emap->setCurrentItem(sel);
 
323
    } 
 
324
    /*
 
325
    else 
 
326
    {
 
327
        emap->clearEdit(); // set box line empty
 
328
    }
 
329
    */
 
330
 
 
331
    setLayers();
 
332
}
 
333
 
 
334
void QgsGrassSelect::setLayers()
 
335
{
 
336
    #ifdef QGISDEBUG    
 
337
    std::cerr << "setLayers()" << std::endl;
 
338
    #endif
 
339
    
 
340
    elayer->clear();
 
341
    
 
342
    if (type != VECTOR ) return;
 
343
    if ( emap->count() < 1 ) return;
 
344
 
 
345
    QStringList layers = vectorLayers ( egisdbase->text(),
 
346
              elocation->currentText(), emapset->currentText(),
 
347
              emap->currentText().ascii() );
 
348
    
 
349
    int idx = 0;
 
350
    int sel = -1;
 
351
    for ( int i = 0; i < layers.count(); i++ ) 
 
352
    {
 
353
        elayer->insertItem ( layers[i], -1 );
 
354
        if ( layers[i] == lastLayer ) sel = idx;
 
355
        idx++;
 
356
    }
 
357
        
 
358
    // if last used layer has not been found
 
359
    // make default a map from layer 1
 
360
    if (sel == -1)
 
361
    {
 
362
      for ( int j = 0; j < layers.count(); j++ )
 
363
      {
 
364
        if (layers[j].left(1) == "1")
 
365
        {
 
366
          sel = j;
 
367
          break;
 
368
        }
 
369
      }
 
370
    }
 
371
    
 
372
    if ( sel >= 0 ) {
 
373
        elayer->setCurrentItem(sel);
 
374
    } else {
 
375
        elayer->clearEdit(); // set box line empty
 
376
    }
 
377
 
 
378
    if ( elayer->count() == 1 ) {
 
379
        elayer->setDisabled(true);
 
380
    } else {
 
381
        elayer->setDisabled(false);
 
382
    }
 
383
}
 
384
 
 
385
QStringList QgsGrassSelect::vectorLayers ( QString gisdbase,
 
386
          QString location, QString mapset, QString mapName )
 
387
{
 
388
    QStringList list;
 
389
 
 
390
    // Set location
 
391
    QgsGrass::setLocation ( gisdbase, location);
 
392
 
 
393
    /* Open vector */
 
394
    QgsGrass::resetError();
 
395
    Vect_set_open_level (2);
 
396
    struct Map_info map;
 
397
    int level = Vect_open_old_head (&map, (char *) mapName.ascii(), 
 
398
                                    (char *) mapset.ascii());
 
399
 
 
400
    if ( QgsGrass::getError() == QgsGrass::FATAL ) {
 
401
        std::cerr << "Cannot open GRASS vector: " << QgsGrass::getErrorMessage().toLocal8Bit().data() << std::endl;
 
402
        return list;
 
403
    }
 
404
 
 
405
    if ( level < 2 ) {
 
406
        std::cerr << "Cannot open vector on level 2" << std::endl;
 
407
        QMessageBox::warning( 0, tr("Warning"), tr("Cannot open vector on level 2 (topology not available).") );
 
408
        return list;
 
409
    }
 
410
 
 
411
    #ifdef QGISDEBUG
 
412
    std::cerr << "GRASS vector successfully opened" << std::endl;
 
413
    #endif
 
414
 
 
415
 
 
416
    // Get layers
 
417
    int ncidx = Vect_cidx_get_num_fields ( &map );
 
418
 
 
419
    for ( int i = 0; i < ncidx; i++ ) {
 
420
        int field = Vect_cidx_get_field_number ( &map, i);
 
421
        QString fs;
 
422
        fs.sprintf("%d",field);
 
423
 
 
424
        #ifdef QGISDEBUG
 
425
        std::cerr << "i = " << i << " layer = " << field << std::endl;
 
426
        #endif
 
427
 
 
428
        /* Points */
 
429
        int npoints = Vect_cidx_get_type_count ( &map, field, GV_POINT);
 
430
        if ( npoints > 0 ) {
 
431
            QString l = fs + "_point";
 
432
            list.append ( l );
 
433
        }
 
434
 
 
435
        /* Lines */
 
436
        /* Lines without category appears in layer 0, but not boundaries */
 
437
        int tp;
 
438
        if ( field == 0 ) 
 
439
            tp = GV_LINE;
 
440
        else
 
441
            tp = GV_LINE | GV_BOUNDARY;
 
442
        
 
443
        int nlines = Vect_cidx_get_type_count ( &map, field, tp);
 
444
        if ( nlines > 0 ) {
 
445
            QString l = fs + "_line";
 
446
            list.append ( l );
 
447
        }
 
448
 
 
449
        /* Polygons */
 
450
        int nareas = Vect_cidx_get_type_count ( &map, field, GV_AREA);
 
451
        if ( nareas > 0 ) {
 
452
            QString l = fs + "_polygon";
 
453
            list.append ( l );
 
454
        }
 
455
    }
 
456
    Vect_close ( &map );
 
457
 
 
458
    return list;
 
459
}
 
460
 
 
461
void QgsGrassSelect::on_GisdbaseBrowse_clicked()
 
462
{
 
463
    
 
464
    QString Gisdbase = QFileDialog::getExistingDirectory( this,
 
465
                                 tr("Choose existing GISDBASE"), egisdbase->text() );
 
466
 
 
467
    if ( !Gisdbase.isNull() ) 
 
468
    {
 
469
        egisdbase->setText ( Gisdbase );
 
470
    }
 
471
}
 
472
 
 
473
void QgsGrassSelect::on_ok_clicked()
 
474
{
 
475
    saveWindowLocation();
 
476
 
 
477
    gisdbase = egisdbase->text();
 
478
    lastGisdbase = QString( gisdbase );
 
479
    
 
480
    if ( elocation->count() == 0 ) {
 
481
        QString msg = tr("Wrong GISDBASE, no locations available.");
 
482
        QMessageBox::warning(this, tr("Wrong GISDBASE"), msg);
 
483
        return;
 
484
    }
 
485
 
 
486
    //write to qgsettings as gisdbase seems to be valid
 
487
    QSettings settings;
 
488
    settings.writeEntry("/GRASS/lastGisdbase",lastGisdbase );
 
489
 
 
490
    location = elocation->currentText();
 
491
    lastLocation = location;
 
492
 
 
493
    mapset = emapset->currentText();
 
494
    lastMapset = mapset;
 
495
    
 
496
    map = emap->currentText().stripWhiteSpace();
 
497
 
 
498
    if ( type != QgsGrassSelect::MAPSET && map.isEmpty() ) {
 
499
        QString msg = tr("Select a map.");
 
500
        QMessageBox::warning(0, tr("No map"), msg);
 
501
        return;
 
502
    }
 
503
 
 
504
    if ( type == QgsGrassSelect::VECTOR ) 
 
505
    {
 
506
        if ( elayer->count() == 0 ) 
 
507
        { 
 
508
            QMessageBox::warning(0, tr("No layer"), 
 
509
                    tr("No layers available in this map"));
 
510
            return;
 
511
        }
 
512
        lastVectorMap = map;
 
513
        layer = elayer->currentText().stripWhiteSpace();
 
514
        lastLayer = layer;
 
515
    } else if ( type == QgsGrassSelect::RASTER) { 
 
516
        lastRasterMap = map;
 
517
        if ( map.find(" (GROUP)") != -1 ) {
 
518
            map.remove ( " (GROUP)" );
 
519
            selectedType = QgsGrassSelect::GROUP;
 
520
        } else {
 
521
            selectedType = QgsGrassSelect::RASTER;
 
522
        }
 
523
    } else if ( type == QgsGrassSelect::MAPCALC ) {
 
524
        lastMapcalc = map;
 
525
    }   
 
526
    QDialog::accept();
 
527
}
 
528
 
 
529
void QgsGrassSelect::on_cancel_clicked()
 
530
{
 
531
    saveWindowLocation();
 
532
    QDialog::reject();
 
533
}