📄 qgsgrassprovider.cpp
字号:
{ // the map is already opened, return map id#ifdef QGISDEBUG std::cerr << "The map is already opened with ID = " << i << std::endl;#endif mMaps[i].nUsers++; return i; } } GMAP map; map.valid = false; map.frozen = false; map.gisdbase = gisdbase; map.location = location; map.mapset = mapset; map.mapName = mapName; map.path = tmpPath; map.nUsers = 1; map.version = 1; map.update = 0; map.map = (struct Map_info *) malloc ( sizeof(struct Map_info) ); // Set GRASS location QgsGrass::setLocation ( gisdbase, location ); #ifdef QGISDEBUG std::cerr << "Setting gisdbase, location: " << gisdbase.toLocal8Bit().data() << ", " << location.toLocal8Bit().data() << std::endl;#endif // Find the vector char *ms = G_find_vector2 ( (char *) mapName.ascii(), (char *) mapset.ascii()) ; if ( ms == NULL) { std::cerr << "Cannot find GRASS vector" << std::endl; return -1; } // Read the time of vector dir before Vect_open_old, because it may take long time (when the vector // could be owerwritten) QFileInfo di ( gisdbase + "/" + location + "/" + mapset + "/vector/" + mapName ); map.lastModified = di.lastModified(); di.setFile ( gisdbase + "/" + location + "/" + mapset + "/vector/" + mapName + "/dbln" ); map.lastAttributesModified = di.lastModified(); // Do we have topology and cidx (level2) int level = 2; QgsGrass::resetError(); Vect_set_open_level (2); Vect_open_old_head ( map.map, (char *) mapName.ascii(), (char *) mapset.ascii()); if ( QgsGrass::getError() == QgsGrass::FATAL ) { std::cerr << "Cannot open GRASS vector head on level2: " << QgsGrass::getErrorMessage().toLocal8Bit().data() << std::endl; level = 1; } else { Vect_close ( map.map ); } if ( level == 1 ) { QMessageBox::StandardButton ret = QMessageBox::question ( 0, "Warning", "GRASS vector map " + mapName + + " does not have topology. Build topology?", QMessageBox::Ok | QMessageBox::Cancel ); if ( ret == QMessageBox::Cancel ) return -1; } // Open vector QgsGrass::resetError(); // to "catch" error after Vect_open_old() Vect_set_open_level (level); Vect_open_old ( map.map, (char *) mapName.ascii(), (char *) mapset.ascii()); if ( QgsGrass::getError() == QgsGrass::FATAL ) { std::cerr << "Cannot open GRASS vector: " << QgsGrass::getErrorMessage().toLocal8Bit().data() << std::endl; return -1; } if ( level == 1 ) { QgsGrass::resetError(); Vect_build ( map.map, stderr ); if ( QgsGrass::getError() == QgsGrass::FATAL ) { std::cerr << "Cannot build topology: " << QgsGrass::getErrorMessage().toLocal8Bit().data() << std::endl; return -1; } }#ifdef QGISDEBUG std::cerr << "GRASS map successfully opened" << std::endl;#endif map.valid = true; // Add new map to maps mMaps.push_back(map); return mMaps.size() - 1; // map id }void QgsGrassProvider::updateMap ( int mapId ){#ifdef QGISDEBUG std::cerr << "QgsGrassProvider::updateMap() mapId = " << mapId << std::endl;#endif /* Close map */ GMAP *map = &(mMaps[mapId]); bool closeMap = map->valid; map->valid = false; map->version++; QgsGrass::setLocation ( (char *) map->gisdbase.ascii(), (char *) map->location.ascii() ); // TODO: Should be done better / in other place ? // TODO: Is it necessary for close ? G__setenv( (char *)"MAPSET", (char *) map->mapset.ascii() ); if ( closeMap ) Vect_close ( map->map ); QFileInfo di ( map->gisdbase + "/" + map->location + "/" + map->mapset + "/vector/" + map->mapName ); map->lastModified = di.lastModified(); di.setFile ( map->gisdbase + "/" + map->location + "/" + map->mapset + "/vector/" + map->mapName + "/dbln" ); map->lastAttributesModified = di.lastModified(); // Reopen vector QgsGrass::resetError(); // to "catch" error after Vect_open_old() Vect_set_open_level (2); Vect_open_old ( map->map, (char *) map->mapName.ascii(), (char *) map->mapset.ascii()); if ( QgsGrass::getError() == QgsGrass::FATAL ) { std::cerr << "Cannot reopen GRASS vector: " << QgsGrass::getErrorMessage().toLocal8Bit().data() << std::endl; // TODO if reopen fails, mLayers should be also updated return; }#ifdef QGISDEBUG std::cerr << "GRASS map successfully reopened for reading." << std::endl;#endif for ( unsigned int i = 0; i < mLayers.size(); i++) { // if ( !(mLayers[i].valid) ) continue; // ? if ( mLayers[i].mapId == mapId ) { loadLayerSourcesFromMap ( mLayers[i] ); } } map->valid = true;}void QgsGrassProvider::closeMap( int mapId ){#ifdef QGISDEBUG std::cerr << "Close map " << mapId << " nUsers = " << mMaps[mapId].nUsers << std::endl;#endif // TODO: not tested because delete is never used for providers mMaps[mapId].nUsers--; if ( mMaps[mapId].nUsers == 0 ) { // No more users, free sources#ifdef QGISDEBUG std::cerr << "No more users -> delete map" << std::endl;#endif // TODO: do this better, probably maintain QgsGrassEdit as one user if ( mMaps[mapId].update ) { QMessageBox::warning( 0, "Warning", "The vector was currently edited, " "you can expect crash soon." ); } if ( mMaps[mapId].valid ) { Vect_close ( mMaps[mapId].map ); } mMaps[mapId].valid = false; }}bool QgsGrassProvider::mapOutdated( int mapId ){#ifdef QGISDEBUG std::cerr << "QgsGrassProvider::mapOutdated()" << std::endl;#endif GMAP *map = &(mMaps[mapId]); QString dp = map->gisdbase + "/" + map->location + "/" + map->mapset + "/vector/" + map->mapName; QFileInfo di ( dp ); if ( map->lastModified < di.lastModified() ) {#ifdef QGISDEBUG std::cerr << "**** The map " << mapId << " was modified ****" << std::endl;#endif return true; } return false;}bool QgsGrassProvider::attributesOutdated( int mapId ){#ifdef QGISDEBUG std::cerr << "QgsGrassProvider::attributesOutdated()" << std::endl;#endif GMAP *map = &(mMaps[mapId]); QString dp = map->gisdbase + "/" + map->location + "/" + map->mapset + "/vector/" + map->mapName + "/dbln"; QFileInfo di ( dp ); if ( map->lastAttributesModified < di.lastModified() ) {#ifdef QGISDEBUG std::cerr << "**** The attributes of the map " << mapId << " were modified ****" << std::endl;#endif return true; } return false;}/** Set feature attributes */void QgsGrassProvider::setFeatureAttributes ( int layerId, int cat, QgsFeature *feature ){#if QGISDEBUG > 3 std::cerr << "setFeatureAttributes cat = " << cat << std::endl;#endif if ( mLayers[layerId].nColumns > 0 ) { // find cat GATT key; key.cat = cat; GATT *att = (GATT *) bsearch ( &key, mLayers[layerId].attributes, mLayers[layerId].nAttributes, sizeof(GATT), cmpAtt); for (int i = 0; i < mLayers[layerId].nColumns; i++) { if ( att != NULL ) { Q3CString cstr( att->values[i] ); feature->addAttribute (i, QVariant(mEncoding->toUnicode(cstr)) ); } else { /* it may happen that attributes are missing -> set to empty string */ feature->addAttribute (i, QVariant()); } } } else { feature->addAttribute (0, QVariant(cat)); }}void QgsGrassProvider::setFeatureAttributes ( int layerId, int cat, QgsFeature *feature, const QgsAttributeList& attlist){#if QGISDEBUG > 3 std::cerr << "setFeatureAttributes cat = " << cat << std::endl;#endif if ( mLayers[layerId].nColumns > 0 ) { // find cat GATT key; key.cat = cat; GATT *att = (GATT *) bsearch ( &key, mLayers[layerId].attributes, mLayers[layerId].nAttributes, sizeof(GATT), cmpAtt); for (QgsAttributeList::const_iterator iter=attlist.begin(); iter!=attlist.end();++iter) { if ( att != NULL ) { Q3CString cstr( att->values[*iter] ); feature->addAttribute (*iter, QVariant( mEncoding->toUnicode(cstr) )); } else { /* it may happen that attributes are missing -> set to empty string */ feature->addAttribute (*iter, QVariant()); } } } else { feature->addAttribute (0, QVariant(cat)); }}/** Get pointer to map */struct Map_info *QgsGrassProvider::layerMap ( int layerId ){ return ( mMaps[mLayers[layerId].mapId].map );}QgsSpatialRefSys QgsGrassProvider::getSRS(){ QString WKT; struct Cell_head cellhd; QgsGrass::setLocation ( mGisdbase, mLocation ); G_get_default_window(&cellhd); if (cellhd.proj != PROJECTION_XY) { struct Key_Value *projinfo = G_get_projinfo(); struct Key_Value *projunits = G_get_projunits(); char *wkt = GPJ_grass_to_wkt ( projinfo, projunits, 0, 0 ); WKT = QString(wkt); free ( wkt); } QgsSpatialRefSys srs; srs.createFromWkt(WKT); return srs;}int QgsGrassProvider::grassLayer(){ return mLayerField;}int QgsGrassProvider::grassLayer(QString name){ // Get field number int pos = name.find('_'); if ( pos == -1 ) { return -1; } return name.left(pos).toInt();}int QgsGrassProvider::grassLayerType(QString name){ int pos = name.find('_'); if ( pos == -1 ) { return -1; } QString ts = name.right( name.length() - pos - 1 ); if ( ts.compare("point") == 0 ) { return GV_POINT; // ?! centroids may be points } else if ( ts.compare("line") == 0 ) { return GV_LINES; } else if ( ts.compare("polygon") == 0 ) { return GV_AREA; } return -1;}//----------------------------------------- Edit -------------------------------------------------------bool QgsGrassProvider::isGrassEditable ( void ){#ifdef QGISDEBUG std::cerr << "QgsGrassProvider::isGrassEditable" << std::endl;#endif if ( !isValid() ) return false; /* Check if current user is owner of mapset */ if ( G__mapset_permissions2((char*)mGisdbase.ascii(),(char*)mLocation.ascii(),(char*)mMapset.ascii()) != 1 ) return false; // TODO: check format? (cannot edit OGR layers) return true;}bool QgsGrassProvider::isEdited ( void ){#if QGISDEBUG > 3 std::cerr << "QgsGrassProvider::isEdited" << std::endl;#endif GMAP *map = &(mMaps[mLayers[mLayerId].mapId]); return (map->update);}bool QgsGrassProvider::isFrozen ( void ){#if QGISDEBUG > 3 std::cerr << "QgsGrassProvider::isFrozen" << std::endl;#endif GMAP *map = &(mMaps[mLayers[mLayerId].mapId]); return (map->frozen);}void QgsGrassProvider::freeze(){#ifdef QGISDEBUG std::cerr << "QgsGrassProvider::freeze" << std::endl;#endif if ( !isValid() ) return; GMAP *map = &(mMaps[mLayers[mLayerId].mapId]); if ( map->frozen ) return; map->frozen = true; Vect_close ( map->map );}void QgsGrassProvider::thaw(){#ifdef QGISDEBUG std::cerr << "QgsGrassProvider::thaw" << std::endl;#endif if ( !isValid() ) return; GMAP *map = &(mMaps[mLayers[mLayerId].mapId]); if ( !map->frozen ) return; if ( reopenMap() ) { map->frozen = false; }}bool QgsGrassProvider::startEdit ( void ){#ifdef QGISDEBUG std::cerr << "QgsGrassProvider::startEdit" << std::endl; std::cerr << " uri = " << dataSourceUri().toLocal8Bit().data() << std::endl; std::cerr << " mMaps.size() = " << mMaps.size() << std::endl;#endif if ( !isGrassEditable() ) return false; // Check number of maps (the problem may appear if static variables are not shared - runtime linker) if ( mMaps.size() == 0 ) { QMessageBox::warning( 0, "Warning", "No maps opened in mMaps, probably problem in runtime linking, " "static variables are not shared by provider and plugin." ); return false; } /* Close map */ GMAP *map = &(mMaps[mLayers[mLayerId].mapId]); map->valid = false; QgsGrass::setLocation ( (char *) map->gisdbase.ascii(), (char *) map->location.ascii() ); // Set current mapset (mapset was previously checked by isGrassEditable() ) // TODO: Should be done better / in other place ? G__setenv( (char *)"MAPSET", (char *) map->mapset.ascii() ); Vect_close ( map->map ); // TODO: Catch error QgsGrass::resetError(); int level = Vect_open_update ( map->map, (char *) map->mapName.ascii(), (char *) map->mapset.ascii() ); if ( level < 2 ) { if ( QgsGrass::getError() == QgsGrass::FATAL ) { std::cerr << "Cannot open GRASS vector for update: " << QgsGrass::getErrorMessage().toLocal8Bit().data() << std::endl; } else { std::cerr << "Cannot open GRASS vector for update on level 2." << std::endl; } // reopen vector for reading QgsGrass::resetError(); Vect_set_open_level (2); level = Vect_open_old ( map->map, (char *) map->mapName.ascii(), (char *) map->mapset.ascii() ); if ( level < 2 ) { if ( QgsGrass::getError() == QgsGrass::FATAL ) { std::cerr << "Cannot reopen GRASS vector: " << QgsGrass::getErrorMessage().toLocal8Bit().data() << std::endl; } else { std::cerr << "Cannot reopen GRASS vector on level 2." << std::endl; } } else { map->valid = true; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -