Skip to content

Commit

Permalink
Revert "[Backport ltr] Manual backport of 51456 merge feature relocat…
Browse files Browse the repository at this point in the history
…ion"
  • Loading branch information
signedav committed Mar 31, 2023
1 parent bc12bf4 commit a78e7af
Show file tree
Hide file tree
Showing 9 changed files with 62 additions and 335 deletions.
15 changes: 0 additions & 15 deletions python/core/auto_generated/vector/qgsvectorlayereditutils.sip.in
Expand Up @@ -310,21 +310,6 @@ editing.
:return: 2 in case vertex already exists or point does not intersect segment

.. versionadded:: 3.16
%End

bool mergeFeatures( const QgsFeatureId &targetFeatureId, const QgsFeatureIds &mergeFeatureIds, const QgsAttributes &mergeAttributes, const QgsGeometry &unionGeometry, QString &errorMessage /Out/ );
%Docstring
Merge features into a single one.

:param targetFeatureId: id of the target feature (will be updated)
:param mergeFeatureIds: id list of features to merge (will be deleted)
:param mergeAttributes: are the resulting attributes in the merged feature
:param unionGeometry: is the resulting geometry of the merged feature

:return: - ``True`` if the merge was successful, or ``False`` if the operation failed.
- errorMessage: will be set to a descriptive error message if any occurs

.. versionadded:: 3.30
%End

};
Expand Down
87 changes: 61 additions & 26 deletions src/app/qgisapp.cpp
Expand Up @@ -102,7 +102,6 @@
#include "qgsdockablewidgethelper.h"
#include "vertextool/qgsvertexeditor.h"
#include "qgsvectorlayerutils.h"
#include "qgsvectorlayereditutils.h"
#include "qgsadvanceddigitizingdockwidget.h"
#include "qgsabstractdatasourcewidget.h"
#include "qgsmeshlayer.h"
Expand Down Expand Up @@ -9518,8 +9517,9 @@ void QgisApp::mergeSelectedFeatures()
return;
}

// Check at least two features are selected
if ( vl->selectedFeatureIds().size() < 2 )
//get selected feature ids (as a QSet<int> )
const QgsFeatureIds &featureIdSet = vl->selectedFeatureIds();
if ( featureIdSet.size() < 2 )
{
visibleMessageBar()->pushMessage(
tr( "Not enough features selected" ),
Expand Down Expand Up @@ -9593,38 +9593,73 @@ void QgisApp::mergeSelectedFeatures()
}
return;
}
else if ( !QgsWkbTypes::isMultiType( vl->wkbType() ) )
}

QgsAttributes attrs = d.mergedAttributes();
QgsAttributeMap newAttributes;
QString errorMessage;
QgsFeatureId mergeFeatureId = FID_NULL;
for ( int i = 0; i < attrs.count(); ++i )
{
QVariant val = attrs.at( i );
bool isDefaultValue = vl->fields().fieldOrigin( i ) == QgsFields::OriginProvider &&
vl->dataProvider() &&
vl->dataProvider()->defaultValueClause( vl->fields().fieldOriginIndex( i ) ) == val;
bool isPrimaryKey = vl->fields().fieldOrigin( i ) == QgsFields::OriginProvider &&
vl->dataProvider() &&
vl->dataProvider()->pkAttributeIndexes().contains( vl->fields().fieldOriginIndex( i ) );

if ( isPrimaryKey && !isDefaultValue )
mergeFeatureId = val.toLongLong();

// convert to destination data type
if ( !isDefaultValue && !vl->fields().at( i ).convertCompatible( val, &errorMessage ) )
{
const QgsGeometryCollection *c = qgsgeometry_cast<const QgsGeometryCollection *>( unionGeom.constGet() );
if ( ( c && c->partCount() > 1 ) || !unionGeom.convertToSingleType() )
{
visibleMessageBar()->pushMessage(
tr( "Merge failed" ),
tr( "Resulting geometry type (multipart) is incompatible with layer type (singlepart)." ),
Qgis::MessageLevel::Critical );
return;
}
visibleMessageBar()->pushMessage(
tr( "Invalid result" ),
tr( "Could not store value '%1' in field of type %2: %3" ).arg( attrs.at( i ).toString(), vl->fields().at( i ).typeName(), errorMessage ),
Qgis::MessageLevel::Warning );
}
newAttributes[ i ] = val;
}

QString errorMessage;
QgsVectorLayerEditUtils vectorLayerEditUtils( vl );
bool success = vectorLayerEditUtils.mergeFeatures( d.targetFeatureId(), vl->selectedFeatureIds(), d.mergedAttributes(), unionGeom, errorMessage );
vl->beginEditCommand( tr( "Merged features" ) );

if ( !success )
QgsFeature mergeFeature;
if ( mergeFeatureId == FID_NULL )
{
visibleMessageBar()->pushMessage(
tr( "Merge failed" ),
errorMessage,
Qgis::MessageLevel::Critical );
// Create new feature
mergeFeature = QgsVectorLayerUtils::createFeature( vl, unionGeom, newAttributes );
}
else if ( success && !errorMessage.isEmpty() )
else
{
visibleMessageBar()->pushMessage(
tr( "Invalid result" ),
errorMessage,
Qgis::MessageLevel::Warning );
// Merge into existing feature
featureIdsAfter.remove( mergeFeatureId );
}

// Delete other features
QgsFeatureIds::const_iterator feature_it = featureIdsAfter.constBegin();
for ( ; feature_it != featureIdsAfter.constEnd(); ++feature_it )
{
vl->deleteFeature( *feature_it );
}


if ( mergeFeatureId == FID_NULL )
{
// Add the new feature
vl->addFeature( mergeFeature );
}
else
{
// Modify merge feature
vl->changeGeometry( mergeFeatureId, unionGeom );
vl->changeAttributeValues( mergeFeatureId, newAttributes );
}

vl->endEditCommand();

vl->triggerRepaint();
}

void QgisApp::vertexTool()
Expand Down
16 changes: 0 additions & 16 deletions src/app/qgsmergeattributesdialog.cpp
Expand Up @@ -108,9 +108,6 @@ QgsMergeAttributesDialog::QgsMergeAttributesDialog( const QgsFeatureList &featur
break;
}

if ( ! mFeatureList.isEmpty() )
mTargetFeatureId = mFeatureList.first().id();

connect( mSkipAllButton, &QAbstractButton::clicked, this, &QgsMergeAttributesDialog::setAllToSkip );
connect( mTableWidget, &QTableWidget::cellChanged, this, &QgsMergeAttributesDialog::tableWidgetCellChanged );

Expand Down Expand Up @@ -468,8 +465,6 @@ void QgsMergeAttributesDialog::setAllAttributesFromFeature( QgsFeatureId feature
currentComboBox->setCurrentIndex( currentComboBox->findData( QStringLiteral( "f%1" ).arg( FID_TO_STRING( featureId ) ) ) );
}
}

mTargetFeatureId = featureId;
}

QVariant QgsMergeAttributesDialog::calcStatistic( int col, QgsStatisticalSummary::Statistic stat )
Expand Down Expand Up @@ -671,18 +666,12 @@ void QgsMergeAttributesDialog::mRemoveFeatureFromSelectionButton_clicked()
f_it != mFeatureList.end();
++f_it )
{
if ( f_it->id() == mTargetFeatureId )
mTargetFeatureId = FID_NULL;

if ( f_it->id() == featureId )
{
mFeatureList.erase( f_it );
break;
}
}

if ( mTargetFeatureId == FID_NULL && !mFeatureList.isEmpty() )
mTargetFeatureId = mFeatureList.first().id();
}

void QgsMergeAttributesDialog::tableWidgetCellChanged( int row, int column )
Expand Down Expand Up @@ -756,11 +745,6 @@ QgsAttributes QgsMergeAttributesDialog::mergedAttributes() const
return results;
}

QgsFeatureId QgsMergeAttributesDialog::targetFeatureId() const
{
return mTargetFeatureId;
}

QSet<int> QgsMergeAttributesDialog::skippedAttributeIndexes() const
{
QSet<int> skipped;
Expand Down
13 changes: 0 additions & 13 deletions src/app/qgsmergeattributesdialog.h
Expand Up @@ -49,18 +49,6 @@ class APP_EXPORT QgsMergeAttributesDialog: public QDialog, private Ui::QgsMergeA

QgsAttributes mergedAttributes() const;

/**
* Returns the id of the target feature.
* By default it is the first feature of the list. Otherwise the feature explicitly selected
* with buttons "Take attributes from selected feature" or "Take attributes from feature with
* the largest area".
*
* \returns The id of the target feature.
*
* \since QGIS 3.30
*/
QgsFeatureId targetFeatureId() const;

/**
* Returns a list of attribute indexes which should be skipped when merging (e.g., attributes
* which have been set to "skip"
Expand Down Expand Up @@ -114,7 +102,6 @@ class APP_EXPORT QgsMergeAttributesDialog: public QDialog, private Ui::QgsMergeA
void createRubberBandForFeature( QgsFeatureId featureId );

QgsFeatureList mFeatureList;
QgsFeatureId mTargetFeatureId = FID_NULL;
QgsVectorLayer *mVectorLayer = nullptr;
QgsMapCanvas *mMapCanvas = nullptr;
//! Item that highlights the selected feature in the merge table
Expand Down
50 changes: 0 additions & 50 deletions src/core/vector/qgsvectorlayereditutils.cpp
Expand Up @@ -721,56 +721,6 @@ int QgsVectorLayerEditUtils::addTopologicalPoints( const QgsPointXY &p )
return addTopologicalPoints( QgsPoint( p ) );
}

bool QgsVectorLayerEditUtils::mergeFeatures( const QgsFeatureId &targetFeatureId, const QgsFeatureIds &mergeFeatureIds, const QgsAttributes &mergeAttributes, const QgsGeometry &unionGeometry, QString &errorMessage )
{
errorMessage.clear();

if ( mergeFeatureIds.isEmpty() )
{
errorMessage = QObject::tr( "List of features to merge is empty" );
return false;
}

QgsAttributeMap newAttributes;
for ( int i = 0; i < mergeAttributes.count(); ++i )
{
QVariant val = mergeAttributes.at( i );

bool isDefaultValue = mLayer->fields().fieldOrigin( i ) == QgsFields::OriginProvider &&
mLayer->dataProvider() &&
mLayer->dataProvider()->defaultValueClause( mLayer->fields().fieldOriginIndex( i ) ) == val;

// convert to destination data type
QString errorMessageConvertCompatible;
if ( !isDefaultValue && !mLayer->fields().at( i ).convertCompatible( val, &errorMessageConvertCompatible ) )
{
if ( errorMessage.isEmpty() )
errorMessage = QObject::tr( "Could not store value '%1' in field of type %2: %3" ).arg( mergeAttributes.at( i ).toString(), mLayer->fields().at( i ).typeName(), errorMessageConvertCompatible );
}
newAttributes[ i ] = val;
}

mLayer->beginEditCommand( QObject::tr( "Merged features" ) );

// Delete other features but the target feature
QgsFeatureIds::const_iterator feature_it = mergeFeatureIds.constBegin();
for ( ; feature_it != mergeFeatureIds.constEnd(); ++feature_it )
{
if ( *feature_it != targetFeatureId )
mLayer->deleteFeature( *feature_it );
}

// Modify merge feature
QgsGeometry mergeGeometry = unionGeometry;
mLayer->changeGeometry( targetFeatureId, mergeGeometry );
mLayer->changeAttributeValues( targetFeatureId, newAttributes );

mLayer->endEditCommand();

mLayer->triggerRepaint();

return true;
}

bool QgsVectorLayerEditUtils::boundingBoxFromPointList( const QgsPointSequence &list, double &xmin, double &ymin, double &xmax, double &ymax ) const
{
Expand Down
14 changes: 0 additions & 14 deletions src/core/vector/qgsvectorlayereditutils.h
Expand Up @@ -268,20 +268,6 @@ class CORE_EXPORT QgsVectorLayerEditUtils
*/
int addTopologicalPoints( const QgsPointSequence &ps );

/**
* Merge features into a single one.
* \param targetFeatureId id of the target feature (will be updated)
* \param mergeFeatureIds id list of features to merge (will be deleted)
* \param mergeAttributes are the resulting attributes in the merged feature
* \param unionGeometry is the resulting geometry of the merged feature
* \param errorMessage will be set to a descriptive error message if any occurs
*
* \returns TRUE if the merge was successful, or FALSE if the operation failed.
*
* \since QGIS 3.30
*/
bool mergeFeatures( const QgsFeatureId &targetFeatureId, const QgsFeatureIds &mergeFeatureIds, const QgsAttributes &mergeAttributes, const QgsGeometry &unionGeometry, QString &errorMessage SIP_OUT );

private:

/**
Expand Down
1 change: 0 additions & 1 deletion tests/src/app/CMakeLists.txt
Expand Up @@ -46,7 +46,6 @@ set(TESTS
testqgsmeshcalculatordialog.cpp
testqgsgpsinformationwidget.cpp
testqgslabelpropertydialog.cpp
testqgsmergeattributesdialog.cpp
)

if (HAVE_GEOREFERENCER)
Expand Down
97 changes: 0 additions & 97 deletions tests/src/app/testqgsmergeattributesdialog.cpp

This file was deleted.

0 comments on commit a78e7af

Please sign in to comment.