QGIS API Documentation  3.8.0-Zanzibar (11aff65)
qgseditformconfig.cpp
Go to the documentation of this file.
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 #include "qgseditformconfig_p.h"
16 #include "qgseditformconfig.h"
18 #include "qgspathresolver.h"
19 #include "qgsproject.h"
20 #include "qgsreadwritecontext.h"
21 #include "qgsrelationmanager.h"
22 #include "qgslogger.h"
23 #include "qgsxmlutils.h"
24 #include "qgsapplication.h"
25 
26 //#include "qgseditorwidgetregistry.h"
27 
29 {
30  qDeleteAll( mChildren );
31 }
32 
34  : d( new QgsEditFormConfigPrivate() )
35 {
36 }
37 
38 QVariantMap QgsEditFormConfig::widgetConfig( const QString &widgetName ) const
39 {
40  int fieldIndex = d->mFields.indexOf( widgetName );
41  if ( fieldIndex != -1 )
42  return d->mFields.at( fieldIndex ).editorWidgetSetup().config();
43  else
44  return d->mWidgetConfigs.value( widgetName );
45 }
46 
47 void QgsEditFormConfig::setFields( const QgsFields &fields )
48 {
49  d.detach();
50  d->mFields = fields;
51 
52  if ( !d->mConfiguredRootContainer )
53  {
54  d->mInvisibleRootContainer->clear();
55  for ( int i = 0; i < d->mFields.size(); ++i )
56  {
57  QgsAttributeEditorField *field = new QgsAttributeEditorField( d->mFields.at( i ).name(), i, d->mInvisibleRootContainer );
58  d->mInvisibleRootContainer->addChildElement( field );
59  }
60  }
61 }
62 
63 void QgsEditFormConfig::onRelationsLoaded()
64 {
65  const QList<QgsAttributeEditorElement *> relations = d->mInvisibleRootContainer->findElements( QgsAttributeEditorElement::AeTypeRelation );
66 
67  for ( QgsAttributeEditorElement *relElem : relations )
68  {
69  QgsAttributeEditorRelation *rel = dynamic_cast< QgsAttributeEditorRelation * >( relElem );
70  if ( !rel )
71  continue;
72 
73  rel->init( QgsProject::instance()->relationManager() );
74  }
75 }
76 
77 bool QgsEditFormConfig::setWidgetConfig( const QString &widgetName, const QVariantMap &config )
78 {
79  if ( d->mFields.indexOf( widgetName ) != -1 )
80  {
81  QgsDebugMsg( QStringLiteral( "Trying to set a widget config for a field on QgsEditFormConfig. Use layer->setEditorWidgetSetup() instead." ) );
82  return false;
83  }
84 
85  d.detach();
86  d->mWidgetConfigs[widgetName] = config;
87  return true;
88 }
89 
90 bool QgsEditFormConfig::removeWidgetConfig( const QString &widgetName )
91 {
92  d.detach();
93  return d->mWidgetConfigs.remove( widgetName ) != 0;
94 }
95 
97  : d( o.d )
98 {
99 }
100 
102 {}
103 
105 {
106  d = o.d;
107  return *this;
108 }
109 
111 {
112  return d == o.d;
113 }
114 
116 {
117  d.detach();
118  d->mInvisibleRootContainer->addChildElement( data );
119 }
120 
121 QList<QgsAttributeEditorElement *> QgsEditFormConfig::tabs() const
122 {
123  return d->mInvisibleRootContainer->children();
124 }
125 
127 {
128  d.detach();
129  d->mInvisibleRootContainer->clear();
130 }
131 
133 {
134  return d->mInvisibleRootContainer;
135 }
136 
138 {
139  return d->mEditorLayout;
140 }
141 
143 {
144  d.detach();
145  d->mEditorLayout = editorLayout;
146 
147  if ( editorLayout == TabLayout )
148  d->mConfiguredRootContainer = true;
149 }
150 
152 {
153  return d->mUiFormPath;
154 }
155 
156 void QgsEditFormConfig::setUiForm( const QString &ui )
157 {
158  if ( !ui.isEmpty() && !QUrl::fromUserInput( ui ).isLocalFile() )
159  {
160  // any existing download will not be restarted!
162  }
163 
164  if ( ui.isEmpty() )
165  {
167  }
168  else
169  {
171  }
172  d->mUiFormPath = ui;
173 }
174 
175 bool QgsEditFormConfig::readOnly( int idx ) const
176 {
177  if ( idx >= 0 && idx < d->mFields.count() )
178  {
179  if ( d->mFields.fieldOrigin( idx ) == QgsFields::OriginJoin
180  || d->mFields.fieldOrigin( idx ) == QgsFields::OriginExpression )
181  return true;
182  return !d->mFieldEditables.value( d->mFields.at( idx ).name(), true );
183  }
184  else
185  return false;
186 }
187 
188 bool QgsEditFormConfig::labelOnTop( int idx ) const
189 {
190  if ( idx >= 0 && idx < d->mFields.count() )
191  return d->mLabelOnTop.value( d->mFields.at( idx ).name(), false );
192  else
193  return false;
194 }
195 
197 {
198  if ( idx >= 0 && idx < d->mFields.count() )
199  {
200  d.detach();
201  d->mFieldEditables[ d->mFields.at( idx ).name()] = !readOnly;
202  }
203 }
204 
205 void QgsEditFormConfig::setLabelOnTop( int idx, bool onTop )
206 {
207  if ( idx >= 0 && idx < d->mFields.count() )
208  {
209  d.detach();
210  d->mLabelOnTop[ d->mFields.at( idx ).name()] = onTop;
211  }
212 }
213 
215 {
216  return d->mInitFunction;
217 }
218 
219 void QgsEditFormConfig::setInitFunction( const QString &function )
220 {
221  d.detach();
222  d->mInitFunction = function;
223 }
224 
226 {
227  return d->mInitCode;
228 }
229 
230 void QgsEditFormConfig::setInitCode( const QString &code )
231 {
232  d.detach();
233  d->mInitCode = code;
234 }
235 
237 {
238  return d->mInitFilePath;
239 }
240 
241 void QgsEditFormConfig::setInitFilePath( const QString &filePath )
242 {
243  d.detach();
244  d->mInitFilePath = filePath;
245 }
246 
248 {
249  return d->mInitCodeSource;
250 }
251 
253 {
254  d.detach();
255  d->mInitCodeSource = initCodeSource;
256 }
257 
259 {
260  return d->mSuppressForm;
261 }
262 
264 {
265  d.detach();
266  d->mSuppressForm = s;
267 }
268 
269 void QgsEditFormConfig::readXml( const QDomNode &node, QgsReadWriteContext &context )
270 {
271  QgsReadWriteContextCategoryPopper p = context.enterCategory( QObject::tr( "Edit form config" ) );
272 
273  d.detach();
274 
275  QDomNode editFormNode = node.namedItem( QStringLiteral( "editform" ) );
276  if ( !editFormNode.isNull() )
277  {
278  QDomElement e = editFormNode.toElement();
279  const bool tolerantRemoteUrls = e.hasAttribute( QStringLiteral( "tolerant" ) );
280  if ( !e.text().isEmpty() )
281  {
282  const QString uiFormPath = context.pathResolver().readPath( e.text() );
283  // <= 3.2 had a bug where invalid ui paths would get written into projects on load
284  // to avoid restoring these invalid paths, we take a less-tolerant approach for older (untrustworthy) projects
285  // and only set ui forms paths IF they are local files OR start with "http(s)".
286  const bool localFile = QFileInfo::exists( uiFormPath );
287  if ( localFile || tolerantRemoteUrls || uiFormPath.startsWith( QLatin1String( "http" ) ) )
288  setUiForm( uiFormPath );
289  }
290  }
291 
292  QDomNode editFormInitNode = node.namedItem( QStringLiteral( "editforminit" ) );
293  if ( !editFormInitNode.isNull() )
294  {
295  d->mInitFunction = editFormInitNode.toElement().text();
296  }
297 
298  QDomNode editFormInitCodeSourceNode = node.namedItem( QStringLiteral( "editforminitcodesource" ) );
299  if ( !editFormInitCodeSourceNode.isNull() && !editFormInitCodeSourceNode.toElement().text().isEmpty() )
300  {
301  setInitCodeSource( static_cast< QgsEditFormConfig::PythonInitCodeSource >( editFormInitCodeSourceNode.toElement().text().toInt() ) );
302  }
303 
304  QDomNode editFormInitCodeNode = node.namedItem( QStringLiteral( "editforminitcode" ) );
305  if ( !editFormInitCodeNode.isNull() )
306  {
307  setInitCode( editFormInitCodeNode.toElement().text() );
308  }
309 
310  // Temporary < 2.12 b/w compatibility "dot" support patch
311  // \see: https://github.com/qgis/QGIS/pull/2498
312  // For b/w compatibility, check if there's a dot in the function name
313  // and if yes, transform it in an import statement for the module
314  // and set the PythonInitCodeSource to CodeSourceDialog
315  int dotPos = d->mInitFunction.lastIndexOf( '.' );
316  if ( dotPos >= 0 ) // It's a module
317  {
319  setInitCode( QStringLiteral( "from %1 import %2\n" ).arg( d->mInitFunction.left( dotPos ), d->mInitFunction.mid( dotPos + 1 ) ) );
320  setInitFunction( d->mInitFunction.mid( dotPos + 1 ) );
321  }
322 
323  QDomNode editFormInitFilePathNode = node.namedItem( QStringLiteral( "editforminitfilepath" ) );
324  if ( !editFormInitFilePathNode.isNull() && !editFormInitFilePathNode.toElement().text().isEmpty() )
325  {
326  setInitFilePath( context.pathResolver().readPath( editFormInitFilePathNode.toElement().text() ) );
327  }
328 
329  QDomNode fFSuppNode = node.namedItem( QStringLiteral( "featformsuppress" ) );
330  if ( fFSuppNode.isNull() )
331  {
332  d->mSuppressForm = QgsEditFormConfig::SuppressDefault;
333  }
334  else
335  {
336  QDomElement e = fFSuppNode.toElement();
337  d->mSuppressForm = static_cast< QgsEditFormConfig::FeatureFormSuppress >( e.text().toInt() );
338  }
339 
340  // tab display
341  QDomNode editorLayoutNode = node.namedItem( QStringLiteral( "editorlayout" ) );
342  if ( editorLayoutNode.isNull() )
343  {
344  d->mEditorLayout = QgsEditFormConfig::GeneratedLayout;
345  }
346  else
347  {
348  if ( editorLayoutNode.toElement().text() == QLatin1String( "uifilelayout" ) )
349  {
350  d->mEditorLayout = QgsEditFormConfig::UiFileLayout;
351  }
352  else if ( editorLayoutNode.toElement().text() == QLatin1String( "tablayout" ) )
353  {
354  d->mEditorLayout = QgsEditFormConfig::TabLayout;
355  }
356  else
357  {
358  d->mEditorLayout = QgsEditFormConfig::GeneratedLayout;
359  }
360  }
361 
362  d->mFieldEditables.clear();
363  QDomNodeList editableNodeList = node.namedItem( QStringLiteral( "editable" ) ).toElement().childNodes();
364  for ( int i = 0; i < editableNodeList.size(); ++i )
365  {
366  QDomElement editableElement = editableNodeList.at( i ).toElement();
367  d->mFieldEditables.insert( editableElement.attribute( QStringLiteral( "name" ) ), static_cast< bool >( editableElement.attribute( QStringLiteral( "editable" ) ).toInt() ) );
368  }
369 
370  d->mLabelOnTop.clear();
371  QDomNodeList labelOnTopNodeList = node.namedItem( QStringLiteral( "labelOnTop" ) ).toElement().childNodes();
372  for ( int i = 0; i < labelOnTopNodeList.size(); ++i )
373  {
374  QDomElement labelOnTopElement = labelOnTopNodeList.at( i ).toElement();
375  d->mLabelOnTop.insert( labelOnTopElement.attribute( QStringLiteral( "name" ) ), static_cast< bool >( labelOnTopElement.attribute( QStringLiteral( "labelOnTop" ) ).toInt() ) );
376  }
377 
378  QDomNodeList widgetsNodeList = node.namedItem( QStringLiteral( "widgets" ) ).toElement().childNodes();
379 
380  for ( int i = 0; i < widgetsNodeList.size(); ++i )
381  {
382  QDomElement widgetElement = widgetsNodeList.at( i ).toElement();
383  QVariant config = QgsXmlUtils::readVariant( widgetElement.firstChildElement( QStringLiteral( "config" ) ) );
384 
385  d->mWidgetConfigs[widgetElement.attribute( QStringLiteral( "name" ) )] = config.toMap();
386  }
387 
388  // tabs and groups display info
389  QDomNode attributeEditorFormNode = node.namedItem( QStringLiteral( "attributeEditorForm" ) );
390  if ( !attributeEditorFormNode.isNull() )
391  {
392  QDomNodeList attributeEditorFormNodeList = attributeEditorFormNode.toElement().childNodes();
393 
394  if ( attributeEditorFormNodeList.size() )
395  {
396  d->mConfiguredRootContainer = true;
397  clearTabs();
398 
399  for ( int i = 0; i < attributeEditorFormNodeList.size(); i++ )
400  {
401  QDomElement elem = attributeEditorFormNodeList.at( i ).toElement();
402 
403  QgsAttributeEditorElement *attributeEditorWidget = attributeEditorElementFromDomElement( elem, nullptr, node.namedItem( QStringLiteral( "id" ) ).toElement().text(), context );
404  addTab( attributeEditorWidget );
405  }
406 
407  onRelationsLoaded();
408  }
409  }
410 }
411 
412 void QgsEditFormConfig::writeXml( QDomNode &node, const QgsReadWriteContext &context ) const
413 {
414  QDomDocument doc( node.ownerDocument() );
415 
416  QDomElement efField = doc.createElement( QStringLiteral( "editform" ) );
417  efField.setAttribute( QStringLiteral( "tolerant" ), QStringLiteral( "1" ) );
418  QDomText efText = doc.createTextNode( context.pathResolver().writePath( uiForm() ) );
419  efField.appendChild( efText );
420  node.appendChild( efField );
421 
422  QDomElement efiField = doc.createElement( QStringLiteral( "editforminit" ) );
423  if ( !initFunction().isEmpty() )
424  efiField.appendChild( doc.createTextNode( initFunction() ) );
425  node.appendChild( efiField );
426 
427  QDomElement eficsField = doc.createElement( QStringLiteral( "editforminitcodesource" ) );
428  eficsField.appendChild( doc.createTextNode( QString::number( initCodeSource() ) ) );
429  node.appendChild( eficsField );
430 
431  QDomElement efifpField = doc.createElement( QStringLiteral( "editforminitfilepath" ) );
432  efifpField.appendChild( doc.createTextNode( context.pathResolver().writePath( initFilePath() ) ) );
433  node.appendChild( efifpField );
434 
435  QDomElement eficField = doc.createElement( QStringLiteral( "editforminitcode" ) );
436  eficField.appendChild( doc.createCDATASection( initCode() ) );
437  node.appendChild( eficField );
438 
439  QDomElement fFSuppElem = doc.createElement( QStringLiteral( "featformsuppress" ) );
440  QDomText fFSuppText = doc.createTextNode( QString::number( suppress() ) );
441  fFSuppElem.appendChild( fFSuppText );
442  node.appendChild( fFSuppElem );
443 
444  // tab display
445  QDomElement editorLayoutElem = doc.createElement( QStringLiteral( "editorlayout" ) );
446  switch ( layout() )
447  {
449  editorLayoutElem.appendChild( doc.createTextNode( QStringLiteral( "uifilelayout" ) ) );
450  break;
451 
453  editorLayoutElem.appendChild( doc.createTextNode( QStringLiteral( "tablayout" ) ) );
454  break;
455 
457  default:
458  editorLayoutElem.appendChild( doc.createTextNode( QStringLiteral( "generatedlayout" ) ) );
459  break;
460  }
461 
462  node.appendChild( editorLayoutElem );
463 
464  // tabs and groups of edit form
465  if ( !tabs().empty() && d->mConfiguredRootContainer )
466  {
467  QDomElement tabsElem = doc.createElement( QStringLiteral( "attributeEditorForm" ) );
468 
469  QDomElement rootElem = d->mInvisibleRootContainer->toDomElement( doc );
470  QDomNodeList elemList = rootElem.childNodes();
471 
472  while ( !elemList.isEmpty() )
473  {
474  tabsElem.appendChild( elemList.at( 0 ) );
475  }
476 
477  node.appendChild( tabsElem );
478  }
479 
480  QDomElement editableElem = doc.createElement( QStringLiteral( "editable" ) );
481  for ( auto editIt = d->mFieldEditables.constBegin(); editIt != d->mFieldEditables.constEnd(); ++editIt )
482  {
483  QDomElement fieldElem = doc.createElement( QStringLiteral( "field" ) );
484  fieldElem.setAttribute( QStringLiteral( "name" ), editIt.key() );
485  fieldElem.setAttribute( QStringLiteral( "editable" ), editIt.value() ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
486  editableElem.appendChild( fieldElem );
487  }
488  node.appendChild( editableElem );
489 
490  QDomElement labelOnTopElem = doc.createElement( QStringLiteral( "labelOnTop" ) );
491  for ( auto labelOnTopIt = d->mLabelOnTop.constBegin(); labelOnTopIt != d->mLabelOnTop.constEnd(); ++labelOnTopIt )
492  {
493  QDomElement fieldElem = doc.createElement( QStringLiteral( "field" ) );
494  fieldElem.setAttribute( QStringLiteral( "name" ), labelOnTopIt.key() );
495  fieldElem.setAttribute( QStringLiteral( "labelOnTop" ), labelOnTopIt.value() ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
496  labelOnTopElem.appendChild( fieldElem );
497  }
498  node.appendChild( labelOnTopElem );
499 
500  QDomElement widgetsElem = doc.createElement( QStringLiteral( "widgets" ) );
501 
502  QMap<QString, QVariantMap >::ConstIterator configIt( d->mWidgetConfigs.constBegin() );
503 
504  while ( configIt != d->mWidgetConfigs.constEnd() )
505  {
506  QDomElement widgetElem = doc.createElement( QStringLiteral( "widget" ) );
507  widgetElem.setAttribute( QStringLiteral( "name" ), configIt.key() );
508  // widgetElem.setAttribute( "notNull", );
509 
510  QDomElement configElem = QgsXmlUtils::writeVariant( configIt.value(), doc );
511  configElem.setTagName( QStringLiteral( "config" ) );
512  widgetElem.appendChild( configElem );
513  widgetsElem.appendChild( widgetElem );
514  ++configIt;
515  }
516 
517  node.appendChild( widgetsElem );
518 
520 }
521 
523 {
524  QgsAttributeEditorElement *newElement = nullptr;
525 
526  if ( elem.tagName() == QLatin1String( "attributeEditorContainer" ) )
527  {
528  QColor backgroundColor( elem.attribute( QStringLiteral( "backgroundColor" ), QString() ) );
529  QgsAttributeEditorContainer *container = new QgsAttributeEditorContainer( context.projectTranslator()->translate( QStringLiteral( "project:layers:%1:formcontainers" ).arg( layerId ),
530  elem.attribute( QStringLiteral( "name" ) ) ), parent, backgroundColor );
531  bool ok;
532  int cc = elem.attribute( QStringLiteral( "columnCount" ) ).toInt( &ok );
533  if ( !ok )
534  cc = 0;
535  container->setColumnCount( cc );
536 
537  bool isGroupBox = elem.attribute( QStringLiteral( "groupBox" ) ).toInt( &ok );
538  if ( ok )
539  container->setIsGroupBox( isGroupBox );
540  else
541  container->setIsGroupBox( parent );
542 
543  bool visibilityExpressionEnabled = elem.attribute( QStringLiteral( "visibilityExpressionEnabled" ) ).toInt( &ok );
544  QgsOptionalExpression visibilityExpression;
545  if ( ok )
546  {
547  visibilityExpression.setEnabled( visibilityExpressionEnabled );
548  visibilityExpression.setData( QgsExpression( elem.attribute( QStringLiteral( "visibilityExpression" ) ) ) );
549  }
550  container->setVisibilityExpression( visibilityExpression );
551 
552  QDomNodeList childNodeList = elem.childNodes();
553 
554  for ( int i = 0; i < childNodeList.size(); i++ )
555  {
556  QDomElement childElem = childNodeList.at( i ).toElement();
557  QgsAttributeEditorElement *myElem = attributeEditorElementFromDomElement( childElem, container, layerId, context );
558  if ( myElem )
559  container->addChildElement( myElem );
560  }
561 
562  newElement = container;
563  }
564  else if ( elem.tagName() == QLatin1String( "attributeEditorField" ) )
565  {
566  QString name = elem.attribute( QStringLiteral( "name" ) );
567  int idx = d->mFields.lookupField( name );
568  newElement = new QgsAttributeEditorField( name, idx, parent );
569  }
570  else if ( elem.tagName() == QLatin1String( "attributeEditorRelation" ) )
571  {
572  // At this time, the relations are not loaded
573  // So we only grab the id and delegate the rest to onRelationsLoaded()
574  QgsAttributeEditorRelation *relElement = new QgsAttributeEditorRelation( elem.attribute( QStringLiteral( "relation" ), QStringLiteral( "[None]" ) ), parent );
575  relElement->setShowLinkButton( elem.attribute( QStringLiteral( "showLinkButton" ), QStringLiteral( "1" ) ).toInt() );
576  relElement->setShowUnlinkButton( elem.attribute( QStringLiteral( "showUnlinkButton" ), QStringLiteral( "1" ) ).toInt() );
577  newElement = relElement;
578  }
579  else if ( elem.tagName() == QLatin1String( "attributeEditorQmlElement" ) )
580  {
581  QgsAttributeEditorQmlElement *qmlElement = new QgsAttributeEditorQmlElement( elem.attribute( QStringLiteral( "name" ) ), parent );
582  qmlElement->setQmlCode( elem.text() );
583  newElement = qmlElement;
584  }
585  else if ( elem.tagName() == QLatin1String( "attributeEditorHtmlElement" ) )
586  {
587  QgsAttributeEditorHtmlElement *htmlElement = new QgsAttributeEditorHtmlElement( elem.attribute( QStringLiteral( "name" ) ), parent );
588  htmlElement->setHtmlCode( elem.text() );
589  newElement = htmlElement;
590  }
591 
592  if ( newElement )
593  {
594  if ( elem.hasAttribute( QStringLiteral( "showLabel" ) ) )
595  newElement->setShowLabel( elem.attribute( QStringLiteral( "showLabel" ) ).toInt() );
596  else
597  newElement->setShowLabel( true );
598  }
599 
600  return newElement;
601 }
602 
604 {
605  return mColumnCount;
606 }
607 
609 {
610  mColumnCount = columnCount;
611 }
612 
614 {
615  QgsAttributeEditorContainer *element = new QgsAttributeEditorContainer( name(), parent );
616 
617  const auto childElements = children();
618 
619  for ( QgsAttributeEditorElement *child : childElements )
620  {
621  element->addChildElement( child->clone( element ) );
622  }
623  element->mIsGroupBox = mIsGroupBox;
624  element->mColumnCount = mColumnCount;
625  element->mVisibilityExpression = mVisibilityExpression;
626 
627  return element;
628 }
629 
630 void QgsAttributeEditorContainer::saveConfiguration( QDomElement &elem ) const
631 {
632  elem.setAttribute( QStringLiteral( "columnCount" ), mColumnCount );
633  elem.setAttribute( QStringLiteral( "groupBox" ), mIsGroupBox ? 1 : 0 );
634  elem.setAttribute( QStringLiteral( "visibilityExpressionEnabled" ), mVisibilityExpression.enabled() ? 1 : 0 );
635  elem.setAttribute( QStringLiteral( "visibilityExpression" ), mVisibilityExpression->expression() );
636  if ( mBackgroundColor.isValid() )
637  elem.setAttribute( QStringLiteral( "backgroundColor" ), mBackgroundColor.name( ) );
638  const auto constMChildren = mChildren;
639  for ( QgsAttributeEditorElement *child : constMChildren )
640  {
641  QDomDocument doc = elem.ownerDocument();
642  elem.appendChild( child->toDomElement( doc ) );
643  }
644 }
645 
646 QString QgsAttributeEditorContainer::typeIdentifier() const
647 {
648  return QStringLiteral( "attributeEditorContainer" );
649 }
Class for parsing and evaluation of expressions (formerly called "search strings").
The class is used as a container of context for various read/write operations on other objects...
An attribute editor widget that will represent arbitrary QML code.
Use the Python code provided in the dialog.
bool init(QgsRelationManager *relManager)
Initializes the relation from the id.
Field comes from a joined layer (originIndex / 1000 = index of the join, originIndex % 1000 = index w...
Definition: qgsfields.h:50
This is an abstract base class for any elements of a drag and drop form.
EditorLayout
The different types to layout the attribute editor.
void readXml(const QDomNode &node, QgsReadWriteContext &context)
Read XML information Deserialize on project load.
static QgsApplication * instance()
Returns the singleton instance of the QgsApplication.
void setInitFilePath(const QString &filePath)
Set Python external file path for edit form initialization.
MAYBE_UNUSED NODISCARD QgsReadWriteContextCategoryPopper enterCategory(const QString &category, const QString &details=QString())
Push a category to the stack.
QString readPath(const QString &filename) const
Turn filename read from the project file to an absolute path.
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QList< QgsAttributeEditorElement *> tabs() const
Returns a list of tabs for EditorLayout::TabLayout obtained from the invisible root container...
Use a layout with tabs and group boxes. Needs to be configured.
The download will start immediately, not need to run QgsFecthedContent::download() ...
Container of fields for a vector layer.
Definition: qgsfields.h:42
QVariantMap widgetConfig(const QString &widgetName) const
Gets the configuration for the editor widget with the given name.
This element will load a field&#39;s widget onto the form.
Allows entering a context category and takes care of leaving this category on deletion of the class...
This element will load a relation editor onto the form.
void setInitFunction(const QString &function)
Set Python function for edit form initialization.
PythonInitCodeSource initCodeSource() const
Returns Python code source for edit form initialization (if it shall be loaded from a file...
void setColumnCount(int columnCount)
Set the number of columns in this group.
An attribute editor widget that will represent arbitrary HTML code.
Use the application-wide setting.
const QgsProjectTranslator * projectTranslator() const
Returns the project translator.
void setLabelOnTop(int idx, bool onTop)
If this is set to true, the widget at the given index will receive its label on the previous line whi...
QgsEditFormConfig()
Create a new edit form config.
void setQmlCode(const QString &qmlCode)
Sets the QML code that will be represented within this widget to qmlCode.
void setData(const T &data)
Set the payload data.
Definition: qgsoptional.h:129
An expression with an additional enabled flag.
static QVariant readVariant(const QDomElement &element)
Read a QVariant from a QDomElement.
void setShowLabel(bool showLabel)
Controls if this element should be labeled with a title (field, relation or groupname).
void setLayout(EditorLayout editorLayout)
Sets the active layout style for the attribute editor for this layer.
void addTab(QgsAttributeEditorElement *data)
Adds a new element to the invisible root container in the layout.
FeatureFormSuppress
Types of feature form suppression after feature creation.
void setInitCode(const QString &code)
Set Python code for edit form initialization.
void clearTabs()
Clears all the tabs for the attribute editor form with EditorLayout::TabLayout.
QgsAttributeEditorContainer * invisibleRootContainer()
Gets the invisible root container for the drag and drop designer form (EditorLayout::TabLayout).
EditorLayout layout() const
Gets the active layout style for the attribute editor for this layer.
void setSuppress(FeatureFormSuppress s)
Sets type of feature form pop-up suppression after feature creation (overrides app setting) ...
virtual QString translate(const QString &context, const QString &sourceText, const char *disambiguation=nullptr, int n=-1) const =0
The derived translate() translates with QTranslator and qm file the sourceText.
void setShowLinkButton(bool showLinkButton)
Determines if the "link feature" button should be shown.
QgsAttributeEditorElement * attributeEditorElementFromDomElement(QDomElement &elem, QgsAttributeEditorElement *parent, const QString &layerId=QString(), const QgsReadWriteContext &context=QgsReadWriteContext())
Deserialize drag and drop designer elements.
void setShowUnlinkButton(bool showUnlinkButton)
Determines if the "unlink feature" button should be shown.
void writeXml(QDomNode &node, const QgsReadWriteContext &context) const
Write XML information Serialize on project save.
QString initCode() const
Gets Python code for edit form initialization.
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths.
bool operator==(const QgsEditFormConfig &o)
FeatureFormSuppress suppress() const
Type of feature form pop-up suppression after feature creation (overrides app setting) ...
QgsEditFormConfig & operator=(const QgsEditFormConfig &o)
void setUiForm(const QString &ui)
Set path to the .ui form.
void setHtmlCode(const QString &htmlCode)
Sets the HTML code that will be represented within this widget to htmlCode.
void setInitCodeSource(PythonInitCodeSource initCodeSource)
Sets if Python code shall be used for edit form initialization and its origin.
Autogenerate a simple tabular layout for the form.
void setReadOnly(int idx, bool readOnly=true)
If set to false, the widget at the given index will be read-only.
Load a .ui file for the layout. Needs to be configured.
int columnCount() const
Gets the number of columns in this group.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:438
static QgsNetworkContentFetcherRegistry * networkContentFetcherRegistry()
Returns the application&#39;s network content registry used for fetching temporary files during QGIS sess...
This is a container for attribute editors, used to group them visually in the attribute form if it is...
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
bool setWidgetConfig(const QString &widgetName, const QVariantMap &config)
Set the editor widget config for a widget which is not for a simple field.
const QgsFetchedContent * fetch(const QString &url, FetchingMode fetchingMode=DownloadLater)
Initialize a download for the given URL.
virtual void addChildElement(QgsAttributeEditorElement *element)
Add a child element to this container.
bool readOnly(int idx) const
This returns true if the field is manually set to read only or if the field does not support editing ...
bool removeWidgetConfig(const QString &widgetName)
Remove the configuration for the editor widget with the given name.
bool labelOnTop(int idx) const
If this returns true, the widget at the given index will receive its label on the previous line while...
void setEnabled(bool enabled)
Set if this optional is enabled.
Definition: qgsoptional.h:99
Field is calculated from an expression.
Definition: qgsfields.h:52
static QDomElement writeVariant(const QVariant &value, QDomDocument &doc)
Write a QVariant to a QDomElement.
QString initFunction() const
Gets Python function for edit form initialization.
PythonInitCodeSource
The Python init code source options.
QgsAttributeEditorElement * clone(QgsAttributeEditorElement *parent) const override
Creates a deep copy of this element.
QString uiForm() const
Returns the path or URL to the .ui form.
QString initFilePath() const
Gets Python external file path for edit form initialization.