From 7ad1caf435227fa25d39a81e25400a880b167e35 Mon Sep 17 00:00:00 2001 From: ahuarte47 Date: Thu, 28 Nov 2013 23:55:43 +0100 Subject: [PATCH] #9094: Add Ctrl+D and D support for remove layers --- src/app/qgisapp.cpp | 23 +- src/app/qgisapp.h | 4 +- .../ogr/Copia de qgsogrfeatureiterator.cpp | 456 ++++++++++++++++++ 3 files changed, 474 insertions(+), 9 deletions(-) create mode 100644 src/providers/ogr/Copia de qgsogrfeatureiterator.cpp diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp index eb4fd448476e..c17042f3d917 100644 --- a/src/app/qgisapp.cpp +++ b/src/app/qgisapp.cpp @@ -4800,7 +4800,7 @@ void QgisApp::layerProperties() showLayerProperties( activeLayer() ); } -void QgisApp::deleteSelected( QgsMapLayer *layer, QWidget* parent ) +void QgisApp::deleteSelected( QgsMapLayer *layer, QWidget* parent, bool promptConfirmation ) { if ( !layer ) { @@ -4845,6 +4845,13 @@ void QgisApp::deleteSelected( QgsMapLayer *layer, QWidget* parent ) return; } + //display a warning + int numberOfDeletedFeatures = vlayer->selectedFeaturesIds().size(); + if ( promptConfirmation && QMessageBox::warning( parent, tr( "Delete features" ), tr( "Delete %n feature(s)?", "number of features to delete", numberOfDeletedFeatures ), QMessageBox::Ok, QMessageBox::Cancel ) == QMessageBox::Cancel ) + { + return; + } + vlayer->beginEditCommand( tr( "Features deleted" ) ); if ( !vlayer->deleteSelectedFeatures() ) { @@ -6470,10 +6477,8 @@ void QgisApp::removeAllLayers() QgsMapLayerRegistry::instance()->removeAllMapLayers(); } -void QgisApp::removeLayer() +void QgisApp::removeLayer( bool promptConfirmation ) { - int numberOfRemovedLayers = 0; - if ( mMapCanvas && mMapCanvas->isDrawing() ) { return; @@ -6489,12 +6494,11 @@ void QgisApp::removeLayer() QgsVectorLayer *vlayer = qobject_cast( layer ); if ( vlayer && vlayer->isEditable() && !toggleEditing( vlayer, true ) ) return; - - numberOfRemovedLayers++; } //display a warning - if ( QMessageBox::warning( this, tr( "Remove layers" ), tr( "Remove %n layer(s)?", "number of layers to remove", numberOfRemovedLayers ), QMessageBox::Ok, QMessageBox::Cancel ) == QMessageBox::Cancel ) + int numberOfRemovedLayers = mMapLegend->selectedLayers().size(); + if ( promptConfirmation && QMessageBox::warning( this, tr( "Remove layers" ), tr( "Remove %n layer(s)?", "number of layers to remove", numberOfRemovedLayers ), QMessageBox::Ok, QMessageBox::Cancel ) == QMessageBox::Cancel ) { return; } @@ -9052,6 +9056,11 @@ void QgisApp::keyPressEvent( QKeyEvent * e ) { stopRendering(); } + //remove selected layers + else if ( e->key() == Qt::Key_D ) + { + removeLayer( true ); + } #if defined(Q_OS_WIN)&& defined(QGISDEBUG) else if ( e->key() == Qt::Key_Backslash && e->modifiers() & Qt::ControlModifier ) { diff --git a/src/app/qgisapp.h b/src/app/qgisapp.h index b1c7134c59c1..3b441b49f183 100644 --- a/src/app/qgisapp.h +++ b/src/app/qgisapp.h @@ -577,7 +577,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow void loadGDALSublayers( QString uri, QStringList list ); /**Deletes the selected attributes for the currently selected vector layer*/ - void deleteSelected( QgsMapLayer *layer = 0, QWidget* parent = 0 ); + void deleteSelected( QgsMapLayer *layer = 0, QWidget* parent = 0, bool promptConfirmation = false ); //! project was written void writeProject( QDomDocument & ); @@ -686,7 +686,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow //! Slot to handle user center input; void userCenter(); //! Remove a layer from the map and legend - void removeLayer(); + void removeLayer( bool promptConfirmation = false ); /** Duplicate map layer(s) in legend * @note added in 1.9 */ void duplicateLayers( const QList lyrList = QList() ); diff --git a/src/providers/ogr/Copia de qgsogrfeatureiterator.cpp b/src/providers/ogr/Copia de qgsogrfeatureiterator.cpp new file mode 100644 index 000000000000..38ab5fa38e99 --- /dev/null +++ b/src/providers/ogr/Copia de qgsogrfeatureiterator.cpp @@ -0,0 +1,456 @@ +/*************************************************************************** + qgsogrfeatureiterator.cpp + --------------------- + begin : Juli 2012 + copyright : (C) 2012 by Martin Dobias + email : wonder dot sk at gmail dot com + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +#include "qgsogrfeatureiterator.h" + +#include "qgsogrprovider.h" + +#include "qgsapplication.h" +#include "qgsgeometry.h" +#include "qgslogger.h" +#include "qgsmessagelog.h" + +#include +#include + +#include // for setting gdal options + +// using from provider: +// - setRelevantFields(), mRelevantFieldsForNextFeature +// - ogrLayer +// - mFetchFeaturesWithoutGeom +// - mAttributeFields +// - mEncoding + + +QgsOgrFeatureIterator::QgsOgrFeatureIterator( QgsOgrProvider* p, const QgsFeatureRequest& request ) + : QgsAbstractFeatureIterator( request ) + , P( p ) + , ogrDataSource( 0 ) + , ogrLayer( 0 ) + , mSubsetStringSet( false ) +{ + mFeatureFetched = false; + + //CPLSetConfigOption( "VSI_CACHE", "TRUE" ); + + ogrDataSource = OGROpen( TO8F( P->filePath() ), false, NULL ); + + if ( P->layerName().isNull() ) + { + ogrLayer = OGR_DS_GetLayer( ogrDataSource, P->layerIndex() ); + } + else + { + ogrLayer = OGR_DS_GetLayerByName( ogrDataSource, TO8( p->layerName() ) ); + } + + if ( !P->subsetString().isEmpty() ) + { + ogrLayer = P->setSubsetString( ogrLayer, ogrDataSource ); + mSubsetStringSet = true; + } + + ensureRelevantFields(); + + // spatial query to select features + if ( mRequest.filterType() == QgsFeatureRequest::FilterRect ) + { + OGRGeometryH filter = 0; + QString wktExtent = QString( "POLYGON((%1))" ).arg( mRequest.filterRect().asPolygon() ); + QByteArray ba = wktExtent.toAscii(); + const char *wktText = ba; + + OGR_G_CreateFromWkt(( char ** )&wktText, NULL, &filter ); + QgsDebugMsg( "Setting spatial filter using " + wktExtent ); + OGR_L_SetSpatialFilter( ogrLayer, filter ); + OGR_G_DestroyGeometry( filter ); + } + else + { + OGR_L_SetSpatialFilter( ogrLayer, 0 ); + } + + //start with first feature + rewind(); +} + +QgsOgrFeatureIterator::~QgsOgrFeatureIterator() +{ + close(); +} + +void QgsOgrFeatureIterator::ensureRelevantFields() +{ + mFetchGeometry = ( mRequest.filterType() == QgsFeatureRequest::FilterRect ) || !( mRequest.flags() & QgsFeatureRequest::NoGeometry ); + QgsAttributeList attrs = ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) ? mRequest.subsetOfAttributes() : P->attributeIndexes(); + P->setRelevantFields( ogrLayer, mFetchGeometry, attrs ); + P->mRelevantFieldsForNextFeature = true; +} + + +bool QgsOgrFeatureIterator::fetchFeature( QgsFeature& feature ) +{ + feature.setValid( false ); + + if ( mClosed ) + return false; + + if ( !P->mRelevantFieldsForNextFeature ) + ensureRelevantFields(); + + if ( mRequest.filterType() == QgsFeatureRequest::FilterFid ) + { + OGRFeatureH fet = OGR_L_GetFeature( ogrLayer, FID_TO_NUMBER( mRequest.filterFid() ) ); + if ( !fet ) + { + close(); + return false; + } + + if ( readFeature( fet, feature ) ) + OGR_F_Destroy( fet ); + + feature.setValid( true ); + close(); // the feature has been read: we have finished here + return true; + } + + OGRFeatureH fet; + + while (( fet = OGR_L_GetNextFeature( ogrLayer ) ) ) + { + if ( !readFeature( fet, feature ) ) + continue; + + // we have a feature, end this cycle + feature.setValid( true ); + OGR_F_Destroy( fet ); + return true; + + } // while + + QgsDebugMsg( "Feature is null" ); + + close(); + return false; +} + + +bool QgsOgrFeatureIterator::rewind() +{ + if ( mClosed ) + return false; + + OGR_L_ResetReading( ogrLayer ); + + return true; +} + + +bool QgsOgrFeatureIterator::close() +{ + if ( mClosed ) + return false; + + P->mActiveIterators.remove( this ); + + if ( mSubsetStringSet ) + { + OGR_DS_ReleaseResultSet( ogrDataSource, ogrLayer ); + } + + OGR_DS_Destroy( ogrDataSource ); + + mClosed = true; + ogrDataSource = 0; + return true; +} + + +void QgsOgrFeatureIterator::getFeatureAttribute( OGRFeatureH ogrFet, QgsFeature & f, int attindex ) +{ + OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, attindex ); + + if ( ! fldDef ) + { + QgsDebugMsg( "ogrFet->GetFieldDefnRef(attindex) returns NULL" ); + return; + } + + QVariant value; + + if ( OGR_F_IsFieldSet( ogrFet, attindex ) ) + { + switch ( P->mAttributeFields[attindex].type() ) + { + case QVariant::String: value = QVariant( P->mEncoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attindex ) ) ); break; + case QVariant::Int: value = QVariant( OGR_F_GetFieldAsInteger( ogrFet, attindex ) ); break; + case QVariant::Double: value = QVariant( OGR_F_GetFieldAsDouble( ogrFet, attindex ) ); break; + case QVariant::Date: + case QVariant::DateTime: + { + int year, month, day, hour, minute, second, tzf; + + OGR_F_GetFieldAsDateTime( ogrFet, attindex, &year, &month, &day, &hour, &minute, &second, &tzf ); + if ( P->mAttributeFields[attindex].type() == QVariant::Date ) + value = QDate( year, month, day ); + else + value = QDateTime( QDate( year, month, day ), QTime( hour, minute, second ) ); + } + break; + default: + assert( 0 && "unsupported field type" ); + } + } + else + { + value = QVariant( QString::null ); + } + + f.setAttribute( attindex, value ); +} + + +bool QgsOgrFeatureIterator::readFeature( OGRFeatureH fet, QgsFeature& feature ) +{ + feature.setFeatureId( OGR_F_GetFID( fet ) ); + feature.initAttributes( P->fields().count() ); + feature.setFields( &P->mAttributeFields ); // allow name-based attribute lookups + + bool useIntersect = mRequest.flags() & QgsFeatureRequest::ExactIntersect; + bool geometryTypeFilter = P->mOgrGeometryTypeFilter != wkbUnknown; + if ( mFetchGeometry || useIntersect || geometryTypeFilter ) + { + OGRGeometryH geom = OGR_F_GetGeometryRef( fet ); + + if ( geom ) + { + notifyReadedFeature( fet, geom, feature ); + + // get the wkb representation + int memorySize = OGR_G_WkbSize( geom ); + unsigned char *wkb = new unsigned char[memorySize]; + OGR_G_ExportToWkb( geom, ( OGRwkbByteOrder ) QgsApplication::endian(), wkb ); + + QgsGeometry* geometry = feature.geometry(); + if ( !geometry ) feature.setGeometryAndOwnership( wkb, memorySize ); else geometry->fromWkb( wkb, memorySize ); + + notifyLoadedFeature( fet, feature ); + } + if (( useIntersect && ( !feature.geometry() || !feature.geometry()->intersects( mRequest.filterRect() ) ) ) + || ( geometryTypeFilter && ( !feature.geometry() || QgsOgrProvider::ogrWkbSingleFlatten(( OGRwkbGeometryType )feature.geometry()->wkbType() ) != P->mOgrGeometryTypeFilter ) ) ) + { + OGR_F_Destroy( fet ); + return false; + } + } + + if ( !mFetchGeometry ) + { + feature.setGeometry( 0 ); + } + + // fetch attributes + if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) + { + const QgsAttributeList& attrs = mRequest.subsetOfAttributes(); + for ( QgsAttributeList::const_iterator it = attrs.begin(); it != attrs.end(); ++it ) + { + getFeatureAttribute( fet, feature, *it ); + } + } + else + { + // all attributes + for ( int idx = 0; idx < P->mAttributeFields.count(); ++idx ) + { + getFeatureAttribute( fet, feature, idx ); + } + } + + return true; +} + +//! notify the OGRFeatureH was readed of the data provider +void QgsOgrFeatureIterator::notifyReadedFeature( OGRFeatureH fet, OGRGeometryH geom, QgsFeature& feature ) +{ +} +//! notify the OGRFeatureH was loaded to the QgsFeature object +void QgsOgrFeatureIterator::notifyLoadedFeature( OGRFeatureH fet, QgsFeature& feature ) +{ +} + +/*************************************************************************** + MapToPixel simplification classes + ---------------------- + begin : October 2013 + copyright : (C) 2013 by Alvaro Huarte + email : http://wiki.osgeo.org/wiki/Alvaro_Huarte + + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include + +//! Provides a specialized FeatureIterator for enable map2pixel simplification of the geometries +QgsOgrSimplifiedFeatureIterator::QgsOgrSimplifiedFeatureIterator( QgsOgrProvider* p, const QgsFeatureRequest& request ) : QgsOgrFeatureIterator( p, request ) +{ + mPointBufferCount = 512; + mPointBufferPtr = (OGRRawPoint*)OGRMalloc( mPointBufferCount * sizeof(OGRRawPoint) ); +} +QgsOgrSimplifiedFeatureIterator::~QgsOgrSimplifiedFeatureIterator( ) +{ + if ( mPointBufferPtr ) + { + OGRFree( mPointBufferPtr ); + mPointBufferPtr = NULL; + } +} + +//! Returns a point buffer of the specified size +OGRRawPoint* QgsOgrSimplifiedFeatureIterator::mallocPoints( int numPoints ) +{ + if ( mPointBufferPtr && mPointBufferCount < numPoints ) + { + OGRFree( mPointBufferPtr ); + mPointBufferPtr = NULL; + } + if ( mPointBufferPtr==NULL ) + { + mPointBufferCount = numPoints; + mPointBufferPtr = (OGRRawPoint*)OGRMalloc( mPointBufferCount * sizeof(OGRRawPoint) ); + } + return mPointBufferPtr; +} + +//! Simplify the OGR-geometry using the specified tolerance +bool QgsOgrSimplifiedFeatureIterator::simplifyOgrGeometry( const QgsFeatureRequest& request, OGRGeometry* geometry, bool isaLinearRing ) +{ + OGRwkbGeometryType wkbGeometryType = wkbFlatten( geometry->getGeometryType() ); + + // Simplify the geometry rewriting temporally its WKB-stream for saving calloc's. + if ( wkbGeometryType == wkbLineString ) + { + OGRLineString* lineString = (OGRLineString*)geometry; + + int numPoints = lineString->getNumPoints(); + if ( (isaLinearRing && numPoints<=5) || (!isaLinearRing && numPoints<=2) ) return false; + + OGREnvelope env; + geometry->getEnvelope( &env ); + QgsRectangle envelope( env.MinX, env.MinY, env.MaxX, env.MaxY ); + + // Can replace the geometry by its BBOX ? + if ( request.flags() & QgsFeatureRequest::SimplifyEnvelope && request.canbeGeneralizedByMapBoundingBox( envelope ) ) + { + OGRRawPoint* points = NULL; + int numPoints = 0; + + double x1 = envelope.xMinimum(); + double y1 = envelope.yMinimum(); + double x2 = envelope.xMaximum(); + double y2 = envelope.yMaximum(); + + if ( isaLinearRing ) + { + numPoints = 5; + points = mallocPoints( numPoints ); + points[0].x = x1; points[0].y = y1; + points[1].x = x2; points[1].y = y1; + points[2].x = x2; points[2].y = y2; + points[3].x = x1; points[3].y = y2; + points[4].x = x1; points[4].y = y1; + } + else + { + numPoints = 2; + points = mallocPoints( numPoints ); + points[0].x = x1; points[0].y = y1; + points[1].x = x2; points[1].y = y2; + } + lineString->setPoints( numPoints, points ); + lineString->flattenTo2D(); + return true; + } + else + if ( request.flags() & QgsFeatureRequest::SimplifyGeometry ) + { + QGis::GeometryType geometryType = isaLinearRing ? QGis::Polygon : QGis::Line; + int numSimplifiedPoints = 0; + + OGRRawPoint* points = mallocPoints( numPoints ); + double* xptr = (double*)points; + double* yptr = xptr+1; + lineString->getPoints( points ); + + if ( request.simplifyGeometry( request.flags(), geometryType, envelope, xptr, 16, yptr, 16, numPoints, numSimplifiedPoints ) ) + { + lineString->setPoints( numSimplifiedPoints, points ); + lineString->flattenTo2D(); + } + return numSimplifiedPoints!=numPoints; + } + } + else + if ( wkbGeometryType == wkbPolygon ) + { + OGRPolygon* polygon = (OGRPolygon*)geometry; + bool result = simplifyOgrGeometry( request, polygon->getExteriorRing(), true ); + + for ( int i = 0, numInteriorRings = polygon->getNumInteriorRings(); i < numInteriorRings; ++i ) + { + result |= simplifyOgrGeometry( request, polygon->getInteriorRing(i), true ); + } + if ( result ) polygon->flattenTo2D(); + return result; + } + else + if ( wkbGeometryType == wkbMultiLineString || wkbGeometryType == wkbMultiPolygon ) + { + OGRGeometryCollection* collection = (OGRGeometryCollection*)geometry; + bool result = false; + + for ( int i = 0, numGeometries = collection->getNumGeometries(); i < numGeometries; ++i ) + { + result |= simplifyOgrGeometry( request, collection->getGeometryRef(i), wkbGeometryType==wkbMultiPolygon ); + } + if ( result ) collection->flattenTo2D(); + return result; + } + return false; +} + +//! notify the OGRFeatureH was readed of the data provider +void QgsOgrSimplifiedFeatureIterator::notifyReadedFeature( OGRFeatureH fet, OGRGeometryH geom, QgsFeature& feature ) +{ + if ( mRequest.flags() & ( QgsFeatureRequest::SimplifyGeometry | QgsFeatureRequest::SimplifyEnvelope ) ) + { + OGRwkbGeometryType wkbType = QgsOgrProvider::ogrWkbSingleFlatten( OGR_G_GetGeometryType(geom) ); + + if ( wkbType == wkbLineString || wkbType == wkbPolygon ) + { + simplifyOgrGeometry( mRequest, (OGRGeometry*)geom, wkbType==wkbPolygon ); + } + } + QgsOgrFeatureIterator::notifyReadedFeature( fet, geom, feature ); +} + +/***************************************************************************/