29 #include <QFormLayout>
30 #include <QGridLayout>
34 #include <QPushButton>
35 #include <QScrollArea>
39 int QgsAttributeForm::sFormCounter = 0;
46 , mFormNr( sFormCounter++ )
48 , mIsAddDialog( false )
49 , mPreventFeatureRefresh( false )
50 , mEditCommandMessage(
tr(
"Attributes changed" ) )
59 connect( vl, SIGNAL( attributeAdded(
int ) ),
this, SLOT( onAttributeAdded(
int ) ) );
60 connect( vl, SIGNAL( attributeDeleted(
int ) ),
this, SLOT( onAttributeDeleted(
int ) ) );
62 connect( vl, SIGNAL( updatedFields() ),
this, SLOT( onUpdatedFields() ) );
63 connect( vl, SIGNAL( beforeAddingExpressionField(
QString ) ),
this, SLOT( preventFeatureRefresh() ) );
64 connect( vl, SIGNAL( beforeRemovingExpressionField(
int ) ),
this, SLOT( preventFeatureRefresh() ) );
70 qDeleteAll( mInterfaces );
79 connect( mLayer, SIGNAL( beforeModifiedCheck() ),
this, SLOT(
save() ) );
86 disconnect( mLayer, SIGNAL( beforeModifiedCheck() ),
this, SLOT(
save() ) );
97 mInterfaces.
append( iface );
107 mIsAddDialog = isAddDialog;
109 synchronizeEnabledState();
117 if ( eww && eww->
field().
name() == field )
130 synchronizeEnabledState();
145 bool changedLayer =
false;
157 if ( mFeature.
isValid() || mIsAddDialog )
159 bool doUpdate =
false;
203 bool res = mLayer->
addFeature( updatedFeature );
208 mIsAddDialog =
false;
219 for (
int i = 0; i < dst.
count(); ++i )
221 if (( dst.
at( i ) == src.
at( i ) && dst.
at( i ).isNull() == src.
at( i ).isNull() )
222 || !dst.
at( i ).isValid()
230 .arg( dst.
at( i ).toString(), dst.
at( i ).typeName() ).arg( dst.
at( i ).isNull() ).arg( dst.
at( i ).isValid() ) );
232 .arg( src.
at( i ).toString(), src.
at( i ).typeName() ).arg( src.
at( i ).isNull() ).arg( src.
at( i ).isValid() ) );
238 if ( success && n > 0 )
275 void QgsAttributeForm::onAttributeChanged(
const QVariant& value )
284 void QgsAttributeForm::onAttributeAdded(
int idx )
286 mPreventFeatureRefresh =
false;
298 void QgsAttributeForm::onAttributeDeleted(
int idx )
300 mPreventFeatureRefresh =
false;
312 void QgsAttributeForm::onUpdatedFields()
314 mPreventFeatureRefresh =
false;
326 attrs[i].convert(
layer()->fields().at( i ).type() );
341 void QgsAttributeForm::preventFeatureRefresh()
343 mPreventFeatureRefresh =
true;
360 void QgsAttributeForm::synchronizeEnabledState()
362 bool isEditable = ( mFeature.
isValid() || mIsAddDialog ) && mLayer->
isEditable();
366 bool fieldEditable =
true;
374 ww->
setEnabled( isEditable && fieldEditable );
382 void QgsAttributeForm::init()
389 bool buttonBoxVisible =
true;
393 buttonBoxVisible = mButtonBox->
isVisible();
398 qDeleteAll( mWidgets );
401 while (
QWidget* w = this->findChild<QWidget*>() )
415 if ( file.open( QFile::ReadOnly ) )
421 formWidget = loader.
load( &file,
this );
426 mButtonBox = findChild<QDialogButtonBox*>();
443 tabWidget->
addTab( tabPage, widgDef->
name() );
456 tabPageLayout->
addWidget( createWidgetFromDef( widgDef, tabPage, mLayer, mContext, dummy1, dummy2 ) );
460 QgsDebugMsg(
"No support for fields in attribute editor on top level" );
463 formWidget = tabWidget;
470 formWidget =
new QWidget(
this );
496 if ( widgetType ==
"Hidden" )
505 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 ) );
511 addWidgetWrapper( eww );
515 gridLayout->
addWidget( l, row++, 0, 1, 2 );
516 gridLayout->
addWidget( w, row++, 0, 1, 2 );
536 gridLayout->
addItem( spacerItem, row++, 0 );
542 mButtonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
551 connect( mButtonBox, SIGNAL( accepted() ),
this, SLOT(
accept() ) );
554 connect( mLayer, SIGNAL( editingStarted() ),
this, SLOT( synchronizeEnabledState() ) );
555 connect( mLayer, SIGNAL( editingStopped() ),
this, SLOT( synchronizeEnabledState() ) );
564 void QgsAttributeForm::cleanPython()
566 if ( !mPyFormVarName.
isNull() )
568 QString expr =
QString(
"if locals().has_key('%1'): del %1\n" ).
arg( mPyFormVarName );
573 void QgsAttributeForm::initPython()
591 QString reload =
QString(
"if hasattr(%1,'DEBUGMODE') and %1.DEBUGMODE:"
592 " reload(%1)" ).
arg( module.
left( pos ) );
600 static int sFormId = 0;
601 mPyFormVarName =
QString(
"_qgis_featureform_%1_%2" ).
arg( mFormNr ).
arg( sFormId++ );
603 QString form =
QString(
"%1 = sip.wrapinstance( %2, qgis.gui.QgsAttributeForm )" )
604 .
arg( mPyFormVarName )
605 .
arg((
unsigned long )
this );
612 if ( numArgs ==
"3" )
621 .arg( mPyFormVarName );
622 QgsAttributeFormInterface* iface = QgsPythonRunner::evalToSipObject<QgsAttributeFormInterface*>( expr,
"QgsAttributeFormInterface" );
634 switch ( widgetDef->
type() )
643 if ( fldIdx < vl->fields().count() && fldIdx >= 0 )
649 newWidget = eww->
widget();
650 addWidgetWrapper( eww );
667 newWidget = rww->
widget();
669 labelText = QString::null;
685 myContainer = groupBox;
686 newWidget = myContainer;
692 myContainer =
new QWidget( scrollArea );
698 newWidget = scrollArea;
712 QWidget* editor = createWidgetFromDef( childDef, myContainer, vl, context, labelText, labelOnTop );
716 gbLayout->
addWidget( editor, index, 0, 1, 2 );
723 gbLayout->
addWidget( mypLabel, index, 0, 1, 2 );
725 gbLayout->
addWidget( editor, index, 0, 1, 2 );
729 gbLayout->
addWidget( mypLabel, index, 0 );
737 spacer->
setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Preferred );
740 labelText = QString::null;
746 QgsDebugMsg(
"Unknown attribute editor widget type encountered..." );
772 void QgsAttributeForm::createWrappers()
777 Q_FOREACH (
QWidget* myWidget, myWidgets )
796 Q_FOREACH (
const QgsField& field, fields )
805 addWidgetWrapper( eww );
812 void QgsAttributeForm::connectWrappers()
814 bool isFirstEww =
true;
828 connect( eww, SIGNAL( valueChanged(
const QVariant& ) ),
this, SLOT( onAttributeChanged(
const QVariant& ) ) );
838 if ( e->
type() == QEvent::KeyPress )
841 if ( keyEvent && 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.
Allows modification of attribute values.
bool fieldEditable(int idx)
Is edit widget editable.
This is an abstract base class for any elements of a drag and drop form.
EditorLayout editorLayout()
Get the active layout for the attribute editor for this layer.
virtual bool isGroupBox() const
Returns if this ccontainer is going to be rendered as a group box.
bool isValid() const
Returns the validity of this feature.
void beginEditCommand(const QString &text)
Create edit command for undo/redo operations.
QgsFields fields() const
Returns the list of fields of this layer.
void setFrameShape(Shape)
This class contains context information for attribute editor widgets.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
const QObjectList & children() const
void insert(int i, const T &value)
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
This element will load a field's widget onto the form.
This element will load a relation editor onto the form.
bool addFeature(QgsFeature &f, bool alsoUpdateExtent=true)
Adds a feature.
const QgsRelation & relation() const
Get the id of the relation which shall be embedded.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
void setWorkingDirectory(const QDir &dir)
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
virtual bool isEditable() const override
Returns true if the provider is in editing mode.
int idx() const
Return the index of the field.
int lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
QString name() const
Return the name of this element.
QString editForm()
Get edit form.
const char * name() const
void append(const T &value)
QVariant property(const char *name) const
void installEventFilter(QObject *filterObj)
QString attributeDisplayName(int attributeIndex) const
Convenience function that returns the attribute alias if defined or the field name else...
QgsRelation relation(const QString &id) const
Get access to a relation by its id.
QgsAttributes attributes() const
Returns the feature's attributes.
virtual int capabilities() const
Returns a bitmask containing the supported capabilities Note, some capabilities may change depending ...
const QString editorWidgetV2(int fieldIdx) const
Get the id for the editor widget used to represent the field at the given index.
const QgsFields * fields() const
Returns the field map associated with the feature.
void setObjectName(const QString &name)
void triggerRepaint()
Will advice the map canvas (and any other interested party) that this layer requires to be repainted...
This class wraps a request for features to a vector layer (or directly its vector data provider)...
void setOverrideCursor(const QCursor &cursor)
AttributeEditorType type() const
The type of this element.
void destroyEditCommand()
Destroy active command and reverts all changes in it.
void restoreOverrideCursor()
Encapsulate a field in an attribute table or data source.
const QgsField & at(int i) const
Get field at particular index (must be in range 0..N-1)
Q_DECL_DEPRECATED void setFields(const QgsFields *fields, bool initAttributes=false)
Assign a field map with the feature to allow attribute access by attribute name.
Q_DECL_DEPRECATED bool changeAttributeValue(QgsFeatureId fid, int field, const QVariant &value, bool emitSignal)
Changes an attribute value (but does not commit it)
void endEditCommand()
Finish edit command and add it to undo/redo stack.
int indexFromName(const QString &name) const
Look up field's index from name. Returns -1 on error.
bool labelOnTop(int idx)
Label widget on top.
QList< QgsAttributeEditorElement * > children() const
Get a list of the children elements of this container.
static bool eval(const QString &command, QString &result)
Eval a python statement.
void setFrameShadow(Shadow)
void setValid(bool validity)
Sets the validity of the feature.
const T & at(int i) const
static bool run(const QString &command, const QString &messageOnError=QString())
Execute a python statement.
void setTitle(const QString &title)
virtual void setIsGroupBox(bool isGroupBox)
Determines if this container is rendered as collapsible group box or tab in a tabwidget.
This class manages a set of relations between layers.
void addItem(QLayoutItem *item, int row, int column, int rowSpan, int columnSpan, QFlags< Qt::AlignmentFlag > alignment)
static QgsProject * instance()
access to canonical QgsProject instance
int count(const T &value) const
int size() const
Return number of items.
QList< QgsAttributeEditorElement * > & attributeEditorElements()
Returns a list of tabs holding groups and fields.
This is a container for attribute editors, used to group them visually in the attribute form if it is...
QWidget * load(QIODevice *device, QWidget *parentWidget)
QString left(int n) const
QgsVectorDataProvider * dataProvider()
Returns the data provider.
QString editFormInit()
Get python function for edit form initialization.
bool nextFeature(QgsFeature &f)
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
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
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QVariant::Type type() const
Gets variant type of the field as it will be retrieved from data source.