Merge pull request #38730 from 3nids/conf-flag-check-cb

Use a checkable combobox for fields configuration flags
This commit is contained in:
Denis Rouzaud 2020-09-16 07:02:17 +02:00 committed by GitHub
commit f6c98ec5f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 1367 additions and 1212 deletions

View File

@ -292,6 +292,7 @@ Formats string for display
%End
bool convertCompatible( QVariant &v ) const;
%Docstring
Converts the provided variant to a compatible format

View File

@ -1968,24 +1968,36 @@ Convenience function that returns the attribute alias if defined or the field na
Returns a map of field name to attribute alias
%End
QSet<QString> excludeAttributesWms() const;
QSet<QString> excludeAttributesWms() const /Deprecated/;
%Docstring
A set of attributes that are not advertised in WMS requests with QGIS server.
.. deprecated:: QGIS 3.16
use fields().configurationFlags() instead
%End
void setExcludeAttributesWms( const QSet<QString> &att );
void setExcludeAttributesWms( const QSet<QString> &att ) /Deprecated/;
%Docstring
A set of attributes that are not advertised in WMS requests with QGIS server.
.. deprecated:: QGIS 3.16
use setFieldConfigurationFlag instead
%End
QSet<QString> excludeAttributesWfs() const;
QSet<QString> excludeAttributesWfs() const /Deprecated/;
%Docstring
A set of attributes that are not advertised in WFS requests with QGIS server.
.. deprecated:: QGIS 3.16
use fields().configurationFlags() instead
%End
void setExcludeAttributesWfs( const QSet<QString> &att );
void setExcludeAttributesWfs( const QSet<QString> &att ) /Deprecated/;
%Docstring
A set of attributes that are not advertised in WFS requests with QGIS server.
.. deprecated:: QGIS 3.16
use setFieldConfigurationFlag instead
%End
virtual bool deleteAttribute( int attr );
@ -2294,6 +2306,7 @@ can also be set. Setting an empty expression will clear any existing expression
void setEditorWidgetSetup( int index, const QgsEditorWidgetSetup &setup );
%Docstring
\copydoc editorWidgetSetup

View File

@ -62,6 +62,15 @@ no items selected.
:param text: default text
.. seealso:: :py:func:`defaultText`
%End
void addItemWithCheckState( const QString &text, Qt::CheckState state, const QVariant &userData = QVariant() );
%Docstring
Adds an item to the combobox with the given ``text``, check ``state`` (stored in the Qt.CheckStateRole)
and containing the specified ``userData`` (stored in the Qt.UserRole).
The item is appended to the list of existing items.
.. versionadded:: 3.16
%End
QStringList checkedItems() const;
@ -113,6 +122,7 @@ Toggles the item check state
.. seealso:: :py:func:`setItemCheckState`
%End
virtual void hidePopup();
%Docstring

View File

@ -346,6 +346,23 @@ QString QgsField::displayString( const QVariant &v ) const
return v.toString();
}
QString QgsField::readableConfigurationFlag( QgsField::ConfigurationFlag flag )
{
switch ( flag )
{
case ConfigurationFlag::None:
return QObject::tr( "None" );
case ConfigurationFlag::Searchable:
return QObject::tr( "Searchable" );
case ConfigurationFlag::ExposeViaWms:
return QStringLiteral( "Expose via WMS" );
case ConfigurationFlag::ExposeViaWfs:
return QStringLiteral( "Expose via WFS" );
case ConfigurationFlag::DefaultFlags:
return QObject::tr( "Default flags" );
}
}
/***************************************************************************
* This class is considered CRITICAL and any change MUST be accompanied with
* full unit tests in testqgsfield.cpp.

View File

@ -80,8 +80,10 @@ class CORE_EXPORT QgsField
#endif
{
None = 0, //!< No flag is defined
Searchable = 0x1, //!< Defines if the field is searchable (used in the locator search for instance)
DefaultFlags = Searchable, //!< Default set of flags for a field
Searchable = 1 << 1, //!< Defines if the field is searchable (used in the locator search for instance)
ExposeViaWms = 1 << 2, //!< Fields is available if layer is served as WMS from QGIS server
ExposeViaWfs = 1 << 3, //!< Fields is available if layer is served as WFS from QGIS server
DefaultFlags = Searchable | ExposeViaWms | ExposeViaWfs, //!< Default set of flags for a field
};
Q_ENUM( ConfigurationFlag )
Q_DECLARE_FLAGS( ConfigurationFlags, ConfigurationFlag )
@ -327,6 +329,12 @@ class CORE_EXPORT QgsField
//! Formats string for display
QString displayString( const QVariant &v ) const;
/**
* Returns the reabable and translated value of the configuration flag
* \since QGIS 3.16
*/
static QString readableConfigurationFlag( QgsField::ConfigurationFlag flag ) SIP_SKIP;
#ifndef SIP_RUN
/**

View File

@ -274,8 +274,6 @@ QgsVectorLayer *QgsVectorLayer::clone() const
layer->setMapTipTemplate( mapTipTemplate() );
layer->setReadOnly( isReadOnly() );
layer->selectByIds( selectedFeatureIds() );
layer->setExcludeAttributesWms( excludeAttributesWms() );
layer->setExcludeAttributesWfs( excludeAttributesWfs() );
layer->setAttributeTableConfig( attributeTableConfig() );
layer->setFeatureBlendMode( featureBlendMode() );
layer->setOpacity( opacity() );
@ -2306,29 +2304,6 @@ bool QgsVectorLayer::readSymbology( const QDomNode &layerNode, QString &errorMes
updateFields();
//Attributes excluded from WMS and WFS
mExcludeAttributesWMS.clear();
QDomNode excludeWMSNode = layerNode.namedItem( QStringLiteral( "excludeAttributesWMS" ) );
if ( !excludeWMSNode.isNull() )
{
QDomNodeList attributeNodeList = excludeWMSNode.toElement().elementsByTagName( QStringLiteral( "attribute" ) );
for ( int i = 0; i < attributeNodeList.size(); ++i )
{
mExcludeAttributesWMS.insert( attributeNodeList.at( i ).toElement().text() );
}
}
mExcludeAttributesWFS.clear();
QDomNode excludeWFSNode = layerNode.namedItem( QStringLiteral( "excludeAttributesWFS" ) );
if ( !excludeWFSNode.isNull() )
{
QDomNodeList attributeNodeList = excludeWFSNode.toElement().elementsByTagName( QStringLiteral( "attribute" ) );
for ( int i = 0; i < attributeNodeList.size(); ++i )
{
mExcludeAttributesWFS.insert( attributeNodeList.at( i ).toElement().text() );
}
}
// Load editor widget configuration
QDomElement widgetsElem = layerNode.namedItem( QStringLiteral( "fieldConfiguration" ) ).toElement();
QDomNodeList fieldConfigurationElementList = widgetsElem.elementsByTagName( QStringLiteral( "field" ) );
@ -2351,6 +2326,28 @@ bool QgsVectorLayer::readSymbology( const QDomNode &layerNode, QString &errorMes
QgsEditorWidgetSetup setup = QgsEditorWidgetSetup( widgetType, optionsMap );
mFieldWidgetSetups[fieldName] = setup;
}
// Legacy reading for QGIS 3.14 and older projects
// Attributes excluded from WMS and WFS
const QList<QPair<QString, QgsField::ConfigurationFlag>> legacyConfig
{
qMakePair( QStringLiteral( "excludeAttributesWMS" ), QgsField::ConfigurationFlag::ExposeViaWms ),
qMakePair( QStringLiteral( "excludeAttributesWFS" ), QgsField::ConfigurationFlag::ExposeViaWfs )
};
for ( const auto &config : legacyConfig )
{
QDomNode excludeNode = layerNode.namedItem( config.first );
if ( !excludeNode.isNull() )
{
QDomNodeList attributeNodeList = excludeNode.toElement().elementsByTagName( QStringLiteral( "attribute" ) );
for ( int i = 0; i < attributeNodeList.size(); ++i )
{
QString fieldName = attributeNodeList.at( i ).toElement().text();
int index = mFields.indexFromName( fieldName );
setFieldConfigurationFlag( index, config.second, false );
}
}
}
}
if ( categories.testFlag( GeometryOptions ) )
@ -2660,30 +2657,6 @@ bool QgsVectorLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QString
}
node.appendChild( aliasElem );
//exclude attributes WMS
QDomElement excludeWMSElem = doc.createElement( QStringLiteral( "excludeAttributesWMS" ) );
QSet<QString>::const_iterator attWMSIt = mExcludeAttributesWMS.constBegin();
for ( ; attWMSIt != mExcludeAttributesWMS.constEnd(); ++attWMSIt )
{
QDomElement attrElem = doc.createElement( QStringLiteral( "attribute" ) );
QDomText attrText = doc.createTextNode( *attWMSIt );
attrElem.appendChild( attrText );
excludeWMSElem.appendChild( attrElem );
}
node.appendChild( excludeWMSElem );
//exclude attributes WFS
QDomElement excludeWFSElem = doc.createElement( QStringLiteral( "excludeAttributesWFS" ) );
QSet<QString>::const_iterator attWFSIt = mExcludeAttributesWFS.constBegin();
for ( ; attWFSIt != mExcludeAttributesWFS.constEnd(); ++attWFSIt )
{
QDomElement attrElem = doc.createElement( QStringLiteral( "attribute" ) );
QDomText attrText = doc.createTextNode( *attWFSIt );
attrElem.appendChild( attrText );
excludeWFSElem.appendChild( attrElem );
}
node.appendChild( excludeWFSElem );
//default expressions
QDomElement defaultsElem = doc.createElement( QStringLiteral( "defaults" ) );
for ( const QgsField &field : qgis::as_const( mFields ) )
@ -5487,12 +5460,19 @@ void QgsVectorLayer::setFieldConfigurationFlags( int index, QgsField::Configurat
if ( index < 0 || index >= mFields.count() )
return;
mFields.at( index ).setConfigurationFlags( flags );
mFieldConfigurationFlags.insert( mFields.at( index ).name(), flags );
updateFields();
}
void QgsVectorLayer::setFieldConfigurationFlag( int index, QgsField::ConfigurationFlag flag, bool active )
{
if ( index < 0 || index >= mFields.count() )
return;
QgsField::ConfigurationFlags flags = mFields.at( index ).configurationFlags();
flags.setFlag( flag, active );
setFieldConfigurationFlags( index, flags );
}
QgsField::ConfigurationFlags QgsVectorLayer::fieldConfigurationFlags( int index ) const
{

View File

@ -1839,23 +1839,27 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
/**
* A set of attributes that are not advertised in WMS requests with QGIS server.
* \deprecated since QGIS 3.16, use fields().configurationFlags() instead
*/
QSet<QString> excludeAttributesWms() const { return mExcludeAttributesWMS; }
Q_DECL_DEPRECATED QSet<QString> excludeAttributesWms() const SIP_DEPRECATED { return mExcludeAttributesWMS; }
/**
* A set of attributes that are not advertised in WMS requests with QGIS server.
* \deprecated since QGIS 3.16, use setFieldConfigurationFlag instead
*/
void setExcludeAttributesWms( const QSet<QString> &att ) { mExcludeAttributesWMS = att; }
Q_DECL_DEPRECATED void setExcludeAttributesWms( const QSet<QString> &att ) SIP_DEPRECATED { mExcludeAttributesWMS = att; }
/**
* A set of attributes that are not advertised in WFS requests with QGIS server.
* \deprecated since QGIS 3.16, use fields().configurationFlags() instead
*/
QSet<QString> excludeAttributesWfs() const { return mExcludeAttributesWFS; }
Q_DECL_DEPRECATED QSet<QString> excludeAttributesWfs() const SIP_DEPRECATED { return mExcludeAttributesWFS; }
/**
* A set of attributes that are not advertised in WFS requests with QGIS server.
* \deprecated since QGIS 3.16, use setFieldConfigurationFlag instead
*/
void setExcludeAttributesWfs( const QSet<QString> &att ) { mExcludeAttributesWFS = att; }
Q_DECL_DEPRECATED void setExcludeAttributesWfs( const QSet<QString> &att ) SIP_DEPRECATED { mExcludeAttributesWFS = att; }
/**
* Deletes an attribute field (but does not commit it).
@ -2122,6 +2126,12 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
*/
void setFieldConfigurationFlags( int index, QgsField::ConfigurationFlags flags ) SIP_SKIP;
/**
* Sets the given configuration \a flag for the field at given \a index to be \a active or not.
* \since QGIS 3.16
*/
void setFieldConfigurationFlag( int index, QgsField::ConfigurationFlag flag, bool active ) SIP_SKIP;
/**
* Returns the configuration flags of the field at given index
* \see QgsField::ConfigurationFlag

View File

@ -77,8 +77,9 @@ void QgsCheckBoxDelegate::paint( QPainter *painter, const QStyleOptionViewItem &
QgsCheckableComboBox::QgsCheckableComboBox( QWidget *parent )
: QComboBox( parent )
, mSeparator( QStringLiteral( ", " ) )
, mModel( new QgsCheckableItemModel( this ) )
{
setModel( new QgsCheckableItemModel( this ) );
setModel( mModel );
setItemDelegate( new QgsCheckBoxDelegate( this ) );
QLineEdit *lineEdit = new QLineEdit( this );
@ -134,6 +135,12 @@ void QgsCheckableComboBox::setDefaultText( const QString &text )
}
}
void QgsCheckableComboBox::addItemWithCheckState( const QString &text, Qt::CheckState state, const QVariant &userData )
{
QComboBox::addItem( text, userData );
setItemCheckState( count() - 1, state );
}
QStringList QgsCheckableComboBox::checkedItems() const
{
QStringList items;

View File

@ -163,6 +163,14 @@ class GUI_EXPORT QgsCheckableComboBox : public QComboBox
*/
void setDefaultText( const QString &text );
/**
* Adds an item to the combobox with the given \a text, check \a state (stored in the Qt::CheckStateRole)
* and containing the specified \a userData (stored in the Qt::UserRole).
* The item is appended to the list of existing items.
* \since QGIS 3.16
*/
void addItemWithCheckState( const QString &text, Qt::CheckState state, const QVariant &userData = QVariant() );
/**
* Returns currently checked items.
* \see setCheckedItems()
@ -201,6 +209,13 @@ class GUI_EXPORT QgsCheckableComboBox : public QComboBox
*/
void toggleItemCheckState( int index );
/**
* Returns the custom item model which handles checking the items
* \see QgsCheckableItemModel
* \since QGIS 3.16
*/
QgsCheckableItemModel *model() const SIP_SKIP {return mModel;}
/**
* Hides the list of items in the combobox if it is currently
* visible and resets the internal state.
@ -260,6 +275,8 @@ class GUI_EXPORT QgsCheckableComboBox : public QComboBox
QString mSeparator;
QString mDefaultText;
QgsCheckableItemModel *mModel = nullptr;
bool mSkipHide = false;
QMenu *mContextMenu = nullptr;

View File

@ -15,6 +15,7 @@
***************************************************************************/
#include "qgsaddattrdialog.h"
#include "qgscheckablecombobox.h"
#include "qgssourcefieldsproperties.h"
#include "qgsvectorlayer.h"
#include "qgsproject.h"
@ -64,15 +65,9 @@ QgsSourceFieldsProperties::QgsSourceFieldsProperties( QgsVectorLayer *layer, QWi
mFieldsList->setHorizontalHeaderItem( AttrLengthCol, new QTableWidgetItem( tr( "Length" ) ) );
mFieldsList->setHorizontalHeaderItem( AttrPrecCol, new QTableWidgetItem( tr( "Precision" ) ) );
mFieldsList->setHorizontalHeaderItem( AttrCommentCol, new QTableWidgetItem( tr( "Comment" ) ) );
const auto wmsWi = new QTableWidgetItem( QStringLiteral( "WMS" ) );
wmsWi->setToolTip( tr( "Defines if this field is available in QGIS Server WMS service" ) );
mFieldsList->setHorizontalHeaderItem( AttrWMSCol, wmsWi );
const auto wfsWi = new QTableWidgetItem( QStringLiteral( "WFS" ) );
wfsWi->setToolTip( tr( "Defines if this field is available in QGIS Server WFS (and OAPIF) service" ) );
mFieldsList->setHorizontalHeaderItem( AttrWFSCol, wfsWi );
const auto searchableWi = new QTableWidgetItem( QStringLiteral( "Searchable" ) );
searchableWi->setToolTip( tr( "Defines if this field is searchable (active layer locator filter)" ) );
mFieldsList->setHorizontalHeaderItem( AttrSearchableCol, searchableWi );
const auto configurationFlagsWi = new QTableWidgetItem( QStringLiteral( "Configuration" ) );
configurationFlagsWi->setToolTip( tr( "Configures the field" ) );
mFieldsList->setHorizontalHeaderItem( AttrConfigurationFlagsCol, configurationFlagsWi );
mFieldsList->setHorizontalHeaderItem( AttrAliasCol, new QTableWidgetItem( tr( "Alias" ) ) );
mFieldsList->setSortingEnabled( true );
@ -163,6 +158,9 @@ void QgsSourceFieldsProperties::attributeAdded( int idx )
for ( int i = 0; i < mFieldsList->columnCount(); i++ )
{
if ( i == AttrConfigurationFlagsCol )
continue;
switch ( mLayer->fields().fieldOrigin( idx ) )
{
case QgsFields::OriginExpression:
@ -272,20 +270,19 @@ void QgsSourceFieldsProperties::setRow( int row, int idx, const QgsField &field
else
mFieldsList->item( row, AttrNameCol )->setFlags( mFieldsList->item( row, AttrNameCol )->flags() & ~Qt::ItemIsEditable );
//published WMS/WFS attributes
QTableWidgetItem *wmsAttrItem = new QTableWidgetItem();
wmsAttrItem->setCheckState( mLayer->excludeAttributesWms().contains( field.name() ) ? Qt::Unchecked : Qt::Checked );
wmsAttrItem->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable );
mFieldsList->setItem( row, AttrWMSCol, wmsAttrItem );
QTableWidgetItem *wfsAttrItem = new QTableWidgetItem();
wfsAttrItem->setCheckState( mLayer->excludeAttributesWfs().contains( field.name() ) ? Qt::Unchecked : Qt::Checked );
wfsAttrItem->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable );
mFieldsList->setItem( row, AttrWFSCol, wfsAttrItem );
QTableWidgetItem *searchableAttrItem = new QTableWidgetItem();
searchableAttrItem->setCheckState( mLayer->fieldConfigurationFlags( idx ).testFlag( QgsField::ConfigurationFlag::Searchable ) ? Qt::Checked : Qt::Unchecked );
searchableAttrItem->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable );
mFieldsList->setItem( row, AttrSearchableCol, searchableAttrItem );
// Flags
QgsCheckableComboBox *cb = new QgsCheckableComboBox( mFieldsList );
const QList<QgsField::ConfigurationFlag> flagList = qgsEnumMap<QgsField::ConfigurationFlag>().keys();
for ( const QgsField::ConfigurationFlag flag : flagList )
{
if ( flag == QgsField::ConfigurationFlag::None || flag == QgsField::ConfigurationFlag::DefaultFlags )
continue;
cb->addItemWithCheckState( QgsField::readableConfigurationFlag( flag ),
mLayer->fieldConfigurationFlags( idx ).testFlag( flag ) ? Qt::Checked : Qt::Unchecked,
QVariant::fromValue( flag ) );
}
mFieldsList->setCellWidget( row, AttrConfigurationFlagsCol, cb );
}
bool QgsSourceFieldsProperties::addAttribute( const QgsField &field )
@ -307,34 +304,25 @@ bool QgsSourceFieldsProperties::addAttribute( const QgsField &field )
void QgsSourceFieldsProperties::apply()
{
QSet<QString> excludeAttributesWMS, excludeAttributesWFS;
for ( int i = 0; i < mFieldsList->rowCount(); i++ )
{
if ( mFieldsList->item( i, AttrWMSCol )->checkState() == Qt::Unchecked )
{
excludeAttributesWMS.insert( mFieldsList->item( i, AttrNameCol )->text() );
}
if ( mFieldsList->item( i, AttrWFSCol )->checkState() == Qt::Unchecked )
{
excludeAttributesWFS.insert( mFieldsList->item( i, AttrNameCol )->text() );
}
int idx = mFieldsList->item( i, AttrIdCol )->data( Qt::DisplayRole ).toInt();
QgsField::ConfigurationFlags flags = mLayer->fieldConfigurationFlags( idx );
if ( mFieldsList->item( i, AttrSearchableCol )->checkState() == Qt::Checked )
{
flags.setFlag( QgsField::ConfigurationFlag::Searchable, true );
}
else
{
flags.setFlag( QgsField::ConfigurationFlag::Searchable, false );
}
mLayer->setFieldConfigurationFlags( idx, flags );
}
mLayer->setExcludeAttributesWms( excludeAttributesWMS );
mLayer->setExcludeAttributesWfs( excludeAttributesWFS );
QgsCheckableComboBox *cb = qobject_cast<QgsCheckableComboBox *>( mFieldsList->cellWidget( i, AttrConfigurationFlagsCol ) );
if ( cb )
{
QgsCheckableItemModel *model = cb->model();
for ( int r = 0; r < model->rowCount(); ++r )
{
QModelIndex index = model->index( r, 0 );
QgsField::ConfigurationFlag flag = model->data( index, Qt::UserRole ).value<QgsField::ConfigurationFlag>();
bool active = model->data( index, Qt::CheckStateRole ).value<Qt::CheckState>() == Qt::Checked ? true : false;
flags.setFlag( flag, active );
}
mLayer->setFieldConfigurationFlags( idx, flags );
}
}
}
//SLOTS

View File

@ -80,9 +80,7 @@ class GUI_EXPORT QgsSourceFieldsProperties : public QWidget, private Ui_QgsSourc
AttrLengthCol,
AttrPrecCol,
AttrCommentCol,
AttrWMSCol,
AttrWFSCol,
AttrSearchableCol,
AttrConfigurationFlagsCol,
AttrColCount,
};

View File

@ -453,34 +453,38 @@ json QgsLandingPageUtils::projectInfo( const QString &projectUri )
wmsLayer[ "pk" ] = vl->primaryKeyAttributes();
int fieldIdx { 0 };
json fieldsData;
const auto &cFields { vl->fields() };
for ( const auto &f : cFields )
const QgsFields &cFields { vl->fields() };
for ( const QgsField &field : cFields )
{
// TODO: replace with non deprecated method and fix the tests
// if ( !field.configurationFlags().testFlag( QgsField::ConfigurationFlag::ExposeViaWfs ) )
Q_NOWARN_DEPRECATED_PUSH
if ( vl->excludeAttributesWfs().contains( vl->name() ) )
{
++fieldIdx;
continue;
}
const auto &constraints { f.constraints().constraints() };
Q_NOWARN_DEPRECATED_POP
const QgsFieldConstraints::Constraints constraints { field.constraints().constraints() };
const bool notNull { constraints &QgsFieldConstraints::Constraint::ConstraintNotNull &&
f.constraints().constraintStrength( QgsFieldConstraints::Constraint::ConstraintNotNull ) == QgsFieldConstraints::ConstraintStrength::ConstraintStrengthHard };
field.constraints().constraintStrength( QgsFieldConstraints::Constraint::ConstraintNotNull ) == QgsFieldConstraints::ConstraintStrength::ConstraintStrengthHard };
const bool unique { constraints &QgsFieldConstraints::Constraint::ConstraintUnique &&
f.constraints().constraintStrength( QgsFieldConstraints::Constraint::ConstraintUnique ) == QgsFieldConstraints::ConstraintStrength::ConstraintStrengthHard };
field.constraints().constraintStrength( QgsFieldConstraints::Constraint::ConstraintUnique ) == QgsFieldConstraints::ConstraintStrength::ConstraintStrengthHard };
const bool hasExpression { constraints &QgsFieldConstraints::Constraint::ConstraintExpression &&
f.constraints().constraintStrength( QgsFieldConstraints::Constraint::ConstraintExpression ) == QgsFieldConstraints::ConstraintStrength::ConstraintStrengthHard };
field.constraints().constraintStrength( QgsFieldConstraints::Constraint::ConstraintExpression ) == QgsFieldConstraints::ConstraintStrength::ConstraintStrengthHard };
const QString &defaultValue { vl->dataProvider()->defaultValueClause( fieldIdx ) };
const bool isReadOnly( notNull && unique && ! defaultValue.isEmpty() );
fieldsData[ f.name().toStdString() ] =
fieldsData[ field.name().toStdString() ] =
{
{ "type", f.typeName().toStdString() },
{ "label", f.alias().isEmpty() ? f.name().toStdString() : f.alias().toStdString() },
{ "precision", f.precision() },
{ "length", f.length() },
{ "type", field.typeName().toStdString() },
{ "label", field.alias().isEmpty() ? field.name().toStdString() : field.alias().toStdString() },
{ "precision", field.precision() },
{ "length", field.length() },
{ "unique", unique },
{ "not_null", notNull },
{ "has_expression", hasExpression },
{ "default", defaultValue.toStdString() },
{ "expression", f.constraints().constraintExpression().toStdString() },
{ "expression", field.constraints().constraintExpression().toStdString() },
{ "editable", !isReadOnly }
};

View File

@ -262,13 +262,12 @@ namespace QgsWfs
//Attributes
QgsFields fields = layer->fields();
//hidden attributes for this layer
const QSet<QString> &layerExcludedAttributes = layer->excludeAttributesWfs();
for ( int idx = 0; idx < fields.count(); ++idx )
{
const QgsField field = fields.at( idx );
QString attributeName = field.name();
//skip attribute if excluded from WFS publication
if ( layerExcludedAttributes.contains( attributeName ) )
if ( !field.configurationFlags().testFlag( QgsField::ConfigurationFlag::ExposeViaWfs ) )
{
continue;
}

View File

@ -249,7 +249,7 @@ namespace QgsWfs
//Using pending attributes and pending fields
QgsAttributeList attrIndexes = vlayer->attributeList();
QgsFields fields = vlayer->fields();
const QgsFields fields = vlayer->fields();
bool withGeom = true;
if ( !propertyList.isEmpty() && propertyList.first() != QStringLiteral( "*" ) )
{
@ -259,10 +259,10 @@ namespace QgsWfs
// build corresponding propertyname
QList<QString> propertynames;
QList<QString> fieldnames;
for ( int idx = 0; idx < fields.count(); ++idx )
for ( const QgsField &field : fields )
{
fieldnames.append( fields[idx].name() );
propertynames.append( fields.field( idx ).name().replace( ' ', '_' ).replace( cleanTagNameRegExp, QString() ) );
fieldnames.append( field.name() );
propertynames.append( field.name().replace( ' ', '_' ).replace( cleanTagNameRegExp, QString() ) );
}
QString fieldName;
for ( plstIt = propertyList.constBegin(); plstIt != propertyList.constEnd(); ++plstIt )
@ -289,20 +289,21 @@ namespace QgsWfs
}
//excluded attributes for this layer
const QSet<QString> &layerExcludedAttributes = vlayer->excludeAttributesWfs();
if ( !attrIndexes.isEmpty() && !layerExcludedAttributes.isEmpty() )
if ( !attrIndexes.isEmpty() )
{
foreach ( const QString &excludedAttribute, layerExcludedAttributes )
for ( const QgsField &field : fields )
{
int fieldNameIdx = fields.indexOf( excludedAttribute );
if ( fieldNameIdx > -1 && attrIndexes.contains( fieldNameIdx ) )
if ( !field.configurationFlags().testFlag( QgsField::ConfigurationFlag::ExposeViaWfs ) )
{
attrIndexes.removeOne( fieldNameIdx );
int fieldNameIdx = fields.indexOf( field.name() );
if ( fieldNameIdx > -1 && attrIndexes.contains( fieldNameIdx ) )
{
attrIndexes.removeOne( fieldNameIdx );
}
}
}
}
// update request
QgsFeatureRequest featureRequest = query.featureRequest;

View File

@ -242,13 +242,12 @@ QgsFields QgsWfs3AbstractItemsHandler::publishedFields( const QgsVectorLayer *vL
QStringList publishedAttributes = QStringList();
// Removed attributes
// WFS excluded attributes for this layer
const QSet<QString> &layerExcludedAttributes = vLayer->excludeAttributesWfs();
const QgsFields &fields = vLayer->fields();
for ( int i = 0; i < fields.count(); ++i )
for ( const QgsField &field : fields )
{
if ( ! layerExcludedAttributes.contains( fields.at( i ).name() ) )
if ( field.configurationFlags().testFlag( QgsField::ConfigurationFlag::ExposeViaWfs ) )
{
publishedAttributes.push_back( fields.at( i ).name() );
publishedAttributes.push_back( field.name() );
}
}

View File

@ -1862,7 +1862,6 @@ namespace QgsWms
case QgsMapLayerType::VectorLayer:
{
QgsVectorLayer *vLayer = static_cast<QgsVectorLayer *>( currentLayer );
const QSet<QString> &excludedAttributes = vLayer->excludeAttributesWms();
int displayFieldIdx = -1;
QString displayField = QStringLiteral( "maptip" );
@ -1879,7 +1878,7 @@ namespace QgsWms
for ( int idx = 0; idx < layerFields.count(); ++idx )
{
QgsField field = layerFields.at( idx );
if ( excludedAttributes.contains( field.name() ) )
if ( !field.configurationFlags().testFlag( QgsField::ConfigurationFlag::ExposeViaWms ) )
{
continue;
}

View File

@ -1447,7 +1447,6 @@ namespace QgsWms
const QgsFields fields = layer->fields();
bool addWktGeometry = ( QgsServerProjectUtils::wmsFeatureInfoAddWktGeometry( *mProject ) && mWmsParameters.withGeometry() );
bool segmentizeWktGeometry = QgsServerProjectUtils::wmsFeatureInfoSegmentizeWktGeometry( *mProject );
const QSet<QString> &excludedAttributes = layer->excludeAttributesWms();
bool hasGeometry = QgsServerProjectUtils::wmsFeatureInfoAddWktGeometry( *mProject ) || addWktGeometry || featureBBox || layerFilterGeom;
fReq.setFlags( ( ( hasGeometry ) ? QgsFeatureRequest::NoFlags : QgsFeatureRequest::NoGeometry ) | QgsFeatureRequest::ExactIntersect );
@ -1568,7 +1567,7 @@ namespace QgsWms
for ( int i = 0; i < featureAttributes.count(); ++i )
{
//skip attribute if it is explicitly excluded from WMS publication
if ( excludedAttributes.contains( fields.at( i ).name() ) )
if ( !fields.at( i ).configurationFlags().testFlag( QgsField::ConfigurationFlag::ExposeViaWms ) )
{
continue;
}
@ -2417,7 +2416,7 @@ namespace QgsWms
{
QString attributeName = fields.at( i ).name();
//skip attribute if it is explicitly excluded from WMS publication
if ( layer && layer->excludeAttributesWms().contains( attributeName ) )
if ( !fields.at( i ).configurationFlags().testFlag( QgsField::ConfigurationFlag::ExposeViaWms ) )
{
continue;
}

View File

@ -1,5 +1,5 @@
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
<qgis saveUser="ale" version="3.13.0-Master" projectname="Project1 Title" saveUserFull="Alessandro Pasotti">
<qgis saveUserFull="Denis Rouzaud" version="3.15.0-Master" projectname="Project1 Title" saveUser="denis" saveDateTime="2020-09-15T16:25:28">
<homePath path=""/>
<title>Project1 Title</title>
<autotransaction active="0"/>
@ -20,20 +20,20 @@
</projectCrs>
<layer-tree-group>
<customproperties/>
<layer-tree-layer legend_exp="" name="points" providerKey="ogr" source="./project_data.gpkg|layername=points" expanded="1" id="points_842425df_7f45_4091_a6c9_086e1dc1edd1" checked="Qt::Checked">
<layer-tree-layer id="points_842425df_7f45_4091_a6c9_086e1dc1edd1" source="./project_data.gpkg|layername=points" legend_split_behavior="0" patch_size="0,0" name="points" checked="Qt::Checked" expanded="1" legend_exp="" providerKey="ogr">
<customproperties/>
</layer-tree-layer>
<custom-order enabled="0">
<item>points_842425df_7f45_4091_a6c9_086e1dc1edd1</item>
</custom-order>
</layer-tree-group>
<snapping-settings type="1" tolerance="12" mode="2" unit="1" intersection-snapping="0" minScale="0" scaleDependencyMode="0" enabled="0" maxScale="0">
<snapping-settings unit="1" scaleDependencyMode="0" mode="2" tolerance="12" intersection-snapping="0" maxScale="0" type="1" enabled="0" minScale="0" self-snapping="0">
<individual-layer-settings>
<layer-setting type="1" tolerance="12" units="1" id="points_842425df_7f45_4091_a6c9_086e1dc1edd1" minScale="0" enabled="0" maxScale="0"/>
<layer-setting id="points_842425df_7f45_4091_a6c9_086e1dc1edd1" tolerance="12" units="1" maxScale="0" type="1" enabled="0" minScale="0"/>
</individual-layer-settings>
</snapping-settings>
<relations/>
<mapcanvas name="theMapCanvas" annotationsVisible="1">
<mapcanvas annotationsVisible="1" name="theMapCanvas">
<units>degrees</units>
<extent>
<xmin>-23.31087998257129357</xmin>
@ -58,17 +58,65 @@
<rendermaptile>0</rendermaptile>
<expressionContextScope/>
</mapcanvas>
<projectModels/>
<legend updateDrawingOrder="true">
<legendlayer name="points" open="true" checked="Qt::Checked" drawingOrder="-1" showFeatureCount="0">
<filegroup hidden="false" open="true">
<legendlayerfile visible="1" isInOverview="0" layerid="points_842425df_7f45_4091_a6c9_086e1dc1edd1"/>
<legendlayer open="true" drawingOrder="-1" showFeatureCount="0" checked="Qt::Checked" name="points">
<filegroup open="true" hidden="false">
<legendlayerfile layerid="points_842425df_7f45_4091_a6c9_086e1dc1edd1" isInOverview="0" visible="1"/>
</filegroup>
</legendlayer>
</legend>
<mapViewDocks/>
<mapViewDocks3D/>
<main-annotation-layer refreshOnNotifyMessage="" refreshOnNotifyEnabled="0" autoRefreshEnabled="0" autoRefreshTime="0" type="annotation">
<id>Annotations_e424930a_3838_4a42_94ca_e28ac525201f</id>
<datasource></datasource>
<keywordList>
<value></value>
</keywordList>
<layername></layername>
<srs>
<spatialrefsys>
<wkt></wkt>
<proj4></proj4>
<srsid>0</srsid>
<srid>0</srid>
<authid></authid>
<description></description>
<projectionacronym></projectionacronym>
<ellipsoidacronym></ellipsoidacronym>
<geographicflag>false</geographicflag>
</spatialrefsys>
</srs>
<resourceMetadata>
<identifier></identifier>
<parentidentifier></parentidentifier>
<language></language>
<type></type>
<title></title>
<abstract></abstract>
<links/>
<fees></fees>
<encoding></encoding>
<crs>
<spatialrefsys>
<wkt></wkt>
<proj4></proj4>
<srsid>0</srsid>
<srid>0</srid>
<authid></authid>
<description></description>
<projectionacronym></projectionacronym>
<ellipsoidacronym></ellipsoidacronym>
<geographicflag>false</geographicflag>
</spatialrefsys>
</crs>
<extent/>
</resourceMetadata>
<items/>
<layerOpacity>1</layerOpacity>
</main-annotation-layer>
<projectlayers>
<maplayer labelsEnabled="0" wkbType="Point" autoRefreshTime="0" styleCategories="AllStyleCategories" simplifyDrawingTol="1.2" simplifyDrawingHints="0" simplifyAlgorithm="0" type="vector" autoRefreshEnabled="0" simplifyMaxScale="1" refreshOnNotifyMessage="" minScale="100000000" refreshOnNotifyEnabled="0" geometry="Point" simplifyLocal="1" hasScaleBasedVisibilityFlag="0" readOnly="0" maxScale="0">
<maplayer wkbType="Point" simplifyDrawingHints="0" readOnly="0" simplifyLocal="1" autoRefreshTime="0" simplifyAlgorithm="0" labelsEnabled="0" maxScale="0" refreshOnNotifyMessage="" autoRefreshEnabled="0" hasScaleBasedVisibilityFlag="0" styleCategories="AllStyleCategories" geometry="Point" refreshOnNotifyEnabled="0" simplifyMaxScale="1" minScale="100000000" simplifyDrawingTol="1.2" type="vector">
<extent>
<xmin>-1.12365841865539995</xmin>
<ymin>43.23918533325200286</ymin>
@ -85,7 +133,7 @@
</keywordList>
<dataUrl format="">http://data.url</dataUrl>
<attribution href="http://attribution.url">Qgis Server Layer Properties Attribution</attribution>
<metadataUrl format="text/plain" type="FGDC">http://metadata.url</metadataUrl>
<metadataUrl type="FGDC" format="text/plain">http://metadata.url</metadataUrl>
<layername>points</layername>
<srs>
<spatialrefsys>
@ -129,7 +177,7 @@
<role>distributor</role>
</contact>
<links>
<link format="HTML" size="unknown" type="https" name="A link" url="https://www.itopen.it" mimeType="text/html" description="An interesting link"/>
<link size="unknown" url="https://www.itopen.it" description="An interesting link" name="A link" type="https" mimeType="text/html" format="HTML"/>
</links>
<history>Once upon a time ...</history>
<fees>None</fees>
@ -151,7 +199,7 @@
</spatialrefsys>
</crs>
<extent>
<spatial crs="EPSG:4326" minz="0" minx="-154.68031310999998595" miny="31.41943359400000091" maxx="-142.43476867699999389" maxy="40.44245529199999822" dimensions="2" maxz="0"/>
<spatial maxy="40.44245529199999822" maxx="-142.43476867699999389" miny="31.41943359400000091" maxz="0" minx="-154.68031310999998595" minz="0" crs="EPSG:4326" dimensions="2"/>
<temporal>
<period>
<start></start>
@ -175,10 +223,16 @@
<Removable>1</Removable>
<Searchable>1</Searchable>
</flags>
<renderer-v2 type="singleSymbol" symbollevels="0" forceraster="0" enableorderby="0">
<temporal durationField="" endField="" fixedDuration="0" startField="" mode="0" accumulate="0" endExpression="" durationUnit="min" enabled="0" startExpression="">
<fixedRange>
<start></start>
<end></end>
</fixedRange>
</temporal>
<renderer-v2 symbollevels="0" enableorderby="0" type="singleSymbol" forceraster="0">
<symbols>
<symbol clip_to_extent="1" type="marker" name="0" force_rhr="0" alpha="1">
<layer locked="0" pass="0" enabled="1" class="SimpleMarker">
<symbol alpha="1" name="0" force_rhr="0" type="marker" clip_to_extent="1">
<layer class="SimpleMarker" pass="0" enabled="1" locked="0">
<prop v="0" k="angle"/>
<prop v="183,72,75,255" k="color"/>
<prop v="1" k="horizontal_anchor_point"/>
@ -199,9 +253,9 @@
<prop v="1" k="vertical_anchor_point"/>
<data_defined_properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</data_defined_properties>
</layer>
@ -219,16 +273,20 @@
<featureBlendMode>0</featureBlendMode>
<layerOpacity>1</layerOpacity>
<SingleCategoryDiagramRenderer attributeLegend="1" diagramType="Histogram">
<DiagramCategory sizeScale="3x:0,0,0,0,0,0" diagramOrientation="Up" backgroundColor="#ffffff" spacing="5" sizeType="MM" minScaleDenominator="0" scaleBasedVisibility="0" backgroundAlpha="255" penAlpha="255" spacingUnit="MM" spacingUnitScale="3x:0,0,0,0,0,0" labelPlacementMethod="XHeight" height="15" maxScaleDenominator="1e+08" enabled="0" minimumSize="0" showAxis="1" lineSizeType="MM" opacity="1" penWidth="0" penColor="#000000" barWidth="5" direction="0" lineSizeScale="3x:0,0,0,0,0,0" scaleDependency="Area" rotationOffset="270" width="15">
<DiagramCategory rotationOffset="270" penWidth="0" penColor="#000000" labelPlacementMethod="XHeight" spacing="5" direction="0" minimumSize="0" scaleBasedVisibility="0" minScaleDenominator="0" showAxis="1" spacingUnitScale="3x:0,0,0,0,0,0" maxScaleDenominator="1e+08" enabled="0" height="15" sizeType="MM" barWidth="5" diagramOrientation="Up" opacity="1" spacingUnit="MM" lineSizeScale="3x:0,0,0,0,0,0" backgroundAlpha="255" scaleDependency="Area" backgroundColor="#ffffff" width="15" penAlpha="255" lineSizeType="MM" sizeScale="3x:0,0,0,0,0,0">
<fontProperties style="Regular" description="Noto Sans,10,-1,5,50,0,0,0,0,0,Regular"/>
<attribute label="" field="" color="#000000"/>
<attribute label="" color="#000000" field=""/>
<axisSymbol>
<symbol clip_to_extent="1" type="line" name="" force_rhr="0" alpha="1">
<layer locked="0" pass="0" enabled="1" class="SimpleLine">
<symbol alpha="1" name="" force_rhr="0" type="line" clip_to_extent="1">
<layer class="SimpleLine" pass="0" enabled="1" locked="0">
<prop v="0" k="align_dash_pattern"/>
<prop v="square" k="capstyle"/>
<prop v="5;2" k="customdash"/>
<prop v="3x:0,0,0,0,0,0" k="customdash_map_unit_scale"/>
<prop v="MM" k="customdash_unit"/>
<prop v="0" k="dash_pattern_offset"/>
<prop v="3x:0,0,0,0,0,0" k="dash_pattern_offset_map_unit_scale"/>
<prop v="MM" k="dash_pattern_offset_unit"/>
<prop v="0" k="draw_inside_polygon"/>
<prop v="bevel" k="joinstyle"/>
<prop v="35,35,35,255" k="line_color"/>
@ -239,13 +297,14 @@
<prop v="3x:0,0,0,0,0,0" k="offset_map_unit_scale"/>
<prop v="MM" k="offset_unit"/>
<prop v="0" k="ring_filter"/>
<prop v="0" k="tweak_dash_pattern_on_corners"/>
<prop v="0" k="use_custom_dash"/>
<prop v="3x:0,0,0,0,0,0" k="width_map_unit_scale"/>
<data_defined_properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</data_defined_properties>
</layer>
@ -253,12 +312,12 @@
</axisSymbol>
</DiagramCategory>
</SingleCategoryDiagramRenderer>
<DiagramLayerSettings linePlacementFlags="18" dist="0" zIndex="0" priority="0" showAll="1" obstacle="0" placement="0">
<DiagramLayerSettings priority="0" showAll="1" obstacle="0" linePlacementFlags="18" zIndex="0" dist="0" placement="0">
<properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</properties>
</DiagramLayerSettings>
@ -267,16 +326,15 @@
<checkConfiguration/>
</geometryOptions>
<referencedLayers/>
<referencingLayers/>
<fieldConfiguration>
<field name="fid">
<field name="fid" configurationFlags="DefaultFlags">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="name">
<field name="name" configurationFlags="DefaultFlags">
<editWidget type="TextEdit">
<config>
<Option/>
@ -285,32 +343,30 @@
</field>
</fieldConfiguration>
<aliases>
<alias name="" field="fid" index="0"/>
<alias name="" field="name" index="1"/>
<alias field="fid" index="0" name=""/>
<alias field="name" index="1" name=""/>
</aliases>
<excludeAttributesWMS/>
<excludeAttributesWFS/>
<defaults>
<default expression="" field="fid" applyOnUpdate="0"/>
<default expression="" field="name" applyOnUpdate="0"/>
</defaults>
<constraints>
<constraint unique_strength="1" constraints="3" exp_strength="0" field="fid" notnull_strength="1"/>
<constraint unique_strength="0" constraints="0" exp_strength="0" field="name" notnull_strength="0"/>
<constraint field="fid" exp_strength="0" constraints="3" notnull_strength="1" unique_strength="1"/>
<constraint field="name" exp_strength="0" constraints="0" notnull_strength="0" unique_strength="0"/>
</constraints>
<constraintExpressions>
<constraint exp="" field="fid" desc=""/>
<constraint exp="" field="name" desc=""/>
<constraint desc="" exp="" field="fid"/>
<constraint desc="" exp="" field="name"/>
</constraintExpressions>
<expressionfields/>
<attributeactions>
<defaultAction key="Canvas" value="{00000000-0000-0000-0000-000000000000}"/>
</attributeactions>
<attributetableconfig sortExpression="" sortOrder="0" actionWidgetStyle="dropDown">
<attributetableconfig sortExpression="" actionWidgetStyle="dropDown" sortOrder="0">
<columns>
<column hidden="0" type="field" name="fid" width="-1"/>
<column hidden="0" type="field" name="name" width="-1"/>
<column hidden="1" type="actions" width="-1"/>
<column hidden="0" name="fid" width="-1" type="field"/>
<column hidden="0" name="name" width="-1" type="field"/>
<column hidden="1" width="-1" type="actions"/>
</columns>
</attributetableconfig>
<conditionalstyles>
@ -342,8 +398,8 @@ def my_form_open(dialog, layer, feature):
<featformsuppress>0</featformsuppress>
<editorlayout>generatedlayout</editorlayout>
<editable>
<field name="fid" editable="1"/>
<field name="name" editable="1"/>
<field editable="1" name="fid"/>
<field editable="1" name="name"/>
</editable>
<labelOnTop>
<field name="fid" labelOnTop="0"/>
@ -485,9 +541,16 @@ def my_form_open(dialog, layer, feature):
</WMTSPngLayers>
<WMTSUrl type="QString"></WMTSUrl>
</properties>
<dataDefinedServerProperties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</dataDefinedServerProperties>
<visibility-presets/>
<transformContext>
<srcDest allowFallback="1" coordinateOp="+proj=pipeline +step +inv +proj=sterea +lat_0=52.1561605555556 +lon_0=5.38763888888889 +k=0.9999079 +x_0=155000 +y_0=463000 +ellps=bessel +step +proj=push +v_3 +step +proj=cart +ellps=bessel +step +proj=helmert +x=565.2369 +y=50.0087 +z=465.658 +rx=0.406857330322398 +ry=-0.350732676542563 +rz=1.8703473836068 +s=4.0812 +convention=coordinate_frame +step +inv +proj=cart +ellps=WGS84 +step +proj=pop +v_3 +step +proj=unitconvert +xy_in=rad +xy_out=deg">
<srcDest coordinateOp="+proj=pipeline +step +inv +proj=sterea +lat_0=52.1561605555556 +lon_0=5.38763888888889 +k=0.9999079 +x_0=155000 +y_0=463000 +ellps=bessel +step +proj=push +v_3 +step +proj=cart +ellps=bessel +step +proj=helmert +x=565.2369 +y=50.0087 +z=465.658 +rx=0.406857330322398 +ry=-0.350732676542563 +rz=1.8703473836068 +s=4.0812 +convention=coordinate_frame +step +inv +proj=cart +ellps=WGS84 +step +proj=pop +v_3 +step +proj=unitconvert +xy_in=rad +xy_out=deg" allowFallback="1">
<src>
<spatialrefsys>
<wkt>PROJCRS["Amersfoort / RD New",BASEGEOGCRS["Amersfoort",DATUM["Amersfoort",ELLIPSOID["Bessel 1841",6377397.155,299.1528128,LENGTHUNIT["metre",1]]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433]],ID["EPSG",4289]],CONVERSION["RD New",METHOD["Oblique Stereographic",ID["EPSG",9809]],PARAMETER["Latitude of natural origin",52.1561605555556,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8801]],PARAMETER["Longitude of natural origin",5.38763888888889,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8802]],PARAMETER["Scale factor at natural origin",0.9999079,SCALEUNIT["unity",1],ID["EPSG",8805]],PARAMETER["False easting",155000,LENGTHUNIT["metre",1],ID["EPSG",8806]],PARAMETER["False northing",463000,LENGTHUNIT["metre",1],ID["EPSG",8807]]],CS[Cartesian,2],AXIS["easting (X)",east,ORDER[1],LENGTHUNIT["metre",1]],AXIS["northing (Y)",north,ORDER[2],LENGTHUNIT["metre",1]],USAGE[SCOPE["unknown"],AREA["Netherlands - onshore"],BBOX[50.75,3.2,53.7,7.22]],ID["EPSG",28992]]</wkt>
@ -515,7 +578,7 @@ def my_form_open(dialog, layer, feature):
</spatialrefsys>
</dest>
</srcDest>
<srcDest allowFallback="1" coordinateOp="+proj=pipeline +step +inv +proj=laea +lat_0=52 +lon_0=10 +x_0=4321000 +y_0=3210000 +ellps=GRS80 +step +proj=unitconvert +xy_in=rad +xy_out=deg">
<srcDest coordinateOp="+proj=pipeline +step +inv +proj=laea +lat_0=52 +lon_0=10 +x_0=4321000 +y_0=3210000 +ellps=GRS80 +step +proj=unitconvert +xy_in=rad +xy_out=deg" allowFallback="1">
<src>
<spatialrefsys>
<wkt>PROJCRS["ETRS89-extended / LAEA Europe",BASEGEOGCRS["ETRS89",DATUM["European Terrestrial Reference System 1989",ELLIPSOID["GRS 1980",6378137,298.257222101,LENGTHUNIT["metre",1]]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433]],ID["EPSG",4258]],CONVERSION["Europe Equal Area 2001",METHOD["Lambert Azimuthal Equal Area",ID["EPSG",9820]],PARAMETER["Latitude of natural origin",52,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8801]],PARAMETER["Longitude of natural origin",10,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8802]],PARAMETER["False easting",4321000,LENGTHUNIT["metre",1],ID["EPSG",8806]],PARAMETER["False northing",3210000,LENGTHUNIT["metre",1],ID["EPSG",8807]]],CS[Cartesian,2],AXIS["northing (Y)",north,ORDER[1],LENGTHUNIT["metre",1]],AXIS["easting (X)",east,ORDER[2],LENGTHUNIT["metre",1]],USAGE[SCOPE["unknown"],AREA["Europe - LCC &amp; LAEA"],BBOX[24.6,-35.58,84.17,44.83]],ID["EPSG",3035]]</wkt>
@ -573,7 +636,7 @@ def my_form_open(dialog, layer, feature):
<role>custodian</role>
</contact>
<links>
<link format="WTF" size="big" type="OpenSearch1.1:Description" name="link1" url="http://url.com" mimeType="application/octet-stream" description="A link"/>
<link size="big" url="http://url.com" description="A link" name="link1" type="OpenSearch1.1:Description" mimeType="application/octet-stream" format="WTF"/>
</links>
<history>History1</history>
<author>Alessandro Pasotti</author>
@ -585,18 +648,18 @@ def my_form_open(dialog, layer, feature):
<ProjectViewSettings UseProjectScales="0">
<Scales/>
</ProjectViewSettings>
<ProjectTimeSettings timeStepUnit="h" frameRate="1" timeStep="1"/>
<ProjectTimeSettings frameRate="1" timeStep="1" cumulativeTemporalRange="0" timeStepUnit="h"/>
<ProjectDisplaySettings>
<BearingFormat id="bearing">
<Option type="Map">
<Option type="QChar" name="decimal_separator" value=""/>
<Option type="int" name="decimals" value="6"/>
<Option type="int" name="direction_format" value="0"/>
<Option type="int" name="rounding_type" value="0"/>
<Option type="bool" name="show_plus" value="false"/>
<Option type="bool" name="show_thousand_separator" value="true"/>
<Option type="bool" name="show_trailing_zeros" value="false"/>
<Option type="QChar" name="thousand_separator" value=""/>
<Option name="decimal_separator" value="" type="QChar"/>
<Option name="decimals" value="6" type="int"/>
<Option name="direction_format" value="0" type="int"/>
<Option name="rounding_type" value="0" type="int"/>
<Option name="show_plus" value="false" type="bool"/>
<Option name="show_thousand_separator" value="true" type="bool"/>
<Option name="show_trailing_zeros" value="false" type="bool"/>
<Option name="thousand_separator" value="" type="QChar"/>
</Option>
</BearingFormat>
</ProjectDisplaySettings>