QGIS API Documentation  2.5.0-Master
 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"
22 #include "qgsproject.h"
23 #include "qgspythonrunner.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  Q_UNUSED( idx ) // only used for Q_ASSERT
249  if ( mFeature.isValid() )
250  {
252  Q_ASSERT( attrs.size() == idx );
253  attrs.append( QVariant() );
254  mFeature.setFields( &layer()->pendingFields() );
255  mFeature.setAttributes( attrs );
256  }
257  init();
258  setFeature( mFeature );
259 }
260 
262 {
263  if ( mFeature.isValid() )
264  {
266  attrs.remove( idx );
267  mFeature.setFields( &layer()->pendingFields() );
268  mFeature.setAttributes( attrs );
269  }
270  init();
271  setFeature( mFeature );
272 }
273 
275 {
276  bool isEditable = ( mFeature.isValid() || mIsAddDialog ) && mLayer->isEditable();
277 
278  Q_FOREACH( QgsWidgetWrapper* ww, mWidgets )
279  {
280  bool fieldEditable = true;
281  QgsEditorWidgetWrapper* eww = qobject_cast<QgsEditorWidgetWrapper*>( ww );
282  if ( eww )
283  {
284  fieldEditable = mLayer->fieldEditable( eww->fieldIdx() );
285  }
286  ww->setEnabled( isEditable && fieldEditable );
287  }
288 
289  QPushButton* okButton = mButtonBox->button( QDialogButtonBox::Ok );
290  if ( okButton )
291  okButton->setEnabled( isEditable );
292 }
293 
295 {
296  QWidget* formWidget = 0;
297 
298  qDeleteAll( mWidgets );
299  mWidgets.clear();
300 
301  while ( QWidget* w = this->findChild<QWidget*>() )
302  {
303  delete w;
304  }
305  delete layout();
306 
307  // Get a layout
308  setLayout( new QGridLayout( this ) );
309 
310  // Try to load Ui-File for layout
311  if ( mLayer->editorLayout() == QgsVectorLayer::UiFileLayout && !mLayer->editForm().isEmpty() )
312  {
313  QFile file( mLayer->editForm() );
314 
315  if ( file.open( QFile::ReadOnly ) )
316  {
317  QUiLoader loader;
318 
319  QFileInfo fi( mLayer->editForm() );
320  loader.setWorkingDirectory( fi.dir() );
321  formWidget = loader.load( &file, this );
322  formWidget->setWindowFlags( Qt::Widget );
323  layout()->addWidget( formWidget );
324  formWidget->show();
325  file.close();
326  createWrappers();
327 
328  formWidget->installEventFilter( this );
329  }
330  }
331 
332  // Tab layout
333  if ( !formWidget && mLayer->editorLayout() == QgsVectorLayer::TabLayout )
334  {
335  QTabWidget* tabWidget = new QTabWidget( this );
336  layout()->addWidget( tabWidget );
337 
339  {
340  QWidget* tabPage = new QWidget( tabWidget );
341 
342  tabWidget->addTab( tabPage, widgDef->name() );
343  QGridLayout *tabPageLayout = new QGridLayout( tabPage );
344 
346  {
347  QgsAttributeEditorContainer* containerDef = dynamic_cast<QgsAttributeEditorContainer*>( widgDef );
348  containerDef->setIsGroupBox( false ); // Toplevel widgets are tabs not groupboxes
349  QString dummy1;
350  bool dummy2;
351  tabPageLayout->addWidget( createWidgetFromDef( widgDef, tabPage, mLayer, mContext, dummy1, dummy2 ) );
352  }
353  else
354  {
355  QgsDebugMsg( "No support for fields in attribute editor on top level" );
356  }
357  }
358  formWidget = tabWidget;
359  }
360 
361  // Autogenerate Layout
362  // If there is still no layout loaded (defined as autogenerate or other methods failed)
363  if ( !formWidget )
364  {
365  formWidget = new QWidget( this );
366  QGridLayout* gridLayout = new QGridLayout( formWidget );
367  formWidget->setLayout( gridLayout );
368 
369  // put the form into a scroll area to nicely handle cases with lots of attributes
370 
371  QScrollArea* scrollArea = new QScrollArea( this );
372  scrollArea->setWidget( formWidget );
373  scrollArea->setWidgetResizable( true );
374  scrollArea->setFrameShape( QFrame::NoFrame );
375  scrollArea->setFrameShadow( QFrame::Plain );
376  scrollArea->setFocusProxy( this );
377  layout()->addWidget( scrollArea );
378 
379  int row = 0;
380  Q_FOREACH( const QgsField& field, mLayer->pendingFields().toList() )
381  {
382  int idx = mLayer->fieldNameIndex( field.name() );
383  //show attribute alias if available
384  QString fieldName = mLayer->attributeDisplayName( idx );
385 
386  const QString widgetType = mLayer->editorWidgetV2( idx );
387 
388  if ( widgetType == "Hidden" )
389  continue;
390 
391  const QgsEditorWidgetConfig widgetConfig = mLayer->editorWidgetV2Config( idx );
392  bool labelOnTop = mLayer->labelOnTop( idx );
393 
394  // This will also create the widget
395  QWidget *l = new QLabel( fieldName );
396  QgsEditorWidgetWrapper* eww = QgsEditorWidgetRegistry::instance()->create( widgetType, mLayer, idx, widgetConfig, 0, this, mContext );
397  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 ) );
398 
399  if ( w )
400  w->setObjectName( field.name() );
401 
402  if ( eww )
403  addWidgetWrapper( eww );
404 
405  if ( labelOnTop )
406  {
407  gridLayout->addWidget( l, row++, 0, 1, 2 );
408  gridLayout->addWidget( w, row++, 0, 1, 2 );
409  }
410  else
411  {
412  gridLayout->addWidget( l, row, 0 );
413  gridLayout->addWidget( w, row++, 1 );
414  }
415  }
416 
417  Q_FOREACH( const QgsRelation& rel, QgsProject::instance()->relationManager()->referencedRelations( mLayer ) )
418  {
419  QgsRelationWidgetWrapper* rww = new QgsRelationWidgetWrapper( mLayer, rel, 0, this );
420  rww->setContext( mContext );
421  gridLayout->addWidget( rww->widget(), row++, 0, 1, 2 );
422  mWidgets.append( rww );
423  }
424  }
425 
426  mButtonBox = findChild<QDialogButtonBox*>();
427 
428  if ( !mButtonBox )
429  {
430  mButtonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
431  mButtonBox->setObjectName( "buttonBox" );
432  layout()->addWidget( mButtonBox );
433  }
434 
435  connectWrappers();
436 
437  connect( mButtonBox, SIGNAL( accepted() ), this, SLOT( accept() ) );
438  connect( mButtonBox, SIGNAL( rejected() ), this, SLOT( resetValues() ) );
439 
440  connect( mLayer, SIGNAL( editingStarted() ), this, SLOT( synchronizeEnabledState() ) );
441  connect( mLayer, SIGNAL( editingStopped() ), this, SLOT( synchronizeEnabledState() ) );
442 
443  Q_FOREACH( QgsAttributeFormInterface* iface, mInterfaces )
444  {
445  iface->initForm();
446  }
447 }
448 
450 {
451  if ( !mPyFormVarName.isNull() )
452  {
453  QString expr = QString( "if locals().has_key('%1'): del %1\n" ).arg( mPyFormVarName );
454  QgsPythonRunner::run( expr );
455  }
456 }
457 
459 {
460  cleanPython();
461 
462  // Init Python
463  if ( !mLayer->editFormInit().isEmpty() )
464  {
465  QString module = mLayer->editFormInit();
466 
467  int pos = module.lastIndexOf( "." );
468  if ( pos >= 0 )
469  {
470  QgsPythonRunner::run( QString( "import %1" ).arg( module.left( pos ) ) );
471  }
472 
473  /* Reload the module if the DEBUGMODE switch has been set in the module.
474  If set to False you have to reload QGIS to reset it to True due to Python
475  module caching */
476  QString reload = QString( "if hasattr(%1,'DEBUGMODE') and %1.DEBUGMODE:"
477  " reload(%1)" ).arg( module.left( pos ) );
478 
479  QgsPythonRunner::run( reload );
480 
481  QgsPythonRunner::run( "import inspect" );
482  QString numArgs;
483  QgsPythonRunner::eval( QString( "len(inspect.getargspec(%1)[0])" ).arg( module ), numArgs );
484 
485  mPyFormVarName = QString( "_qgis_featureform_%1" ).arg( mFormNr );
486 
487  QString form = QString( "%1 = sip.wrapinstance( %2, qgis.gui.QgsAttributeForm )" )
488  .arg( mPyFormVarName )
489  .arg(( unsigned long ) this );
490 
491  QgsPythonRunner::run( form );
492 
493  QgsDebugMsg( QString( "running featureForm init: %1" ).arg( mPyFormVarName ) );
494 
495  // Legacy
496  if ( numArgs == "3" )
497  {
499  }
500  else
501  {
502 #if 0
503  QString expr = QString( "%1(%2)" )
504  .arg( mLayer->editFormInit() )
505  .arg( mPyFormVarName );
506  QgsAttributeFormInterface* iface = QgsPythonRunner::evalToSipObject<QgsAttributeFormInterface*>( expr, "QgsAttributeFormInterface" );
507  if ( iface )
508  addInterface( iface );
509 #endif
510  }
511  }
512 }
513 
514 QWidget* QgsAttributeForm::createWidgetFromDef( const QgsAttributeEditorElement *widgetDef, QWidget *parent, QgsVectorLayer *vl, QgsAttributeEditorContext &context, QString &labelText, bool &labelOnTop )
515 {
516  QWidget *newWidget = 0;
517 
518  switch ( widgetDef->type() )
519  {
521  {
522  const QgsAttributeEditorField* fieldDef = dynamic_cast<const QgsAttributeEditorField*>( widgetDef );
523  int fldIdx = fieldDef->idx();
524  if ( fldIdx < vl->pendingFields().count() && fldIdx >= 0 )
525  {
526  const QString widgetType = mLayer->editorWidgetV2( fldIdx );
527  const QgsEditorWidgetConfig widgetConfig = mLayer->editorWidgetV2Config( fldIdx );
528 
529  QgsEditorWidgetWrapper* eww = QgsEditorWidgetRegistry::instance()->create( widgetType, mLayer, fldIdx, widgetConfig, 0, this, mContext );
530  newWidget = eww->widget();
531  addWidgetWrapper( eww );
532 
533  newWidget->setObjectName( mLayer->pendingFields()[ fldIdx ].name() );
534  }
535 
536  labelOnTop = mLayer->labelOnTop( fieldDef->idx() );
537  labelText = mLayer->attributeDisplayName( fieldDef->idx() );
538 
539  break;
540  }
541 
543  {
544  const QgsAttributeEditorRelation* relDef = dynamic_cast<const QgsAttributeEditorRelation*>( widgetDef );
545 
546  QgsRelationWidgetWrapper* rww = new QgsRelationWidgetWrapper( mLayer, relDef->relation(), 0, this );
547  rww->setContext( context );
548  newWidget = rww->widget();
549  mWidgets.append( rww );
550  labelText = QString::null;
551  labelOnTop = true;
552  break;
553  }
554 
556  {
557  const QgsAttributeEditorContainer* container = dynamic_cast<const QgsAttributeEditorContainer*>( widgetDef );
558  QWidget* myContainer;
559 
560  if ( container->isGroupBox() )
561  {
562  QGroupBox* groupBox = new QGroupBox( parent );
563  groupBox->setTitle( container->name() );
564  myContainer = groupBox;
565  newWidget = myContainer;
566  }
567  else
568  {
569  QScrollArea *scrollArea = new QScrollArea( parent );
570 
571  myContainer = new QWidget( scrollArea );
572 
573  scrollArea->setWidget( myContainer );
574  scrollArea->setWidgetResizable( true );
575  scrollArea->setFrameShape( QFrame::NoFrame );
576 
577  newWidget = scrollArea;
578  }
579 
580  QGridLayout* gbLayout = new QGridLayout( myContainer );
581  myContainer->setLayout( gbLayout );
582 
583  int index = 0;
584 
585  QList<QgsAttributeEditorElement*> children = container->children();
586 
587  Q_FOREACH( QgsAttributeEditorElement* childDef, children )
588  {
589  QString labelText;
590  bool labelOnTop;
591  QWidget* editor = createWidgetFromDef( childDef, myContainer, vl, context, labelText, labelOnTop );
592 
593  if ( labelText.isNull() )
594  {
595  gbLayout->addWidget( editor, index, 0, 1, 2 );
596  }
597  else
598  {
599  QLabel* mypLabel = new QLabel( labelText );
600  if ( labelOnTop )
601  {
602  gbLayout->addWidget( mypLabel, index, 0, 1, 2 );
603  ++index;
604  gbLayout->addWidget( editor, index, 0, 1 , 2 );
605  }
606  else
607  {
608  gbLayout->addWidget( mypLabel, index, 0 );
609  gbLayout->addWidget( editor, index, 1 );
610  }
611  }
612 
613  ++index;
614  }
615  gbLayout->addItem( new QSpacerItem( 0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding ), index , 0 );
616 
617  labelText = QString::null;
618  labelOnTop = true;
619  break;
620  }
621 
622  default:
623  QgsDebugMsg( "Unknown attribute editor widget type encountered..." );
624  break;
625  }
626 
627  return newWidget;
628 }
629 
631 {
632  Q_FOREACH( QgsWidgetWrapper* ww, mWidgets )
633  {
634  QgsEditorWidgetWrapper* meww = qobject_cast<QgsEditorWidgetWrapper*>( ww );
635  if ( meww )
636  {
637  if ( meww->field() == eww->field() )
638  {
639  connect( meww, SIGNAL( valueChanged( QVariant ) ), eww, SLOT( setValue( QVariant ) ) );
640  connect( eww, SIGNAL( valueChanged( QVariant ) ), meww, SLOT( setValue( QVariant ) ) );
641  break;
642  }
643  }
644  }
645 
646  mWidgets.append( eww );
647 }
648 
650 {
651  QList<QWidget*> myWidgets = findChildren<QWidget*>();
652  const QList<QgsField> fields = mLayer->pendingFields().toList();
653 
654  Q_FOREACH( QWidget* myWidget, myWidgets )
655  {
656  // Check the widget's properties for a relation definition
657  QVariant vRel = myWidget->property( "qgisRelation" );
658  if ( vRel.isValid() )
659  {
661  QgsRelation relation = relMgr->relation( vRel.toString() );
662  if ( relation.isValid() )
663  {
664  QgsRelationWidgetWrapper* rww = new QgsRelationWidgetWrapper( mLayer, relation, myWidget, this );
666  rww->setContext( mContext );
667  mWidgets.append( rww );
668  }
669  }
670  else
671  {
672  Q_FOREACH( const QgsField& field, fields )
673  {
674  if ( field.name() == myWidget->objectName() )
675  {
676  const QString widgetType = mLayer->editorWidgetV2( field.name() );
677  const QgsEditorWidgetConfig widgetConfig = mLayer->editorWidgetV2Config( field.name() );
678  int idx = mLayer->fieldNameIndex( field.name() );
679 
680  QgsEditorWidgetWrapper* eww = QgsEditorWidgetRegistry::instance()->create( widgetType, mLayer, idx, widgetConfig, myWidget, this, mContext );
681  addWidgetWrapper( eww );
682  }
683  }
684  }
685  }
686 }
687 
689 {
690  bool isFirstEww = true;
691 
692  Q_FOREACH( QgsWidgetWrapper* ww, mWidgets )
693  {
694  QgsEditorWidgetWrapper* eww = qobject_cast<QgsEditorWidgetWrapper*>( ww );
695 
696  if ( eww )
697  {
698  if ( isFirstEww )
699  {
700  setFocusProxy( eww->widget() );
701  isFirstEww = false;
702  }
703 
704  connect( eww, SIGNAL( valueChanged( const QVariant& ) ), this, SLOT( onAttributeChanged( const QVariant& ) ) );
705  }
706  }
707 }
708 
709 
710 bool QgsAttributeForm::eventFilter( QObject* object, QEvent* e )
711 {
712  Q_UNUSED( object )
713 
714  if ( e->type() == QEvent::KeyPress )
715  {
716  QKeyEvent* keyEvent = dynamic_cast<QKeyEvent*>( e );
717  if ( keyEvent->key() == Qt::Key_Escape )
718  {
719  // Re-emit to this form so it will be forwarded to parent
720  event( e );
721  return true;
722  }
723  }
724 
725  return false;
726 }
QList< QgsField > toList() const
Utility function to return a list of QgsField instances.
Definition: qgsfield.cpp:178
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.
virtual void setEnabled(bool enabled)
Is used to enable or disable the edit functionality of the managed widget.
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.
Manages an editor widget Widget and wrapper share the same parent.
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.
virtual QVariant value()=0
Will be used to access the widget's value.
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
QgsField field()
Access the field.
static QgsEditorWidgetRegistry * instance()
This class is a singleton and has therefore to be accessed with this method instead of a constructor...
QgsVectorLayer * layer()
Returns the layer for which this form is shown.
virtual void setFeature(const QgsFeature &feature)=0
Is called, when the value of the widget needs to be changed.
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 setContext(const QgsAttributeEditorContext &context)
Set the context in which this widget is shown.
void showButtonBox()
Shows the button box (Ok/Cancel) and disables auto-commit.
void setConfig(const QgsEditorWidgetConfig &config)
Will set the config of this wrapper to the specified config.
QgsVectorLayer * mLayer
void addWidgetWrapper(QgsEditorWidgetWrapper *eww)
QgsEditorWidgetWrapper * create(const QString &widgetId, QgsVectorLayer *vl, int fieldIdx, const QgsEditorWidgetConfig &config, QWidget *editor, QWidget *parent, const QgsAttributeEditorContext context=QgsAttributeEditorContext())
Create an attribute editor widget wrapper of a given type for a given field.
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
virtual void setValue(const QVariant &value)=0
Is called, when the value of the widget needs to be changed.
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:33
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.
int fieldIdx()
Access the field index.
const QgsFeature & feature()
bool mIsSaving
Set to true while saving to prevent recursive saves.
QWidget * widget()
Access the widget managed by this wrapper.
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
Manages an editor widget Widget and wrapper share the same parent.
bool isNull(const QVariant &v)
#define tr(sourceText)