|
214 | 214 | #endif
|
215 | 215 | #ifdef HAVE_SPATIALITE
|
216 | 216 | #include "qgsspatialitesourceselect.h"
|
| 217 | +#include "qgsnewspatialitelayerdialog.h" |
217 | 218 | #endif
|
218 | 219 |
|
219 | 220 | #include "qgspythonutils.h"
|
@@ -936,11 +937,18 @@ void QgisApp::createActions()
|
936 | 937 |
|
937 | 938 | // Layer Menu Items
|
938 | 939 |
|
939 |
| - mActionNewVectorLayer = new QAction( getThemeIcon( "mActionNewVectorLayer.png" ), tr( "New Vector Layer..." ), this ); |
940 |
| - shortcuts->registerAction( mActionNewVectorLayer, tr( "Ctrl+Shift+N", "Create a New Vector Layer" ) ); |
941 |
| - mActionNewVectorLayer->setStatusTip( tr( "Create a New Vector Layer" ) ); |
| 940 | + mActionNewVectorLayer = new QAction( getThemeIcon( "mActionNewVectorLayer.png" ), tr( "New Vector Layer (shapefile)..." ), this ); |
| 941 | + shortcuts->registerAction( mActionNewVectorLayer, tr( "Ctrl+Shift+N", "Create a New Vector Layer (shapefile)" ) ); |
| 942 | + mActionNewVectorLayer->setStatusTip( tr( "Create a New Vector Layer (shapefile)" ) ); |
942 | 943 | connect( mActionNewVectorLayer, SIGNAL( triggered() ), this, SLOT( newVectorLayer() ) );
|
943 | 944 |
|
| 945 | +#ifdef HAVE_SPATIALITE |
| 946 | + mActionNewSpatialiteLayer = new QAction( getThemeIcon( "mActionNewVectorLayer.png" ), tr( "New Spatialite Layer ..." ), this ); |
| 947 | + shortcuts->registerAction( mActionNewSpatialiteLayer, tr( "Ctrl+Shift+S", "Create a New Spatialite Layer " ) ); |
| 948 | + mActionNewSpatialiteLayer->setStatusTip( tr( "Create a New Spatialite Layer " ) ); |
| 949 | + connect( mActionNewSpatialiteLayer, SIGNAL( triggered() ), this, SLOT( newSpatialiteLayer() ) ); |
| 950 | +#endif |
| 951 | + |
944 | 952 | mActionAddOgrLayer = new QAction( getThemeIcon( "mActionAddOgrLayer.png" ), tr( "Add Vector Layer..." ), this );
|
945 | 953 | shortcuts->registerAction( mActionAddOgrLayer, tr( "Ctrl+Shift+V", "Add a Vector Layer" ) );
|
946 | 954 | mActionAddOgrLayer->setStatusTip( tr( "Add a Vector Layer" ) );
|
@@ -1411,7 +1419,14 @@ void QgisApp::createMenus()
|
1411 | 1419 |
|
1412 | 1420 | mLayerMenu = menuBar()->addMenu( tr( "&Layer" ) );
|
1413 | 1421 |
|
| 1422 | +#ifdef HAVE_SPATIALITE |
| 1423 | + QMenu *newLayerMenu = mLayerMenu->addMenu( tr( "New ") ); |
| 1424 | + newLayerMenu->addAction( mActionNewVectorLayer ); |
| 1425 | + newLayerMenu->addAction( mActionNewSpatialiteLayer ); |
| 1426 | +#else |
1414 | 1427 | mLayerMenu->addAction( mActionNewVectorLayer );
|
| 1428 | +#endif |
| 1429 | + |
1415 | 1430 | mLayerMenu->addAction( mActionAddOgrLayer );
|
1416 | 1431 | mLayerMenu->addAction( mActionAddRasterLayer );
|
1417 | 1432 | #ifdef HAVE_POSTGRESQL
|
@@ -3082,6 +3097,213 @@ void QgisApp::newVectorLayer()
|
3082 | 3097 | addVectorLayers( fileNames, enc, "file" );
|
3083 | 3098 | }
|
3084 | 3099 |
|
| 3100 | +void QgisApp::newSpatialiteLayer() |
| 3101 | +{ |
| 3102 | + if ( mMapCanvas && mMapCanvas->isDrawing() ) |
| 3103 | + { |
| 3104 | + return; |
| 3105 | + } |
| 3106 | + |
| 3107 | + QgsNewSpatialiteLayerDialog spatialiteDialog( this ); |
| 3108 | + if ( spatialiteDialog.exec() == QDialog::Rejected ) |
| 3109 | + { |
| 3110 | + return; |
| 3111 | + } |
| 3112 | + |
| 3113 | + QString geometrytype = spatialiteDialog.selectedType(); |
| 3114 | + //QString fileformat = geomDialog.selectedFileFormat(); |
| 3115 | + QString crsId = spatialiteDialog.selectedCrsId(); |
| 3116 | + QString databaseName = spatialiteDialog.databaseName(); |
| 3117 | + QString newLayerName = spatialiteDialog.layerName(); |
| 3118 | + //QgsDebugMsg( QString( "New file format will be: %1" ).arg( fileformat ) ); |
| 3119 | + |
| 3120 | + // Get the list containing the name/type pairs for each attribute |
| 3121 | + QList<QStringList> * items = spatialiteDialog.attributes( ); |
| 3122 | + |
| 3123 | + // Build up the sql statement for creating the table |
| 3124 | + // |
| 3125 | + QString sql = QString("create table %1 (id integer primary key autoincrement").arg(newLayerName); |
| 3126 | + // iterate through the field names and add them to the create statement |
| 3127 | + // (use indexed access since this is just as fast as iterators |
| 3128 | + for ( int i = 0; i < items->size(); ++i ) |
| 3129 | + { |
| 3130 | + QStringList field = items->at(i); |
| 3131 | + sql += QString(", %1 %2").arg(field.at(0)).arg(field.at(1)); |
| 3132 | + } |
| 3133 | + // complete the create table statement |
| 3134 | + sql += ")"; |
| 3135 | + std::cout << "Creating table in database " << databaseName.toUtf8().data() << std::endl; |
| 3136 | + std::cout << sql.toUtf8().data() << std::endl; // OK |
| 3137 | + |
| 3138 | + QString sqlAddGeom = QString("select AddGeometryColumn('%1', 'geom', %2, '%3', 2)").arg(newLayerName).arg(crsId).arg(geometrytype); |
| 3139 | + std::cout << sqlAddGeom.toUtf8().data() << std::endl; // OK |
| 3140 | + QString sqlCreateIndex = QString("select CreateSpatialIndex('%1', 'geom')").arg(newLayerName); |
| 3141 | + std::cout << sqlCreateIndex.toUtf8().data() << std::endl; // OK |
| 3142 | + |
| 3143 | + sqlite3 *db; |
| 3144 | + int rc = sqlite3_open( databaseName.toUtf8(), &db ); |
| 3145 | + if ( rc != SQLITE_OK ) |
| 3146 | + { |
| 3147 | + QMessageBox::warning( this, "Spatialite Database", tr( "Unable to open the database: %1").arg(databaseName ) ); |
| 3148 | + } |
| 3149 | + else |
| 3150 | + { |
| 3151 | + char * errmsg; |
| 3152 | + rc = sqlite3_exec( db, sql.toUtf8(), NULL, NULL, &errmsg); |
| 3153 | + if ( rc != SQLITE_OK ) |
| 3154 | + { |
| 3155 | + QMessageBox::warning( this, tr( "Error deleting bookmark" ), |
| 3156 | + tr( "Failed to create the Spatialite table %1. The database returned:\n%2" ).arg( newLayerName ).arg( errmsg ) ); |
| 3157 | + sqlite3_free( errmsg ); |
| 3158 | + } |
| 3159 | + else |
| 3160 | + { |
| 3161 | + // create the geometry column and the spatial index |
| 3162 | + rc = sqlite3_exec( db, sqlAddGeom.toUtf8(), NULL, NULL, &errmsg); |
| 3163 | + if ( rc != SQLITE_OK ) |
| 3164 | + { |
| 3165 | + QMessageBox::warning( this, tr( "Error Creating Geometry Column" ), |
| 3166 | + tr( "Failed to create the geometry column. The database returned:\n%1" ).arg( errmsg ) ); |
| 3167 | + sqlite3_free( errmsg ); |
| 3168 | + } |
| 3169 | + else |
| 3170 | + { |
| 3171 | + // create the spatial index |
| 3172 | + rc = sqlite3_exec( db, sqlCreateIndex.toUtf8(), NULL, NULL, &errmsg); |
| 3173 | + if ( rc != SQLITE_OK ) |
| 3174 | + { |
| 3175 | + QMessageBox::warning( this, tr( "Error Creating Spatial Index" ), |
| 3176 | + tr( "Failed to create the spatial index. The database returned:\n%1" ).arg( errmsg ) ); |
| 3177 | + sqlite3_free( errmsg ); |
| 3178 | + } |
| 3179 | + } |
| 3180 | + } |
| 3181 | + |
| 3182 | + |
| 3183 | + } |
| 3184 | + |
| 3185 | + |
| 3186 | + /* |
| 3187 | + bool haveLastUsedFilter = false; // by default, there is no last |
| 3188 | + // used filter |
| 3189 | + QString enc; |
| 3190 | + QString fileName; |
| 3191 | +
|
| 3192 | + QSettings settings; // where we keep last used filter in |
| 3193 | + // persistent state |
| 3194 | +
|
| 3195 | + haveLastUsedFilter = settings.contains( "/UI/lastVectorFileFilter" ); |
| 3196 | + QString lastUsedFilter = settings.value( "/UI/lastVectorFileFilter", |
| 3197 | + QVariant( QString::null ) ).toString(); |
| 3198 | +
|
| 3199 | + QString lastUsedDir = settings.value( "/UI/lastVectorFileFilterDir", |
| 3200 | + "." ).toString(); |
| 3201 | +
|
| 3202 | + QgsDebugMsg( "Saving vector file dialog without filters: " ); |
| 3203 | +
|
| 3204 | + QgsEncodingFileDialog* openFileDialog = new QgsEncodingFileDialog( this, |
| 3205 | + tr( "Save As" ), lastUsedDir, "", QString( "" ) ); |
| 3206 | +
|
| 3207 | + // allow for selection of more than one file |
| 3208 | + openFileDialog->setFileMode( QFileDialog::AnyFile ); |
| 3209 | + openFileDialog->setAcceptMode( QFileDialog::AcceptSave ); |
| 3210 | + openFileDialog->setConfirmOverwrite( true ); |
| 3211 | +
|
| 3212 | + if ( haveLastUsedFilter ) // set the filter to the last one used |
| 3213 | + { |
| 3214 | + openFileDialog->selectFilter( lastUsedFilter ); |
| 3215 | + } |
| 3216 | +
|
| 3217 | + int res; |
| 3218 | + while (( res = openFileDialog->exec() ) == QDialog::Accepted ) |
| 3219 | + { |
| 3220 | + fileName = openFileDialog->selectedFiles().first(); |
| 3221 | +
|
| 3222 | + if ( fileformat == "ESRI Shapefile" ) |
| 3223 | + { |
| 3224 | + if ( !isValidShapeFileName( fileName ) ) |
| 3225 | + { |
| 3226 | + fileName += ".shp"; |
| 3227 | + } |
| 3228 | +
|
| 3229 | + if ( !isValidShapeFileName( fileName ) ) |
| 3230 | + { |
| 3231 | + QMessageBox::information( this, |
| 3232 | + tr( "New Shapefile" ), |
| 3233 | + tr( "Shapefiles must end on .shp" ) ); |
| 3234 | + continue; |
| 3235 | + } |
| 3236 | + } |
| 3237 | +
|
| 3238 | + break; |
| 3239 | + } |
| 3240 | +
|
| 3241 | + if ( res == QDialog::Rejected ) |
| 3242 | + { |
| 3243 | + delete openFileDialog; |
| 3244 | + return; |
| 3245 | + } |
| 3246 | +
|
| 3247 | + enc = openFileDialog->encoding(); |
| 3248 | +
|
| 3249 | + // If the file exists, delete it otherwise we'll end up loading that |
| 3250 | + // file, which can cause problems (e.g., if the file contains |
| 3251 | + // linestrings, but we're wanting to create points, we'll end up |
| 3252 | + // with a linestring file). |
| 3253 | + if ( fileformat == "ESRI Shapefile" ) |
| 3254 | + { |
| 3255 | + QgsVectorFileWriter::deleteShapeFile( fileName ); |
| 3256 | + } |
| 3257 | + else |
| 3258 | + { |
| 3259 | + QFile::remove( fileName ); |
| 3260 | + } |
| 3261 | +
|
| 3262 | + settings.setValue( "/UI/lastVectorFileFilter", openFileDialog->selectedFilter() ); |
| 3263 | +
|
| 3264 | + settings.setValue( "/UI/lastVectorFileFilterDir", openFileDialog->directory().absolutePath() ); |
| 3265 | +
|
| 3266 | + delete openFileDialog; |
| 3267 | +
|
| 3268 | + //try to create the new layer with OGRProvider instead of QgsVectorFileWriter |
| 3269 | + QgsProviderRegistry * pReg = QgsProviderRegistry::instance(); |
| 3270 | + QString ogrlib = pReg->library( "ogr" ); |
| 3271 | + // load the data provider |
| 3272 | + QLibrary* myLib = new QLibrary( ogrlib ); |
| 3273 | + bool loaded = myLib->load(); |
| 3274 | + if ( loaded ) |
| 3275 | + { |
| 3276 | + QgsDebugMsg( "ogr provider loaded" ); |
| 3277 | +
|
| 3278 | + typedef bool ( *createEmptyDataSourceProc )( const QString&, const QString&, const QString&, QGis::WkbType, |
| 3279 | + const std::list<std::pair<QString, QString> >&, const QgsCoordinateReferenceSystem * ); |
| 3280 | + createEmptyDataSourceProc createEmptyDataSource = ( createEmptyDataSourceProc ) cast_to_fptr( myLib->resolve( "createEmptyDataSource" ) ); |
| 3281 | + if ( createEmptyDataSource ) |
| 3282 | + { |
| 3283 | + if ( geometrytype != QGis::WKBUnknown ) |
| 3284 | + { |
| 3285 | + QgsCoordinateReferenceSystem srs( crsId, QgsCoordinateReferenceSystem::InternalCrsId ); |
| 3286 | + createEmptyDataSource( fileName, fileformat, enc, geometrytype, attributes, &srs ); |
| 3287 | + } |
| 3288 | + else |
| 3289 | + { |
| 3290 | + QgsDebugMsg( "geometry type not recognised" ); |
| 3291 | + return; |
| 3292 | + } |
| 3293 | + } |
| 3294 | + else |
| 3295 | + { |
| 3296 | + QgsDebugMsg( "Resolving newEmptyDataSource(...) failed" ); |
| 3297 | + } |
| 3298 | + } |
| 3299 | +
|
| 3300 | + //then add the layer to the view |
| 3301 | + QStringList fileNames; |
| 3302 | + fileNames.append( fileName ); |
| 3303 | + //todo: the last parameter will change accordingly to layer type |
| 3304 | + addVectorLayers( fileNames, enc, "file" ); |
| 3305 | + */ |
| 3306 | +} |
3085 | 3307 | void QgisApp::fileOpen()
|
3086 | 3308 | {
|
3087 | 3309 | if ( mMapCanvas && mMapCanvas->isDrawing() )
|
|
0 commit comments