18#include "moc_qgseditformconfig.cpp" 
   34  : d( new QgsEditFormConfigPrivate() )
 
 
   41  d->mDataDefinedFieldProperties[ fieldName ] = properties;
 
 
   46  return d->mDataDefinedFieldProperties.value( fieldName );
 
 
   51  return QgsEditFormConfigPrivate::propertyDefinitions();
 
 
   56  const int fieldIndex = d->mFields.indexOf( widgetName );
 
   57  if ( fieldIndex != -1 )
 
   58    return d->mFields.at( fieldIndex ).editorWidgetSetup().config();
 
   60    return d->mWidgetConfigs.value( widgetName );
 
 
   63void QgsEditFormConfig::setFields( 
const QgsFields &fields )
 
   68  if ( !d->mConfiguredRootContainer )
 
   70    d->mInvisibleRootContainer->clear();
 
   71    for ( 
int i = 0; i < d->mFields.size(); ++i )
 
   74      d->mInvisibleRootContainer->addChildElement( field );
 
   79void QgsEditFormConfig::onRelationsLoaded()
 
   93bool QgsEditFormConfig::legacyUpdateRelationWidgetInTabs( 
QgsAttributeEditorContainer *container,  
const QString &widgetName, 
const QVariantMap &config )
 
   95  const QList<QgsAttributeEditorElement *> children = container->
children();
 
  101      if ( legacyUpdateRelationWidgetInTabs( container, widgetName, config ) )
 
  112        if ( relation->
relation().
id() == widgetName )
 
  114          if ( config.contains( QStringLiteral( 
"nm-rel" ) ) )
 
  118          if ( config.contains( QStringLiteral( 
"force-suppress-popup" ) ) )
 
  132  if ( d->mFields.indexOf( widgetName ) != -1 )
 
  134    QgsDebugError( QStringLiteral( 
"Trying to set a widget config for a field on QgsEditFormConfig. Use layer->setEditorWidgetSetup() instead." ) );
 
  139  if ( config.contains( QStringLiteral( 
"force-suppress-popup" ) ) || config.contains( QStringLiteral( 
"nm-rel" ) ) )
 
  141    QgsMessageLog::logMessage( QStringLiteral( 
"Deprecation Warning: Trying to set a relation config directly on the relation %1. Relation settings should be done for the specific widget instance instead. Use attributeEditorRelation->setNmRelationId() or attributeEditorRelation->setForceSuppressFormPopup() instead." ).arg( widgetName ) );
 
  142    legacyUpdateRelationWidgetInTabs( d->mInvisibleRootContainer, widgetName, config );
 
  146  d->mWidgetConfigs[widgetName] = config;
 
 
  153  return d->mWidgetConfigs.remove( widgetName ) != 0;
 
 
  178  d->mInvisibleRootContainer->addChildElement( data );
 
 
  183  return d->mInvisibleRootContainer->children();
 
 
  189  d->mInvisibleRootContainer->clear();
 
 
  194  return d->mInvisibleRootContainer;
 
 
  199  return d->mEditorLayout;
 
 
  205  d->mEditorLayout = editorLayout;
 
  208    d->mConfiguredRootContainer = 
true;
 
 
  213  return d->mUiFormPath;
 
 
  218  if ( !ui.isEmpty() && !QUrl::fromUserInput( ui ).isLocalFile() )
 
 
  237  if ( idx >= 0 && idx < d->mFields.count() )
 
  242    if ( d->mFields.at( idx ).isReadOnly() )
 
  244    return !d->mFieldEditables.value( d->mFields.at( idx ).name(), 
true );
 
 
  252  if ( idx >= 0 && idx < d->mFields.count() )
 
  253    return d->mLabelOnTop.value( d->mFields.at( idx ).name(), 
false );
 
 
  260  if ( idx >= 0 && idx < d->mFields.count() )
 
  263    d->mFieldEditables[ d->mFields.at( idx ).name()] = !
readOnly;
 
 
  269  if ( idx >= 0 && idx < d->mFields.count() )
 
  272    d->mLabelOnTop[ d->mFields.at( idx ).name()] = onTop;
 
 
  278  if ( index >= 0 && index < d->mFields.count() )
 
  279    return d->mReuseLastValue.value( d->mFields.at( index ).name(), 
false );
 
 
  286  if ( index >= 0 && index < d->mFields.count() )
 
  289    d->mReuseLastValue[ d->mFields.at( index ).name()] = reuse;
 
 
  295  return d->mInitFunction;
 
 
  301  d->mInitFunction = function;
 
 
  317  return d->mInitFilePath;
 
 
  323  d->mInitFilePath = filePath;
 
  326  if ( !filePath.isEmpty() && !QUrl::fromUserInput( filePath ).isLocalFile() )
 
 
  335  return d->mInitCodeSource;
 
 
  346  return d->mSuppressForm;
 
 
  352  d->mSuppressForm = s;
 
 
  361  const QDomNode editFormNode = node.namedItem( QStringLiteral( 
"editform" ) );
 
  362  if ( !editFormNode.isNull() )
 
  364    const QDomElement e = editFormNode.toElement();
 
  365    const bool tolerantRemoteUrls = e.hasAttribute( QStringLiteral( 
"tolerant" ) );
 
  366    if ( !e.text().isEmpty() )
 
  372      const bool localFile = QFileInfo::exists( uiFormPath );
 
  373      if ( localFile || tolerantRemoteUrls || uiFormPath.startsWith( QLatin1String( 
"http" ) ) )
 
  378  const QDomNode editFormInitNode = node.namedItem( QStringLiteral( 
"editforminit" ) );
 
  379  if ( !editFormInitNode.isNull() )
 
  381    d->mInitFunction = editFormInitNode.toElement().text();
 
  384  const QDomNode editFormInitCodeSourceNode = node.namedItem( QStringLiteral( 
"editforminitcodesource" ) );
 
  385  if ( !editFormInitCodeSourceNode.isNull() && !editFormInitCodeSourceNode.toElement().text().isEmpty() )
 
  390  const QDomNode editFormInitCodeNode = node.namedItem( QStringLiteral( 
"editforminitcode" ) );
 
  391  if ( !editFormInitCodeNode.isNull() )
 
  393    setInitCode( editFormInitCodeNode.toElement().text() );
 
  401  const int dotPos = d->mInitFunction.lastIndexOf( 
'.' );
 
  405    setInitCode( QStringLiteral( 
"from %1 import %2\n" ).arg( d->mInitFunction.left( dotPos ), d->mInitFunction.mid( dotPos + 1 ) ) );
 
  409  const QDomNode editFormInitFilePathNode = node.namedItem( QStringLiteral( 
"editforminitfilepath" ) );
 
  410  if ( !editFormInitFilePathNode.isNull() && !editFormInitFilePathNode.toElement().text().isEmpty() )
 
  415  const QDomNode fFSuppNode = node.namedItem( QStringLiteral( 
"featformsuppress" ) );
 
  416  if ( fFSuppNode.isNull() )
 
  422    const QDomElement e = fFSuppNode.toElement();
 
  427  const QDomNode editorLayoutNode = node.namedItem( QStringLiteral( 
"editorlayout" ) );
 
  428  if ( editorLayoutNode.isNull() )
 
  434    if ( editorLayoutNode.toElement().text() == QLatin1String( 
"uifilelayout" ) )
 
  438    else if ( editorLayoutNode.toElement().text() == QLatin1String( 
"tablayout" ) )
 
  448  d->mFieldEditables.clear();
 
  449  const QDomNodeList editableNodeList = node.namedItem( QStringLiteral( 
"editable" ) ).toElement().childNodes();
 
  450  for ( 
int i = 0; i < editableNodeList.size(); ++i )
 
  452    const QDomElement editableElement = editableNodeList.at( i ).toElement();
 
  453    d->mFieldEditables.insert( editableElement.attribute( QStringLiteral( 
"name" ) ), 
static_cast< bool >( editableElement.attribute( QStringLiteral( 
"editable" ) ).toInt() ) );
 
  456  d->mLabelOnTop.clear();
 
  457  const QDomNodeList labelOnTopNodeList = node.namedItem( QStringLiteral( 
"labelOnTop" ) ).toElement().childNodes();
 
  458  for ( 
int i = 0; i < labelOnTopNodeList.size(); ++i )
 
  460    const QDomElement labelOnTopElement = labelOnTopNodeList.at( i ).toElement();
 
  461    d->mLabelOnTop.insert( labelOnTopElement.attribute( QStringLiteral( 
"name" ) ), 
static_cast< bool >( labelOnTopElement.attribute( QStringLiteral( 
"labelOnTop" ) ).toInt() ) );
 
  464  d->mReuseLastValue.clear();
 
  465  const QDomNodeList reuseLastValueNodeList = node.namedItem( QStringLiteral( 
"reuseLastValue" ) ).toElement().childNodes();
 
  466  for ( 
int i = 0; i < reuseLastValueNodeList.size(); ++i )
 
  468    const QDomElement reuseLastValueElement = reuseLastValueNodeList.at( i ).toElement();
 
  469    d->mReuseLastValue.insert( reuseLastValueElement.attribute( QStringLiteral( 
"name" ) ), 
static_cast< bool >( reuseLastValueElement.attribute( QStringLiteral( 
"reuseLastValue" ) ).toInt() ) );
 
  473  const QDomNodeList fieldDDPropertiesNodeList = node.namedItem( QStringLiteral( 
"dataDefinedFieldProperties" ) ).toElement().childNodes();
 
  474  for ( 
int i = 0; i < fieldDDPropertiesNodeList.size(); ++i )
 
  476    const QDomElement DDElement = fieldDDPropertiesNodeList.at( i ).toElement();
 
  479    d->mDataDefinedFieldProperties.insert( DDElement.attribute( QStringLiteral( 
"name" ) ), collection );
 
  482  const QDomNodeList widgetsNodeList = node.namedItem( QStringLiteral( 
"widgets" ) ).toElement().childNodes();
 
  484  for ( 
int i = 0; i < widgetsNodeList.size(); ++i )
 
  486    const QDomElement widgetElement = widgetsNodeList.at( i ).toElement();
 
  489    d->mWidgetConfigs[widgetElement.attribute( QStringLiteral( 
"name" ) )] = config.toMap();
 
  493  const QDomNode attributeEditorFormNode = node.namedItem( QStringLiteral( 
"attributeEditorForm" ) );
 
  494  if ( !attributeEditorFormNode.isNull() )
 
  496    const QDomNodeList attributeEditorFormNodeList = attributeEditorFormNode.toElement().childNodes();
 
  498    if ( attributeEditorFormNodeList.size() )
 
  500      d->mConfiguredRootContainer = 
true;
 
  503      for ( 
int i = 0; i < attributeEditorFormNodeList.size(); i++ )
 
  505        QDomElement elem = attributeEditorFormNodeList.at( i ).toElement();
 
  507        fixLegacyConfig( elem );
 
  509        const QString layerId = node.namedItem( QStringLiteral( 
"id" ) ).toElement().text();
 
  511        if ( attributeEditorWidget )
 
  512          addTab( attributeEditorWidget );
 
 
  520void QgsEditFormConfig::fixLegacyConfig( QDomElement &el )
 const 
  524  if ( el.tagName() == QLatin1String( 
"attributeEditorRelation" ) )
 
  526    if ( !el.hasAttribute( QStringLiteral( 
"forceSuppressFormPopup" ) ) )
 
  529      const bool forceSuppress = 
widgetConfig( el.attribute( QStringLiteral( 
"relation" ) ) ).value( QStringLiteral( 
"force-suppress-popup" ), 
false ).toBool();
 
  530      el.setAttribute( QStringLiteral( 
"forceSuppressFormPopup" ), forceSuppress ? 1 : 0 );
 
  532    if ( !el.hasAttribute( QStringLiteral( 
"nmRelationId" ) ) )
 
  535      el.setAttribute( QStringLiteral( 
"nmRelationId" ), 
widgetConfig( el.attribute( QStringLiteral( 
"relation" ) ) ).value( QStringLiteral( 
"nm-rel" ) ).toString() );
 
  539  const QDomNodeList children = el.childNodes();
 
  540  for ( 
int i = 0; i < children.size(); i++ )
 
  542    QDomElement child = children.at( i ).toElement();
 
  543    fixLegacyConfig( child );
 
  544    el.replaceChild( child, children.at( i ) );
 
  550  QDomDocument doc( node.ownerDocument() );
 
  552  QDomElement efField  = doc.createElement( QStringLiteral( 
"editform" ) );
 
  553  efField.setAttribute( QStringLiteral( 
"tolerant" ), QStringLiteral( 
"1" ) );
 
  555  efField.appendChild( efText );
 
  556  node.appendChild( efField );
 
  558  QDomElement efiField  = doc.createElement( QStringLiteral( 
"editforminit" ) );
 
  560    efiField.appendChild( doc.createTextNode( 
initFunction() ) );
 
  561  node.appendChild( efiField );
 
  563  QDomElement eficsField  = doc.createElement( QStringLiteral( 
"editforminitcodesource" ) );
 
  564  eficsField.appendChild( doc.createTextNode( QString::number( 
static_cast< int >( 
initCodeSource() ) ) ) );
 
  565  node.appendChild( eficsField );
 
  567  QDomElement efifpField  = doc.createElement( QStringLiteral( 
"editforminitfilepath" ) );
 
  569  node.appendChild( efifpField );
 
  571  QDomElement eficField  = doc.createElement( QStringLiteral( 
"editforminitcode" ) );
 
  572  eficField.appendChild( doc.createCDATASection( 
initCode() ) );
 
  573  node.appendChild( eficField );
 
  575  QDomElement fFSuppElem  = doc.createElement( QStringLiteral( 
"featformsuppress" ) );
 
  576  const QDomText fFSuppText = doc.createTextNode( QString::number( 
static_cast< int >( 
suppress() ) ) );
 
  577  fFSuppElem.appendChild( fFSuppText );
 
  578  node.appendChild( fFSuppElem );
 
  581  QDomElement editorLayoutElem  = doc.createElement( QStringLiteral( 
"editorlayout" ) );
 
  585      editorLayoutElem.appendChild( doc.createTextNode( QStringLiteral( 
"uifilelayout" ) ) );
 
  589      editorLayoutElem.appendChild( doc.createTextNode( QStringLiteral( 
"tablayout" ) ) );
 
  594      editorLayoutElem.appendChild( doc.createTextNode( QStringLiteral( 
"generatedlayout" ) ) );
 
  598  node.appendChild( editorLayoutElem );
 
  601  if ( !
tabs().empty() && d->mConfiguredRootContainer )
 
  603    QDomElement tabsElem = doc.createElement( QStringLiteral( 
"attributeEditorForm" ) );
 
  604    const QDomElement rootElem = d->mInvisibleRootContainer->toDomElement( doc );
 
  605    const QDomNodeList elemList = rootElem.childNodes();
 
  606    while ( !elemList.isEmpty() )
 
  608      tabsElem.appendChild( elemList.at( 0 ) );
 
  610    node.appendChild( tabsElem );
 
  613  QDomElement editableElem = doc.createElement( QStringLiteral( 
"editable" ) );
 
  614  for ( 
auto editIt = d->mFieldEditables.constBegin(); editIt != d->mFieldEditables.constEnd(); ++editIt )
 
  616    QDomElement fieldElem = doc.createElement( QStringLiteral( 
"field" ) );
 
  617    fieldElem.setAttribute( QStringLiteral( 
"name" ), editIt.key() );
 
  618    fieldElem.setAttribute( QStringLiteral( 
"editable" ), editIt.value() ? QStringLiteral( 
"1" ) : QStringLiteral( 
"0" ) );
 
  619    editableElem.appendChild( fieldElem );
 
  621  node.appendChild( editableElem );
 
  623  QDomElement labelOnTopElem = doc.createElement( QStringLiteral( 
"labelOnTop" ) );
 
  624  for ( 
auto labelOnTopIt = d->mLabelOnTop.constBegin(); labelOnTopIt != d->mLabelOnTop.constEnd(); ++labelOnTopIt )
 
  626    QDomElement fieldElem = doc.createElement( QStringLiteral( 
"field" ) );
 
  627    fieldElem.setAttribute( QStringLiteral( 
"name" ), labelOnTopIt.key() );
 
  628    fieldElem.setAttribute( QStringLiteral( 
"labelOnTop" ), labelOnTopIt.value() ? QStringLiteral( 
"1" ) : QStringLiteral( 
"0" ) );
 
  629    labelOnTopElem.appendChild( fieldElem );
 
  631  node.appendChild( labelOnTopElem );
 
  633  QDomElement reuseLastValueElem = doc.createElement( QStringLiteral( 
"reuseLastValue" ) );
 
  634  for ( 
auto reuseLastValueIt = d->mReuseLastValue.constBegin(); reuseLastValueIt != d->mReuseLastValue.constEnd(); ++reuseLastValueIt )
 
  636    QDomElement fieldElem = doc.createElement( QStringLiteral( 
"field" ) );
 
  637    fieldElem.setAttribute( QStringLiteral( 
"name" ), reuseLastValueIt.key() );
 
  638    fieldElem.setAttribute( QStringLiteral( 
"reuseLastValue" ), reuseLastValueIt.value() ? QStringLiteral( 
"1" ) : QStringLiteral( 
"0" ) );
 
  639    reuseLastValueElem.appendChild( fieldElem );
 
  641  node.appendChild( reuseLastValueElem );
 
  644  QDomElement ddFieldPropsElement = doc.createElement( QStringLiteral( 
"dataDefinedFieldProperties" ) );
 
  645  for ( 
auto it = d->mDataDefinedFieldProperties.constBegin(); it != d->mDataDefinedFieldProperties.constEnd(); ++it )
 
  647    QDomElement ddPropsElement = doc.createElement( QStringLiteral( 
"field" ) );
 
  648    ddPropsElement.setAttribute( QStringLiteral( 
"name" ), it.key() );
 
  650    ddFieldPropsElement.appendChild( ddPropsElement );
 
  652  node.appendChild( ddFieldPropsElement );
 
  654  QDomElement widgetsElem = doc.createElement( QStringLiteral( 
"widgets" ) );
 
  656  QMap<QString, QVariantMap >::ConstIterator configIt( d->mWidgetConfigs.constBegin() );
 
  658  while ( configIt != d->mWidgetConfigs.constEnd() )
 
  660    QDomElement widgetElem = doc.createElement( QStringLiteral( 
"widget" ) );
 
  661    widgetElem.setAttribute( QStringLiteral( 
"name" ), configIt.key() );
 
  665    configElem.setTagName( QStringLiteral( 
"config" ) );
 
  666    widgetElem.appendChild( configElem );
 
  667    widgetsElem.appendChild( widgetElem );
 
  671  node.appendChild( widgetsElem );
 
 
AttributeFormSuppression
Available form types for layout of the attribute form editor.
 
@ Default
Use the application-wide setting.
 
AttributeFormPythonInitCodeSource
The Python init code source for attribute forms.
 
@ Dialog
Use the Python code provided in the dialog.
 
AttributeFormLayout
Available form types for layout of the attribute form editor.
 
@ DragAndDrop
"Drag and drop" layout. Needs to be configured.
 
@ AutoGenerated
Autogenerate a simple tabular layout for the form.
 
@ UiFile
Load a .ui file for the layout. Needs to be configured.
 
@ Immediate
Action will start immediately.
 
@ Expression
Field is calculated from an expression.
 
@ Join
Field originates from a joined layer.
 
virtual bool readXml(const QDomElement &collectionElem, const QgsPropertiesDefinition &definitions)
Reads property collection state from an XML element.
 
static QgsNetworkContentFetcherRegistry * networkContentFetcherRegistry()
Returns the application's network content registry used for fetching temporary files during QGIS sess...
 
A container for attribute editors, used to group them visually in the attribute form if it is set to ...
 
QList< QgsAttributeEditorElement * > children() const
Gets a list of the children elements of this container.
 
An abstract base class for any elements of a drag and drop form.
 
static QgsAttributeEditorElement * create(const QDomElement &element, const QString &layerId, const QgsFields &fields, const QgsReadWriteContext &context, QgsAttributeEditorElement *parent=nullptr)
Constructs the editor element from the given element.
 
This element will load a field's widget onto the form.
 
This element will load a relation editor onto the form.
 
void setNmRelationId(const QVariant &nmRelationId=QVariant())
Sets nmRelationId for the relation id of the second relation involved in an N:M relation.
 
bool init(QgsRelationManager *relManager)
Initializes the relation from the id.
 
const QgsRelation & relation() const
Gets the id of the relation which shall be embedded.
 
void setForceSuppressFormPopup(bool forceSuppressFormPopup)
Sets force suppress form popup status to forceSuppressFormPopup.
 
Container of fields for a vector layer.
 
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
Adds a message to the log instance (and creates it if necessary).
 
QgsFetchedContent * fetch(const QString &url, Qgis::ActionStart fetchingMode=Qgis::ActionStart::Deferred, const QString &authConfig=QString())
Initialize a download for the given URL.
 
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
 
QString readPath(const QString &filename) const
Turn filename read from the project file to an absolute path.
 
QgsRelationManager * relationManager
 
static QgsProject * instance()
Returns the QgsProject singleton instance.
 
A grouped map of multiple QgsProperty objects, each referenced by an integer key value.
 
Allows entering a context category and takes care of leaving this category on deletion of the class.
 
A container for the context for various read/write operations on objects.
 
MAYBE_UNUSED NODISCARD QgsReadWriteContextCategoryPopper enterCategory(const QString &category, const QString &details=QString()) const
Push a category to the stack.
 
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths.
 
static QDomElement writeVariant(const QVariant &value, QDomDocument &doc)
Write a QVariant to a QDomElement.
 
static QVariant readVariant(const QDomElement &element)
Read a QVariant from a QDomElement.
 
#define QgsDebugError(str)
 
QMap< int, QgsPropertyDefinition > QgsPropertiesDefinition
Definition of available properties.