QGIS API Documentation  2.4.0-Chugiak
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgsattributeform.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsattributeform.cpp
3  --------------------------------------
4  Date : 3.5.2014
5  Copyright : (C) 2014 Matthias Kuhn
6  Email : matthias dot kuhn at gmx 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 "qgsattributeform.h"
17 
18 #include "qgsattributeeditor.h"
21 #include "qgseditorwidgetregistry.h"
22 #include "qgsproject.h"
23 #include "qgspythonrunner.h"
24 #include "qgsrelationwidgetwrapper.h"
25 
26 #include <QDir>
27 #include <QFileInfo>
28 #include <QFormLayout>
29 #include <QGridLayout>
30 #include <QGroupBox>
31 #include <QKeyEvent>
32 #include <QLabel>
33 #include <QPushButton>
34 #include <QScrollArea>
35 #include <QTabWidget>
36 #include <QUiLoader>
37 
39 
41  : QWidget( parent )
42  , mLayer( vl )
43  , mContext( context )
44  , mFormNr( sFormCounter++ )
45  , mIsSaving( false )
46  , mIsAddDialog( false )
47  , mEditCommandMessage( tr( "Attributes changed" ) )
48 {
49  init();
50  initPython();
51  setFeature( feature );
52 
53  connect( vl, SIGNAL( attributeAdded( int ) ), this, SLOT( onAttributeAdded( int ) ) );
54  connect( vl, SIGNAL( attributeDeleted( int ) ), this, SLOT( onAttributeDeleted( int ) ) );
55 }
56 
58 {
59  cleanPython();
60  qDeleteAll( mInterfaces );
61 }
62 
64 {
65  mButtonBox->hide();
66 
67  // Make sure that changes are taken into account if somebody tries to figure out if there have been some
68  connect( mLayer, SIGNAL( beforeModifiedCheck() ), this, SLOT( save() ) );
69 }
70 
72 {
73  mButtonBox->show();
74 
75  disconnect( mLayer, SIGNAL( beforeModifiedCheck() ), this, SLOT( save() ) );
76 }
77 
79 {
80  mInterfaces.append( iface );
81 }
82 
84 {
85  return mFeature.isValid() && mLayer->isEditable() ;
86 }
87 
88 void QgsAttributeForm::setIsAddDialog( bool isAddDialog )
89 {
90  mIsAddDialog = isAddDialog;
91 
93 }
94 
95 void QgsAttributeForm::changeAttribute( const QString& field, const QVariant& value )
96 {
97  Q_FOREACH( QgsWidgetWrapper* ww, mWidgets )
98  {
99  QgsEditorWidgetWrapper* eww = qobject_cast<QgsEditorWidgetWrapper*>( ww );
100  if ( eww && eww->field().name() == field )
101  {
102  eww->setValue( value );
103  }
104  }
105 }
106 
108 {
109  mFeature = feature;
110 
111  resetValues();
112 
114 
115  Q_FOREACH( QgsAttributeFormInterface* iface, mInterfaces )
116  {
117  iface->featureChanged();
118  }
119 }
120 
122 {
123  if ( mIsSaving )
124  return true;
125 
126  mIsSaving = true;
127 
128  bool success = true;
129 
130  emit beforeSave( success );
131 
132  // Somebody wants to prevent this form from saving
133  if ( !success )
134  return false;
135 
136  QgsFeature updatedFeature = QgsFeature( mFeature );
137 
138  if ( mFeature.isValid() || mIsAddDialog )
139  {
140  bool doUpdate = false;
141 
142  // An add dialog should perform an action by default
143  // and not only if attributes have "changed"
144  if ( mIsAddDialog )
145  doUpdate = true;
146 
149 
150  Q_FOREACH( QgsWidgetWrapper* ww, mWidgets )
151  {
152  QgsEditorWidgetWrapper* eww = qobject_cast<QgsEditorWidgetWrapper*>( ww );
153  if ( eww )
154  {
155  QVariant dstVar = dst[eww->fieldIdx()];
156  QVariant srcVar = eww->value();
157  if ( dstVar != srcVar && srcVar.isValid() )
158  {
159  dst[eww->fieldIdx()] = srcVar;
160 
161  doUpdate = true;
162  }
163  }
164  }
165 
166  updatedFeature.setAttributes( dst );
167 
168  Q_FOREACH( QgsAttributeFormInterface* iface, mInterfaces )
169  {
170  if ( !iface->acceptChanges( updatedFeature ) )
171  {
172  doUpdate = false;
173  }
174  }
175 
176  if ( doUpdate )
177  {
178  if ( mIsAddDialog )
179  {
180  mFeature.setValid( true );
182  bool res = mLayer->addFeature( updatedFeature );
183  if ( res )
185  else
187  }
188  else
189  {
191 
192  int n = 0;
193  for ( int i = 0; i < dst.count(); ++i )
194  {
195  if ( dst[i] == src[i] || !dst[i].isValid() )
196  {
197  QgsDebugMsg( "equal or invalid destination" );
198  QgsDebugMsg( QString( "dst:'%1' (type:%2,isNull:%3,isValid:%4)" )
199  .arg( dst[i].toString() ).arg( dst[i].typeName() ).arg( dst[i].isNull() ).arg( dst[i].isValid() ) );
200  QgsDebugMsg( QString( "src:'%1' (type:%2,isNull:%3,isValid:%4)" )
201  .arg( src[i].toString() ).arg( src[i].typeName() ).arg( src[i].isNull() ).arg( src[i].isValid() ) );
202  continue;
203  }
204 
205  success &= mLayer->changeAttributeValue( mFeature.id(), i, dst[i], src[i] );
206  n++;
207  }
208 
209  if ( success && n > 0 )
210  {
212  mFeature.setAttributes( dst );
213  }
214  else
215  {
217  }
218  }
219  }
220  }
221 
222  emit featureSaved( updatedFeature );
223 
224  mIsSaving = false;
225 
226  return success;
227 }
228 
230 {
231  Q_FOREACH( QgsWidgetWrapper* ww, mWidgets )
232  {
233  ww->setFeature( mFeature );
234  }
235 }
236 
237 void QgsAttributeForm::onAttributeChanged( const QVariant& value )
238 {
239  QgsEditorWidgetWrapper* eww = qobject_cast<QgsEditorWidgetWrapper*>( sender() );
240 
241  Q_ASSERT( eww );
242 
243  emit attributeChanged( eww->field().name(), value );
244 }
245 
247 {
248  if ( mFeature.isValid() )
249  {
251  Q_ASSERT( attrs.size() == idx );
252  attrs.append( QVariant() );
253  mFeature.setFields( &layer()->pendingFields() );
254  mFeature.setAttributes( attrs );
255  }
256  init();
257  setFeature( mFeature );
258 }
259 
261 {
262  if ( mFeature.isValid() )
263  {
265  attrs.remove( idx );
266  mFeature.setFields( &layer()->pendingFields() );
267  mFeature.setAttributes( attrs );
268  }
269  init();
270  setFeature( mFeature );
271 }
272 
274 {
275  bool isEditable = ( mFeature.isValid() || mIsAddDialog ) && mLayer->isEditable();
276 
277  Q_FOREACH( QgsWidgetWrapper* ww, mWidgets )
278  {
279  bool fieldEditable = true;
280  QgsEditorWidgetWrapper* eww = qobject_cast<QgsEditorWidgetWrapper*>( ww );
281  if ( eww )
282  {
283  fieldEditable = mLayer->fieldEditable( eww->fieldIdx() );
284  }
285  ww->setEnabled( isEditable && fieldEditable );
286  }
287 
288  QPushButton* okButton = mButtonBox->button( QDialogButtonBox::Ok );
289  if ( okButton )
290  okButton->setEnabled( isEditable );
291 }
292 
294 {
295  QWidget* formWidget = 0;
296 
297  qDeleteAll( mWidgets );
298  mWidgets.clear();
299 
300  while ( QWidget* w = this->findChild<QWidget*>() )
301  {
302  delete w;
303  }
304  delete this->layout();
305 
306  // Get a layout
307  setLayout( new QGridLayout( this ) );
308 
309  // Try to load Ui-File for layout
310  if ( mLayer->editorLayout() == QgsVectorLayer::UiFileLayout && !mLayer->editForm().isEmpty() )
311  {
312  QFile file( mLayer->editForm() );
313 
314  if ( file.open( QFile::ReadOnly ) )
315  {
316  QUiLoader loader;
317 
318  QFileInfo fi( mLayer->editForm() );
319  loader.setWorkingDirectory( fi.dir() );
320  formWidget = loader.load( &file, this );
321  formWidget->setWindowFlags( Qt::Widget );
322  layout()->addWidget( formWidget );
323  formWidget->show();
324  file.close();
325  createWrappers();
326 
327  formWidget->installEventFilter( this );
328  }
329  }
330 
331  // Tab layout
332  if ( !formWidget && mLayer->editorLayout() == QgsVectorLayer::TabLayout )
333  {
334  QTabWidget* tabWidget = new QTabWidget( this );
335  layout()->addWidget( tabWidget );
336 
338  {
339  QWidget* tabPage = new QWidget( tabWidget );
340 
341  tabWidget->addTab( tabPage, widgDef->name() );
342  QGridLayout *tabPageLayout = new QGridLayout( tabPage );
343 
345  {
346  QgsAttributeEditorContainer* containerDef = dynamic_cast<QgsAttributeEditorContainer*>( widgDef );
347  containerDef->setIsGroupBox( false ); // Toplevel widgets are tabs not groupboxes
348  QString dummy1;
349  bool dummy2;
350  tabPageLayout->addWidget( createWidgetFromDef( widgDef, tabPage, mLayer, mContext, dummy1, dummy2 ) );
351  }
352  else
353  {
354  QgsDebugMsg( "No support for fields in attribute editor on top level" );
355  }
356  }
357  formWidget = tabWidget;
358  }
359 
360  // Autogenerate Layout
361  // If there is still no layout loaded (defined as autogenerate or other methods failed)
362  if ( !formWidget )
363  {
364  formWidget = new QWidget( this );
365  QGridLayout* gridLayout = new QGridLayout( formWidget );
366  formWidget->setLayout( gridLayout );
367 
368  // put the form into a scroll area to nicely handle cases with lots of attributes
369  QScrollArea* scrollArea = new QScrollArea( this );
370  scrollArea->setWidget( formWidget );
371  scrollArea->setWidgetResizable( true );
372  scrollArea->setFrameShape( QFrame::NoFrame );
373  scrollArea->setFrameShadow( QFrame::Plain );
374  layout()->addWidget( scrollArea );
375 
376  int row = 0;
377  Q_FOREACH( const QgsField& field, mLayer->pendingFields().toList() )
378  {
379  int idx = mLayer->fieldNameIndex( field.name() );
380  //show attribute alias if available
381  QString fieldName = mLayer->attributeDisplayName( idx );
382 
383  const QString widgetType = mLayer->editorWidgetV2( idx );
384 
385  if ( widgetType != "Hidden" )
386  {
387  const QgsEditorWidgetConfig widgetConfig = mLayer->editorWidgetV2Config( idx );
388  bool labelOnTop = mLayer->labelOnTop( idx );
389 
390  // This will also create the widget
391  QWidget *l = new QLabel( fieldName );
392  QgsEditorWidgetWrapper* eww = QgsEditorWidgetRegistry::instance()->create( widgetType, mLayer, idx, widgetConfig, 0, this, mContext );
393  QWidget *w = eww ? eww->widget() : new QLabel( QString( "<p style=\"color: red; font-style: italic;\">Failed to create widget with type '%1'</p>" ).arg( widgetType ) );
394 
395  if ( eww )
396  mWidgets.append( eww );
397 
398  if ( labelOnTop )
399  {
400  gridLayout->addWidget( l, row++, 0, 1, 2 );
401  gridLayout->addWidget( w, row++, 0, 1, 2 );
402  }
403  else
404  {
405  gridLayout->addWidget( l, row, 0 );
406  gridLayout->addWidget( w, row++, 1 );
407  }
408  }
409  }
410 
411  Q_FOREACH( const QgsRelation& rel, QgsProject::instance()->relationManager()->referencedRelations( mLayer ) )
412  {
413  QgsRelationWidgetWrapper* rww = new QgsRelationWidgetWrapper( mLayer, rel, 0, this );
414  rww->setContext( mContext );
415  gridLayout->addWidget( rww->widget(), row++, 0, 1, 2 );
416  mWidgets.append( rww );
417  }
418  }
419 
420  mButtonBox = findChild<QDialogButtonBox*>();
421 
422  if ( !mButtonBox )
423  {
424  mButtonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
425  mButtonBox->setObjectName( "buttonBox" );
426  layout()->addWidget( mButtonBox );
427  }
428 
429  connectWrappers();
430 
431  connect( mButtonBox, SIGNAL( accepted() ), this, SLOT( accept() ) );
432  connect( mButtonBox, SIGNAL( rejected() ), this, SLOT( resetValues() ) );
433 
434  connect( mLayer, SIGNAL( editingStarted() ), this, SLOT( synchronizeEnabledState() ) );
435  connect( mLayer, SIGNAL( editingStopped() ), this, SLOT( synchronizeEnabledState() ) );
436 
437  Q_FOREACH( QgsAttributeFormInterface* iface, mInterfaces )
438  {
439  iface->initForm();
440  }
441 }
442 
444 {
445  if ( !mPyFormVarName.isNull() )
446  {
447  QString expr = QString( "if locals().has_key('%1'): del %1\n" ).arg( mPyFormVarName );
448  QgsPythonRunner::run( expr );
449  }
450 }
451 
453 {
454  cleanPython();
455 
456  // Init Python
457  if ( !mLayer->editFormInit().isEmpty() )
458  {
459  QString module = mLayer->editFormInit();
460 
461  int pos = module.lastIndexOf( "." );
462  if ( pos >= 0 )
463  {
464  QgsPythonRunner::run( QString( "import %1" ).arg( module.left( pos ) ) );
465  }
466 
467  /* Reload the module if the DEBUGMODE switch has been set in the module.
468  If set to False you have to reload QGIS to reset it to True due to Python
469  module caching */
470  QString reload = QString( "if hasattr(%1,'DEBUGMODE') and %1.DEBUGMODE:"
471  " reload(%1)" ).arg( module.left( pos ) );
472 
473  QgsPythonRunner::run( reload );
474 
475  QgsPythonRunner::run( "import inspect" );
476  QString numArgs;
477  QgsPythonRunner::eval( QString( "len(inspect.getargspec(%1)[0])" ).arg( module ), numArgs );
478 
479  mPyFormVarName = QString( "_qgis_featureform_%1" ).arg( mFormNr );
480 
481  QString form = QString( "%1 = sip.wrapinstance( %2, qgis.gui.QgsAttributeForm )" )
482  .arg( mPyFormVarName )
483  .arg(( unsigned long ) this );
484 
485  QgsPythonRunner::run( form );
486 
487  QgsDebugMsg( QString( "running featureForm init: %1" ).arg( mPyFormVarName ) );
488 
489  // Legacy
490  if ( numArgs == "3" )
491  {
493  }
494  else
495  {
496 #if 0
497  QString expr = QString( "%1(%2)" )
498  .arg( mLayer->editFormInit() )
499  .arg( mPyFormVarName );
500  QgsAttributeFormInterface* iface = QgsPythonRunner::evalToSipObject<QgsAttributeFormInterface*>( expr, "QgsAttributeFormInterface" );
501  if ( iface )
502  addInterface( iface );
503 #endif
504  }
505  }
506 }
507 
508 QWidget* QgsAttributeForm::createWidgetFromDef( const QgsAttributeEditorElement *widgetDef, QWidget *parent, QgsVectorLayer *vl, QgsAttributeEditorContext &context, QString &labelText, bool &labelOnTop )
509 {
510  QWidget *newWidget = 0;
511 
512  switch ( widgetDef->type() )
513  {
515  {
516  const QgsAttributeEditorField* fieldDef = dynamic_cast<const QgsAttributeEditorField*>( widgetDef );
517  int fldIdx = fieldDef->idx();
518  if ( fldIdx < vl->pendingFields().count() && fldIdx >= 0 )
519  {
520  const QString widgetType = mLayer->editorWidgetV2( fldIdx );
521  const QgsEditorWidgetConfig widgetConfig = mLayer->editorWidgetV2Config( fldIdx );
522 
523  QgsEditorWidgetWrapper* eww = QgsEditorWidgetRegistry::instance()->create( widgetType, mLayer, fldIdx, widgetConfig, 0, this, mContext );
524  newWidget = eww->widget();
525  mWidgets.append( eww );
526  }
527 
528  labelOnTop = mLayer->labelOnTop( fieldDef->idx() );
529  labelText = mLayer->attributeDisplayName( fieldDef->idx() );
530  break;
531  }
532 
534  {
535  const QgsAttributeEditorRelation* relDef = dynamic_cast<const QgsAttributeEditorRelation*>( widgetDef );
536 
537  QgsRelationWidgetWrapper* rww = new QgsRelationWidgetWrapper( mLayer, relDef->relation(), 0, this );
538  rww->setContext( context );
539  newWidget = rww->widget();
540  mWidgets.append( rww );
541  labelText = QString::null;
542  labelOnTop = true;
543  break;
544  }
545 
547  {
548  const QgsAttributeEditorContainer* container = dynamic_cast<const QgsAttributeEditorContainer*>( widgetDef );
549  QWidget* myContainer;
550 
551  if ( container->isGroupBox() )
552  {
553  QGroupBox* groupBox = new QGroupBox( parent );
554  groupBox->setTitle( container->name() );
555  myContainer = groupBox;
556  newWidget = myContainer;
557  }
558  else
559  {
560  QScrollArea *scrollArea = new QScrollArea( parent );
561 
562  myContainer = new QWidget( scrollArea );
563 
564  scrollArea->setWidget( myContainer );
565  scrollArea->setWidgetResizable( true );
566  scrollArea->setFrameShape( QFrame::NoFrame );
567 
568  newWidget = scrollArea;
569  }
570 
571  QGridLayout* gbLayout = new QGridLayout( myContainer );
572  myContainer->setLayout( gbLayout );
573 
574  int index = 0;
575 
576  QList<QgsAttributeEditorElement*> children = container->children();
577 
578  Q_FOREACH( QgsAttributeEditorElement* childDef, children )
579  {
580  QString labelText;
581  bool labelOnTop;
582  QWidget* editor = createWidgetFromDef( childDef, myContainer, vl, context, labelText, labelOnTop );
583 
584  if ( labelText.isNull() )
585  {
586  gbLayout->addWidget( editor, index, 0, 1, 2 );
587  }
588  else
589  {
590  QLabel* mypLabel = new QLabel( labelText );
591  if ( labelOnTop )
592  {
593  gbLayout->addWidget( mypLabel, index, 0, 1, 2 );
594  ++index;
595  gbLayout->addWidget( editor, index, 0, 1 , 2 );
596  }
597  else
598  {
599  gbLayout->addWidget( mypLabel, index, 0 );
600  gbLayout->addWidget( editor, index, 1 );
601  }
602  }
603 
604  ++index;
605  }
606  gbLayout->addItem( new QSpacerItem( 0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding ), index , 0 );
607 
608  labelText = QString::null;
609  labelOnTop = true;
610  break;
611  }
612 
613  default:
614  QgsDebugMsg( "Unknown attribute editor widget type encountered..." );
615  break;
616  }
617 
618  return newWidget;
619 }
620 
622 {
623  QList<QWidget*> myWidgets = findChildren<QWidget*>();
624  const QList<QgsField> fields = mLayer->pendingFields().toList();
625 
626  Q_FOREACH( QWidget* myWidget, myWidgets )
627  {
628  // Check the widget's properties for a relation definition
629  QVariant vRel = myWidget->property( "qgisRelation" );
630  if ( vRel.isValid() )
631  {
633  QgsRelation relation = relMgr->relation( vRel.toString() );
634  if ( relation.isValid() )
635  {
636  QgsRelationWidgetWrapper* rww = new QgsRelationWidgetWrapper( mLayer, relation, myWidget, this );
637  rww->setConfig( QgsEditorWidgetConfig() );
638  rww->setContext( mContext );
639  mWidgets.append( rww );
640  }
641  }
642  else
643  {
644  Q_FOREACH( const QgsField& field, fields )
645  {
646  if ( field.name() == myWidget->objectName() )
647  {
648  const QString widgetType = mLayer->editorWidgetV2( field.name() );
649  const QgsEditorWidgetConfig widgetConfig = mLayer->editorWidgetV2Config( field.name() );
650  int idx = mLayer->fieldNameIndex( field.name() );
651 
652  QgsEditorWidgetWrapper* eww = QgsEditorWidgetRegistry::instance()->create( widgetType, mLayer, idx, widgetConfig, myWidget, this, mContext );
653  mWidgets.append( eww );
654  }
655  }
656  }
657  }
658 }
659 
661 {
662  Q_FOREACH( QgsWidgetWrapper* ww, mWidgets )
663  {
664  QgsEditorWidgetWrapper* eww = qobject_cast<QgsEditorWidgetWrapper*>( ww );
665 
666  if ( eww )
667  connect( eww, SIGNAL( valueChanged( const QVariant& ) ), this, SLOT( onAttributeChanged( const QVariant& ) ) );
668  }
669 }
670 
671 
672 bool QgsAttributeForm::eventFilter( QObject* object, QEvent* e )
673 {
674  Q_UNUSED( object )
675 
676  if ( e->type() == QEvent::KeyPress )
677  {
678  QKeyEvent* keyEvent = dynamic_cast<QKeyEvent*>( e );
679  if ( keyEvent->key() == Qt::Key_Escape )
680  {
681  // Re-emit to this form so it will be forwarded to parent
682  event( e );
683  return true;
684  }
685  }
686 
687  return false;
688 }
QList< QgsField > toList() const
Utility function to return a list of QgsField instances.
Definition: qgsfield.cpp:167
QgsFeatureId id() const
Get the feature id for this feature.
Definition: qgsfeature.cpp:100
const QgsEditorWidgetConfig editorWidgetV2Config(int fieldIdx) const
Get the configuration for the editor widget used to represent the field at the given index...
const QString & name() const
Gets the name of the field.
Definition: qgsfield.cpp:58
void resetValues()
Sets all values to the values of the current feature.
bool isValid() const
Returns the validity of this relation.
void createWrappers()
Creates widget wrappers for all suitable widgets found.
static unsigned index
bool fieldEditable(int idx)
is edit widget editable
EditorLayout editorLayout()
get the active layout for the attribute editor for this layer (added in 1.9)
virtual bool isGroupBox() const
Q_DECL_DEPRECATED void accept()
Alias for save()
bool isValid() const
Return the validity of this feature.
Definition: qgsfeature.cpp:171
void hideButtonBox()
Hides the button box (Ok/Cancel) and enables auto-commit.
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
This class contains context information for attribute editor widgets.
void beginEditCommand(QString text)
Create edit command for undo/redo operations.
bool editable()
Returns if the form is currently in editable mode.
bool save()
Save all the values from the editors to the layer.
void setIsAddDialog(bool isAddDialog)
Toggles the form mode between edit feature and add feature.
static bool eval(QString command, QString &result)
Eval a python statement.
void setAttributes(const QgsAttributes &attrs)
Definition: qgsfeature.h:144
bool addFeature(QgsFeature &f, bool alsoUpdateExtent=true)
Adds a feature.
const QgsRelation & relation() const
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:113
QDialogButtonBox * mButtonBox
QgsVectorLayer * layer()
Returns the layer for which this form is shown.
QgsAttributeEditorContext mContext
QWidget * createWidgetFromDef(const QgsAttributeEditorElement *widgetDef, QWidget *parent, QgsVectorLayer *vl, QgsAttributeEditorContext &context, QString &labelText, bool &labelOnTop)
QList< QgsAttributeFormInterface * > mInterfaces
QString editForm()
get edit form (added in 1.4)
void showButtonBox()
Shows the button box (Ok/Cancel) and disables auto-commit.
QgsVectorLayer * mLayer
QString attributeDisplayName(int attributeIndex) const
Convenience function that returns the attribute alias if defined or the field name else...
void onAttributeChanged(const QVariant &value)
void setFeature(const QgsFeature &feature)
Update all editors to correspond to a different feature.
static bool run(QString command, QString messageOnError=QString())
execute a python statement
QgsRelation relation(const QString &id) const
QList< QgsWidgetWrapper * > mWidgets
const QString editorWidgetV2(int fieldIdx) const
Get the id for the editor widget used to represent the field at the given index.
AttributeEditorType type() const
void destroyEditCommand()
Destroy active command and reverts all changes in it.
Q_DECL_DEPRECATED bool changeAttributeValue(QgsFeatureId fid, int field, QVariant value, bool emitSignal)
Changes an attribute value (but does not commit it)
const QgsAttributes & attributes() const
Definition: qgsfeature.h:142
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:31
static int sFormCounter
void beforeSave(bool &ok)
Will be emitted before the feature is saved.
void setFields(const QgsFields *fields, bool initAttributes=false)
Assign a field map with the feature to allow attribute access by attribute name.
Definition: qgsfeature.cpp:161
void endEditCommand()
Finish edit command and add it to undo/redo stack.
bool labelOnTop(int idx)
label widget on top
void onAttributeAdded(int idx)
QList< QgsAttributeEditorElement * > children() const
QgsAttributeForm(QgsVectorLayer *vl, const QgsFeature feature=QgsFeature(), QgsAttributeEditorContext context=QgsAttributeEditorContext(), QWidget *parent=0)
This class helps to support legacy open form scripts to be compatible with the new QgsAttributeForm s...
void featureSaved(const QgsFeature &feature)
Is emitted, when a feature is changed or added.
virtual bool acceptChanges(const QgsFeature &feature)
QString file
Definition: qgssvgcache.cpp:76
void setValid(bool validity)
Set the validity of the feature.
Definition: qgsfeature.cpp:176
bool eventFilter(QObject *object, QEvent *event)
Intercepts keypress on custom form (escape should not close it)
void changeAttribute(const QString &field, const QVariant &value)
Call this to change the content of a given attribute.
void attributeChanged(QString attribute, const QVariant &value)
Notifies about changes of attributes.
QVector< QVariant > QgsAttributes
Definition: qgsfeature.h:100
virtual void setIsGroupBox(bool isGroupBox)
This class manages a set of relations between layers.
static QgsProject * instance()
access to canonical QgsProject instance
Definition: qgsproject.cpp:362
QList< QgsAttributeEditorElement * > & attributeEditorElements()
Returns a list of tabs holding groups and fields.
void addInterface(QgsAttributeFormInterface *iface)
Takes ownership.
QMap< QString, QVariant > QgsEditorWidgetConfig
Holds a set of configuration parameters for a editor widget wrapper.
const QgsFeature & feature()
bool mIsSaving
Set to true while saving to prevent recursive saves.
const QgsFields & pendingFields() const
returns field list in the to-be-committed state
void onAttributeDeleted(int idx)
QString editFormInit()
get python function for edit form initialization (added in 1.4)
virtual bool isEditable() const
Returns true if the provider is in editing mode.
Represents a vector layer which manages a vector based data sets.
int fieldNameIndex(const QString &fieldName) const
Returns the index of a field name or -1 if the field does not exist.
QgsRelationManager * relationManager() const
bool isNull(const QVariant &v)
#define tr(sourceText)