mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-25 00:58:06 -05:00
[gui] Fix value map editor widget configuration's load from CSV parsing
This commit is contained in:
parent
4e035e686b
commit
4131eb265c
@ -301,14 +301,18 @@ void QgsValueMapConfigDlg::loadFromCSVButtonPushed()
|
||||
const QString fileName = QFileDialog::getOpenFileName( nullptr, tr( "Load Value Map from File" ), QDir::homePath() );
|
||||
if ( fileName.isNull() )
|
||||
return;
|
||||
loadMapFromCSV( fileName );
|
||||
}
|
||||
|
||||
QFile f( fileName );
|
||||
void QgsValueMapConfigDlg::loadMapFromCSV( const QString &filePath )
|
||||
{
|
||||
QFile f( filePath );
|
||||
|
||||
if ( !f.open( QIODevice::ReadOnly ) )
|
||||
{
|
||||
QMessageBox::information( nullptr,
|
||||
tr( "Load Value Map from File" ),
|
||||
tr( "Could not open file %1\nError was: %2" ).arg( fileName, f.errorString() ),
|
||||
tr( "Could not open file %1\nError was: %2" ).arg( filePath, f.errorString() ),
|
||||
QMessageBox::Cancel );
|
||||
return;
|
||||
}
|
||||
@ -316,53 +320,26 @@ void QgsValueMapConfigDlg::loadFromCSVButtonPushed()
|
||||
QTextStream s( &f );
|
||||
s.setAutoDetectUnicode( true );
|
||||
|
||||
const thread_local QRegularExpression re0( "^([^;]*?);(.*?)$" );
|
||||
const thread_local QRegularExpression re1( "^([^,]*?),(.*?)$" );
|
||||
|
||||
const thread_local QRegularExpression re( "(?:^\"|[;,]\")(\"\"|[\\w\\W]*?)(?=\"[;,]|\"$)|(?:^(?!\")|[;,](?!\"))([^;,]*?)(?=$|[;,])|(\\r\\n|\\n)" );
|
||||
QList<QPair<QString, QVariant>> map;
|
||||
|
||||
while ( !s.atEnd() )
|
||||
{
|
||||
const QString l = s.readLine().trimmed();
|
||||
|
||||
QString key;
|
||||
QString val;
|
||||
|
||||
const QRegularExpressionMatch re0match = re0.match( l );
|
||||
if ( re0match.hasMatch() )
|
||||
QRegularExpressionMatchIterator matches = re.globalMatch( l );
|
||||
QStringList ceils;
|
||||
while ( matches.hasNext() && ceils.size() < 2 )
|
||||
{
|
||||
key = re0match.captured( 1 ).trimmed();
|
||||
val = re0match.captured( 2 ).trimmed();
|
||||
}
|
||||
else
|
||||
{
|
||||
const QRegularExpressionMatch re1match = re1.match( l );
|
||||
if ( re1match.hasMatch() )
|
||||
{
|
||||
key = re1match.captured( 1 ).trimmed();
|
||||
val = re1match.captured( 2 ).trimmed();
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const QRegularExpressionMatch match = matches.next();
|
||||
ceils << match.capturedTexts().last().trimmed().replace( QLatin1String( "\"\"" ), QLatin1String( "\"" ) );
|
||||
}
|
||||
|
||||
if ( ( key.startsWith( '\"' ) && key.endsWith( '\"' ) ) ||
|
||||
( key.startsWith( '\'' ) && key.endsWith( '\'' ) ) )
|
||||
{
|
||||
key = key.mid( 1, key.length() - 2 );
|
||||
}
|
||||
|
||||
if ( ( val.startsWith( '\"' ) && val.endsWith( '\"' ) ) ||
|
||||
( val.startsWith( '\'' ) && val.endsWith( '\'' ) ) )
|
||||
{
|
||||
val = val.mid( 1, val.length() - 2 );
|
||||
}
|
||||
if ( ceils.size() != 2 )
|
||||
continue;
|
||||
|
||||
QString key = ceils[0];
|
||||
QString val = ceils[1];
|
||||
if ( key == QgsApplication::nullRepresentation() )
|
||||
key = QgsValueMapFieldFormatter::NULL_VALUE;
|
||||
|
||||
map.append( qMakePair( key, val ) );
|
||||
}
|
||||
|
||||
|
@ -58,6 +58,13 @@ class GUI_EXPORT QgsValueMapConfigDlg : public QgsEditorConfigWidget, private Ui
|
||||
*/
|
||||
void updateMap( const QList<QPair<QString, QVariant>> &list, bool insertNull );
|
||||
|
||||
/**
|
||||
* Updates the displayed table with the values from a CSV file.
|
||||
* \param filePath the absolute file path of the CSV file.
|
||||
* \since QGIS 3.24
|
||||
*/
|
||||
void loadMapFromCSV( const QString &filePath );
|
||||
|
||||
/**
|
||||
* Populates a \a comboBox with the appropriate entries based on a value map \a configuration.
|
||||
*
|
||||
|
@ -58,6 +58,7 @@ set(TESTS
|
||||
testqgslayoutgui.cpp
|
||||
testqgslayoutview.cpp
|
||||
testqgsvaluemapwidgetwrapper.cpp
|
||||
testqgsvaluemapconfigdlg.cpp
|
||||
testqgsvaluerelationwidgetwrapper.cpp
|
||||
testqgsrelationeditorwidget.cpp
|
||||
testqgsrelationreferencewidget.cpp
|
||||
|
90
tests/src/gui/testqgsvaluemapconfigdlg.cpp
Normal file
90
tests/src/gui/testqgsvaluemapconfigdlg.cpp
Normal file
@ -0,0 +1,90 @@
|
||||
/***************************************************************************
|
||||
testqgsvaluemapconfigdlg.cpp
|
||||
--------------------------------------
|
||||
Date : 14 02 2021
|
||||
Copyright : (C) 2019 Stephen Knox
|
||||
Email : stephenknox73 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 "qgstest.h"
|
||||
|
||||
#include "editorwidgets/qgsvaluemapconfigdlg.h"
|
||||
#include "qgsgui.h"
|
||||
#include "qgseditorwidgetregistry.h"
|
||||
#include "qgsapplication.h"
|
||||
#include "qgsproject.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
|
||||
class TestQgsValueMapConfigDlg : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TestQgsValueMapConfigDlg() = default;
|
||||
|
||||
private slots:
|
||||
void initTestCase(); // will be called before the first testfunction is executed.
|
||||
void cleanupTestCase(); // will be called after the last testfunction was executed.
|
||||
void init(); // will be called before each testfunction is executed.
|
||||
void cleanup(); // will be called after every testfunction.
|
||||
|
||||
void testLoadFromCSV();
|
||||
};
|
||||
|
||||
void TestQgsValueMapConfigDlg::initTestCase()
|
||||
{
|
||||
QgsApplication::init();
|
||||
QgsApplication::initQgis();
|
||||
QgsGui::editorWidgetRegistry()->initEditors();
|
||||
}
|
||||
|
||||
void TestQgsValueMapConfigDlg::cleanupTestCase()
|
||||
{
|
||||
QgsApplication::exitQgis();
|
||||
}
|
||||
|
||||
void TestQgsValueMapConfigDlg::init()
|
||||
{
|
||||
}
|
||||
|
||||
void TestQgsValueMapConfigDlg::cleanup()
|
||||
{
|
||||
}
|
||||
|
||||
void TestQgsValueMapConfigDlg::testLoadFromCSV()
|
||||
{
|
||||
const QString dataDir( TEST_DATA_DIR );
|
||||
QgsVectorLayer vl( QStringLiteral( "LineString?crs=epsg:3111&field=pk:int&field=name:string" ), QStringLiteral( "vl1" ), QStringLiteral( "memory" ) );
|
||||
|
||||
QList<QVariant> valueList;
|
||||
QVariantMap value;
|
||||
value.insert( QStringLiteral( "Basic unquoted record" ), QString( "1" ) );
|
||||
valueList << value;
|
||||
value.clear();
|
||||
value.insert( QStringLiteral( "Forest type" ), QString( "2" ) );
|
||||
valueList << value;
|
||||
value.clear();
|
||||
value.insert( QStringLiteral( "So-called \"data\"" ), QString( "three" ) );
|
||||
valueList << value;
|
||||
value.clear();
|
||||
value.insert( QStringLiteral( "444" ), QString( "4" ) );
|
||||
valueList << value;
|
||||
value.clear();
|
||||
value.insert( QStringLiteral( "five" ), QString( "5" ) );
|
||||
valueList << value;
|
||||
|
||||
QgsValueMapConfigDlg *valueMapConfig = static_cast<QgsValueMapConfigDlg *>( QgsGui::editorWidgetRegistry()->createConfigWidget( QStringLiteral( "ValueMap" ), &vl, 1, nullptr ) );
|
||||
valueMapConfig->loadMapFromCSV( dataDir + QStringLiteral( "/valuemapsample.csv" ) );
|
||||
QCOMPARE( valueMapConfig->config().value( QStringLiteral( "map" ) ).toList(), valueList );
|
||||
delete valueMapConfig;
|
||||
}
|
||||
|
||||
QGSTEST_MAIN( TestQgsValueMapConfigDlg )
|
||||
#include "testqgsvaluemapconfigdlg.moc"
|
5
tests/testdata/valuemapsample.csv
vendored
Normal file
5
tests/testdata/valuemapsample.csv
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
1,Basic unquoted record,Some description
|
||||
2,Forest type,"Quoted data"
|
||||
three,"So-called ""data""",Unquoted remark
|
||||
4,"444",No comment
|
||||
5,five
|
Can't render this file because it has a wrong number of fields in line 5.
|
Loading…
x
Reference in New Issue
Block a user