mirror of
https://github.com/qgis/QGIS.git
synced 2025-11-30 00:04:58 -05:00
parent
5ea353ba22
commit
303a6f261c
@ -206,48 +206,95 @@ QgsFeatureList QgsClipboard::stringToFeatureList( const QString &string, const Q
|
|||||||
return features;
|
return features;
|
||||||
|
|
||||||
// otherwise try to read in as WKT
|
// otherwise try to read in as WKT
|
||||||
const QStringList values = string.split( '\n' );
|
if ( string.isEmpty() || string.split( '\n' ).count() == 0 )
|
||||||
if ( values.isEmpty() || string.isEmpty() )
|
|
||||||
return features;
|
return features;
|
||||||
|
|
||||||
const QgsFields sourceFields = retrieveFields();
|
// Poor man's csv parser
|
||||||
|
bool isInsideQuotes {false};
|
||||||
|
QgsAttributes attrs;
|
||||||
|
QgsGeometry geom;
|
||||||
|
QString attrVal;
|
||||||
|
bool isFirstLine {string.startsWith( QStringLiteral( "wkt_geom" ) )};
|
||||||
|
// it seems there is no other way to check for header
|
||||||
|
const bool hasHeader{string.startsWith( QStringLiteral( "wkt_geom" ) )};
|
||||||
|
QgsGeometry geometry;
|
||||||
|
bool setFields {fields.isEmpty()};
|
||||||
|
QgsFields fieldsFromClipboard;
|
||||||
|
|
||||||
const auto constValues = values;
|
auto parseFunc = [ & ]( const QChar & c )
|
||||||
for ( const QString &row : constValues )
|
|
||||||
{
|
{
|
||||||
// Assume that it's just WKT for now. because GeoJSON is managed by
|
|
||||||
// previous QgsOgrUtils::stringToFeatureList call
|
|
||||||
// Get the first value of a \t separated list. WKT clipboard pasted
|
|
||||||
// feature has first element the WKT geom.
|
|
||||||
// This split is to fix the following issue: https://github.com/qgis/QGIS/issues/24769
|
|
||||||
// Value separators are set in generateClipboardText
|
|
||||||
QStringList fieldValues = row.split( '\t' );
|
|
||||||
if ( fieldValues.isEmpty() )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
QgsFeature feature;
|
// parse geom only if it wasn't successfully set before
|
||||||
feature.setFields( sourceFields );
|
if ( geometry.isNull() )
|
||||||
feature.initAttributes( fieldValues.size() - 1 );
|
|
||||||
|
|
||||||
//skip header line
|
|
||||||
if ( fieldValues.at( 0 ) == QLatin1String( "wkt_geom" ) )
|
|
||||||
{
|
{
|
||||||
continue;
|
geometry = QgsGeometry::fromWkt( attrVal );
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( int i = 1; i < fieldValues.size(); ++i )
|
if ( isFirstLine ) // ... name
|
||||||
{
|
{
|
||||||
feature.setAttribute( i - 1, fieldValues.at( i ) );
|
if ( attrVal != QStringLiteral( "wkt_geom" ) ) // ignore this one
|
||||||
|
{
|
||||||
|
fieldsFromClipboard.append( QgsField{attrVal, QVariant::String } );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // ... or value
|
||||||
|
{
|
||||||
|
attrs.append( attrVal );
|
||||||
}
|
}
|
||||||
|
|
||||||
const QgsGeometry geometry = QgsGeometry::fromWkt( fieldValues[0] );
|
// end of record, create a new feature if it's not the header
|
||||||
if ( !geometry.isNull() )
|
if ( c == QChar( '\n' ) )
|
||||||
{
|
{
|
||||||
feature.setGeometry( geometry );
|
if ( isFirstLine )
|
||||||
|
{
|
||||||
|
isFirstLine = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QgsFeature feature{setFields ? fieldsFromClipboard : fields};
|
||||||
|
feature.setGeometry( geometry );
|
||||||
|
if ( hasHeader || !geometry.isNull() )
|
||||||
|
{
|
||||||
|
attrs.pop_front();
|
||||||
|
}
|
||||||
|
feature.setAttributes( attrs );
|
||||||
|
features.append( feature );
|
||||||
|
geometry = QgsGeometry();
|
||||||
|
attrs.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
attrVal.clear();
|
||||||
|
};
|
||||||
|
|
||||||
features.append( feature );
|
for ( auto c = string.constBegin(); c < string.constEnd(); ++c )
|
||||||
|
{
|
||||||
|
if ( *c == QChar( '\n' ) || *c == QChar( '\t' ) )
|
||||||
|
{
|
||||||
|
if ( isInsideQuotes )
|
||||||
|
{
|
||||||
|
attrVal.append( *c );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parseFunc( *c );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( *c == QChar( '\"' ) )
|
||||||
|
{
|
||||||
|
isInsideQuotes = !isInsideQuotes;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
attrVal.append( *c );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handle missing newline
|
||||||
|
if ( !string.endsWith( QChar( '\n' ) ) )
|
||||||
|
{
|
||||||
|
parseFunc( QChar( '\n' ) );
|
||||||
|
}
|
||||||
|
|
||||||
return features;
|
return features;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -121,6 +121,7 @@ void TestQgisAppClipboard::copyPaste()
|
|||||||
|
|
||||||
void TestQgisAppClipboard::copyToText()
|
void TestQgisAppClipboard::copyToText()
|
||||||
{
|
{
|
||||||
|
|
||||||
//set clipboard to some QgsFeatures
|
//set clipboard to some QgsFeatures
|
||||||
QgsFields fields;
|
QgsFields fields;
|
||||||
fields.append( QgsField( QStringLiteral( "int_field" ), QVariant::Int ) );
|
fields.append( QgsField( QStringLiteral( "int_field" ), QVariant::Int ) );
|
||||||
@ -221,13 +222,28 @@ void TestQgisAppClipboard::copyToText()
|
|||||||
settings.setEnumValue( QStringLiteral( "/qgis/copyFeatureFormat" ), QgsClipboard::AttributesWithWKT );
|
settings.setEnumValue( QStringLiteral( "/qgis/copyFeatureFormat" ), QgsClipboard::AttributesWithWKT );
|
||||||
mQgisApp->clipboard()->generateClipboardText( result, resultHtml );
|
mQgisApp->clipboard()->generateClipboardText( result, resultHtml );
|
||||||
QCOMPARE( result, QString( "wkt_geom\tint_field\tstring_field\nPoint (5 6)\t1\tSingle line text\nPoint (7 8)\t2\t\"Unix Multiline \nText\"\nPoint (9 10)\t3\t\"Windows Multiline \r\nText\"" ) );
|
QCOMPARE( result, QString( "wkt_geom\tint_field\tstring_field\nPoint (5 6)\t1\tSingle line text\nPoint (7 8)\t2\t\"Unix Multiline \nText\"\nPoint (9 10)\t3\t\"Windows Multiline \r\nText\"" ) );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestQgisAppClipboard::pasteWkt()
|
void TestQgisAppClipboard::pasteWkt()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// test issue GH #44989
|
||||||
|
QgsFeatureList features = mQgisApp->clipboard()->stringToFeatureList( QStringLiteral( "wkt_geom\tint_field\tstring_field\nPoint (5 6)\t1\tSingle line text\nPoint (7 8)\t2\t\"Unix Multiline \nText\"\nPoint (9 10)\t3\t\"Windows Multiline \r\nText\"" ), QgsFields() );
|
||||||
|
QCOMPARE( features.length(), 3 );
|
||||||
|
QVERIFY( features.at( 0 ).hasGeometry() && !features.at( 0 ).geometry().isNull() );
|
||||||
|
QVERIFY( features.at( 1 ).hasGeometry() && !features.at( 1 ).geometry().isNull() );
|
||||||
|
QVERIFY( features.at( 2 ).hasGeometry() && !features.at( 2 ).geometry().isNull() );
|
||||||
|
QCOMPARE( features.at( 0 ).fields().count(), 2 );
|
||||||
|
QCOMPARE( features.at( 0 ).attributeCount(), 2 );
|
||||||
|
QCOMPARE( features.at( 1 ).fields().count(), 2 );
|
||||||
|
QCOMPARE( features.at( 1 ).attributeCount(), 2 );
|
||||||
|
QCOMPARE( features.at( 2 ).fields().count(), 2 );
|
||||||
|
QCOMPARE( features.at( 2 ).attributeCount(), 2 );
|
||||||
|
|
||||||
mQgisApp->clipboard()->setText( QStringLiteral( "POINT (125 10)\nPOINT (111 30)" ) );
|
mQgisApp->clipboard()->setText( QStringLiteral( "POINT (125 10)\nPOINT (111 30)" ) );
|
||||||
|
|
||||||
QgsFeatureList features = mQgisApp->clipboard()->copyOf();
|
features = mQgisApp->clipboard()->copyOf();
|
||||||
QCOMPARE( features.length(), 2 );
|
QCOMPARE( features.length(), 2 );
|
||||||
QVERIFY( features.at( 0 ).hasGeometry() && !features.at( 0 ).geometry().isNull() );
|
QVERIFY( features.at( 0 ).hasGeometry() && !features.at( 0 ).geometry().isNull() );
|
||||||
QCOMPARE( features.at( 0 ).geometry().constGet()->wkbType(), QgsWkbTypes::Point );
|
QCOMPARE( features.at( 0 ).geometry().constGet()->wkbType(), QgsWkbTypes::Point );
|
||||||
@ -248,7 +264,8 @@ void TestQgisAppClipboard::pasteWkt()
|
|||||||
features = mQgisApp->clipboard()->copyOf();
|
features = mQgisApp->clipboard()->copyOf();
|
||||||
QCOMPARE( features.length(), 2 );
|
QCOMPARE( features.length(), 2 );
|
||||||
|
|
||||||
QVERIFY( features.at( 0 ).hasGeometry() && !features.at( 0 ).geometry().isNull() );
|
QVERIFY( features.at( 0 ).hasGeometry() );
|
||||||
|
QVERIFY( !features.at( 0 ).geometry().isNull() );
|
||||||
QCOMPARE( features.at( 0 ).geometry().constGet()->wkbType(), QgsWkbTypes::Point );
|
QCOMPARE( features.at( 0 ).geometry().constGet()->wkbType(), QgsWkbTypes::Point );
|
||||||
featureGeom = features.at( 0 ).geometry();
|
featureGeom = features.at( 0 ).geometry();
|
||||||
point = dynamic_cast< const QgsPoint * >( featureGeom.constGet() );
|
point = dynamic_cast< const QgsPoint * >( featureGeom.constGet() );
|
||||||
@ -262,7 +279,7 @@ void TestQgisAppClipboard::pasteWkt()
|
|||||||
QCOMPARE( point->y(), 10.0 );
|
QCOMPARE( point->y(), 10.0 );
|
||||||
|
|
||||||
//clipboard should support features without geometry
|
//clipboard should support features without geometry
|
||||||
mQgisApp->clipboard()->setText( QStringLiteral( "\tMNL\t11\t282\tkm\t\t\t\n\tMNL\t11\t347.80000000000001\tkm\t\t\t" ) );
|
mQgisApp->clipboard()->setText( QStringLiteral( "MNL\t11\t282\tkm\t\t\t\nMNL\t11\t347.80000000000001\tkm\t\t\t" ) );
|
||||||
features = mQgisApp->clipboard()->copyOf();
|
features = mQgisApp->clipboard()->copyOf();
|
||||||
QCOMPARE( features.length(), 2 );
|
QCOMPARE( features.length(), 2 );
|
||||||
QVERIFY( !features.at( 0 ).hasGeometry() );
|
QVERIFY( !features.at( 0 ).hasGeometry() );
|
||||||
@ -375,6 +392,7 @@ void TestQgisAppClipboard::pasteGeoJson()
|
|||||||
mQgisApp->clipboard()->setText( QStringLiteral( "{\n\"type\": \"Feature\",\"geometry\": {\"type\": \"Point\",\"coordinates\": [125, 10]},\"properties\": {\"name\": \"Dinagat Islands\"}}" ) );
|
mQgisApp->clipboard()->setText( QStringLiteral( "{\n\"type\": \"Feature\",\"geometry\": {\"type\": \"Point\",\"coordinates\": [125, 10]},\"properties\": {\"name\": \"Dinagat Islands\"}}" ) );
|
||||||
|
|
||||||
const QgsFeatureList features = mQgisApp->clipboard()->copyOf( fields );
|
const QgsFeatureList features = mQgisApp->clipboard()->copyOf( fields );
|
||||||
|
|
||||||
QCOMPARE( features.length(), 1 );
|
QCOMPARE( features.length(), 1 );
|
||||||
QVERIFY( features.at( 0 ).hasGeometry() && !features.at( 0 ).geometry().isNull() );
|
QVERIFY( features.at( 0 ).hasGeometry() && !features.at( 0 ).geometry().isNull() );
|
||||||
QCOMPARE( features.at( 0 ).geometry().constGet()->wkbType(), QgsWkbTypes::Point );
|
QCOMPARE( features.at( 0 ).geometry().constGet()->wkbType(), QgsWkbTypes::Point );
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user