void QgsMapToolSelectUtils::setSelectedFeatures( QgsMapCanvas *canvas, const QgsGeometry &selectGeometry, QgsVectorLayer::SelectBehavior selectBehavior, bool doContains, bool singleSelect ) { QgsVectorLayer *vlayer = QgsMapToolSelectUtils::getCurrentVectorLayer( canvas ); if ( !vlayer ) return; QApplication::setOverrideCursor( Qt::WaitCursor ); QgsFeatureIds selectedFeatures = getMatchingFeatures( canvas, selectGeometry, doContains, singleSelect ); vlayer->selectByIds( selectedFeatures, selectBehavior ); QApplication::restoreOverrideCursor(); }
QgsLayerRestorer::~QgsLayerRestorer() { for ( QgsMapLayer *layer : mLayerSettings.keys() ) { QgsLayerSettings settings = mLayerSettings[layer]; layer->styleManager()->setCurrentStyle( settings.mNamedStyle ); layer->setName( mLayerSettings[layer].name ); // if a SLD file has been loaded for rendering, we restore the previous one QString errMsg; QDomElement root = settings.mSldStyle.firstChildElement( "StyledLayerDescriptor" ); QDomElement el = root.firstChildElement( "NamedLayer" ); if ( layer->customProperty( "readSLD", false ).toBool() ) { layer->readSld( el, errMsg ); } layer->removeCustomProperty( "readSLD" ); switch ( layer->type() ) { case QgsMapLayer::LayerType::VectorLayer: { QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( layer ); if ( vLayer ) { vLayer->setOpacity( settings.mOpacity ); vLayer->selectByIds( settings.mSelectedFeatureIds ); vLayer->setSubsetString( settings.mFilter ); } break; } case QgsMapLayer::LayerType::RasterLayer: { QgsRasterLayer *rLayer = qobject_cast<QgsRasterLayer *>( layer ); if ( rLayer ) { rLayer->renderer()->setOpacity( settings.mOpacity ); } break; } case QgsMapLayer::MeshLayer: case QgsMapLayer::PluginLayer: break; } } }
QVariantMap QgsSelectByLocationAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) { QgsVectorLayer *selectLayer = parameterAsVectorLayer( parameters, QStringLiteral( "INPUT" ), context ); QgsVectorLayer::SelectBehavior method = static_cast< QgsVectorLayer::SelectBehavior >( parameterAsEnum( parameters, QStringLiteral( "METHOD" ), context ) ); std::unique_ptr< QgsFeatureSource > intersectSource( parameterAsSource( parameters, QStringLiteral( "INTERSECT" ), context ) ); const QList< int > selectedPredicates = parameterAsEnums( parameters, QStringLiteral( "PREDICATE" ), context ); QgsFeatureIds selectedIds; auto addToSelection = [&]( const QgsFeature & feature ) { selectedIds.insert( feature.id() ); }; process( selectLayer, intersectSource.get(), selectedPredicates, addToSelection, true, feedback ); selectLayer->selectByIds( selectedIds, method ); QVariantMap results; results.insert( QStringLiteral( "OUTPUT" ), parameters.value( QStringLiteral( "INPUT" ) ) ); return results; }
void QgsMapToolSelectUtils::selectSingleFeature( QgsMapCanvas *canvas, const QgsGeometry &selectGeometry, Qt::KeyboardModifiers modifiers ) { QgsVectorLayer *vlayer = QgsMapToolSelectUtils::getCurrentVectorLayer( canvas ); if ( !vlayer ) return; QApplication::setOverrideCursor( Qt::WaitCursor ); QgsFeatureIds selectedFeatures = getMatchingFeatures( canvas, selectGeometry, false, true ); if ( selectedFeatures.isEmpty() ) { if ( !( modifiers & Qt::ShiftModifier || modifiers & Qt::ControlModifier ) ) { // if no modifiers then clicking outside features clears the selection // but if there's a shift or ctrl modifier, then it's likely the user was trying // to modify an existing selection by adding or subtracting features and just // missed the feature vlayer->removeSelection(); } QApplication::restoreOverrideCursor(); return; } QgsVectorLayer::SelectBehavior behavior = QgsVectorLayer::SetSelection; //either shift or control modifier switches to "toggle" selection mode if ( modifiers & Qt::ShiftModifier || modifiers & Qt::ControlModifier ) { QgsFeatureId selectId = *selectedFeatures.constBegin(); QgsFeatureIds layerSelectedFeatures = vlayer->selectedFeatureIds(); if ( layerSelectedFeatures.contains( selectId ) ) behavior = QgsVectorLayer::RemoveFromSelection; else behavior = QgsVectorLayer::AddToSelection; } vlayer->selectByIds( selectedFeatures, behavior ); QApplication::restoreOverrideCursor(); }
/** * Selection routine called by the mouse release event * @param point = QgsPointXY representing the x, y coordinates of the mouse release event */ void eVisEventIdTool::select( const QgsPointXY &point ) { if ( !mCanvas ) return; QgsVectorLayer *myLayer = ( QgsVectorLayer * )mCanvas->currentLayer(); // create the search rectangle. this was modeled after the QgsMapIdentifyTool in core QGIS application double searchWidth = QgsMapTool::searchRadiusMU( mCanvas ); QgsRectangle myRectangle; myRectangle.setXMinimum( point.x() - searchWidth ); myRectangle.setXMaximum( point.x() + searchWidth ); myRectangle.setYMinimum( point.y() - searchWidth ); myRectangle.setYMaximum( point.y() + searchWidth ); //Transform rectangle to map coordinates myRectangle = toLayerCoordinates( myLayer, myRectangle ); //select features QgsFeatureIterator fit = myLayer->getFeatures( QgsFeatureRequest().setFilterRect( myRectangle ).setFlags( QgsFeatureRequest::ExactIntersect ).setSubsetOfAttributes( QgsAttributeList() ) ); QgsFeature f; QgsFeatureIds newSelectedFeatures; while ( fit.nextFeature( f ) ) { newSelectedFeatures.insert( f.id() ); } myLayer->selectByIds( newSelectedFeatures ); //Launch a new event browser to view selected features mBrowser = new eVisGenericEventBrowserGui( mCanvas, mCanvas, nullptr ); mBrowser->setAttribute( Qt::WA_DeleteOnClose ); }
QDomDocument createTransactionDocument( QgsServerInterface* serverIface, const QString& version, const QgsServerRequest& request ) { Q_UNUSED( version ); QDomDocument doc; QgsWfsProjectParser* configParser = getConfigParser( serverIface ); #ifdef HAVE_SERVER_PYTHON_PLUGINS QgsAccessControl* accessControl = serverIface->accessControls(); #endif const QString requestBody = request.getParameter( QStringLiteral( "REQUEST_BODY" ) ); QString errorMsg; if ( !doc.setContent( requestBody, true, &errorMsg ) ) { throw QgsRequestNotWellFormedException( errorMsg ); } QDomElement docElem = doc.documentElement(); QDomNodeList docChildNodes = docElem.childNodes(); // Re-organize the transaction document QDomDocument mDoc; QDomElement mDocElem = mDoc.createElement( QStringLiteral( "myTransactionDocument" ) ); mDocElem.setAttribute( QStringLiteral( "xmlns" ), QGS_NAMESPACE ); mDocElem.setAttribute( QStringLiteral( "xmlns:wfs" ), WFS_NAMESPACE ); mDocElem.setAttribute( QStringLiteral( "xmlns:gml" ), GML_NAMESPACE ); mDocElem.setAttribute( QStringLiteral( "xmlns:ogc" ), OGC_NAMESPACE ); mDocElem.setAttribute( QStringLiteral( "xmlns:qgs" ), QGS_NAMESPACE ); mDocElem.setAttribute( QStringLiteral( "xmlns:xsi" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema-instance" ) ); mDoc.appendChild( mDocElem ); QDomElement actionElem; QString actionName; QDomElement typeNameElem; QString typeName; for ( int i = docChildNodes.count(); 0 < i; --i ) { actionElem = docChildNodes.at( i - 1 ).toElement(); actionName = actionElem.localName(); if ( actionName == QLatin1String( "Insert" ) ) { QDomElement featureElem = actionElem.firstChild().toElement(); typeName = featureElem.localName(); } else if ( actionName == QLatin1String( "Update" ) ) { typeName = actionElem.attribute( QStringLiteral( "typeName" ) ); } else if ( actionName == QLatin1String( "Delete" ) ) { typeName = actionElem.attribute( QStringLiteral( "typeName" ) ); } if ( typeName.contains( QLatin1String( ":" ) ) ) typeName = typeName.section( QStringLiteral( ":" ), 1, 1 ); QDomNodeList typeNameList = mDocElem.elementsByTagName( typeName ); if ( typeNameList.count() == 0 ) { typeNameElem = mDoc.createElement( typeName ); mDocElem.appendChild( typeNameElem ); } else typeNameElem = typeNameList.at( 0 ).toElement(); typeNameElem.appendChild( actionElem ); } // It's time to make the transaction // Create the response document QDomDocument resp; //wfs:WFS_TransactionRespone element QDomElement respElem = resp.createElement( QStringLiteral( "WFS_TransactionResponse" )/*wfs:WFS_TransactionResponse*/ ); respElem.setAttribute( QStringLiteral( "xmlns" ), WFS_NAMESPACE ); respElem.setAttribute( QStringLiteral( "xmlns:xsi" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema-instance" ) ); respElem.setAttribute( QStringLiteral( "xsi:schemaLocation" ), WFS_NAMESPACE + " http://schemas.opengis.net/wfs/1.0.0/wfs.xsd" ); respElem.setAttribute( QStringLiteral( "xmlns:ogc" ), OGC_NAMESPACE ); respElem.setAttribute( QStringLiteral( "version" ), QStringLiteral( "1.0.0" ) ); resp.appendChild( respElem ); // Store the created feature id for WFS QStringList insertResults; // Get the WFS layers id QStringList wfsLayersId = configParser->wfsLayers();; QList<QgsMapLayer*> layerList; QgsMapLayer* currentLayer = nullptr; // Loop through the layer transaction elements docChildNodes = mDocElem.childNodes(); for ( int i = 0; i < docChildNodes.count(); ++i ) { // Get the vector layer typeNameElem = docChildNodes.at( i ).toElement(); typeName = typeNameElem.tagName(); layerList = configParser->mapLayerFromTypeName( typeName ); // Could be empty! if ( layerList.count() > 0 ) { currentLayer = layerList.at( 0 ); } else { throw QgsRequestNotWellFormedException( QStringLiteral( "Wrong TypeName: %1" ).arg( typeName ) ); } QgsVectorLayer* layer = qobject_cast<QgsVectorLayer*>( currentLayer ); // it's a vectorlayer and defined by the administrator as a WFS layer if ( layer && wfsLayersId.contains( layer->id() ) ) { #ifdef HAVE_SERVER_PYTHON_PLUGINS if ( actionName == QLatin1String( "Insert" ) ) { if ( !accessControl->layerInsertPermission( layer ) ) { throw QgsSecurityAccessException( QStringLiteral( "Feature insert permission denied" ) ); } } else if ( actionName == QLatin1String( "Update" ) ) { if ( !accessControl->layerUpdatePermission( layer ) ) { throw QgsSecurityAccessException( QStringLiteral( "Feature update permission denied" ) ); } } else if ( actionName == QLatin1String( "Delete" ) ) { if ( !accessControl->layerDeletePermission( layer ) ) { throw QgsSecurityAccessException( QStringLiteral( "Feature delete permission denied" ) ); } } #endif // Get the provider and it's capabilities QgsVectorDataProvider* provider = layer->dataProvider(); if ( !provider ) { continue; } int cap = provider->capabilities(); // Start the update transaction layer->startEditing(); if (( cap & QgsVectorDataProvider::ChangeAttributeValues ) && ( cap & QgsVectorDataProvider::ChangeGeometries ) ) { // Loop through the update elements for this layer QDomNodeList upNodeList = typeNameElem.elementsByTagNameNS( WFS_NAMESPACE, QStringLiteral( "Update" ) ); for ( int j = 0; j < upNodeList.count(); ++j ) { if ( !configParser->wfstUpdateLayers().contains( layer->id() ) ) { //no wfs permissions to do updates QString errorMsg = "No permissions to do WFS updates on layer '" + layer->name() + "'"; QgsMessageLog::logMessage( errorMsg, QStringLiteral( "Server" ), QgsMessageLog::CRITICAL ); addTransactionResult( resp, respElem, QStringLiteral( "FAILED" ), QStringLiteral( "Update" ), errorMsg ); return resp; } actionElem = upNodeList.at( j ).toElement(); // Get the Feature Ids for this filter on the layer QDomElement filterElem = actionElem.elementsByTagName( QStringLiteral( "Filter" ) ).at( 0 ).toElement(); QgsFeatureIds fids = getFeatureIdsFromFilter( filterElem, layer ); // Loop through the property elements // Store properties and the geometry element QDomNodeList propertyNodeList = actionElem.elementsByTagName( QStringLiteral( "Property" ) ); QMap<QString, QString> propertyMap; QDomElement propertyElem; QDomElement nameElem; QDomElement valueElem; QDomElement geometryElem; for ( int l = 0; l < propertyNodeList.count(); ++l ) { propertyElem = propertyNodeList.at( l ).toElement(); nameElem = propertyElem.elementsByTagName( QStringLiteral( "Name" ) ).at( 0 ).toElement(); valueElem = propertyElem.elementsByTagName( QStringLiteral( "Value" ) ).at( 0 ).toElement(); if ( nameElem.text() != QLatin1String( "geometry" ) ) { propertyMap.insert( nameElem.text(), valueElem.text() ); } else { geometryElem = valueElem; } } // Update the features QgsFields fields = provider->fields(); QMap<QString, int> fieldMap = provider->fieldNameMap(); QMap<QString, int>::const_iterator fieldMapIt; QString fieldName; bool conversionSuccess; QgsFeatureIds::const_iterator fidIt = fids.constBegin(); for ( ; fidIt != fids.constEnd(); ++fidIt ) { #ifdef HAVE_SERVER_PYTHON_PLUGINS QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest( *fidIt ) ); QgsFeature feature; while ( fit.nextFeature( feature ) ) { if ( !accessControl->allowToEdit( layer, feature ) ) { throw QgsSecurityAccessException( QStringLiteral( "Feature modify permission denied" ) ); } } #endif QMap< QString, QString >::const_iterator it = propertyMap.constBegin(); for ( ; it != propertyMap.constEnd(); ++it ) { fieldName = it.key(); fieldMapIt = fieldMap.find( fieldName ); if ( fieldMapIt == fieldMap.constEnd() ) { continue; } QgsField field = fields.at( fieldMapIt.value() ); if ( field.type() == 2 ) layer->changeAttributeValue( *fidIt, fieldMapIt.value(), it.value().toInt( &conversionSuccess ) ); else if ( field.type() == 6 ) layer->changeAttributeValue( *fidIt, fieldMapIt.value(), it.value().toDouble( &conversionSuccess ) ); else layer->changeAttributeValue( *fidIt, fieldMapIt.value(), it.value() ); } if ( !geometryElem.isNull() ) { QgsGeometry g = QgsOgcUtils::geometryFromGML( geometryElem ); if ( !layer->changeGeometry( *fidIt, g ) ) { throw QgsRequestNotWellFormedException( QStringLiteral( "Error in change geometry" ) ); } } #ifdef HAVE_SERVER_PYTHON_PLUGINS fit = layer->getFeatures( QgsFeatureRequest( *fidIt ) ); while ( fit.nextFeature( feature ) ) { if ( !accessControl->allowToEdit( layer, feature ) ) { layer->rollBack(); throw QgsSecurityAccessException( QStringLiteral( "Feature modify permission denied" ) ); } } #endif } } } // Commit the changes of the update elements if ( !layer->commitChanges() ) { addTransactionResult( resp, respElem, QStringLiteral( "PARTIAL" ), QStringLiteral( "Update" ), layer->commitErrors().join( QStringLiteral( "\n " ) ) ); return resp; } // Start the delete transaction layer->startEditing(); if (( cap & QgsVectorDataProvider::DeleteFeatures ) ) { // Loop through the delete elements QDomNodeList delNodeList = typeNameElem.elementsByTagNameNS( WFS_NAMESPACE, QStringLiteral( "Delete" ) ); for ( int j = 0; j < delNodeList.count(); ++j ) { if ( !configParser->wfstDeleteLayers().contains( layer->id() ) ) { //no wfs permissions to do updates QString errorMsg = "No permissions to do WFS deletes on layer '" + layer->name() + "'"; QgsMessageLog::logMessage( errorMsg, QStringLiteral( "Server" ), QgsMessageLog::CRITICAL ); addTransactionResult( resp, respElem, QStringLiteral( "FAILED" ), QStringLiteral( "Delete" ), errorMsg ); return resp; } actionElem = delNodeList.at( j ).toElement(); QDomElement filterElem = actionElem.firstChild().toElement(); // Get Feature Ids for the Filter element QgsFeatureIds fids = getFeatureIdsFromFilter( filterElem, layer ); #ifdef HAVE_SERVER_PYTHON_PLUGINS QgsFeatureIds::const_iterator fidIt = fids.constBegin(); for ( ; fidIt != fids.constEnd(); ++fidIt ) { QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest( *fidIt ) ); QgsFeature feature; while ( fit.nextFeature( feature ) ) { if ( !accessControl->allowToEdit( layer, feature ) ) { throw QgsSecurityAccessException( QStringLiteral( "Feature modify permission denied" ) ); } } } #endif layer->selectByIds( fids ); layer->deleteSelectedFeatures(); } } // Commit the changes of the delete elements if ( !layer->commitChanges() ) { addTransactionResult( resp, respElem, QStringLiteral( "PARTIAL" ), QStringLiteral( "Delete" ), layer->commitErrors().join( QStringLiteral( "\n " ) ) ); return resp; } // Store the inserted features QgsFeatureList inFeatList; if ( cap & QgsVectorDataProvider::AddFeatures ) { // Get Layer Field Information QgsFields fields = provider->fields(); QMap<QString, int> fieldMap = provider->fieldNameMap(); QMap<QString, int>::const_iterator fieldMapIt; // Loop through the insert elements QDomNodeList inNodeList = typeNameElem.elementsByTagNameNS( WFS_NAMESPACE, QStringLiteral( "Insert" ) ); for ( int j = 0; j < inNodeList.count(); ++j ) { if ( !configParser->wfstInsertLayers().contains( layer->id() ) ) { //no wfs permissions to do updates QString errorMsg = "No permissions to do WFS inserts on layer '" + layer->name() + "'"; QgsMessageLog::logMessage( errorMsg, QStringLiteral( "Server" ), QgsMessageLog::CRITICAL ); addTransactionResult( resp, respElem, QStringLiteral( "FAILED" ), QStringLiteral( "Insert" ), errorMsg ); return resp; } actionElem = inNodeList.at( j ).toElement(); // Loop through the feature element QDomNodeList featNodes = actionElem.childNodes(); for ( int l = 0; l < featNodes.count(); l++ ) { // Add the feature to the layer // and store it to put it's Feature Id in the response inFeatList << QgsFeature( fields ); // Create feature for this layer QDomElement featureElem = featNodes.at( l ).toElement(); QDomNode currentAttributeChild = featureElem.firstChild(); while ( !currentAttributeChild.isNull() ) { QDomElement currentAttributeElement = currentAttributeChild.toElement(); QString attrName = currentAttributeElement.localName(); if ( attrName != QLatin1String( "boundedBy" ) ) { if ( attrName != QLatin1String( "geometry" ) ) //a normal attribute { fieldMapIt = fieldMap.find( attrName ); if ( fieldMapIt == fieldMap.constEnd() ) { continue; } QgsField field = fields.at( fieldMapIt.value() ); QString attrValue = currentAttributeElement.text(); int attrType = field.type(); QgsMessageLog::logMessage( QStringLiteral( "attr: name=%1 idx=%2 value=%3" ).arg( attrName ).arg( fieldMapIt.value() ).arg( attrValue ) ); if ( attrType == QVariant::Int ) inFeatList.last().setAttribute( fieldMapIt.value(), attrValue.toInt() ); else if ( attrType == QVariant::Double ) inFeatList.last().setAttribute( fieldMapIt.value(), attrValue.toDouble() ); else inFeatList.last().setAttribute( fieldMapIt.value(), attrValue ); } else //a geometry attribute { QgsGeometry g = QgsOgcUtils::geometryFromGML( currentAttributeElement ); inFeatList.last().setGeometry( g ); } } currentAttributeChild = currentAttributeChild.nextSibling(); } } } } #ifdef HAVE_SERVER_PYTHON_PLUGINS QgsFeatureList::iterator featureIt = inFeatList.begin(); while ( featureIt != inFeatList.end() ) { if ( !accessControl->allowToEdit( layer, *featureIt ) ) { throw QgsSecurityAccessException( QStringLiteral( "Feature modify permission denied" ) ); } featureIt++; } #endif // add the features if ( !provider->addFeatures( inFeatList ) ) { addTransactionResult( resp, respElem, QStringLiteral( "Partial" ), QStringLiteral( "Insert" ), layer->commitErrors().join( QStringLiteral( "\n " ) ) ); if ( provider->hasErrors() ) { provider->clearErrors(); } return resp; } // Get the Feature Ids of the inserted feature for ( int j = 0; j < inFeatList.size(); j++ ) { insertResults << typeName + "." + QString::number( inFeatList[j].id() ); } } } // Put the Feature Ids of the inserted feature if ( !insertResults.isEmpty() ) { Q_FOREACH ( const QString &fidStr, insertResults ) { QDomElement irElem = doc.createElement( QStringLiteral( "InsertResult" ) ); QDomElement fiElem = doc.createElement( QStringLiteral( "ogc:FeatureId" ) ); fiElem.setAttribute( QStringLiteral( "fid" ), fidStr ); irElem.appendChild( fiElem ); respElem.appendChild( irElem ); }
void QgsGeometryCheckerSetupTab::runChecks() { // Get selected layer QList<QgsVectorLayer *> layers = getSelectedLayers(); if ( layers.isEmpty() ) return; if ( ui.radioButtonOutputNew->isChecked() ) { for ( QgsVectorLayer *layer : layers ) { if ( layer->dataProvider()->dataSourceUri().startsWith( ui.lineEditOutputDirectory->text() ) ) { QMessageBox::critical( this, tr( "Invalid Output Directory" ), tr( "The chosen output directory contains one or more input layers." ) ); return; } } } QgsVectorLayer *lineLayerCheckLayer = ui.comboLineLayerIntersection->isEnabled() ? dynamic_cast<QgsVectorLayer *>( QgsProject::instance()->mapLayer( ui.comboLineLayerIntersection->currentData().toString() ) ) : nullptr; QgsVectorLayer *followBoundaryCheckLayer = ui.comboBoxFollowBoundaries->isEnabled() ? dynamic_cast<QgsVectorLayer *>( QgsProject::instance()->mapLayer( ui.comboBoxFollowBoundaries->currentData().toString() ) ) : nullptr; if ( layers.contains( lineLayerCheckLayer ) || layers.contains( followBoundaryCheckLayer ) ) { QMessageBox::critical( this, tr( "Error" ), tr( "The test layer set contains a layer selected for a topology check." ) ); return; } for ( QgsVectorLayer *layer : layers ) { if ( layer->isEditable() ) { QMessageBox::critical( this, tr( "Editable Input Layer" ), tr( "Input layer are not allowed to be in editing mode." ) ); return; } } bool selectedOnly = ui.checkBoxInputSelectedOnly->isChecked(); // Set window busy setCursor( Qt::WaitCursor ); mRunButton->setEnabled( false ); ui.labelStatus->setText( tr( "<b>Preparing output...</b>" ) ); ui.labelStatus->show(); QApplication::processEvents( QEventLoop::ExcludeUserInputEvents ); QList<QgsVectorLayer *> processLayers; if ( ui.radioButtonOutputNew->isChecked() ) { // Get output directory and file extension QDir outputDir = QDir( ui.lineEditOutputDirectory->text() ); QString outputDriverName = ui.comboBoxOutputFormat->currentText(); QgsVectorFileWriter::MetaData metadata; if ( !QgsVectorFileWriter::driverMetadata( outputDriverName, metadata ) ) { QMessageBox::critical( this, tr( "Unknown Output Format" ), tr( "The specified output format cannot be recognized." ) ); mRunButton->setEnabled( true ); ui.labelStatus->hide(); unsetCursor(); return; } QString outputExtension = metadata.ext; // List over input layers, check which existing project layers need to be removed and create output layers QString filenamePrefix = ui.lineEditFilenamePrefix->text(); QSettings().setValue( "/geometry_checker/previous_values/filename_prefix", filenamePrefix ); QStringList toRemove; QStringList createErrors; for ( QgsVectorLayer *layer : layers ) { QString outputPath = outputDir.absoluteFilePath( filenamePrefix + layer->name() + "." + outputExtension ); // Remove existing layer with same uri from project for ( QgsVectorLayer *projectLayer : QgsProject::instance()->layers<QgsVectorLayer *>() ) { if ( projectLayer->dataProvider()->dataSourceUri().startsWith( outputPath ) ) { toRemove.append( projectLayer->id() ); } } // Create output layer QString errMsg; QgsVectorFileWriter::WriterError err = QgsVectorFileWriter::writeAsVectorFormat( layer, outputPath, layer->dataProvider()->encoding(), layer->crs(), outputDriverName, selectedOnly, &errMsg ); if ( err != QgsVectorFileWriter::NoError ) { createErrors.append( errMsg ); continue; } QgsVectorLayer *newlayer = new QgsVectorLayer( outputPath, QFileInfo( outputPath ).completeBaseName(), QStringLiteral( "ogr" ) ); if ( selectedOnly ) { QgsFeature feature; // Get features to select (only selected features were written up to this point) QgsFeatureIds selectedFeatures = newlayer->allFeatureIds(); // Write non-selected feature ids QgsFeatureList features; QgsFeatureIterator it = layer->getFeatures(); while ( it.nextFeature( feature ) ) { if ( !layer->selectedFeatureIds().contains( feature.id() ) ) { features.append( feature ); } } newlayer->dataProvider()->addFeatures( features ); // Set selected features newlayer->selectByIds( selectedFeatures ); } processLayers.append( newlayer ); } // Remove layers from project if ( !toRemove.isEmpty() ) { QgsProject::instance()->removeMapLayers( toRemove ); } // Error if an output layer could not be created if ( !createErrors.isEmpty() ) { QMessageBox::critical( this, tr( "Layer Creation Failed" ), tr( "Failed to create one or moure output layers:\n%1" ).arg( createErrors.join( "\n" ) ) ); mRunButton->setEnabled( true ); ui.labelStatus->hide(); unsetCursor(); return; } } else { processLayers = layers; } // Check if output layers are editable QList<QgsVectorLayer *> nonEditableLayers; for ( QgsVectorLayer *layer : processLayers ) { if ( ( layer->dataProvider()->capabilities() & QgsVectorDataProvider::ChangeGeometries ) == 0 ) { nonEditableLayers.append( layer ); } } if ( !nonEditableLayers.isEmpty() ) { QStringList nonEditableLayerNames; for ( QgsVectorLayer *layer : nonEditableLayers ) { nonEditableLayerNames.append( layer->name() ); } if ( QMessageBox::Yes != QMessageBox::question( this, tr( "Non-editable Output Layers" ), tr( "The following output layers are ina format that does not support editing features:\n%1\n\nThe geometry check can be performed, but it will not be possible to fix any errors. Do you want to continue?" ).arg( nonEditableLayerNames.join( "\n" ) ), QMessageBox::Yes, QMessageBox::No ) ) { if ( ui.radioButtonOutputNew->isChecked() ) { for ( QgsVectorLayer *layer : processLayers ) { QString layerPath = layer->dataProvider()->dataSourceUri(); delete layer; if ( ui.comboBoxOutputFormat->currentText() == QLatin1String( "ESRI Shapefile" ) ) { QgsVectorFileWriter::deleteShapeFile( layerPath ); } else { QFile( layerPath ).remove(); } } mRunButton->setEnabled( true ); ui.labelStatus->hide(); unsetCursor(); } return; } } // Setup checker ui.labelStatus->setText( tr( "<b>Building spatial index...</b>" ) ); QApplication::processEvents( QEventLoop::ExcludeUserInputEvents ); QMap<QString, QgsFeaturePool *> featurePools; for ( QgsVectorLayer *layer : processLayers ) { double layerToMapUntis = mIface->mapCanvas()->mapSettings().layerToMapUnits( layer ); QgsCoordinateTransform layerToMapTransform = QgsCoordinateTransformCache::instance()->transform( layer->crs().authid(), mIface->mapCanvas()->mapSettings().destinationCrs().authid() ); featurePools.insert( layer->id(), new QgsFeaturePool( layer, layerToMapUntis, layerToMapTransform, selectedOnly ) ); } // LineLayerIntersection check is enabled, make sure there is also a feature pool for that layer if ( ui.checkLineLayerIntersection->isChecked() && !featurePools.keys().contains( ui.comboLineLayerIntersection->currentData().toString() ) ) { QgsVectorLayer *layer = dynamic_cast<QgsVectorLayer *>( QgsProject::instance()->mapLayer( ui.comboLineLayerIntersection->currentData().toString() ) ); Q_ASSERT( layer ); double layerToMapUntis = mIface->mapCanvas()->mapSettings().layerToMapUnits( layer ); QgsCoordinateTransform layerToMapTransform = QgsCoordinateTransformCache::instance()->transform( layer->crs().authid(), mIface->mapCanvas()->mapSettings().destinationCrs().authid() ); featurePools.insert( layer->id(), new QgsFeaturePool( layer, layerToMapUntis, layerToMapTransform, selectedOnly ) ); } QgsGeometryCheckerContext *context = new QgsGeometryCheckerContext( ui.spinBoxTolerance->value(), mIface->mapCanvas()->mapSettings().destinationCrs().authid(), featurePools ); QList<QgsGeometryCheck *> checks; for ( const QgsGeometryCheckFactory *factory : QgsGeometryCheckFactoryRegistry::getCheckFactories() ) { QgsGeometryCheck *check = factory->createInstance( context, ui ); if ( check ) { checks.append( check ); } } QgsGeometryChecker *checker = new QgsGeometryChecker( checks, context ); emit checkerStarted( checker ); if ( ui.radioButtonOutputNew->isChecked() ) { QList<QgsMapLayer *> addLayers; for ( QgsVectorLayer *layer : processLayers ) { addLayers.append( layer ); } QgsProject::instance()->addMapLayers( addLayers ); } // Run ui.buttonBox->addButton( mAbortButton, QDialogButtonBox::ActionRole ); mRunButton->hide(); ui.progressBar->setRange( 0, 0 ); ui.labelStatus->hide(); ui.progressBar->show(); ui.widgetInputs->setEnabled( false ); QEventLoop evLoop; QFutureWatcher<void> futureWatcher; connect( checker, &QgsGeometryChecker::progressValue, ui.progressBar, &QProgressBar::setValue ); connect( &futureWatcher, &QFutureWatcherBase::finished, &evLoop, &QEventLoop::quit ); connect( mAbortButton, &QAbstractButton::clicked, &futureWatcher, &QFutureWatcherBase::cancel ); connect( mAbortButton, &QAbstractButton::clicked, this, &QgsGeometryCheckerSetupTab::showCancelFeedback ); int maxSteps = 0; futureWatcher.setFuture( checker->execute( &maxSteps ) ); ui.progressBar->setRange( 0, maxSteps ); evLoop.exec(); // Restore window unsetCursor(); mAbortButton->setEnabled( true ); ui.buttonBox->removeButton( mAbortButton ); mRunButton->setEnabled( true ); mRunButton->show(); ui.progressBar->hide(); ui.labelStatus->hide(); ui.widgetInputs->setEnabled( true ); // Show result emit checkerFinished( !futureWatcher.isCanceled() ); }
void QgsGeometrySnapperDialog::run() { //! Get layers * QgsVectorLayer* layer = getInputLayer(); QgsVectorLayer* referenceLayer = getReferenceLayer(); if ( !layer || !referenceLayer ) { return; } if ( radioButtonOutputNew->isChecked() && ( layer->dataProvider()->dataSourceUri().startsWith( lineEditOutput->text() ) || referenceLayer->dataProvider()->dataSourceUri().startsWith( lineEditOutput->text() ) ) ) { QMessageBox::critical( this, tr( "Invalid Output Layer" ), tr( "The chosen output layer is the same as an input layer." ) ); return; } bool selectedOnly = checkBoxInputSelectedOnly->isChecked(); //! Duplicate if necessary * if ( radioButtonOutputNew->isChecked() ) { QString filename = lineEditOutput->text(); // Remove existing layer with same uri QStringList toRemove; Q_FOREACH ( QgsMapLayer* maplayer, QgsMapLayerRegistry::instance()->mapLayers() ) { if ( dynamic_cast<QgsVectorLayer*>( maplayer ) && static_cast<QgsVectorLayer*>( maplayer )->dataProvider()->dataSourceUri().startsWith( filename ) ) { toRemove.append( maplayer->id() ); } } if ( !toRemove.isEmpty() ) { QgsMapLayerRegistry::instance()->removeMapLayers( toRemove ); } QString errMsg; QgsVectorFileWriter::WriterError err = QgsVectorFileWriter::writeAsVectorFormat( layer, filename, layer->dataProvider()->encoding(), layer->crs(), mOutputDriverName, selectedOnly, &errMsg ); if ( err != QgsVectorFileWriter::NoError ) { QMessageBox::critical( this, tr( "Layer Creation Failed" ), tr( "Failed to create the output layer: %1" ).arg( errMsg ) ); return; } QgsVectorLayer* newlayer = new QgsVectorLayer( filename, QFileInfo( filename ).completeBaseName(), QStringLiteral( "ogr" ) ); if ( selectedOnly ) { QgsFeature feature; // Get features to select (only selected features were written up to this point) QgsFeatureIds selectedFeatures = newlayer->allFeatureIds(); // Write non-selected feature ids QgsFeatureList features; QgsFeatureIterator it = layer->getFeatures(); while ( it.nextFeature( feature ) ) { if ( !layer->selectedFeaturesIds().contains( feature.id() ) ) { features.append( feature ); } } newlayer->dataProvider()->addFeatures( features ); // Set selected features newlayer->selectByIds( selectedFeatures ); } layer = newlayer; }