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