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  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 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 
370  QScrollArea* scrollArea = new QScrollArea( this );
371  scrollArea->setWidget( formWidget );
372  scrollArea->setWidgetResizable( true );
373  scrollArea->setFrameShape( QFrame::NoFrame );
374  scrollArea->setFrameShadow( QFrame::Plain );
375  scrollArea->setFocusProxy( this );
376  layout()->addWidget( scrollArea );
377 
378  int row = 0;
379  Q_FOREACH( const QgsField& field, mLayer->pendingFields().toList() )
380  {
381  int idx = mLayer->fieldNameIndex( field.name() );
382  //show attribute alias if available
383  QString fieldName = mLayer->attributeDisplayName( idx );
384 
385  const QString widgetType = mLayer->editorWidgetV2( idx );
386 
387  if ( widgetType == "Hidden" )
388  continue;
389 
390  const QgsEditorWidgetConfig widgetConfig = mLayer->editorWidgetV2Config( idx );
391  bool labelOnTop = mLayer->labelOnTop( idx );
392 
393  // This will also create the widget
394  QWidget *l = new QLabel( fieldName );
395  QgsEditorWidgetWrapper* eww = QgsEditorWidgetRegistry::instance()->create( widgetType, mLayer, idx, widgetConfig, 0, this, mContext );
396  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 ) );
397 
398  if ( w )
399  w->setObjectName( field.name() );
400 
401  if ( eww )
402  addWidgetWrapper( eww );
403 
404  if ( labelOnTop )
405  {
406  gridLayout->addWidget( l, row++, 0, 1, 2 );
407  gridLayout->addWidget( w, row++, 0, 1, 2 );
408  }
409  else
410  {
411  gridLayout->addWidget( l, row, 0 );
412  gridLayout->addWidget( w, row++, 1 );
413  }
414  }
415 
416  Q_FOREACH( const QgsRelation& rel, QgsProject::instance()->relationManager()->referencedRelations( mLayer ) )
417  {
418  QgsRelationWidgetWrapper* rww = new QgsRelationWidgetWrapper( mLayer, rel, 0, this );
419  rww->setContext( mContext );
420  gridLayout->addWidget( rww->widget(), row++, 0, 1, 2 );
421  mWidgets.append( rww );
422  }
423  }
424 
425  mButtonBox = findChild<QDialogButtonBox*>();
426 
427  if ( !mButtonBox )
428  {
429  mButtonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
430  mButtonBox->setObjectName( "buttonBox" );
431  layout()->addWidget( mButtonBox );
432  }
433 
434  connectWrappers();
435 
436  connect( mButtonBox, SIGNAL( accepted() ), this, SLOT( accept() ) );
437  connect( mButtonBox, SIGNAL( rejected() ), this, SLOT( resetValues() ) );
438 
439  connect( mLayer, SIGNAL( editingStarted() ), this, SLOT( synchronizeEnabledState() ) );
440  connect( mLayer, SIGNAL( editingStopped() ), this, SLOT( synchronizeEnabledState() ) );
441 
442  Q_FOREACH( QgsAttributeFormInterface* iface, mInterfaces )
443  {
444  iface->initForm();
445  }
446 }
447 
449 {
450  if ( !mPyFormVarName.isNull() )
451  {
452  QString expr = QString( "if locals().has_key('%1'): del %1\n" ).arg( mPyFormVarName );
453  QgsPythonRunner::run( expr );
454  }
455 }
456 
458 {
459  cleanPython();
460 
461  // Init Python
462  if ( !mLayer->editFormInit().isEmpty() )
463  {
464  QString module = mLayer->editFormInit();
465 
466  int pos = module.lastIndexOf( "." );
467  if ( pos >= 0 )
468  {
469  QgsPythonRunner::run( QString( "import %1" ).arg( module.left( pos ) ) );
470  }
471 
472  /* Reload the module if the DEBUGMODE switch has been set in the module.
473  If set to False you have to reload QGIS to reset it to True due to Python
474  module caching */
475  QString reload = QString( "if hasattr(%1,'DEBUGMODE') and %1.DEBUGMODE:"
476  " reload(%1)" ).arg( module.left( pos ) );
477 
478  QgsPythonRunner::run( reload );
479 
480  QgsPythonRunner::run( "import inspect" );
481  QString numArgs;
482  QgsPythonRunner::eval( QString( "len(inspect.getargspec(%1)[0])" ).arg( module ), numArgs );
483 
484  mPyFormVarName = QString( "_qgis_featureform_%1" ).arg( mFormNr );
485 
486  QString form = QString( "%1 = sip.wrapinstance( %2, qgis.gui.QgsAttributeForm )" )
487  .arg( mPyFormVarName )
488  .arg(( unsigned long ) this );
489 
490  QgsPythonRunner::run( form );
491 
492  QgsDebugMsg( QString( "running featureForm init: %1" ).arg( mPyFormVarName ) );
493 
494  // Legacy
495  if ( numArgs == "3" )
496  {
498  }
499  else
500  {
501 #if 0
502  QString expr = QString( "%1(%2)" )
503  .arg( mLayer->editFormInit() )
504  .arg( mPyFormVarName );
505  QgsAttributeFormInterface* iface = QgsPythonRunner::evalToSipObject<QgsAttributeFormInterface*>( expr, "QgsAttributeFormInterface" );
506  if ( iface )
507  addInterface( iface );
508 #endif
509  }
510  }
511 }
512 
513 QWidget* QgsAttributeForm::createWidgetFromDef( const QgsAttributeEditorElement *widgetDef, QWidget *parent, QgsVectorLayer *vl, QgsAttributeEditorContext &context, QString &labelText, bool &labelOnTop )
514 {
515  QWidget *newWidget = 0;
516 
517  switch ( widgetDef->type() )
518  {
520  {
521  const QgsAttributeEditorField* fieldDef = dynamic_cast<const QgsAttributeEditorField*>( widgetDef );
522  int fldIdx = fieldDef->idx();
523  if ( fldIdx < vl->pendingFields().count() && fldIdx >= 0 )
524  {
525  const QString widgetType = mLayer->editorWidgetV2( fldIdx );
526  const QgsEditorWidgetConfig widgetConfig = mLayer->editorWidgetV2Config( fldIdx );
527 
528  QgsEditorWidgetWrapper* eww = QgsEditorWidgetRegistry::instance()->create( widgetType, mLayer, fldIdx, widgetConfig, 0, this, mContext );
529  newWidget = eww->widget();
530  addWidgetWrapper( eww );
531 
532  newWidget->setObjectName( mLayer->pendingFields()[ fldIdx ].name() );
533  }
534 
535  labelOnTop = mLayer->labelOnTop( fieldDef->idx() );
536  labelText = mLayer->attributeDisplayName( fieldDef->idx() );
537 
538  break;
539  }
540 
542  {
543  const QgsAttributeEditorRelation* relDef = dynamic_cast<const QgsAttributeEditorRelation*>( widgetDef );
544 
545  QgsRelationWidgetWrapper* rww = new QgsRelationWidgetWrapper( mLayer, relDef->relation(), 0, this );
546  rww->setContext( context );
547  newWidget = rww->widget();
548  mWidgets.append( rww );
549  labelText = QString::null;
550  labelOnTop = true;
551  break;
552  }
553 
555  {
556  const QgsAttributeEditorContainer* container = dynamic_cast<const QgsAttributeEditorContainer*>( widgetDef );
557  QWidget* myContainer;
558 
559  if ( container->isGroupBox() )
560  {
561  QGroupBox* groupBox = new QGroupBox( parent );
562  groupBox->setTitle( container->name() );
563  myContainer = groupBox;
564  newWidget = myContainer;
565  }
566  else
567  {
568  QScrollArea *scrollArea = new QScrollArea( parent );
569 
570  myContainer = new QWidget( scrollArea );
571 
572  scrollArea->setWidget( myContainer );
573  scrollArea->setWidgetResizable( true );
574  scrollArea->setFrameShape( QFrame::NoFrame );
575 
576  newWidget = scrollArea;
577  }
578 
579  QGridLayout* gbLayout = new QGridLayout( myContainer );
580  myContainer->setLayout( gbLayout );
581 
582  int index = 0;
583 
584  QList<QgsAttributeEditorElement*> children = container->children();
585 
586  Q_FOREACH( QgsAttributeEditorElement* childDef, children )
587  {
588  QString labelText;
589  bool labelOnTop;
590  QWidget* editor = createWidgetFromDef( childDef, myContainer, vl, context, labelText, labelOnTop );
591 
592  if ( labelText.isNull() )
593  {
594  gbLayout->addWidget( editor, index, 0, 1, 2 );
595  }
596  else
597  {
598  QLabel* mypLabel = new QLabel( labelText );
599  if ( labelOnTop )
600  {
601  gbLayout->addWidget( mypLabel, index, 0, 1, 2 );
602  ++index;
603  gbLayout->addWidget( editor, index, 0, 1 , 2 );
604  }
605  else
606  {
607  gbLayout->addWidget( mypLabel, index, 0 );
608  gbLayout->addWidget( editor, index, 1 );
609  }
610  }
611 
612  ++index;
613  }
614  gbLayout->addItem( new QSpacerItem( 0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding ), index , 0 );
615 
616  labelText = QString::null;
617  labelOnTop = true;
618  break;
619  }
620 
621  default:
622  QgsDebugMsg( "Unknown attribute editor widget type encountered..." );
623  break;
624  }
625 
626  return newWidget;
627 }
628 
630 {
631  Q_FOREACH( QgsWidgetWrapper* ww, mWidgets )
632  {
633  QgsEditorWidgetWrapper* meww = qobject_cast<QgsEditorWidgetWrapper*>( ww );
634  if ( meww )
635  {
636  if ( meww->field() == eww->field() )
637  {
638  connect( meww, SIGNAL( valueChanged( QVariant ) ), eww, SLOT( setValue( QVariant ) ) );
639  connect( eww, SIGNAL( valueChanged( QVariant ) ), meww, SLOT( setValue( QVariant ) ) );
640  break;
641  }
642  }
643  }
644 
645  mWidgets.append( eww );
646 }
647 
649 {
650  QList<QWidget*> myWidgets = findChildren<QWidget*>();
651  const QList<QgsField> fields = mLayer->pendingFields().toList();
652 
653  Q_FOREACH( QWidget* myWidget, myWidgets )
654  {
655  // Check the widget's properties for a relation definition
656  QVariant vRel = myWidget->property( "qgisRelation" );
657  if ( vRel.isValid() )
658  {
660  QgsRelation relation = relMgr->relation( vRel.toString() );
661  if ( relation.isValid() )
662  {
663  QgsRelationWidgetWrapper* rww = new QgsRelationWidgetWrapper( mLayer, relation, myWidget, this );
665  rww->setContext( mContext );
666  mWidgets.append( rww );
667  }
668  }
669  else
670  {
671  Q_FOREACH( const QgsField& field, fields )
672  {
673  if ( field.name() == myWidget->objectName() )
674  {
675  const QString widgetType = mLayer->editorWidgetV2( field.name() );
676  const QgsEditorWidgetConfig widgetConfig = mLayer->editorWidgetV2Config( field.name() );
677  int idx = mLayer->fieldNameIndex( field.name() );
678 
679  QgsEditorWidgetWrapper* eww = QgsEditorWidgetRegistry::instance()->create( widgetType, mLayer, idx, widgetConfig, myWidget, this, mContext );
680  addWidgetWrapper( eww );
681  }
682  }
683  }
684  }
685 }
686 
688 {
689  bool isFirstEww = true;
690 
691  Q_FOREACH( QgsWidgetWrapper* ww, mWidgets )
692  {
693  QgsEditorWidgetWrapper* eww = qobject_cast<QgsEditorWidgetWrapper*>( ww );
694 
695  if ( eww )
696  {
697  if ( isFirstEww )
698  {
699  setFocusProxy( eww->widget() );
700  isFirstEww = false;
701  }
702 
703  connect( eww, SIGNAL( valueChanged( const QVariant& ) ), this, SLOT( onAttributeChanged( const QVariant& ) ) );
704  }
705  }
706 }
707 
708 
709 bool QgsAttributeForm::eventFilter( QObject* object, QEvent* e )
710 {
711  Q_UNUSED( object )
712 
713  if ( e->type() == QEvent::KeyPress )
714  {
715  QKeyEvent* keyEvent = dynamic_cast<QKeyEvent*>( e );
716  if ( keyEvent->key() == Qt::Key_Escape )
717  {
718  // Re-emit to this form so it will be forwarded to parent
719  event( e );
720  return true;
721  }
722  }
723 
724  return false;
725 }
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)