mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-03 00:04:47 -04:00
Merge branch 'master' into model-designer-update
This commit is contained in:
commit
5b7c964178
4
debian/rules
vendored
4
debian/rules
vendored
@ -43,7 +43,7 @@ endif
|
||||
|
||||
QT_PLUGINS_DIR = lib/$(DEB_BUILD_MULTIARCH)/qt5/plugins
|
||||
|
||||
ifneq ($(DISTRIBUTION),$(findstring $(DISTRIBUTION),"bookworm jammy kinetic lunar mantic noble oracular"))
|
||||
ifneq ($(DISTRIBUTION),$(findstring $(DISTRIBUTION),"bookworm trixie jammy kinetic lunar mantic noble oracular plucky"))
|
||||
DISTRIBUTION := sid
|
||||
endif
|
||||
|
||||
@ -115,7 +115,7 @@ ifneq (,$(findstring ;$(GRASSVER);, ";7;8;"))
|
||||
-DGRASS_PREFIX$(GRASSVER)=/usr/lib/$(GRASS)
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring $(DISTRIBUTION),"sid kinetic lunar mantic noble oracular"))
|
||||
ifneq (,$(findstring $(DISTRIBUTION),"trixie sid kinetic lunar mantic noble oracular plucky"))
|
||||
CMAKE_OPTS += -DGDAL_LIBRARY=/usr/lib/$(DEB_BUILD_MULTIARCH)/libgdal.so
|
||||
endif
|
||||
|
||||
|
@ -138,7 +138,7 @@ def register_function(
|
||||
"""
|
||||
|
||||
# Format the help text
|
||||
helptemplate = string.Template("<h3>$name function</h3><br>$doc")
|
||||
helptemplate = string.Template("<h3>function $name</h3>\n$doc")
|
||||
name = kwargs.get("name", function.__name__)
|
||||
helptext = kwargs.get("helpText") or function.__doc__ or ""
|
||||
helptext = helptext.strip()
|
||||
|
@ -138,7 +138,7 @@ def register_function(
|
||||
"""
|
||||
|
||||
# Format the help text
|
||||
helptemplate = string.Template("<h3>$name function</h3><br>$doc")
|
||||
helptemplate = string.Template("<h3>function $name</h3>\n$doc")
|
||||
name = kwargs.get("name", function.__name__)
|
||||
helptext = kwargs.get("helpText") or function.__doc__ or ""
|
||||
helptext = helptext.strip()
|
||||
|
@ -2495,6 +2495,7 @@ if(NOT APPLE OR NOT QGIS_MACAPP_FRAMEWORK)
|
||||
|
||||
if(WITH_INTERNAL_NLOHMANN_JSON)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/external/nlohmann/json_fwd.hpp DESTINATION ${QGIS_INCLUDE_DIR}/nlohmann)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/external/nlohmann/detail/abi_macros.hpp DESTINATION ${QGIS_INCLUDE_DIR}/nlohmann/detail)
|
||||
endif()
|
||||
else()
|
||||
|
||||
|
@ -144,7 +144,7 @@ bool QgsOgrProvider::convertField( QgsField &field, const QTextCodec &encoding )
|
||||
}
|
||||
else
|
||||
{
|
||||
// other lists are supported at this moment
|
||||
// other lists are not supported at this moment
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@ -886,9 +886,9 @@ void QgsOgrProvider::loadFields()
|
||||
QMutexLocker locker( datasetMutex );
|
||||
#endif
|
||||
|
||||
for ( int i = 0; i < fdef.GetFieldCount(); ++i )
|
||||
for ( int fieldIndex = 0; fieldIndex < fdef.GetFieldCount(); ++fieldIndex )
|
||||
{
|
||||
OGRFieldDefnH fldDef = fdef.GetFieldDefn( i );
|
||||
OGRFieldDefnH fldDef = fdef.GetFieldDefn( fieldIndex );
|
||||
const OGRFieldType ogrType = OGR_Fld_GetType( fldDef );
|
||||
const OGRFieldSubType ogrSubType = OGR_Fld_GetSubType( fldDef );
|
||||
|
||||
@ -896,6 +896,111 @@ void QgsOgrProvider::loadFields()
|
||||
QMetaType::Type varSubType = QMetaType::Type::UnknownType;
|
||||
QgsOgrUtils::ogrFieldTypeToQVariantType( ogrType, ogrSubType, varType, varSubType );
|
||||
|
||||
// Handle special case for OGRFieldType::OFSTJSON which is not necessarily a map.
|
||||
// If subtype is JSON try to load a feature and check if it's
|
||||
// really an object (rather than something else like an array)
|
||||
// fallback to string.
|
||||
if ( ( ogrType == OFTString || ogrType == OFTWideString ) && ogrSubType == OFSTJSON )
|
||||
{
|
||||
QRecursiveMutex *layerMutex = nullptr;
|
||||
OGRLayerH ogrLayer = mOgrLayer->getHandleAndMutex( layerMutex );
|
||||
QMutexLocker layerLocker( layerMutex );
|
||||
gdal::ogr_feature_unique_ptr f( OGR_L_GetNextFeature( ogrLayer ) );
|
||||
if ( f )
|
||||
{
|
||||
const char *json = OGR_F_GetFieldAsString( f.get(), fieldIndex );
|
||||
if ( json && json[0] != '\0' )
|
||||
{
|
||||
try
|
||||
{
|
||||
const nlohmann::json json_element = json::parse( json );
|
||||
// Check if it's an homogeneous array of numbers or strings
|
||||
if ( json_element.is_array() )
|
||||
{
|
||||
// Check whether the values are all of the same type
|
||||
bool allNumbers = true;
|
||||
bool allIntegers = true;
|
||||
bool allStrings = true;
|
||||
for ( auto &value : json_element )
|
||||
{
|
||||
if ( allStrings && !value.is_string() )
|
||||
{
|
||||
allStrings = false;
|
||||
}
|
||||
if ( allNumbers && !value.is_number() )
|
||||
{
|
||||
allNumbers = false;
|
||||
}
|
||||
if ( allIntegers && !value.is_number_integer() )
|
||||
{
|
||||
allIntegers = false;
|
||||
}
|
||||
}
|
||||
if ( allNumbers )
|
||||
{
|
||||
if ( allIntegers )
|
||||
{
|
||||
varType = QMetaType::Type::QVariantList;
|
||||
varSubType = QMetaType::Type::LongLong;
|
||||
}
|
||||
else
|
||||
{
|
||||
varType = QMetaType::Type::QVariantList;
|
||||
varSubType = QMetaType::Type::Double;
|
||||
}
|
||||
}
|
||||
else if ( allStrings )
|
||||
{
|
||||
varType = QMetaType::Type::QStringList;
|
||||
varSubType = QMetaType::Type::UnknownType;
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsDebugMsgLevel( QStringLiteral( "JSON array contains mixed types, falling back to string" ), 2 );
|
||||
varType = QMetaType::Type::QString;
|
||||
varSubType = QMetaType::Type::UnknownType;
|
||||
}
|
||||
}
|
||||
else if ( ! json_element.is_object() )
|
||||
{
|
||||
QgsDebugMsgLevel( QStringLiteral( "JSON is neither an array nor an object, falling back to string" ), 2 );
|
||||
varType = QMetaType::Type::QString;
|
||||
varSubType = QMetaType::Type::UnknownType;
|
||||
}
|
||||
else if ( json_element.is_number() )
|
||||
{
|
||||
if ( json_element.is_number_float() )
|
||||
{
|
||||
varType = QMetaType::Type::Double;
|
||||
varSubType = QMetaType::Type::UnknownType;
|
||||
}
|
||||
else
|
||||
{
|
||||
varType = QMetaType::Type::LongLong;
|
||||
varSubType = QMetaType::Type::UnknownType;
|
||||
}
|
||||
}
|
||||
else if ( json_element.is_string() )
|
||||
{
|
||||
varType = QMetaType::Type::QString;
|
||||
varSubType = QMetaType::Type::UnknownType;
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsDebugMsgLevel( QStringLiteral( "JSON is not valid, falling back to string" ), 2 );
|
||||
}
|
||||
}
|
||||
catch ( const json::parse_error & )
|
||||
{
|
||||
QgsDebugMsgLevel( QStringLiteral( "JSON is not valid, falling back to string" ), 2 );
|
||||
varType = QMetaType::Type::QString;
|
||||
varSubType = QMetaType::Type::UnknownType;
|
||||
}
|
||||
}
|
||||
OGR_L_ResetReading( ogrLayer );
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: fix this hack
|
||||
#ifdef ANDROID
|
||||
QString name = OGR_Fld_GetNameRef( fldDef );
|
||||
|
@ -635,7 +635,8 @@ QgsAuxiliaryStorage::QgsAuxiliaryStorage( const QString &filename, bool copy )
|
||||
|
||||
QgsAuxiliaryStorage::~QgsAuxiliaryStorage()
|
||||
{
|
||||
QFile::remove( mTmpFileName );
|
||||
if ( QFile::exists( mTmpFileName ) )
|
||||
QFile::remove( mTmpFileName );
|
||||
}
|
||||
|
||||
bool QgsAuxiliaryStorage::isValid() const
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "qgsfontmanager.h"
|
||||
#include "qgsvariantutils.h"
|
||||
#include "qgsogrproviderutils.h"
|
||||
#include "qgsjsonutils.h"
|
||||
|
||||
#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0)
|
||||
#include "qgsweakrelation.h"
|
||||
@ -59,6 +60,7 @@
|
||||
|
||||
#include "ogr_srs_api.h"
|
||||
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
void gdal::OGRDataSourceDeleter::operator()( OGRDataSourceH source ) const
|
||||
{
|
||||
@ -541,24 +543,49 @@ QVariant QgsOgrUtils::getOgrFeatureAttribute( OGRFeatureH ogrFet, const QgsField
|
||||
if ( ok )
|
||||
*ok = true;
|
||||
|
||||
|
||||
auto getJsonValue = [&]() -> bool
|
||||
{
|
||||
const char *json = OGR_F_GetFieldAsString( ogrFet, attIndex );
|
||||
QString jsonContent;
|
||||
if ( encoding )
|
||||
jsonContent = encoding->toUnicode( json ).toUtf8();
|
||||
else
|
||||
jsonContent = QString::fromUtf8( json ).toUtf8();
|
||||
|
||||
try
|
||||
{
|
||||
const nlohmann::json json_element = json::parse( jsonContent.toStdString() );
|
||||
value = QgsJsonUtils::jsonToVariant( json_element );
|
||||
return true;
|
||||
}
|
||||
catch ( const json::parse_error &e )
|
||||
{
|
||||
QgsDebugMsgLevel( QStringLiteral( "Error parsing JSON: %1" ).arg( e.what() ), 2 );
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
if ( OGR_F_IsFieldSetAndNotNull( ogrFet, attIndex ) )
|
||||
{
|
||||
switch ( field.type() )
|
||||
{
|
||||
case QMetaType::Type::QString:
|
||||
{
|
||||
if ( encoding )
|
||||
value = QVariant( encoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
|
||||
else
|
||||
value = QVariant( QString::fromUtf8( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
|
||||
if ( field.typeName() != QStringLiteral( "JSON" ) || ! getJsonValue() )
|
||||
{
|
||||
if ( encoding )
|
||||
value = QVariant( encoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
|
||||
else
|
||||
value = QVariant( QString::fromUtf8( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
// Fixes GH #41076 (empty strings shown as NULL), because we have checked before that it was NOT NULL
|
||||
// Note: QVariant( QString( ) ).isNull( ) is still true on windows so we really need string literal :(
|
||||
if ( value.isNull() )
|
||||
value = QVariant( QStringLiteral( "" ) ); // skip-keyword-check
|
||||
// Fixes GH #41076 (empty strings shown as NULL), because we have checked before that it was NOT NULL
|
||||
// Note: QVariant( QString( ) ).isNull( ) is still true on windows so we really need string literal :(
|
||||
if ( value.isNull() )
|
||||
value = QVariant( QStringLiteral( "" ) ); // skip-keyword-check
|
||||
#endif
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QMetaType::Type::Int:
|
||||
@ -614,21 +641,24 @@ QVariant QgsOgrUtils::getOgrFeatureAttribute( OGRFeatureH ogrFet, const QgsField
|
||||
|
||||
case QMetaType::Type::QStringList:
|
||||
{
|
||||
QStringList list;
|
||||
char **lst = OGR_F_GetFieldAsStringList( ogrFet, attIndex );
|
||||
const int count = CSLCount( lst );
|
||||
if ( count > 0 )
|
||||
if ( field.typeName() != QStringLiteral( "JSON" ) || ! getJsonValue() )
|
||||
{
|
||||
list.reserve( count );
|
||||
for ( int i = 0; i < count; i++ )
|
||||
QStringList list;
|
||||
char **lst = OGR_F_GetFieldAsStringList( ogrFet, attIndex );
|
||||
const int count = CSLCount( lst );
|
||||
if ( count > 0 )
|
||||
{
|
||||
if ( encoding )
|
||||
list << encoding->toUnicode( lst[i] );
|
||||
else
|
||||
list << QString::fromUtf8( lst[i] );
|
||||
list.reserve( count );
|
||||
for ( int i = 0; i < count; i++ )
|
||||
{
|
||||
if ( encoding )
|
||||
list << encoding->toUnicode( lst[i] );
|
||||
else
|
||||
list << QString::fromUtf8( lst[i] );
|
||||
}
|
||||
}
|
||||
value = list;
|
||||
}
|
||||
value = list;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -638,72 +668,84 @@ QVariant QgsOgrUtils::getOgrFeatureAttribute( OGRFeatureH ogrFet, const QgsField
|
||||
{
|
||||
case QMetaType::Type::QString:
|
||||
{
|
||||
QStringList list;
|
||||
char **lst = OGR_F_GetFieldAsStringList( ogrFet, attIndex );
|
||||
const int count = CSLCount( lst );
|
||||
if ( count > 0 )
|
||||
if ( field.typeName() != QStringLiteral( "JSON" ) || ! getJsonValue() )
|
||||
{
|
||||
list.reserve( count );
|
||||
for ( int i = 0; i < count; i++ )
|
||||
QStringList list;
|
||||
char **lst = OGR_F_GetFieldAsStringList( ogrFet, attIndex );
|
||||
const int count = CSLCount( lst );
|
||||
if ( count > 0 )
|
||||
{
|
||||
if ( encoding )
|
||||
list << encoding->toUnicode( lst[i] );
|
||||
else
|
||||
list << QString::fromUtf8( lst[i] );
|
||||
list.reserve( count );
|
||||
for ( int i = 0; i < count; i++ )
|
||||
{
|
||||
if ( encoding )
|
||||
list << encoding->toUnicode( lst[i] );
|
||||
else
|
||||
list << QString::fromUtf8( lst[i] );
|
||||
}
|
||||
}
|
||||
value = list;
|
||||
}
|
||||
value = list;
|
||||
break;
|
||||
}
|
||||
|
||||
case QMetaType::Type::Int:
|
||||
{
|
||||
QVariantList list;
|
||||
int count = 0;
|
||||
const int *lst = OGR_F_GetFieldAsIntegerList( ogrFet, attIndex, &count );
|
||||
if ( count > 0 )
|
||||
if ( field.typeName() != QStringLiteral( "JSON" ) || ! getJsonValue() )
|
||||
{
|
||||
list.reserve( count );
|
||||
for ( int i = 0; i < count; i++ )
|
||||
QVariantList list;
|
||||
int count = 0;
|
||||
const int *lst = OGR_F_GetFieldAsIntegerList( ogrFet, attIndex, &count );
|
||||
if ( count > 0 )
|
||||
{
|
||||
list << lst[i];
|
||||
list.reserve( count );
|
||||
for ( int i = 0; i < count; i++ )
|
||||
{
|
||||
list << lst[i];
|
||||
}
|
||||
}
|
||||
value = list;
|
||||
}
|
||||
value = list;
|
||||
break;
|
||||
}
|
||||
|
||||
case QMetaType::Type::Double:
|
||||
{
|
||||
QVariantList list;
|
||||
int count = 0;
|
||||
const double *lst = OGR_F_GetFieldAsDoubleList( ogrFet, attIndex, &count );
|
||||
if ( count > 0 )
|
||||
if ( field.typeName() != QStringLiteral( "JSON" ) || ! getJsonValue() )
|
||||
{
|
||||
list.reserve( count );
|
||||
for ( int i = 0; i < count; i++ )
|
||||
QVariantList list;
|
||||
int count = 0;
|
||||
const double *lst = OGR_F_GetFieldAsDoubleList( ogrFet, attIndex, &count );
|
||||
if ( count > 0 )
|
||||
{
|
||||
list << lst[i];
|
||||
list.reserve( count );
|
||||
for ( int i = 0; i < count; i++ )
|
||||
{
|
||||
list << lst[i];
|
||||
}
|
||||
}
|
||||
value = list;
|
||||
}
|
||||
value = list;
|
||||
break;
|
||||
}
|
||||
|
||||
case QMetaType::Type::LongLong:
|
||||
{
|
||||
QVariantList list;
|
||||
int count = 0;
|
||||
const long long *lst = OGR_F_GetFieldAsInteger64List( ogrFet, attIndex, &count );
|
||||
if ( count > 0 )
|
||||
if ( field.typeName() != QStringLiteral( "JSON" ) || ! getJsonValue() )
|
||||
{
|
||||
list.reserve( count );
|
||||
for ( int i = 0; i < count; i++ )
|
||||
QVariantList list;
|
||||
int count = 0;
|
||||
const long long *lst = OGR_F_GetFieldAsInteger64List( ogrFet, attIndex, &count );
|
||||
if ( count > 0 )
|
||||
{
|
||||
list << lst[i];
|
||||
list.reserve( count );
|
||||
for ( int i = 0; i < count; i++ )
|
||||
{
|
||||
list << lst[i];
|
||||
}
|
||||
}
|
||||
value = list;
|
||||
}
|
||||
value = list;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1833,7 +1875,6 @@ void QgsOgrUtils::ogrFieldTypeToQVariantType( OGRFieldType ogrType, OGRFieldSubT
|
||||
if ( ogrSubType == OFSTBoolean )
|
||||
{
|
||||
variantType = QMetaType::Type::Bool;
|
||||
ogrSubType = OFSTBoolean;
|
||||
}
|
||||
else
|
||||
variantType = QMetaType::Type::Int;
|
||||
@ -1862,7 +1903,6 @@ void QgsOgrUtils::ogrFieldTypeToQVariantType( OGRFieldType ogrType, OGRFieldSubT
|
||||
case OFTWideString:
|
||||
if ( ogrSubType == OFSTJSON )
|
||||
{
|
||||
ogrSubType = OFSTJSON;
|
||||
variantType = QMetaType::Type::QVariantMap;
|
||||
variantSubType = QMetaType::Type::QString;
|
||||
}
|
||||
|
@ -498,7 +498,7 @@ QgsGraduatedSymbolRendererWidget::QgsGraduatedSymbolRendererWidget( QgsVectorLay
|
||||
|
||||
mModel = new QgsGraduatedSymbolRendererModel( this, screen() );
|
||||
|
||||
mExpressionWidget->setFilters( QgsFieldProxyModel::Numeric | QgsFieldProxyModel::Date );
|
||||
mExpressionWidget->setFilters( QgsFieldProxyModel::Numeric );
|
||||
mExpressionWidget->setLayer( mLayer );
|
||||
|
||||
btnChangeGraduatedSymbol->setLayer( mLayer );
|
||||
|
@ -166,7 +166,7 @@ QgsGrassProvider::QgsGrassProvider( const QString &uri )
|
||||
mLayerField = grassLayer( mLayerName );
|
||||
if ( mLayerField == -1 )
|
||||
{
|
||||
QgsDebugError( QString( "Invalid layer name, no underscore found: %1" ).arg( mLayerName ) );
|
||||
QgsDebugError( QString( "Invalid layer name, no underscore found: \"%1\"" ).arg( mLayerName ) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -777,13 +777,16 @@ void QgsGrassVectorMapLayer::deleteColumn( const QgsField &field, QString &error
|
||||
|
||||
if ( error.isEmpty() )
|
||||
{
|
||||
QgsDebugError( "error = " + error );
|
||||
int index = mTableFields.indexFromName( field.name() );
|
||||
if ( index != -1 )
|
||||
{
|
||||
mTableFields.remove( index );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsDebugError( "error = " + error );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsGrassVectorMapLayer::insertCats( QString &error )
|
||||
|
@ -1793,7 +1793,7 @@ void QgsWmsCapabilities::parseWMTSContents( const QDomElement &element )
|
||||
|
||||
tileMatrix.scaleDenom = secondChildElement.firstChildElement( QStringLiteral( "ScaleDenominator" ) ).text().toDouble();
|
||||
|
||||
QStringList topLeft = secondChildElement.firstChildElement( QStringLiteral( "TopLeftCorner" ) ).text().split( ' ' );
|
||||
QStringList topLeft = secondChildElement.firstChildElement( QStringLiteral( "TopLeftCorner" ) ).text().split( ' ', Qt::SkipEmptyParts );
|
||||
if ( topLeft.size() == 2 )
|
||||
{
|
||||
if ( invert )
|
||||
@ -1856,8 +1856,8 @@ void QgsWmsCapabilities::parseWMTSContents( const QDomElement &element )
|
||||
QDomElement bbox = childElement.firstChildElement( QStringLiteral( "ows:WGS84BoundingBox" ) );
|
||||
if ( !bbox.isNull() )
|
||||
{
|
||||
QStringList ll = bbox.firstChildElement( QStringLiteral( "ows:LowerCorner" ) ).text().split( ' ' );
|
||||
QStringList ur = bbox.firstChildElement( QStringLiteral( "ows:UpperCorner" ) ).text().split( ' ' );
|
||||
QStringList ll = bbox.firstChildElement( QStringLiteral( "ows:LowerCorner" ) ).text().split( ' ', Qt::SkipEmptyParts );
|
||||
QStringList ur = bbox.firstChildElement( QStringLiteral( "ows:UpperCorner" ) ).text().split( ' ', Qt::SkipEmptyParts );
|
||||
|
||||
if ( ll.size() == 2 && ur.size() == 2 )
|
||||
{
|
||||
@ -1872,8 +1872,8 @@ void QgsWmsCapabilities::parseWMTSContents( const QDomElement &element )
|
||||
!bbox.isNull();
|
||||
bbox = bbox.nextSiblingElement( QStringLiteral( "ows:BoundingBox" ) ) )
|
||||
{
|
||||
QStringList ll = bbox.firstChildElement( QStringLiteral( "ows:LowerCorner" ) ).text().split( ' ' );
|
||||
QStringList ur = bbox.firstChildElement( QStringLiteral( "ows:UpperCorner" ) ).text().split( ' ' );
|
||||
QStringList ll = bbox.firstChildElement( QStringLiteral( "ows:LowerCorner" ) ).text().split( ' ', Qt::SkipEmptyParts );
|
||||
QStringList ur = bbox.firstChildElement( QStringLiteral( "ows:UpperCorner" ) ).text().split( ' ', Qt::SkipEmptyParts );
|
||||
|
||||
if ( ll.size() == 2 && ur.size() == 2 )
|
||||
{
|
||||
|
@ -58,6 +58,8 @@ class TestQgsOgrProvider : public QgsTest
|
||||
void testExtent();
|
||||
void testVsiCredentialOptions();
|
||||
void testVsiCredentialOptionsQuerySublayers();
|
||||
void testJSONFields_data();
|
||||
void testJSONFields();
|
||||
|
||||
private:
|
||||
QString mTestDataDir;
|
||||
@ -579,5 +581,229 @@ void TestQgsOgrProvider::testVsiCredentialOptionsQuerySublayers()
|
||||
}
|
||||
|
||||
|
||||
void TestQgsOgrProvider::testJSONFields_data()
|
||||
{
|
||||
QTest::addColumn<QString>( "jsonData" );
|
||||
QTest::addColumn<int>( "expectedType" );
|
||||
QTest::addColumn<int>( "expectedSubType" );
|
||||
|
||||
QTest::newRow( "array of map string fallback" ) << QStringLiteral( R"json(
|
||||
{
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"array_of_map": [
|
||||
{
|
||||
"a": 1,
|
||||
"b": 2.0
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
)json" ) << static_cast<int>( QMetaType::Type::QString )
|
||||
<< static_cast<int>( QMetaType::Type::UnknownType );
|
||||
|
||||
QTest::newRow( "simple map" ) << QStringLiteral( R"json(
|
||||
{
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"map": {
|
||||
"a": 1,
|
||||
"b": 2.0
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
)json" ) << static_cast<int>( QMetaType::Type::QVariantMap )
|
||||
<< static_cast<int>( QMetaType::Type::QString );
|
||||
|
||||
QTest::newRow( "complex map" ) << QStringLiteral( R"json(
|
||||
{
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"map": {
|
||||
"a": 1,
|
||||
"b": [2.0, "c"]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
)json" ) << static_cast<int>( QMetaType::Type::QVariantMap )
|
||||
<< static_cast<int>( QMetaType::Type::QString );
|
||||
|
||||
QTest::newRow( "int" ) << QStringLiteral( R"json(
|
||||
{
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"int": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
)json" ) << static_cast<int>( QMetaType::Type::Int )
|
||||
<< static_cast<int>( QMetaType::Type::UnknownType );
|
||||
|
||||
QTest::newRow( "stringlist" ) << QStringLiteral( R"json(
|
||||
{
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"string_list": [ "a", "b", "c" ]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
)json" ) << static_cast<int>( QMetaType::Type::QStringList )
|
||||
<< static_cast<int>( QMetaType::Type::QString );
|
||||
|
||||
QTest::newRow( "string" ) << QStringLiteral( R"json(
|
||||
{
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"string": "a"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
)json" ) << static_cast<int>( QMetaType::Type::QString )
|
||||
<< static_cast<int>( QMetaType::Type::UnknownType );
|
||||
|
||||
QTest::newRow( "double" ) << QStringLiteral( R"json(
|
||||
{
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"double": 1.0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
)json" ) << static_cast<int>( QMetaType::Type::Double )
|
||||
<< static_cast<int>( QMetaType::Type::UnknownType );
|
||||
|
||||
QTest::newRow( "bool" ) << QStringLiteral( R"json(
|
||||
{
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"bool": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
)json" ) << static_cast<int>( QMetaType::Type::Bool )
|
||||
<< static_cast<int>( QMetaType::Type::UnknownType );
|
||||
|
||||
QTest::newRow( "int list" ) << QStringLiteral( R"json(
|
||||
{
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"int_list": [1, 2, 3]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
)json" ) << static_cast<int>( QMetaType::Type::QVariantList )
|
||||
<< static_cast<int>( QMetaType::Type::Int );
|
||||
|
||||
QTest::newRow( "real list" ) << QStringLiteral( R"json(
|
||||
{
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"real_list": [1.0, 2.1, 3]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
)json" ) << static_cast<int>( QMetaType::Type::QVariantList )
|
||||
<< static_cast<int>( QMetaType::Type::Double );
|
||||
|
||||
|
||||
QTest::newRow( "array mixed types string fallback" ) << QStringLiteral( R"json(
|
||||
{
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"mixed_list": [1, 2.0, "a", true]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
)json" ) << static_cast<int>( QMetaType::Type::QString )
|
||||
<< static_cast<int>( QMetaType::Type::UnknownType );
|
||||
|
||||
QTest::newRow( "array mixed numeric types" ) << QStringLiteral( R"json(
|
||||
{
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"mixed_numeric_list": [1, 2.3]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
)json" ) << static_cast<int>( QMetaType::Type::QVariantList )
|
||||
<< static_cast<int>( QMetaType::Type::Double );
|
||||
}
|
||||
|
||||
void TestQgsOgrProvider::testJSONFields()
|
||||
{
|
||||
QFETCH( QString, jsonData );
|
||||
QFETCH( int, expectedType );
|
||||
QFETCH( int, expectedSubType );
|
||||
|
||||
QTemporaryDir dir;
|
||||
QString filePath = dir.path() + "/test.json";
|
||||
QFile file( filePath );
|
||||
if ( file.open( QIODevice::WriteOnly ) )
|
||||
{
|
||||
QTextStream textStream( &file );
|
||||
textStream << jsonData;
|
||||
file.close();
|
||||
}
|
||||
QgsVectorLayer layer { filePath, QStringLiteral( "json" ), QLatin1String( "ogr" ) };
|
||||
QVERIFY( layer.isValid() );
|
||||
QgsFields fields = layer.fields();
|
||||
QCOMPARE( fields.count(), 1 );
|
||||
QgsField field = fields.at( 0 );
|
||||
QCOMPARE( static_cast<int>( field.type() ), expectedType );
|
||||
QCOMPARE( static_cast<int>( field.subType() ), expectedSubType );
|
||||
}
|
||||
|
||||
|
||||
QGSTEST_MAIN( TestQgsOgrProvider )
|
||||
#include "testqgsogrprovider.moc"
|
||||
|
@ -568,11 +568,11 @@ void TestQgsVectorFileWriter::testExportArrayToGpkg()
|
||||
const QgsVectorLayer vl2( QStringLiteral( "%1|layername=test" ).arg( fileName ), "src_test", "ogr" );
|
||||
QVERIFY( vl2.isValid() );
|
||||
QCOMPARE( vl2.featureCount(), 1L );
|
||||
QCOMPARE( vl2.fields().at( 1 ).type(), QMetaType::Type::QVariantMap );
|
||||
QCOMPARE( vl2.fields().at( 1 ).subType(), QMetaType::Type::QString );
|
||||
QCOMPARE( vl2.fields().at( 1 ).type(), QMetaType::Type::QVariantList );
|
||||
QCOMPARE( vl2.fields().at( 1 ).subType(), QMetaType::Type::LongLong );
|
||||
QCOMPARE( vl2.fields().at( 1 ).typeName(), QStringLiteral( "JSON" ) );
|
||||
QCOMPARE( vl2.fields().at( 2 ).type(), QMetaType::Type::QVariantMap );
|
||||
QCOMPARE( vl2.fields().at( 2 ).subType(), QMetaType::Type::QString );
|
||||
QCOMPARE( vl2.fields().at( 2 ).type(), QMetaType::Type::QStringList );
|
||||
QCOMPARE( vl2.fields().at( 2 ).subType(), QMetaType::Type::UnknownType );
|
||||
QCOMPARE( vl2.fields().at( 2 ).typeName(), QStringLiteral( "JSON" ) );
|
||||
QCOMPARE( vl2.getFeature( 1 ).attribute( 1 ).toList(), QVariantList() << 1 << 2 << 3 );
|
||||
QCOMPARE( vl2.getFeature( 1 ).attribute( 2 ).toStringList(), QStringList() << "a" << "b" << "c" );
|
||||
|
@ -127,13 +127,13 @@ QString TestQgsGrassCommand::toString() const
|
||||
{
|
||||
if ( grassFeature.hasGeometry() )
|
||||
{
|
||||
string += "<br>grass: " + grassFeature.geometry().asWkt( 1 );
|
||||
string += "grass: " + grassFeature.geometry().asWkt( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
if ( expectedFeature.hasGeometry() )
|
||||
{
|
||||
string += "<br>expected: " + expectedFeature.geometry().asWkt( 1 );
|
||||
string += "expected: " + expectedFeature.geometry().asWkt( 1 );
|
||||
}
|
||||
}
|
||||
else if ( command == DeleteFeature )
|
||||
@ -243,11 +243,16 @@ class TestQgsGrassProvider : public QgsTest
|
||||
|
||||
void TestQgsGrassProvider::reportRow( const QString &message )
|
||||
{
|
||||
mReport += message + "<br>\n";
|
||||
for ( const QString &line : message.split( '\n' ) )
|
||||
{
|
||||
qDebug() << line;
|
||||
}
|
||||
}
|
||||
void TestQgsGrassProvider::reportHeader( const QString &message )
|
||||
{
|
||||
mReport += "<h2>" + message + "</h2>\n";
|
||||
qDebug() << "------";
|
||||
qDebug() << message;
|
||||
qDebug() << "------";
|
||||
}
|
||||
|
||||
//runs before all tests
|
||||
@ -264,8 +269,8 @@ void TestQgsGrassProvider::initTestCase()
|
||||
QgsApplication::initQgis();
|
||||
QString mySettings = QgsApplication::showSettings();
|
||||
mySettings = mySettings.replace( QLatin1String( "\n" ), QLatin1String( "<br />\n" ) );
|
||||
mReport += QStringLiteral( "<h1>GRASS %1 provider tests</h1>\n" ).arg( GRASS_BUILD_VERSION );
|
||||
mReport += "<p>" + mySettings + "</p>\n";
|
||||
reportHeader( QStringLiteral( "<h1>GRASS %1 provider tests</h1>\n" ).arg( GRASS_BUILD_VERSION ) );
|
||||
reportRow( mySettings );
|
||||
|
||||
#ifndef Q_OS_WIN
|
||||
reportRow( "LD_LIBRARY_PATH: " + QString( getenv( "LD_LIBRARY_PATH" ) ) );
|
||||
@ -1163,7 +1168,7 @@ void TestQgsGrassProvider::edit()
|
||||
|
||||
Q_FOREACH ( const TestQgsGrassCommand &command, commandGroup.commands )
|
||||
{
|
||||
reportRow( "<br>command: " + command.toString() );
|
||||
reportRow( "command: " + command.toString() );
|
||||
bool commandOk = true;
|
||||
|
||||
if ( command.command == TestQgsGrassCommand::StartEditing )
|
||||
@ -1388,7 +1393,7 @@ void TestQgsGrassProvider::edit()
|
||||
{
|
||||
for ( int j = editCommands.size() - 1; j >= 0; j-- )
|
||||
{
|
||||
reportRow( "<br>undo command: " + editCommands[j].toString() );
|
||||
reportRow( "undo command: " + editCommands[j].toString() );
|
||||
grassLayer->undoStack()->undo();
|
||||
expectedLayer->undoStack()->undo();
|
||||
if ( !compare( expectedLayers, ok ) )
|
||||
@ -1418,7 +1423,7 @@ void TestQgsGrassProvider::edit()
|
||||
{
|
||||
for ( int j = 0; j < editCommands.size(); j++ )
|
||||
{
|
||||
reportRow( "<br>redo command: " + editCommands[j].toString() );
|
||||
reportRow( "redo command: " + editCommands[j].toString() );
|
||||
grassLayer->undoStack()->redo();
|
||||
expectedLayer->undoStack()->redo();
|
||||
if ( !compare( expectedLayers, ok ) )
|
||||
|
@ -596,6 +596,44 @@ class TestQgsWmsCapabilities : public QObject
|
||||
QCOMPARE( res.end(), range.end() );
|
||||
QCOMPARE( static_cast<int>( resFormat ), format );
|
||||
}
|
||||
|
||||
void wmtsWithRedundantSpaces()
|
||||
{
|
||||
QgsWmsCapabilities capabilities;
|
||||
const QgsWmsParserSettings config;
|
||||
|
||||
// Note: Redundant spaces in the coordinate tuples
|
||||
const QByteArray configData( R"""(<Capabilities>
|
||||
<Contents>
|
||||
<Layer>
|
||||
<ows:Identifier>Layer1</ows:Identifier>
|
||||
<ows:WGS84BoundingBox>
|
||||
<ows:LowerCorner>109.999000 -45.081000</ows:LowerCorner>
|
||||
<ows:UpperCorner>155.005000 -9.978000</ows:UpperCorner>
|
||||
</ows:WGS84BoundingBox>
|
||||
</Layer>
|
||||
<TileMatrixSet>
|
||||
<ows:Identifier>WholeWorld_CRS_84</ows:Identifier>
|
||||
<ows:SupportedCRS>urn:ogc:def:crs:OGC:1.3:CRS84</ows:SupportedCRS>
|
||||
<WellKnownScaleSet>urn:ogc:def:wkss:OGC:1.0:GlobalCRS84Pixel</WellKnownScaleSet>
|
||||
<TileMatrix>
|
||||
<ows:Identifier>1g</ows:Identifier>
|
||||
<ScaleDenominator>397569609.975977</ScaleDenominator>
|
||||
<TopLeftCorner>-180 90</TopLeftCorner>
|
||||
<TileWidth>320</TileWidth>
|
||||
<TileHeight>200</TileHeight>
|
||||
<MatrixWidth>2</MatrixWidth>
|
||||
<MatrixHeight>1</MatrixHeight>
|
||||
</TileMatrix>
|
||||
</TileMatrixSet>
|
||||
</Contents>
|
||||
</Capabilities>)""" );
|
||||
|
||||
QVERIFY( capabilities.parseResponse( configData, config ) );
|
||||
QCOMPARE( capabilities.supportedTileMatrixSets().size(), 1 );
|
||||
QgsWmtsTileLayer layer = capabilities.supportedTileLayers().at( 0 );
|
||||
QCOMPARE( layer.boundingBoxes.first().box, QgsRectangle( 109.999, -45.081, 155.005, -9.978 ) );
|
||||
}
|
||||
};
|
||||
|
||||
QGSTEST_MAIN( TestQgsWmsCapabilities )
|
||||
|
@ -120,13 +120,13 @@ class TestQgsExpressionCustomFunctions(unittest.TestCase):
|
||||
"""Test help about python function."""
|
||||
QgsExpression.registerFunction(self.help_with_variable)
|
||||
html = (
|
||||
"<h3>help_with_variable function</h3><br>" "The help comes from a variable."
|
||||
"<h3>function help_with_variable</h3>\n" "The help comes from a variable."
|
||||
)
|
||||
self.assertEqual(self.help_with_variable.helpText(), html)
|
||||
|
||||
QgsExpression.registerFunction(self.help_with_docstring)
|
||||
html = (
|
||||
"<h3>help_with_docstring function</h3><br>"
|
||||
"<h3>function help_with_docstring</h3>\n"
|
||||
"The help comes from the python docstring."
|
||||
)
|
||||
self.assertEqual(self.help_with_docstring.helpText(), html)
|
||||
|
Loading…
x
Reference in New Issue
Block a user