21 #include "qgseditorwidgetregistry.h"
24 #include "qgsrelationwidgetwrapper.h"
28 #include <QFormLayout>
29 #include <QGridLayout>
33 #include <QPushButton>
34 #include <QScrollArea>
44 , mFormNr( sFormCounter++ )
46 , mIsAddDialog( false )
47 , mEditCommandMessage(
tr(
"Attributes changed" ) )
53 connect( vl, SIGNAL( attributeAdded(
int ) ),
this, SLOT(
onAttributeAdded(
int ) ) );
54 connect( vl, SIGNAL( attributeDeleted(
int ) ),
this, SLOT(
onAttributeDeleted(
int ) ) );
68 connect(
mLayer, SIGNAL( beforeModifiedCheck() ),
this, SLOT(
save() ) );
75 disconnect(
mLayer, SIGNAL( beforeModifiedCheck() ),
this, SLOT(
save() ) );
97 Q_FOREACH( QgsWidgetWrapper* ww,
mWidgets )
99 QgsEditorWidgetWrapper* eww = qobject_cast<QgsEditorWidgetWrapper*>( ww );
100 if ( eww && eww->field().name() == field )
102 eww->setValue( value );
140 bool doUpdate =
false;
150 Q_FOREACH( QgsWidgetWrapper* ww,
mWidgets )
152 QgsEditorWidgetWrapper* eww = qobject_cast<QgsEditorWidgetWrapper*>( ww );
155 QVariant dstVar = dst[eww->fieldIdx()];
156 QVariant srcVar = eww->value();
159 if ( ( dstVar != srcVar || dstVar.isNull() != srcVar.isNull() ) && srcVar.isValid() )
161 dst[eww->fieldIdx()] = srcVar;
195 for (
int i = 0; i < dst.count(); ++i )
197 if ( ( dst[i] == src[i] && dst[i].
isNull() == src[i].
isNull() ) || !dst[i].isValid() )
200 QgsDebugMsg( QString(
"dst:'%1' (type:%2,isNull:%3,isValid:%4)" )
201 .arg( dst[i].toString() ).arg( dst[i].typeName() ).arg( dst[i].
isNull() ).arg( dst[i].isValid() ) );
202 QgsDebugMsg( QString(
"src:'%1' (type:%2,isNull:%3,isValid:%4)" )
203 .arg( src[i].toString() ).arg( src[i].typeName() ).arg( src[i].
isNull() ).arg( src[i].isValid() ) );
211 if ( success && n > 0 )
233 Q_FOREACH( QgsWidgetWrapper* ww,
mWidgets )
241 QgsEditorWidgetWrapper* eww = qobject_cast<QgsEditorWidgetWrapper*>( sender() );
253 Q_ASSERT( attrs.size() == idx );
254 attrs.append( QVariant() );
279 Q_FOREACH( QgsWidgetWrapper* ww,
mWidgets )
281 bool fieldEditable =
true;
282 QgsEditorWidgetWrapper* eww = qobject_cast<QgsEditorWidgetWrapper*>( ww );
287 ww->setEnabled( isEditable && fieldEditable );
290 QPushButton* okButton =
mButtonBox->button( QDialogButtonBox::Ok );
292 okButton->setEnabled( isEditable );
297 QWidget* formWidget = 0;
302 while ( QWidget* w = this->findChild<QWidget*>() )
306 delete this->layout();
309 setLayout(
new QGridLayout(
this ) );
316 if (
file.open( QFile::ReadOnly ) )
321 loader.setWorkingDirectory( fi.dir() );
322 formWidget = loader.load( &
file,
this );
323 formWidget->setWindowFlags( Qt::Widget );
324 layout()->addWidget( formWidget );
329 formWidget->installEventFilter(
this );
336 QTabWidget* tabWidget =
new QTabWidget(
this );
337 layout()->addWidget( tabWidget );
341 QWidget* tabPage =
new QWidget( tabWidget );
343 tabWidget->addTab( tabPage, widgDef->
name() );
344 QGridLayout *tabPageLayout =
new QGridLayout( tabPage );
356 QgsDebugMsg(
"No support for fields in attribute editor on top level" );
359 formWidget = tabWidget;
366 formWidget =
new QWidget(
this );
367 QGridLayout* gridLayout =
new QGridLayout( formWidget );
368 formWidget->setLayout( gridLayout );
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 layout()->addWidget( scrollArea );
387 if ( widgetType !=
"Hidden" )
393 QWidget *l =
new QLabel( fieldName );
394 QgsEditorWidgetWrapper* eww = QgsEditorWidgetRegistry::instance()->create( widgetType,
mLayer, idx, widgetConfig, 0,
this,
mContext );
395 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 ) );
402 gridLayout->addWidget( l, row++, 0, 1, 2 );
403 gridLayout->addWidget( w, row++, 0, 1, 2 );
407 gridLayout->addWidget( l, row, 0 );
408 gridLayout->addWidget( w, row++, 1 );
415 QgsRelationWidgetWrapper* rww =
new QgsRelationWidgetWrapper(
mLayer, rel, 0,
this );
417 gridLayout->addWidget( rww->widget(), row++, 0, 1, 2 );
426 mButtonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
449 QString expr = QString(
"if locals().has_key('%1'): del %1\n" ).arg(
mPyFormVarName );
463 int pos = module.lastIndexOf(
"." );
472 QString reload = QString(
"if hasattr(%1,'DEBUGMODE') and %1.DEBUGMODE:"
473 " reload(%1)" ).arg( module.left( pos ) );
483 QString form = QString(
"%1 = sip.wrapinstance( %2, qgis.gui.QgsAttributeForm )" )
485 .arg((
unsigned long )
this );
492 if ( numArgs ==
"3" )
499 QString expr = QString(
"%1(%2)" )
502 QgsAttributeFormInterface* iface = QgsPythonRunner::evalToSipObject<QgsAttributeFormInterface*>( expr,
"QgsAttributeFormInterface" );
512 QWidget *newWidget = 0;
514 switch ( widgetDef->
type() )
519 int fldIdx = fieldDef->
idx();
520 if ( fldIdx < vl->pendingFields().count() && fldIdx >= 0 )
525 QgsEditorWidgetWrapper* eww = QgsEditorWidgetRegistry::instance()->create( widgetType,
mLayer, fldIdx, widgetConfig, 0,
this,
mContext );
526 newWidget = eww->widget();
539 QgsRelationWidgetWrapper* rww =
new QgsRelationWidgetWrapper(
mLayer, relDef->
relation(), 0, this );
540 rww->setContext( context );
541 newWidget = rww->widget();
543 labelText = QString::null;
551 QWidget* myContainer;
555 QGroupBox* groupBox =
new QGroupBox( parent );
556 groupBox->setTitle( container->
name() );
557 myContainer = groupBox;
558 newWidget = myContainer;
562 QScrollArea *scrollArea =
new QScrollArea( parent );
564 myContainer =
new QWidget( scrollArea );
566 scrollArea->setWidget( myContainer );
567 scrollArea->setWidgetResizable(
true );
568 scrollArea->setFrameShape( QFrame::NoFrame );
570 newWidget = scrollArea;
573 QGridLayout* gbLayout =
new QGridLayout( myContainer );
574 myContainer->setLayout( gbLayout );
578 QList<QgsAttributeEditorElement*> children = container->
children();
584 QWidget* editor =
createWidgetFromDef( childDef, myContainer, vl, context, labelText, labelOnTop );
586 if ( labelText.isNull() )
588 gbLayout->addWidget( editor, index, 0, 1, 2 );
592 QLabel* mypLabel =
new QLabel( labelText );
595 gbLayout->addWidget( mypLabel, index, 0, 1, 2 );
597 gbLayout->addWidget( editor, index, 0, 1 , 2 );
601 gbLayout->addWidget( mypLabel, index, 0 );
602 gbLayout->addWidget( editor, index, 1 );
608 gbLayout->addItem(
new QSpacerItem( 0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding ), index , 0 );
610 labelText = QString::null;
616 QgsDebugMsg(
"Unknown attribute editor widget type encountered..." );
625 QList<QWidget*> myWidgets = findChildren<QWidget*>();
628 Q_FOREACH( QWidget* myWidget, myWidgets )
631 QVariant vRel = myWidget->property(
"qgisRelation" );
632 if ( vRel.isValid() )
638 QgsRelationWidgetWrapper* rww =
new QgsRelationWidgetWrapper(
mLayer, relation, myWidget,
this );
646 Q_FOREACH(
const QgsField& field, fields )
648 if ( field.
name() == myWidget->objectName() )
654 QgsEditorWidgetWrapper* eww = QgsEditorWidgetRegistry::instance()->create( widgetType,
mLayer, idx, widgetConfig, myWidget,
this,
mContext );
664 Q_FOREACH( QgsWidgetWrapper* ww,
mWidgets )
666 QgsEditorWidgetWrapper* eww = qobject_cast<QgsEditorWidgetWrapper*>( ww );
669 connect( eww, SIGNAL( valueChanged(
const QVariant& ) ),
this, SLOT(
onAttributeChanged(
const QVariant& ) ) );
678 if ( e->type() == QEvent::KeyPress )
680 QKeyEvent* keyEvent =
dynamic_cast<QKeyEvent*
>( e );
681 if ( keyEvent->key() == Qt::Key_Escape )
QList< QgsField > toList() const
Utility function to return a list of QgsField instances.
QgsFeatureId id() const
Get the feature id for this feature.
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.
bool isValid() const
Returns the validity of this relation.
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
bool isValid() const
Return the validity of this feature.
This class contains context information for attribute editor widgets.
void beginEditCommand(QString text)
Create edit command for undo/redo operations.
static bool eval(QString command, QString &result)
Eval a python statement.
void setAttributes(const QgsAttributes &attrs)
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...
QString editForm()
get edit form (added in 1.4)
QString attributeDisplayName(int attributeIndex) const
Convenience function that returns the attribute alias if defined or the field name else...
static bool run(QString command, QString messageOnError=QString())
execute a python statement
QgsRelation relation(const QString &id) const
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
Encapsulate a field in an attribute table or data source.
void setFields(const QgsFields *fields, bool initAttributes=false)
Assign a field map with the feature to allow attribute access by attribute name.
void endEditCommand()
Finish edit command and add it to undo/redo stack.
bool labelOnTop(int idx)
label widget on top
QList< QgsAttributeEditorElement * > children() const
void setValid(bool validity)
Set the validity of the feature.
QVector< QVariant > QgsAttributes
virtual void setIsGroupBox(bool isGroupBox)
This class manages a set of relations between layers.
static QgsProject * instance()
access to canonical QgsProject instance
QList< QgsAttributeEditorElement * > & attributeEditorElements()
Returns a list of tabs holding groups and fields.
const QgsFields & pendingFields() const
returns field list in the to-be-committed state
QString editFormInit()
get python function for edit form initialization (added in 1.4)
virtual bool isEditable() const
Returns true if the provider is in editing mode.
Represents a vector layer which manages a vector based data sets.
int fieldNameIndex(const QString &fieldName) const
Returns the index of a field name or -1 if the field does not exist.
QgsRelationManager * relationManager() const
bool isNull(const QVariant &v)