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  if ( !mIsAddDialog )
69  connect( mLayer, SIGNAL( beforeModifiedCheck() ), this, SLOT( save() ) );
70 }
71 
73 {
74  mButtonBox->show();
75 
76  disconnect( mLayer, SIGNAL( beforeModifiedCheck() ), this, SLOT( save() ) );
77 }
78 
80 {
81  disconnect( mButtonBox, SIGNAL( accepted() ), this, SLOT( accept() ) );
82  disconnect( mButtonBox, SIGNAL( rejected() ), this, SLOT( resetValues() ) );
83 }
84 
86 {
87  mInterfaces.append( iface );
88 }
89 
91 {
92  return mFeature.isValid() && mLayer->isEditable() ;
93 }
94 
95 void QgsAttributeForm::setIsAddDialog( bool isAddDialog )
96 {
97  mIsAddDialog = isAddDialog;
98 
100 }
101 
102 void QgsAttributeForm::changeAttribute( const QString& field, const QVariant& value )
103 {
104  Q_FOREACH ( QgsWidgetWrapper* ww, mWidgets )
105  {
106  QgsEditorWidgetWrapper* eww = qobject_cast<QgsEditorWidgetWrapper*>( ww );
107  if ( eww && eww->field().name() == field )
108  {
109  eww->setValue( value );
110  }
111  }
112 }
113 
115 {
116  mFeature = feature;
117 
118  resetValues();
119 
121 
122  Q_FOREACH ( QgsAttributeFormInterface* iface, mInterfaces )
123  {
124  iface->featureChanged();
125  }
126 }
127 
129 {
130  if ( mIsSaving )
131  return true;
132 
133  mIsSaving = true;
134 
135  bool success = true;
136 
137  emit beforeSave( success );
138 
139  // Somebody wants to prevent this form from saving
140  if ( !success )
141  return false;
142 
143  QgsFeature updatedFeature = QgsFeature( mFeature );
144 
145  if ( mFeature.isValid() || mIsAddDialog )
146  {
147  bool doUpdate = false;
148 
149  // An add dialog should perform an action by default
150  // and not only if attributes have "changed"
151  if ( mIsAddDialog )
152  doUpdate = true;
153 
156 
157  Q_FOREACH ( QgsWidgetWrapper* ww, mWidgets )
158  {
159  QgsEditorWidgetWrapper* eww = qobject_cast<QgsEditorWidgetWrapper*>( ww );
160  if ( eww )
161  {
162  QVariant dstVar = dst[eww->fieldIdx()];
163  QVariant srcVar = eww->value();
164  // need to check dstVar.isNull() != srcVar.isNull()
165  // otherwise if dstVar=NULL and scrVar=0, then dstVar = srcVar
166  if (( dstVar != srcVar || dstVar.isNull() != srcVar.isNull() ) && srcVar.isValid() )
167  {
168  dst[eww->fieldIdx()] = srcVar;
169 
170  doUpdate = true;
171  }
172  }
173  }
174 
175  updatedFeature.setAttributes( dst );
176 
177  Q_FOREACH ( QgsAttributeFormInterface* iface, mInterfaces )
178  {
179  if ( !iface->acceptChanges( updatedFeature ) )
180  {
181  doUpdate = false;
182  }
183  }
184 
185  if ( doUpdate )
186  {
187  if ( mIsAddDialog )
188  {
189  mFeature.setValid( true );
191  bool res = mLayer->addFeature( updatedFeature );
192  if ( res )
193  {
194  mFeature.setAttributes( updatedFeature.attributes() );
196  }
197  else
199  }
200  else
201  {
203 
204  int n = 0;
205  for ( int i = 0; i < dst.count(); ++i )
206  {
207  if (( dst[i] == src[i] && dst[i].isNull() == src[i].isNull() ) || !dst[i].isValid() )
208  {
209  QgsDebugMsg( "equal or invalid destination" );
210  QgsDebugMsg( QString( "dst:'%1' (type:%2,isNull:%3,isValid:%4)" )
211  .arg( dst[i].toString() ).arg( dst[i].typeName() ).arg( dst[i].isNull() ).arg( dst[i].isValid() ) );
212  QgsDebugMsg( QString( "src:'%1' (type:%2,isNull:%3,isValid:%4)" )
213  .arg( src[i].toString() ).arg( src[i].typeName() ).arg( src[i].isNull() ).arg( src[i].isValid() ) );
214  continue;
215  }
216 
217  success &= mLayer->changeAttributeValue( mFeature.id(), i, dst[i], src[i] );
218  n++;
219  }
220 
221  if ( success && n > 0 )
222  {
224  mFeature.setAttributes( dst );
225  }
226  else
227  {
229  }
230  }
231  }
232  }
233 
234  emit featureSaved( updatedFeature );
235 
237 
238  mIsSaving = false;
239 
240  return success;
241 }
242 
244 {
245  Q_FOREACH ( QgsWidgetWrapper* ww, mWidgets )
246  {
247  ww->setFeature( mFeature );
248  }
249 }
250 
251 void QgsAttributeForm::onAttributeChanged( const QVariant& value )
252 {
253  QgsEditorWidgetWrapper* eww = qobject_cast<QgsEditorWidgetWrapper*>( sender() );
254 
255  Q_ASSERT( eww );
256 
257  emit attributeChanged( eww->field().name(), value );
258 }
259 
261 {
262  Q_UNUSED( idx ) // only used for Q_ASSERT
263  if ( mFeature.isValid() )
264  {
266  Q_ASSERT( attrs.size() == idx );
267  attrs.append( QVariant() );
268  mFeature.setFields( &layer()->pendingFields() );
269  mFeature.setAttributes( attrs );
270  }
271  init();
272  setFeature( mFeature );
273 }
274 
276 {
277  if ( mFeature.isValid() )
278  {
280  attrs.remove( idx );
281  mFeature.setFields( &layer()->pendingFields() );
282  mFeature.setAttributes( attrs );
283  }
284  init();
285  setFeature( mFeature );
286 }
287 
289 {
290  bool isEditable = ( mFeature.isValid() || mIsAddDialog ) && mLayer->isEditable();
291 
292  Q_FOREACH ( QgsWidgetWrapper* ww, mWidgets )
293  {
294  bool fieldEditable = true;
295  QgsEditorWidgetWrapper* eww = qobject_cast<QgsEditorWidgetWrapper*>( ww );
296  if ( eww )
297  {
298  fieldEditable = mLayer->fieldEditable( eww->fieldIdx() );
299  }
300  ww->setEnabled( isEditable && fieldEditable );
301  }
302 
303  QPushButton* okButton = mButtonBox->button( QDialogButtonBox::Ok );
304  if ( okButton )
305  okButton->setEnabled( isEditable );
306 }
307 
309 {
310  QWidget* formWidget = 0;
311 
312  qDeleteAll( mWidgets );
313  mWidgets.clear();
314 
315  while ( QWidget* w = this->findChild<QWidget*>() )
316  {
317  delete w;
318  }
319  delete layout();
320 
321  // Get a layout
322  setLayout( new QGridLayout( this ) );
323 
324  // Try to load Ui-File for layout
325  if ( mLayer->editorLayout() == QgsVectorLayer::UiFileLayout && !mLayer->editForm().isEmpty() )
326  {
327  QFile file( mLayer->editForm() );
328 
329  if ( file.open( QFile::ReadOnly ) )
330  {
331  QUiLoader loader;
332 
333  QFileInfo fi( mLayer->editForm() );
334  loader.setWorkingDirectory( fi.dir() );
335  formWidget = loader.load( &file, this );
336  formWidget->setWindowFlags( Qt::Widget );
337  layout()->addWidget( formWidget );
338  formWidget->show();
339  file.close();
340  createWrappers();
341 
342  formWidget->installEventFilter( this );
343  }
344  }
345 
346  // Tab layout
347  if ( !formWidget && mLayer->editorLayout() == QgsVectorLayer::TabLayout )
348  {
349  QTabWidget* tabWidget = new QTabWidget( this );
350  layout()->addWidget( tabWidget );
351 
352  Q_FOREACH ( QgsAttributeEditorElement *widgDef, mLayer->attributeEditorElements() )
353  {
354  QWidget* tabPage = new QWidget( tabWidget );
355 
356  tabWidget->addTab( tabPage, widgDef->name() );
357  QGridLayout *tabPageLayout = new QGridLayout( tabPage );
358 
360  {
361  QgsAttributeEditorContainer* containerDef = dynamic_cast<QgsAttributeEditorContainer*>( widgDef );
362  containerDef->setIsGroupBox( false ); // Toplevel widgets are tabs not groupboxes
363  QString dummy1;
364  bool dummy2;
365  tabPageLayout->addWidget( createWidgetFromDef( widgDef, tabPage, mLayer, mContext, dummy1, dummy2 ) );
366  }
367  else
368  {
369  QgsDebugMsg( "No support for fields in attribute editor on top level" );
370  }
371  }
372  formWidget = tabWidget;
373  }
374 
375  // Autogenerate Layout
376  // If there is still no layout loaded (defined as autogenerate or other methods failed)
377  if ( !formWidget )
378  {
379  formWidget = new QWidget( this );
380  QGridLayout* gridLayout = new QGridLayout( formWidget );
381  formWidget->setLayout( gridLayout );
382 
383  // put the form into a scroll area to nicely handle cases with lots of attributes
384 
385  QScrollArea* scrollArea = new QScrollArea( this );
386  scrollArea->setWidget( formWidget );
387  scrollArea->setWidgetResizable( true );
388  scrollArea->setFrameShape( QFrame::NoFrame );
389  scrollArea->setFrameShadow( QFrame::Plain );
390  scrollArea->setFocusProxy( this );
391  layout()->addWidget( scrollArea );
392 
393  int row = 0;
394  Q_FOREACH ( const QgsField& field, mLayer->pendingFields().toList() )
395  {
396  int idx = mLayer->fieldNameIndex( field.name() );
397  //show attribute alias if available
398  QString fieldName = mLayer->attributeDisplayName( idx );
399 
400  const QString widgetType = mLayer->editorWidgetV2( idx );
401 
402  if ( widgetType == "Hidden" )
403  continue;
404 
405  const QgsEditorWidgetConfig widgetConfig = mLayer->editorWidgetV2Config( idx );
406  bool labelOnTop = mLayer->labelOnTop( idx );
407 
408  // This will also create the widget
409  QWidget *l = new QLabel( fieldName );
410  QgsEditorWidgetWrapper* eww = QgsEditorWidgetRegistry::instance()->create( widgetType, mLayer, idx, widgetConfig, 0, this, mContext );
411  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 ) );
412 
413  if ( w )
414  w->setObjectName( field.name() );
415 
416  if ( eww )
417  addWidgetWrapper( eww );
418 
419  if ( labelOnTop )
420  {
421  gridLayout->addWidget( l, row++, 0, 1, 2 );
422  gridLayout->addWidget( w, row++, 0, 1, 2 );
423  }
424  else
425  {
426  gridLayout->addWidget( l, row, 0 );
427  gridLayout->addWidget( w, row++, 1 );
428  }
429  }
430 
431  Q_FOREACH ( const QgsRelation& rel, QgsProject::instance()->relationManager()->referencedRelations( mLayer ) )
432  {
433  QgsRelationWidgetWrapper* rww = new QgsRelationWidgetWrapper( mLayer, rel, 0, this );
434  rww->setContext( mContext );
435  gridLayout->addWidget( rww->widget(), row++, 0, 1, 2 );
436  mWidgets.append( rww );
437  }
438  }
439 
440  mButtonBox = findChild<QDialogButtonBox*>();
441 
442  if ( !mButtonBox )
443  {
444  mButtonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
445  mButtonBox->setObjectName( "buttonBox" );
446  layout()->addWidget( mButtonBox );
447  }
448 
449  connectWrappers();
450 
451  connect( mButtonBox, SIGNAL( accepted() ), this, SLOT( accept() ) );
452  connect( mButtonBox, SIGNAL( rejected() ), this, SLOT( resetValues() ) );
453 
454  connect( mLayer, SIGNAL( editingStarted() ), this, SLOT( synchronizeEnabledState() ) );
455  connect( mLayer, SIGNAL( editingStopped() ), this, SLOT( synchronizeEnabledState() ) );
456 
457  Q_FOREACH ( QgsAttributeFormInterface* iface, mInterfaces )
458  {
459  iface->initForm();
460  }
461 }
462 
464 {
465  if ( !mPyFormVarName.isNull() )
466  {
467  QString expr = QString( "if locals().has_key('%1'): del %1\n" ).arg( mPyFormVarName );
468  QgsPythonRunner::run( expr );
469  }
470 }
471 
473 {
474  cleanPython();
475 
476  // Init Python
477  if ( !mLayer->editFormInit().isEmpty() )
478  {
479  QString module = mLayer->editFormInit();
480 
481  int pos = module.lastIndexOf( "." );
482  if ( pos >= 0 )
483  {
484  QgsPythonRunner::run( QString( "import %1" ).arg( module.left( pos ) ) );
485  }
486 
487  /* Reload the module if the DEBUGMODE switch has been set in the module.
488  If set to False you have to reload QGIS to reset it to True due to Python
489  module caching */
490  QString reload = QString( "if hasattr(%1,'DEBUGMODE') and %1.DEBUGMODE:"
491  " reload(%1)" ).arg( module.left( pos ) );
492 
493  QgsPythonRunner::run( reload );
494 
495  QgsPythonRunner::run( "import inspect" );
496  QString numArgs;
497  QgsPythonRunner::eval( QString( "len(inspect.getargspec(%1)[0])" ).arg( module ), numArgs );
498 
499  mPyFormVarName = QString( "_qgis_featureform_%1" ).arg( mFormNr );
500 
501  QString form = QString( "%1 = sip.wrapinstance( %2, qgis.gui.QgsAttributeForm )" )
502  .arg( mPyFormVarName )
503  .arg(( unsigned long ) this );
504 
505  QgsPythonRunner::run( form );
506 
507  QgsDebugMsg( QString( "running featureForm init: %1" ).arg( mPyFormVarName ) );
508 
509  // Legacy
510  if ( numArgs == "3" )
511  {
513  }
514  else
515  {
516 #if 0
517  QString expr = QString( "%1(%2)" )
518  .arg( mLayer->editFormInit() )
519  .arg( mPyFormVarName );
520  QgsAttributeFormInterface* iface = QgsPythonRunner::evalToSipObject<QgsAttributeFormInterface*>( expr, "QgsAttributeFormInterface" );
521  if ( iface )
522  addInterface( iface );
523 #endif
524  }
525  }
526 }
527 
528 QWidget* QgsAttributeForm::createWidgetFromDef( const QgsAttributeEditorElement *widgetDef, QWidget *parent, QgsVectorLayer *vl, QgsAttributeEditorContext &context, QString &labelText, bool &labelOnTop )
529 {
530  QWidget *newWidget = 0;
531 
532  switch ( widgetDef->type() )
533  {
535  {
536  const QgsAttributeEditorField* fieldDef = dynamic_cast<const QgsAttributeEditorField*>( widgetDef );
537  int fldIdx = fieldDef->idx();
538  if ( fldIdx < vl->pendingFields().count() && fldIdx >= 0 )
539  {
540  const QString widgetType = mLayer->editorWidgetV2( fldIdx );
541  const QgsEditorWidgetConfig widgetConfig = mLayer->editorWidgetV2Config( fldIdx );
542 
543  QgsEditorWidgetWrapper* eww = QgsEditorWidgetRegistry::instance()->create( widgetType, mLayer, fldIdx, widgetConfig, 0, this, mContext );
544  newWidget = eww->widget();
545  addWidgetWrapper( eww );
546 
547  newWidget->setObjectName( mLayer->pendingFields()[ fldIdx ].name() );
548  }
549 
550  labelOnTop = mLayer->labelOnTop( fieldDef->idx() );
551  labelText = mLayer->attributeDisplayName( fieldDef->idx() );
552 
553  break;
554  }
555 
557  {
558  const QgsAttributeEditorRelation* relDef = dynamic_cast<const QgsAttributeEditorRelation*>( widgetDef );
559 
560  QgsRelationWidgetWrapper* rww = new QgsRelationWidgetWrapper( mLayer, relDef->relation(), 0, this );
561  rww->setContext( context );
562  newWidget = rww->widget();
563  mWidgets.append( rww );
564  labelText = QString::null;
565  labelOnTop = true;
566  break;
567  }
568 
570  {
571  const QgsAttributeEditorContainer* container = dynamic_cast<const QgsAttributeEditorContainer*>( widgetDef );
572  QWidget* myContainer;
573 
574  if ( container->isGroupBox() )
575  {
576  QGroupBox* groupBox = new QGroupBox( parent );
577  groupBox->setTitle( container->name() );
578  myContainer = groupBox;
579  newWidget = myContainer;
580  }
581  else
582  {
583  QScrollArea *scrollArea = new QScrollArea( parent );
584 
585  myContainer = new QWidget( scrollArea );
586 
587  scrollArea->setWidget( myContainer );
588  scrollArea->setWidgetResizable( true );
589  scrollArea->setFrameShape( QFrame::NoFrame );
590 
591  newWidget = scrollArea;
592  }
593 
594  QGridLayout* gbLayout = new QGridLayout( myContainer );
595  myContainer->setLayout( gbLayout );
596 
597  int index = 0;
598 
599  QList<QgsAttributeEditorElement*> children = container->children();
600 
601  Q_FOREACH ( QgsAttributeEditorElement* childDef, children )
602  {
603  QString labelText;
604  bool labelOnTop;
605  QWidget* editor = createWidgetFromDef( childDef, myContainer, vl, context, labelText, labelOnTop );
606 
607  if ( labelText.isNull() )
608  {
609  gbLayout->addWidget( editor, index, 0, 1, 2 );
610  }
611  else
612  {
613  QLabel* mypLabel = new QLabel( labelText );
614  if ( labelOnTop )
615  {
616  gbLayout->addWidget( mypLabel, index, 0, 1, 2 );
617  ++index;
618  gbLayout->addWidget( editor, index, 0, 1 , 2 );
619  }
620  else
621  {
622  gbLayout->addWidget( mypLabel, index, 0 );
623  gbLayout->addWidget( editor, index, 1 );
624  }
625  }
626 
627  ++index;
628  }
629  gbLayout->addItem( new QSpacerItem( 0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding ), index , 0 );
630 
631  labelText = QString::null;
632  labelOnTop = true;
633  break;
634  }
635 
636  default:
637  QgsDebugMsg( "Unknown attribute editor widget type encountered..." );
638  break;
639  }
640 
641  return newWidget;
642 }
643 
645 {
646  Q_FOREACH ( QgsWidgetWrapper* ww, mWidgets )
647  {
648  QgsEditorWidgetWrapper* meww = qobject_cast<QgsEditorWidgetWrapper*>( ww );
649  if ( meww )
650  {
651  if ( meww->field() == eww->field() )
652  {
653  connect( meww, SIGNAL( valueChanged( QVariant ) ), eww, SLOT( setValue( QVariant ) ) );
654  connect( eww, SIGNAL( valueChanged( QVariant ) ), meww, SLOT( setValue( QVariant ) ) );
655  break;
656  }
657  }
658  }
659 
660  mWidgets.append( eww );
661 }
662 
664 {
665  QList<QWidget*> myWidgets = findChildren<QWidget*>();
666  const QList<QgsField> fields = mLayer->pendingFields().toList();
667 
668  Q_FOREACH ( QWidget* myWidget, myWidgets )
669  {
670  // Check the widget's properties for a relation definition
671  QVariant vRel = myWidget->property( "qgisRelation" );
672  if ( vRel.isValid() )
673  {
675  QgsRelation relation = relMgr->relation( vRel.toString() );
676  if ( relation.isValid() )
677  {
678  QgsRelationWidgetWrapper* rww = new QgsRelationWidgetWrapper( mLayer, relation, myWidget, this );
680  rww->setContext( mContext );
681  mWidgets.append( rww );
682  }
683  }
684  else
685  {
686  Q_FOREACH ( const QgsField& field, fields )
687  {
688  if ( field.name() == myWidget->objectName() )
689  {
690  const QString widgetType = mLayer->editorWidgetV2( field.name() );
691  const QgsEditorWidgetConfig widgetConfig = mLayer->editorWidgetV2Config( field.name() );
692  int idx = mLayer->fieldNameIndex( field.name() );
693 
694  QgsEditorWidgetWrapper* eww = QgsEditorWidgetRegistry::instance()->create( widgetType, mLayer, idx, widgetConfig, myWidget, this, mContext );
695  addWidgetWrapper( eww );
696  }
697  }
698  }
699  }
700 }
701 
703 {
704  bool isFirstEww = true;
705 
706  Q_FOREACH ( QgsWidgetWrapper* ww, mWidgets )
707  {
708  QgsEditorWidgetWrapper* eww = qobject_cast<QgsEditorWidgetWrapper*>( ww );
709 
710  if ( eww )
711  {
712  if ( isFirstEww )
713  {
714  setFocusProxy( eww->widget() );
715  isFirstEww = false;
716  }
717 
718  connect( eww, SIGNAL( valueChanged( const QVariant& ) ), this, SLOT( onAttributeChanged( const QVariant& ) ) );
719  }
720  }
721 }
722 
723 
724 bool QgsAttributeForm::eventFilter( QObject* object, QEvent* e )
725 {
726  Q_UNUSED( object )
727 
728  if ( e->type() == QEvent::KeyPress )
729  {
730  QKeyEvent* keyEvent = dynamic_cast<QKeyEvent*>( e );
731  if ( keyEvent->key() == Qt::Key_Escape )
732  {
733  // Re-emit to this form so it will be forwarded to parent
734  event( e );
735  return true;
736  }
737  }
738 
739  return false;
740 }
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 disconnectButtonBox()
Disconnects the button box (Ok/Cancel) from the accept/resetValues slots If this method is called...
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)
void triggerRepaint()
Will advice the map canvas (and any other interested party) that this layer requires to be repainted...
#define tr(sourceText)