Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgsvectordataproviderfeaturepool.h 3 : : -------------------------------------- 4 : : Date : 3.9.2018 5 : : Copyright : (C) 2018 by Matthias Kuhn 6 : : email : matthias@opengis.ch 7 : : *************************************************************************** 8 : : * * 9 : : * This program is free software; you can redistribute it and/or modify * 10 : : * it under the terms of the GNU General Public License as published by * 11 : : * the Free Software Foundation; either version 2 of the License, or * 12 : : * (at your option) any later version. * 13 : : * * 14 : : ***************************************************************************/ 15 : : 16 : : #include "qgsvectordataproviderfeaturepool.h" 17 : : #include "qgsthreadingutils.h" 18 : : 19 : : #include "qgsfeaturerequest.h" 20 : : 21 : 64 : QgsVectorDataProviderFeaturePool::QgsVectorDataProviderFeaturePool( QgsVectorLayer *layer, bool selectedOnly ) 22 : 64 : : QgsFeaturePool( layer ) 23 : 64 : , mSelectedOnly( selectedOnly ) 24 : 128 : { 25 : : // Build spatial index 26 : 64 : QgsFeature feature; 27 : 64 : QgsFeatureRequest req; 28 : 64 : QgsFeatureIds featureIds; 29 : 64 : if ( selectedOnly ) 30 : : { 31 : 0 : featureIds = layer->selectedFeatureIds(); 32 : 0 : req.setFilterFids( featureIds ); 33 : 0 : } 34 : : 35 : 64 : QgsFeatureIterator it = layer->getFeatures( req ); 36 : 1003 : while ( it.nextFeature( feature ) ) 37 : : { 38 : 939 : if ( feature.hasGeometry() ) 39 : : { 40 : 939 : insertFeature( feature ); 41 : 939 : featureIds.insert( feature.id() ); 42 : 939 : } 43 : : else 44 : : { 45 : 0 : featureIds.remove( feature.id() ); 46 : : } 47 : : } 48 : 64 : setFeatureIds( featureIds ); 49 : 64 : } 50 : : 51 : 2 : bool QgsVectorDataProviderFeaturePool::addFeature( QgsFeature &feature, Flags flags ) 52 : : { 53 : : Q_UNUSED( flags ) 54 : 2 : QgsFeatureList features; 55 : 2 : features.append( feature ); 56 : : 57 : 2 : bool res = false; 58 : : 59 : 4 : auto addFeatureSynchronized = [ this, &features, &res ]() 60 : : { 61 : 2 : QgsVectorLayer *lyr = layer(); 62 : 2 : if ( lyr ) 63 : 2 : res = lyr->dataProvider()->addFeatures( features ); 64 : 2 : }; 65 : : 66 : 2 : QgsThreadingUtils::runOnMainThread( addFeatureSynchronized ); 67 : : 68 : 2 : if ( !res ) 69 : 0 : return false; 70 : : 71 : 2 : feature.setId( features.front().id() ); 72 : 2 : if ( mSelectedOnly ) 73 : : { 74 : 0 : QgsThreadingUtils::runOnMainThread( [ this, feature ]() 75 : : { 76 : 0 : QgsVectorLayer *lyr = layer(); 77 : 0 : if ( lyr ) 78 : : { 79 : 0 : QgsFeatureIds selectedFeatureIds = lyr->selectedFeatureIds(); 80 : 0 : selectedFeatureIds.insert( feature.id() ); 81 : 0 : lyr->selectByIds( selectedFeatureIds ); 82 : 0 : } 83 : 0 : } ); 84 : 0 : } 85 : : 86 : 2 : insertFeature( feature ); 87 : : 88 : 2 : return res; 89 : 2 : } 90 : : 91 : 0 : bool QgsVectorDataProviderFeaturePool::addFeatures( QgsFeatureList &features, QgsFeatureSink::Flags flags ) 92 : : { 93 : : Q_UNUSED( flags ) 94 : : 95 : 0 : bool res = false; 96 : : 97 : 0 : auto addFeatureSynchronized = [ this, &features, &res ]() 98 : : { 99 : 0 : QgsVectorLayer *lyr = layer(); 100 : 0 : if ( lyr ) 101 : 0 : res = lyr->dataProvider()->addFeatures( features ); 102 : 0 : }; 103 : : 104 : 0 : QgsThreadingUtils::runOnMainThread( addFeatureSynchronized ); 105 : : 106 : 0 : if ( !res ) 107 : 0 : return false; 108 : : 109 : 0 : if ( mSelectedOnly ) 110 : : { 111 : 0 : QgsThreadingUtils::runOnMainThread( [ this, features ]() 112 : : { 113 : 0 : QgsVectorLayer *lyr = layer(); 114 : 0 : if ( lyr ) 115 : : { 116 : 0 : QgsFeatureIds selectedFeatureIds = lyr->selectedFeatureIds(); 117 : 0 : for ( const QgsFeature &feature : std::as_const( features ) ) 118 : 0 : selectedFeatureIds.insert( feature.id() ); 119 : 0 : lyr->selectByIds( selectedFeatureIds ); 120 : 0 : } 121 : 0 : } ); 122 : 0 : } 123 : : 124 : 0 : for ( const QgsFeature &feature : std::as_const( features ) ) 125 : 0 : insertFeature( feature ); 126 : : 127 : 0 : return res; 128 : 0 : } 129 : : 130 : 15 : void QgsVectorDataProviderFeaturePool::updateFeature( QgsFeature &feature ) 131 : : { 132 : 15 : QgsFeature origFeature; 133 : 15 : getFeature( feature.id(), origFeature ); 134 : : 135 : 15 : QgsGeometryMap geometryMap; 136 : 15 : geometryMap.insert( feature.id(), feature.geometry() ); 137 : 15 : QgsChangedAttributesMap changedAttributesMap; 138 : 15 : QgsAttributeMap attribMap; 139 : 39 : for ( int i = 0, n = feature.attributes().size(); i < n; ++i ) 140 : : { 141 : 24 : attribMap.insert( i, feature.attributes().at( i ) ); 142 : 24 : } 143 : 15 : changedAttributesMap.insert( feature.id(), attribMap ); 144 : : 145 : 45 : QgsThreadingUtils::runOnMainThread( [this, geometryMap, changedAttributesMap]() 146 : : { 147 : 15 : QgsVectorLayer *lyr = layer(); 148 : 15 : if ( lyr ) 149 : : { 150 : 15 : lyr->dataProvider()->changeGeometryValues( geometryMap ); 151 : 15 : lyr->dataProvider()->changeAttributeValues( changedAttributesMap ); 152 : 15 : } 153 : 15 : } ); 154 : : 155 : 15 : refreshCache( feature ); 156 : 15 : } 157 : : 158 : 8 : void QgsVectorDataProviderFeaturePool::deleteFeature( QgsFeatureId fid ) 159 : : { 160 : 8 : removeFeature( fid ); 161 : 16 : QgsThreadingUtils::runOnMainThread( [this, fid]() 162 : : { 163 : 8 : QgsVectorLayer *lyr = layer(); 164 : 8 : if ( lyr ) 165 : : { 166 : 8 : lyr->dataProvider()->deleteFeatures( QgsFeatureIds() << fid ); 167 : 8 : } 168 : 8 : } ); 169 : 8 : }