LCOV - code coverage report
Current view: top level - core/editform - qgseditformconfig.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 16 394 4.1 %
Date: 2021-03-26 12:19:53 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /***************************************************************************
       2                 :            :     qgseditformconfig.cpp
       3                 :            :     ---------------------
       4                 :            :     begin                : November 2015
       5                 :            :     copyright            : (C) 2015 by Matthias Kuhn
       6                 :            :     email                : matthias at opengis dot ch
       7                 :            :  ***************************************************************************
       8                 :            :  *                                                                         *
       9                 :            :  *   This program is free software; you can redistribute it and/or modify  *
      10                 :            :  *   it under the terms of the GNU General Public License as published by  *
      11                 :            :  *   the Free Software Foundation; either version 2 of the License, or     *
      12                 :            :  *   (at your option) any later version.                                   *
      13                 :            :  *                                                                         *
      14                 :            :  ***************************************************************************/
      15                 :            : 
      16                 :            : #include "qgseditformconfig_p.h"
      17                 :            : #include "qgseditformconfig.h"
      18                 :            : #include "qgsnetworkcontentfetcherregistry.h"
      19                 :            : #include "qgspathresolver.h"
      20                 :            : #include "qgsproject.h"
      21                 :            : #include "qgsreadwritecontext.h"
      22                 :            : #include "qgsrelationmanager.h"
      23                 :            : #include "qgslogger.h"
      24                 :            : #include "qgsxmlutils.h"
      25                 :            : #include "qgsapplication.h"
      26                 :            : #include "qgsmessagelog.h"
      27                 :            : #include "qgsattributeeditorcontainer.h"
      28                 :            : #include "qgsattributeeditorfield.h"
      29                 :            : #include "qgsattributeeditorrelation.h"
      30                 :            : #include <QUrl>
      31                 :            : 
      32                 :         78 : QgsEditFormConfig::QgsEditFormConfig()
      33                 :         78 :   : d( new QgsEditFormConfigPrivate() )
      34                 :            : {
      35                 :         78 : }
      36                 :            : 
      37                 :          0 : void QgsEditFormConfig::setDataDefinedFieldProperties( const QString &fieldName, const QgsPropertyCollection &properties )
      38                 :            : {
      39                 :          0 :   d.detach();
      40                 :          0 :   d->mDataDefinedFieldProperties[ fieldName ] = properties;
      41                 :          0 : }
      42                 :            : 
      43                 :          0 : QgsPropertyCollection QgsEditFormConfig::dataDefinedFieldProperties( const QString &fieldName ) const
      44                 :            : {
      45                 :          0 :   return d->mDataDefinedFieldProperties.value( fieldName );
      46                 :          0 : }
      47                 :            : 
      48                 :          0 : const QgsPropertiesDefinition &QgsEditFormConfig::propertyDefinitions()
      49                 :            : {
      50                 :          0 :   return QgsEditFormConfigPrivate::propertyDefinitions();
      51                 :            : }
      52                 :            : 
      53                 :          0 : QVariantMap QgsEditFormConfig::widgetConfig( const QString &widgetName ) const
      54                 :            : {
      55                 :          0 :   int fieldIndex = d->mFields.indexOf( widgetName );
      56                 :          0 :   if ( fieldIndex != -1 )
      57                 :          0 :     return d->mFields.at( fieldIndex ).editorWidgetSetup().config();
      58                 :            :   else
      59                 :          0 :     return d->mWidgetConfigs.value( widgetName );
      60                 :          0 : }
      61                 :            : 
      62                 :         64 : void QgsEditFormConfig::setFields( const QgsFields &fields )
      63                 :            : {
      64                 :         64 :   d.detach();
      65                 :         64 :   d->mFields = fields;
      66                 :            : 
      67                 :         64 :   if ( !d->mConfiguredRootContainer )
      68                 :            :   {
      69                 :         64 :     d->mInvisibleRootContainer->clear();
      70                 :        148 :     for ( int i = 0; i < d->mFields.size(); ++i )
      71                 :            :     {
      72                 :         84 :       QgsAttributeEditorField *field = new QgsAttributeEditorField( d->mFields.at( i ).name(), i, d->mInvisibleRootContainer );
      73                 :         84 :       d->mInvisibleRootContainer->addChildElement( field );
      74                 :         84 :     }
      75                 :         64 :   }
      76                 :         64 : }
      77                 :            : 
      78                 :          0 : void QgsEditFormConfig::onRelationsLoaded()
      79                 :            : {
      80                 :          0 :   const QList<QgsAttributeEditorElement *> relations = d->mInvisibleRootContainer->findElements( QgsAttributeEditorElement::AeTypeRelation );
      81                 :            : 
      82                 :          0 :   for ( QgsAttributeEditorElement *relElem : relations )
      83                 :            :   {
      84                 :          0 :     QgsAttributeEditorRelation *rel = dynamic_cast< QgsAttributeEditorRelation * >( relElem );
      85                 :          0 :     if ( !rel )
      86                 :          0 :       continue;
      87                 :            : 
      88                 :          0 :     rel->init( QgsProject::instance()->relationManager() );
      89                 :            :   }
      90                 :          0 : }
      91                 :            : 
      92                 :          0 : bool QgsEditFormConfig::legacyUpdateRelationWidgetInTabs( QgsAttributeEditorContainer *container,  const QString &widgetName, const QVariantMap &config )
      93                 :            : {
      94                 :          0 :   const QList<QgsAttributeEditorElement *> children = container->children();
      95                 :          0 :   for ( QgsAttributeEditorElement *child : children )
      96                 :            :   {
      97                 :          0 :     if ( child->type() ==  QgsAttributeEditorElement::AeTypeContainer )
      98                 :            :     {
      99                 :          0 :       QgsAttributeEditorContainer *container = dynamic_cast<QgsAttributeEditorContainer *>( child );
     100                 :          0 :       if ( legacyUpdateRelationWidgetInTabs( container, widgetName, config ) )
     101                 :            :       {
     102                 :            :         //return when a relation has been set in a child or child child...
     103                 :          0 :         return true;
     104                 :            :       }
     105                 :          0 :     }
     106                 :          0 :     else if ( child->type() ==  QgsAttributeEditorElement::AeTypeRelation )
     107                 :            :     {
     108                 :          0 :       QgsAttributeEditorRelation *relation = dynamic_cast< QgsAttributeEditorRelation * >( child );
     109                 :          0 :       if ( relation )
     110                 :            :       {
     111                 :          0 :         if ( relation->relation().id() == widgetName )
     112                 :            :         {
     113                 :          0 :           if ( config.contains( QStringLiteral( "nm-rel" ) ) )
     114                 :            :           {
     115                 :          0 :             relation->setNmRelationId( config[QStringLiteral( "nm-rel" )] );
     116                 :          0 :           }
     117                 :          0 :           if ( config.contains( QStringLiteral( "force-suppress-popup" ) ) )
     118                 :            :           {
     119                 :          0 :             relation->setForceSuppressFormPopup( config[QStringLiteral( "force-suppress-popup" )].toBool() );
     120                 :          0 :           }
     121                 :          0 :           return true;
     122                 :            :         }
     123                 :          0 :       }
     124                 :          0 :     }
     125                 :            :   }
     126                 :          0 :   return false;
     127                 :          0 : }
     128                 :            : 
     129                 :          0 : bool QgsEditFormConfig::setWidgetConfig( const QString &widgetName, const QVariantMap &config )
     130                 :            : {
     131                 :          0 :   if ( d->mFields.indexOf( widgetName ) != -1 )
     132                 :            :   {
     133                 :          0 :     QgsDebugMsg( QStringLiteral( "Trying to set a widget config for a field on QgsEditFormConfig. Use layer->setEditorWidgetSetup() instead." ) );
     134                 :          0 :     return false;
     135                 :            :   }
     136                 :            : 
     137                 :            :   //for legacy use it writes the relation editor configuration into the first instance of the widget
     138                 :          0 :   if ( config.contains( QStringLiteral( "force-suppress-popup" ) ) || config.contains( QStringLiteral( "nm-rel" ) ) )
     139                 :            :   {
     140                 :          0 :     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 ) );
     141                 :          0 :     legacyUpdateRelationWidgetInTabs( d->mInvisibleRootContainer, widgetName, config );
     142                 :          0 :   }
     143                 :            : 
     144                 :          0 :   d.detach();
     145                 :          0 :   d->mWidgetConfigs[widgetName] = config;
     146                 :          0 :   return true;
     147                 :          0 : }
     148                 :            : 
     149                 :          0 : bool QgsEditFormConfig::removeWidgetConfig( const QString &widgetName )
     150                 :            : {
     151                 :          0 :   d.detach();
     152                 :          0 :   return d->mWidgetConfigs.remove( widgetName ) != 0;
     153                 :            : }
     154                 :            : 
     155                 :          0 : QgsEditFormConfig::QgsEditFormConfig( const QgsEditFormConfig &o ) //NOLINT
     156                 :          0 :   : d( o.d )
     157                 :            : {
     158                 :          0 : }
     159                 :            : 
     160                 :         62 : QgsEditFormConfig::~QgsEditFormConfig() //NOLINT
     161                 :         62 : {}
     162                 :            : 
     163                 :          0 : QgsEditFormConfig &QgsEditFormConfig::operator=( const QgsEditFormConfig &o )  //NOLINT
     164                 :            : {
     165                 :          0 :   d = o.d;
     166                 :          0 :   return *this;
     167                 :            : }
     168                 :            : 
     169                 :          0 : bool QgsEditFormConfig::operator==( const QgsEditFormConfig &o )
     170                 :            : {
     171                 :          0 :   return d == o.d;
     172                 :            : }
     173                 :            : 
     174                 :          0 : void QgsEditFormConfig::addTab( QgsAttributeEditorElement *data )
     175                 :            : {
     176                 :          0 :   d.detach();
     177                 :          0 :   d->mInvisibleRootContainer->addChildElement( data );
     178                 :          0 : }
     179                 :            : 
     180                 :          0 : QList<QgsAttributeEditorElement *> QgsEditFormConfig::tabs() const
     181                 :            : {
     182                 :          0 :   return d->mInvisibleRootContainer->children();
     183                 :            : }
     184                 :            : 
     185                 :          0 : void QgsEditFormConfig::clearTabs()
     186                 :            : {
     187                 :          0 :   d.detach();
     188                 :          0 :   d->mInvisibleRootContainer->clear();
     189                 :          0 : }
     190                 :            : 
     191                 :          0 : QgsAttributeEditorContainer *QgsEditFormConfig::invisibleRootContainer()
     192                 :            : {
     193                 :          0 :   return d->mInvisibleRootContainer;
     194                 :            : }
     195                 :            : 
     196                 :          0 : QgsEditFormConfig::EditorLayout QgsEditFormConfig::layout() const
     197                 :            : {
     198                 :          0 :   return d->mEditorLayout;
     199                 :            : }
     200                 :            : 
     201                 :          0 : void QgsEditFormConfig::setLayout( QgsEditFormConfig::EditorLayout editorLayout )
     202                 :            : {
     203                 :          0 :   d.detach();
     204                 :          0 :   d->mEditorLayout = editorLayout;
     205                 :            : 
     206                 :          0 :   if ( editorLayout == TabLayout )
     207                 :          0 :     d->mConfiguredRootContainer = true;
     208                 :          0 : }
     209                 :            : 
     210                 :          0 : QString QgsEditFormConfig::uiForm() const
     211                 :            : {
     212                 :          0 :   return d->mUiFormPath;
     213                 :            : }
     214                 :            : 
     215                 :          0 : void QgsEditFormConfig::setUiForm( const QString &ui )
     216                 :            : {
     217                 :          0 :   if ( !ui.isEmpty() && !QUrl::fromUserInput( ui ).isLocalFile() )
     218                 :            :   {
     219                 :            :     // any existing download will not be restarted!
     220                 :          0 :     QgsApplication::instance()->networkContentFetcherRegistry()->fetch( ui, QgsNetworkContentFetcherRegistry::DownloadImmediately );
     221                 :          0 :   }
     222                 :            : 
     223                 :          0 :   if ( ui.isEmpty() )
     224                 :            :   {
     225                 :          0 :     setLayout( GeneratedLayout );
     226                 :          0 :   }
     227                 :            :   else
     228                 :            :   {
     229                 :          0 :     setLayout( UiFileLayout );
     230                 :            :   }
     231                 :          0 :   d->mUiFormPath = ui;
     232                 :          0 : }
     233                 :            : 
     234                 :          0 : bool QgsEditFormConfig::readOnly( int idx ) const
     235                 :            : {
     236                 :          0 :   if ( idx >= 0 && idx < d->mFields.count() )
     237                 :            :   {
     238                 :          0 :     if ( d->mFields.fieldOrigin( idx ) == QgsFields::OriginJoin
     239                 :          0 :          || d->mFields.fieldOrigin( idx ) == QgsFields::OriginExpression )
     240                 :          0 :       return true;
     241                 :          0 :     return !d->mFieldEditables.value( d->mFields.at( idx ).name(), true );
     242                 :            :   }
     243                 :            :   else
     244                 :          0 :     return false;
     245                 :          0 : }
     246                 :            : 
     247                 :          0 : bool QgsEditFormConfig::labelOnTop( int idx ) const
     248                 :            : {
     249                 :          0 :   if ( idx >= 0 && idx < d->mFields.count() )
     250                 :          0 :     return d->mLabelOnTop.value( d->mFields.at( idx ).name(), false );
     251                 :            :   else
     252                 :          0 :     return false;
     253                 :          0 : }
     254                 :            : 
     255                 :          0 : void QgsEditFormConfig::setReadOnly( int idx, bool readOnly )
     256                 :            : {
     257                 :          0 :   if ( idx >= 0 && idx < d->mFields.count() )
     258                 :            :   {
     259                 :          0 :     d.detach();
     260                 :          0 :     d->mFieldEditables[ d->mFields.at( idx ).name()] = !readOnly;
     261                 :          0 :   }
     262                 :          0 : }
     263                 :            : 
     264                 :          0 : void QgsEditFormConfig::setLabelOnTop( int idx, bool onTop )
     265                 :            : {
     266                 :          0 :   if ( idx >= 0 && idx < d->mFields.count() )
     267                 :            :   {
     268                 :          0 :     d.detach();
     269                 :          0 :     d->mLabelOnTop[ d->mFields.at( idx ).name()] = onTop;
     270                 :          0 :   }
     271                 :          0 : }
     272                 :            : 
     273                 :          0 : bool QgsEditFormConfig::reuseLastValue( int index ) const
     274                 :            : {
     275                 :          0 :   if ( index >= 0 && index < d->mFields.count() )
     276                 :          0 :     return d->mReuseLastValue.value( d->mFields.at( index ).name(), false );
     277                 :            :   else
     278                 :          0 :     return false;
     279                 :          0 : }
     280                 :            : 
     281                 :          0 : void QgsEditFormConfig::setReuseLastValue( int index, bool reuse )
     282                 :            : {
     283                 :          0 :   if ( index >= 0 && index < d->mFields.count() )
     284                 :            :   {
     285                 :          0 :     d.detach();
     286                 :          0 :     d->mReuseLastValue[ d->mFields.at( index ).name()] = reuse;
     287                 :          0 :   }
     288                 :          0 : }
     289                 :            : 
     290                 :          0 : QString QgsEditFormConfig::initFunction() const
     291                 :            : {
     292                 :          0 :   return d->mInitFunction;
     293                 :            : }
     294                 :            : 
     295                 :          0 : void QgsEditFormConfig::setInitFunction( const QString &function )
     296                 :            : {
     297                 :          0 :   d.detach();
     298                 :          0 :   d->mInitFunction = function;
     299                 :          0 : }
     300                 :            : 
     301                 :          0 : QString QgsEditFormConfig::initCode() const
     302                 :            : {
     303                 :          0 :   return d->mInitCode;
     304                 :            : }
     305                 :            : 
     306                 :          0 : void QgsEditFormConfig::setInitCode( const QString &code )
     307                 :            : {
     308                 :          0 :   d.detach();
     309                 :          0 :   d->mInitCode = code;
     310                 :          0 : }
     311                 :            : 
     312                 :          0 : QString QgsEditFormConfig::initFilePath() const
     313                 :            : {
     314                 :          0 :   return d->mInitFilePath;
     315                 :            : }
     316                 :            : 
     317                 :          0 : void QgsEditFormConfig::setInitFilePath( const QString &filePath )
     318                 :            : {
     319                 :          0 :   d.detach();
     320                 :          0 :   d->mInitFilePath = filePath;
     321                 :            : 
     322                 :            :   // if this is an URL, download file as there is a good chance it will be used later
     323                 :          0 :   if ( !filePath.isEmpty() && !QUrl::fromUserInput( filePath ).isLocalFile() )
     324                 :            :   {
     325                 :            :     // any existing download will not be restarted!
     326                 :          0 :     QgsApplication::instance()->networkContentFetcherRegistry()->fetch( filePath, QgsNetworkContentFetcherRegistry::DownloadImmediately );
     327                 :          0 :   }
     328                 :          0 : }
     329                 :            : 
     330                 :          0 : QgsEditFormConfig::PythonInitCodeSource QgsEditFormConfig::initCodeSource() const
     331                 :            : {
     332                 :          0 :   return d->mInitCodeSource;
     333                 :            : }
     334                 :            : 
     335                 :          0 : void QgsEditFormConfig::setInitCodeSource( const QgsEditFormConfig::PythonInitCodeSource initCodeSource )
     336                 :            : {
     337                 :          0 :   d.detach();
     338                 :          0 :   d->mInitCodeSource = initCodeSource;
     339                 :          0 : }
     340                 :            : 
     341                 :          0 : QgsEditFormConfig::FeatureFormSuppress QgsEditFormConfig::suppress() const
     342                 :            : {
     343                 :          0 :   return d->mSuppressForm;
     344                 :            : }
     345                 :            : 
     346                 :          0 : void QgsEditFormConfig::setSuppress( QgsEditFormConfig::FeatureFormSuppress s )
     347                 :            : {
     348                 :          0 :   d.detach();
     349                 :          0 :   d->mSuppressForm = s;
     350                 :          0 : }
     351                 :            : 
     352                 :          0 : void QgsEditFormConfig::readXml( const QDomNode &node, QgsReadWriteContext &context )
     353                 :            : {
     354                 :          0 :   QgsReadWriteContextCategoryPopper p = context.enterCategory( QObject::tr( "Edit form config" ) );
     355                 :            : 
     356                 :          0 :   d.detach();
     357                 :            : 
     358                 :          0 :   QDomNode editFormNode = node.namedItem( QStringLiteral( "editform" ) );
     359                 :          0 :   if ( !editFormNode.isNull() )
     360                 :            :   {
     361                 :          0 :     QDomElement e = editFormNode.toElement();
     362                 :          0 :     const bool tolerantRemoteUrls = e.hasAttribute( QStringLiteral( "tolerant" ) );
     363                 :          0 :     if ( !e.text().isEmpty() )
     364                 :            :     {
     365                 :          0 :       const QString uiFormPath = context.pathResolver().readPath( e.text() );
     366                 :            :       // <= 3.2 had a bug where invalid ui paths would get written into projects on load
     367                 :            :       // to avoid restoring these invalid paths, we take a less-tolerant approach for older (untrustworthy) projects
     368                 :            :       // and only set ui forms paths IF they are local files OR start with "http(s)".
     369                 :          0 :       const bool localFile = QFileInfo::exists( uiFormPath );
     370                 :          0 :       if ( localFile || tolerantRemoteUrls || uiFormPath.startsWith( QLatin1String( "http" ) ) )
     371                 :          0 :         setUiForm( uiFormPath );
     372                 :          0 :     }
     373                 :          0 :   }
     374                 :            : 
     375                 :          0 :   QDomNode editFormInitNode = node.namedItem( QStringLiteral( "editforminit" ) );
     376                 :          0 :   if ( !editFormInitNode.isNull() )
     377                 :            :   {
     378                 :          0 :     d->mInitFunction = editFormInitNode.toElement().text();
     379                 :          0 :   }
     380                 :            : 
     381                 :          0 :   QDomNode editFormInitCodeSourceNode = node.namedItem( QStringLiteral( "editforminitcodesource" ) );
     382                 :          0 :   if ( !editFormInitCodeSourceNode.isNull() && !editFormInitCodeSourceNode.toElement().text().isEmpty() )
     383                 :            :   {
     384                 :          0 :     setInitCodeSource( static_cast< QgsEditFormConfig::PythonInitCodeSource >( editFormInitCodeSourceNode.toElement().text().toInt() ) );
     385                 :          0 :   }
     386                 :            : 
     387                 :          0 :   QDomNode editFormInitCodeNode = node.namedItem( QStringLiteral( "editforminitcode" ) );
     388                 :          0 :   if ( !editFormInitCodeNode.isNull() )
     389                 :            :   {
     390                 :          0 :     setInitCode( editFormInitCodeNode.toElement().text() );
     391                 :          0 :   }
     392                 :            : 
     393                 :            :   // Temporary < 2.12 b/w compatibility "dot" support patch
     394                 :            :   // \see: https://github.com/qgis/QGIS/pull/2498
     395                 :            :   // For b/w compatibility, check if there's a dot in the function name
     396                 :            :   // and if yes, transform it in an import statement for the module
     397                 :            :   // and set the PythonInitCodeSource to CodeSourceDialog
     398                 :          0 :   int dotPos = d->mInitFunction.lastIndexOf( '.' );
     399                 :          0 :   if ( dotPos >= 0 ) // It's a module
     400                 :            :   {
     401                 :          0 :     setInitCodeSource( QgsEditFormConfig::CodeSourceDialog );
     402                 :          0 :     setInitCode( QStringLiteral( "from %1 import %2\n" ).arg( d->mInitFunction.left( dotPos ), d->mInitFunction.mid( dotPos + 1 ) ) );
     403                 :          0 :     setInitFunction( d->mInitFunction.mid( dotPos + 1 ) );
     404                 :          0 :   }
     405                 :            : 
     406                 :          0 :   QDomNode editFormInitFilePathNode = node.namedItem( QStringLiteral( "editforminitfilepath" ) );
     407                 :          0 :   if ( !editFormInitFilePathNode.isNull() && !editFormInitFilePathNode.toElement().text().isEmpty() )
     408                 :            :   {
     409                 :          0 :     setInitFilePath( context.pathResolver().readPath( editFormInitFilePathNode.toElement().text() ) );
     410                 :          0 :   }
     411                 :            : 
     412                 :          0 :   QDomNode fFSuppNode = node.namedItem( QStringLiteral( "featformsuppress" ) );
     413                 :          0 :   if ( fFSuppNode.isNull() )
     414                 :            :   {
     415                 :          0 :     d->mSuppressForm = QgsEditFormConfig::SuppressDefault;
     416                 :          0 :   }
     417                 :            :   else
     418                 :            :   {
     419                 :          0 :     QDomElement e = fFSuppNode.toElement();
     420                 :          0 :     d->mSuppressForm = static_cast< QgsEditFormConfig::FeatureFormSuppress >( e.text().toInt() );
     421                 :          0 :   }
     422                 :            : 
     423                 :            :   // tab display
     424                 :          0 :   QDomNode editorLayoutNode = node.namedItem( QStringLiteral( "editorlayout" ) );
     425                 :          0 :   if ( editorLayoutNode.isNull() )
     426                 :            :   {
     427                 :          0 :     d->mEditorLayout = QgsEditFormConfig::GeneratedLayout;
     428                 :          0 :   }
     429                 :            :   else
     430                 :            :   {
     431                 :          0 :     if ( editorLayoutNode.toElement().text() == QLatin1String( "uifilelayout" ) )
     432                 :            :     {
     433                 :          0 :       d->mEditorLayout = QgsEditFormConfig::UiFileLayout;
     434                 :          0 :     }
     435                 :          0 :     else if ( editorLayoutNode.toElement().text() == QLatin1String( "tablayout" ) )
     436                 :            :     {
     437                 :          0 :       d->mEditorLayout = QgsEditFormConfig::TabLayout;
     438                 :          0 :     }
     439                 :            :     else
     440                 :            :     {
     441                 :          0 :       d->mEditorLayout = QgsEditFormConfig::GeneratedLayout;
     442                 :            :     }
     443                 :            :   }
     444                 :            : 
     445                 :          0 :   d->mFieldEditables.clear();
     446                 :          0 :   QDomNodeList editableNodeList = node.namedItem( QStringLiteral( "editable" ) ).toElement().childNodes();
     447                 :          0 :   for ( int i = 0; i < editableNodeList.size(); ++i )
     448                 :            :   {
     449                 :          0 :     QDomElement editableElement = editableNodeList.at( i ).toElement();
     450                 :          0 :     d->mFieldEditables.insert( editableElement.attribute( QStringLiteral( "name" ) ), static_cast< bool >( editableElement.attribute( QStringLiteral( "editable" ) ).toInt() ) );
     451                 :          0 :   }
     452                 :            : 
     453                 :          0 :   d->mLabelOnTop.clear();
     454                 :          0 :   QDomNodeList labelOnTopNodeList = node.namedItem( QStringLiteral( "labelOnTop" ) ).toElement().childNodes();
     455                 :          0 :   for ( int i = 0; i < labelOnTopNodeList.size(); ++i )
     456                 :            :   {
     457                 :          0 :     QDomElement labelOnTopElement = labelOnTopNodeList.at( i ).toElement();
     458                 :          0 :     d->mLabelOnTop.insert( labelOnTopElement.attribute( QStringLiteral( "name" ) ), static_cast< bool >( labelOnTopElement.attribute( QStringLiteral( "labelOnTop" ) ).toInt() ) );
     459                 :          0 :   }
     460                 :            : 
     461                 :          0 :   d->mReuseLastValue.clear();
     462                 :          0 :   const QDomNodeList reuseLastValueNodeList = node.namedItem( QStringLiteral( "reuseLastValue" ) ).toElement().childNodes();
     463                 :          0 :   for ( int i = 0; i < reuseLastValueNodeList.size(); ++i )
     464                 :            :   {
     465                 :          0 :     const QDomElement reuseLastValueElement = reuseLastValueNodeList.at( i ).toElement();
     466                 :          0 :     d->mReuseLastValue.insert( reuseLastValueElement.attribute( QStringLiteral( "name" ) ), static_cast< bool >( reuseLastValueElement.attribute( QStringLiteral( "reuseLastValue" ) ).toInt() ) );
     467                 :          0 :   }
     468                 :            : 
     469                 :            :   // Read data defined field properties
     470                 :          0 :   QDomNodeList fieldDDPropertiesNodeList = node.namedItem( QStringLiteral( "dataDefinedFieldProperties" ) ).toElement().childNodes();
     471                 :          0 :   for ( int i = 0; i < fieldDDPropertiesNodeList.size(); ++i )
     472                 :            :   {
     473                 :          0 :     QDomElement DDElement = fieldDDPropertiesNodeList.at( i ).toElement();
     474                 :          0 :     QgsPropertyCollection collection;
     475                 :          0 :     collection.readXml( DDElement, propertyDefinitions() );
     476                 :          0 :     d->mDataDefinedFieldProperties.insert( DDElement.attribute( QStringLiteral( "name" ) ), collection );
     477                 :          0 :   }
     478                 :            : 
     479                 :          0 :   QDomNodeList widgetsNodeList = node.namedItem( QStringLiteral( "widgets" ) ).toElement().childNodes();
     480                 :            : 
     481                 :          0 :   for ( int i = 0; i < widgetsNodeList.size(); ++i )
     482                 :            :   {
     483                 :          0 :     QDomElement widgetElement = widgetsNodeList.at( i ).toElement();
     484                 :          0 :     QVariant config = QgsXmlUtils::readVariant( widgetElement.firstChildElement( QStringLiteral( "config" ) ) );
     485                 :            : 
     486                 :          0 :     d->mWidgetConfigs[widgetElement.attribute( QStringLiteral( "name" ) )] = config.toMap();
     487                 :          0 :   }
     488                 :            : 
     489                 :            :   // tabs and groups display info
     490                 :          0 :   QDomNode attributeEditorFormNode = node.namedItem( QStringLiteral( "attributeEditorForm" ) );
     491                 :          0 :   if ( !attributeEditorFormNode.isNull() )
     492                 :            :   {
     493                 :          0 :     QDomNodeList attributeEditorFormNodeList = attributeEditorFormNode.toElement().childNodes();
     494                 :            : 
     495                 :          0 :     if ( attributeEditorFormNodeList.size() )
     496                 :            :     {
     497                 :          0 :       d->mConfiguredRootContainer = true;
     498                 :          0 :       clearTabs();
     499                 :            : 
     500                 :          0 :       for ( int i = 0; i < attributeEditorFormNodeList.size(); i++ )
     501                 :            :       {
     502                 :          0 :         QDomElement elem = attributeEditorFormNodeList.at( i ).toElement();
     503                 :            : 
     504                 :          0 :         fixLegacyConfig( elem );
     505                 :            : 
     506                 :          0 :         const QString layerId = node.namedItem( QStringLiteral( "id" ) ).toElement().text();
     507                 :          0 :         QgsAttributeEditorElement *attributeEditorWidget = QgsAttributeEditorElement::create( elem, layerId, d->mFields, context, nullptr );
     508                 :          0 :         if ( attributeEditorWidget )
     509                 :          0 :           addTab( attributeEditorWidget );
     510                 :          0 :       }
     511                 :            : 
     512                 :          0 :       onRelationsLoaded();
     513                 :          0 :     }
     514                 :          0 :   }
     515                 :          0 : }
     516                 :            : 
     517                 :          0 : void QgsEditFormConfig::fixLegacyConfig( QDomElement &el )
     518                 :            : {
     519                 :            :   // recursive method to move widget config into attribute element config
     520                 :            : 
     521                 :          0 :   if ( el.tagName() == QLatin1String( "attributeEditorRelation" ) )
     522                 :            :   {
     523                 :          0 :     if ( !el.hasAttribute( QStringLiteral( "forceSuppressFormPopup" ) ) )
     524                 :            :     {
     525                 :            :       // pre QGIS 3.16 compatibility - the widgets section is read before
     526                 :          0 :       bool forceSuppress = widgetConfig( el.attribute( QStringLiteral( "relation" ) ) ).value( QStringLiteral( "force-suppress-popup" ), false ).toBool();
     527                 :          0 :       el.setAttribute( QStringLiteral( "forceSuppressFormPopup" ), forceSuppress ? 1 : 0 );
     528                 :          0 :     }
     529                 :          0 :     if ( !el.hasAttribute( QStringLiteral( "nmRelationId" ) ) )
     530                 :            :     {
     531                 :            :       // pre QGIS 3.16 compatibility - the widgets section is read before
     532                 :          0 :       el.setAttribute( QStringLiteral( "nmRelationId" ), widgetConfig( el.attribute( QStringLiteral( "relation" ) ) ).value( QStringLiteral( "nm-rel" ) ).toString() );
     533                 :          0 :     }
     534                 :          0 :   }
     535                 :            : 
     536                 :          0 :   const QDomNodeList children = el.childNodes();
     537                 :          0 :   for ( int i = 0; i < children.size(); i++ )
     538                 :            :   {
     539                 :          0 :     QDomElement child = children.at( i ).toElement();
     540                 :          0 :     fixLegacyConfig( child );
     541                 :          0 :     el.replaceChild( child, children.at( i ) );
     542                 :          0 :   }
     543                 :          0 : }
     544                 :            : 
     545                 :          0 : void QgsEditFormConfig::writeXml( QDomNode &node, const QgsReadWriteContext &context ) const
     546                 :            : {
     547                 :          0 :   QDomDocument doc( node.ownerDocument() );
     548                 :            : 
     549                 :          0 :   QDomElement efField  = doc.createElement( QStringLiteral( "editform" ) );
     550                 :          0 :   efField.setAttribute( QStringLiteral( "tolerant" ), QStringLiteral( "1" ) );
     551                 :          0 :   QDomText efText = doc.createTextNode( context.pathResolver().writePath( uiForm() ) );
     552                 :          0 :   efField.appendChild( efText );
     553                 :          0 :   node.appendChild( efField );
     554                 :            : 
     555                 :          0 :   QDomElement efiField  = doc.createElement( QStringLiteral( "editforminit" ) );
     556                 :          0 :   if ( !initFunction().isEmpty() )
     557                 :          0 :     efiField.appendChild( doc.createTextNode( initFunction() ) );
     558                 :          0 :   node.appendChild( efiField );
     559                 :            : 
     560                 :          0 :   QDomElement eficsField  = doc.createElement( QStringLiteral( "editforminitcodesource" ) );
     561                 :          0 :   eficsField.appendChild( doc.createTextNode( QString::number( initCodeSource() ) ) );
     562                 :          0 :   node.appendChild( eficsField );
     563                 :            : 
     564                 :          0 :   QDomElement efifpField  = doc.createElement( QStringLiteral( "editforminitfilepath" ) );
     565                 :          0 :   efifpField.appendChild( doc.createTextNode( context.pathResolver().writePath( initFilePath() ) ) );
     566                 :          0 :   node.appendChild( efifpField );
     567                 :            : 
     568                 :          0 :   QDomElement eficField  = doc.createElement( QStringLiteral( "editforminitcode" ) );
     569                 :          0 :   eficField.appendChild( doc.createCDATASection( initCode() ) );
     570                 :          0 :   node.appendChild( eficField );
     571                 :            : 
     572                 :          0 :   QDomElement fFSuppElem  = doc.createElement( QStringLiteral( "featformsuppress" ) );
     573                 :          0 :   QDomText fFSuppText = doc.createTextNode( QString::number( suppress() ) );
     574                 :          0 :   fFSuppElem.appendChild( fFSuppText );
     575                 :          0 :   node.appendChild( fFSuppElem );
     576                 :            : 
     577                 :            :   // tab display
     578                 :          0 :   QDomElement editorLayoutElem  = doc.createElement( QStringLiteral( "editorlayout" ) );
     579                 :          0 :   switch ( layout() )
     580                 :            :   {
     581                 :            :     case QgsEditFormConfig::UiFileLayout:
     582                 :          0 :       editorLayoutElem.appendChild( doc.createTextNode( QStringLiteral( "uifilelayout" ) ) );
     583                 :          0 :       break;
     584                 :            : 
     585                 :            :     case QgsEditFormConfig::TabLayout:
     586                 :          0 :       editorLayoutElem.appendChild( doc.createTextNode( QStringLiteral( "tablayout" ) ) );
     587                 :          0 :       break;
     588                 :            : 
     589                 :            :     case QgsEditFormConfig::GeneratedLayout:
     590                 :            :     default:
     591                 :          0 :       editorLayoutElem.appendChild( doc.createTextNode( QStringLiteral( "generatedlayout" ) ) );
     592                 :          0 :       break;
     593                 :            :   }
     594                 :            : 
     595                 :          0 :   node.appendChild( editorLayoutElem );
     596                 :            : 
     597                 :            :   // tabs and groups of edit form
     598                 :          0 :   if ( !tabs().empty() && d->mConfiguredRootContainer )
     599                 :            :   {
     600                 :          0 :     QDomElement tabsElem = doc.createElement( QStringLiteral( "attributeEditorForm" ) );
     601                 :          0 :     QDomElement rootElem = d->mInvisibleRootContainer->toDomElement( doc );
     602                 :          0 :     QDomNodeList elemList = rootElem.childNodes();
     603                 :          0 :     while ( !elemList.isEmpty() )
     604                 :            :     {
     605                 :          0 :       tabsElem.appendChild( elemList.at( 0 ) );
     606                 :            :     }
     607                 :          0 :     node.appendChild( tabsElem );
     608                 :          0 :   }
     609                 :            : 
     610                 :          0 :   QDomElement editableElem = doc.createElement( QStringLiteral( "editable" ) );
     611                 :          0 :   for ( auto editIt = d->mFieldEditables.constBegin(); editIt != d->mFieldEditables.constEnd(); ++editIt )
     612                 :            :   {
     613                 :          0 :     QDomElement fieldElem = doc.createElement( QStringLiteral( "field" ) );
     614                 :          0 :     fieldElem.setAttribute( QStringLiteral( "name" ), editIt.key() );
     615                 :          0 :     fieldElem.setAttribute( QStringLiteral( "editable" ), editIt.value() ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
     616                 :          0 :     editableElem.appendChild( fieldElem );
     617                 :          0 :   }
     618                 :          0 :   node.appendChild( editableElem );
     619                 :            : 
     620                 :          0 :   QDomElement labelOnTopElem = doc.createElement( QStringLiteral( "labelOnTop" ) );
     621                 :          0 :   for ( auto labelOnTopIt = d->mLabelOnTop.constBegin(); labelOnTopIt != d->mLabelOnTop.constEnd(); ++labelOnTopIt )
     622                 :            :   {
     623                 :          0 :     QDomElement fieldElem = doc.createElement( QStringLiteral( "field" ) );
     624                 :          0 :     fieldElem.setAttribute( QStringLiteral( "name" ), labelOnTopIt.key() );
     625                 :          0 :     fieldElem.setAttribute( QStringLiteral( "labelOnTop" ), labelOnTopIt.value() ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
     626                 :          0 :     labelOnTopElem.appendChild( fieldElem );
     627                 :          0 :   }
     628                 :          0 :   node.appendChild( labelOnTopElem );
     629                 :            : 
     630                 :          0 :   QDomElement reuseLastValueElem = doc.createElement( QStringLiteral( "reuseLastValue" ) );
     631                 :          0 :   for ( auto reuseLastValueIt = d->mReuseLastValue.constBegin(); reuseLastValueIt != d->mReuseLastValue.constEnd(); ++reuseLastValueIt )
     632                 :            :   {
     633                 :          0 :     QDomElement fieldElem = doc.createElement( QStringLiteral( "field" ) );
     634                 :          0 :     fieldElem.setAttribute( QStringLiteral( "name" ), reuseLastValueIt.key() );
     635                 :          0 :     fieldElem.setAttribute( QStringLiteral( "reuseLastValue" ), reuseLastValueIt.value() ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
     636                 :          0 :     reuseLastValueElem.appendChild( fieldElem );
     637                 :          0 :   }
     638                 :          0 :   node.appendChild( reuseLastValueElem );
     639                 :            : 
     640                 :            :   // Store data defined field properties
     641                 :          0 :   QDomElement ddFieldPropsElement = doc.createElement( QStringLiteral( "dataDefinedFieldProperties" ) );
     642                 :          0 :   for ( auto it = d->mDataDefinedFieldProperties.constBegin(); it != d->mDataDefinedFieldProperties.constEnd(); ++it )
     643                 :            :   {
     644                 :          0 :     QDomElement ddPropsElement = doc.createElement( QStringLiteral( "field" ) );
     645                 :          0 :     ddPropsElement.setAttribute( QStringLiteral( "name" ), it.key() );
     646                 :          0 :     it.value().writeXml( ddPropsElement, propertyDefinitions() );
     647                 :          0 :     ddFieldPropsElement.appendChild( ddPropsElement );
     648                 :          0 :   }
     649                 :          0 :   node.appendChild( ddFieldPropsElement );
     650                 :            : 
     651                 :          0 :   QDomElement widgetsElem = doc.createElement( QStringLiteral( "widgets" ) );
     652                 :            : 
     653                 :          0 :   QMap<QString, QVariantMap >::ConstIterator configIt( d->mWidgetConfigs.constBegin() );
     654                 :            : 
     655                 :          0 :   while ( configIt != d->mWidgetConfigs.constEnd() )
     656                 :            :   {
     657                 :          0 :     QDomElement widgetElem = doc.createElement( QStringLiteral( "widget" ) );
     658                 :          0 :     widgetElem.setAttribute( QStringLiteral( "name" ), configIt.key() );
     659                 :            :     // widgetElem.setAttribute( "notNull",  );
     660                 :            : 
     661                 :          0 :     QDomElement configElem = QgsXmlUtils::writeVariant( configIt.value(), doc );
     662                 :          0 :     configElem.setTagName( QStringLiteral( "config" ) );
     663                 :          0 :     widgetElem.appendChild( configElem );
     664                 :          0 :     widgetsElem.appendChild( widgetElem );
     665                 :          0 :     ++configIt;
     666                 :          0 :   }
     667                 :            : 
     668                 :          0 :   node.appendChild( widgetsElem );
     669                 :          0 : }
     670                 :            : 
     671                 :          0 : QgsAttributeEditorElement *QgsEditFormConfig::attributeEditorElementFromDomElement( QDomElement &elem, QgsAttributeEditorElement *parent, const QString &layerId, const QgsReadWriteContext &context )
     672                 :            : {
     673                 :          0 :   return QgsAttributeEditorElement::create( elem, layerId, d->mFields, context, parent );
     674                 :            : }

Generated by: LCOV version 1.14