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