28 #include <QTextStream> 31 #include <QFormLayout> 32 #include <QGridLayout> 36 #include <QPushButton> 37 #include <QScrollArea> 40 #include <QMessageBox> 42 int QgsAttributeForm::sFormCounter = 0;
48 , mButtonBox( nullptr )
49 , mFormNr( sFormCounter++ )
51 , mIsAddDialog( false )
52 , mPreventFeatureRefresh( false )
53 , mEditCommandMessage(
tr(
"Attributes changed" ) )
62 connect( vl, SIGNAL( attributeAdded(
int ) ),
this, SLOT( onAttributeAdded(
int ) ) );
63 connect( vl, SIGNAL( attributeDeleted(
int ) ),
this, SLOT( onAttributeDeleted(
int ) ) );
65 connect( vl, SIGNAL( updatedFields() ),
this, SLOT( onUpdatedFields() ) );
66 connect( vl, SIGNAL( beforeAddingExpressionField(
QString ) ),
this, SLOT( preventFeatureRefresh() ) );
67 connect( vl, SIGNAL( beforeRemovingExpressionField(
int ) ),
this, SLOT( preventFeatureRefresh() ) );
73 qDeleteAll( mInterfaces );
82 connect( mLayer, SIGNAL( beforeModifiedCheck() ),
this, SLOT(
save() ) );
89 disconnect( mLayer, SIGNAL( beforeModifiedCheck() ),
this, SLOT(
save() ) );
100 mInterfaces.
append( iface );
110 mIsAddDialog = isAddDialog;
112 synchronizeEnabledState();
120 if ( eww && eww->
field().
name() == field )
133 synchronizeEnabledState();
148 bool changedLayer =
false;
160 if ( mFeature.
isValid() || mIsAddDialog )
162 bool doUpdate =
false;
183 bool changed = ( dstVar != srcVar && !dstVar.
isNull() && !srcVar.
isNull() )
185 if ( changed && srcVar.
isValid()
211 bool res = mLayer->
addFeature( updatedFeature );
216 mIsAddDialog =
false;
227 for (
int i = 0; i < dst.
count(); ++i )
229 if (( dst.
at( i ) == src.
at( i ) && dst.
at( i ).isNull() == src.
at( i ).isNull() )
230 || !dst.
at( i ).isValid()
238 .arg( dst.
at( i ).toString(), dst.
at( i ).typeName() ).arg( dst.
at( i ).isNull() ).arg( dst.
at( i ).isValid() ) );
240 .arg( src.
at( i ).toString(), src.
at( i ).typeName() ).arg( src.
at( i ).isNull() ).arg( src.
at( i ).isValid() ) );
246 if ( success && n > 0 )
283 void QgsAttributeForm::onAttributeChanged(
const QVariant& value )
292 void QgsAttributeForm::onAttributeAdded(
int idx )
294 mPreventFeatureRefresh =
false;
306 void QgsAttributeForm::onAttributeDeleted(
int idx )
308 mPreventFeatureRefresh =
false;
320 void QgsAttributeForm::onUpdatedFields()
322 mPreventFeatureRefresh =
false;
334 attrs[i].convert(
layer()->fields().at( i ).type() );
349 void QgsAttributeForm::preventFeatureRefresh()
351 mPreventFeatureRefresh =
true;
368 void QgsAttributeForm::synchronizeEnabledState()
370 bool isEditable = ( mFeature.
isValid() || mIsAddDialog ) && mLayer->
isEditable();
374 bool fieldEditable =
true;
382 ww->
setEnabled( isEditable && fieldEditable );
390 void QgsAttributeForm::init()
397 bool buttonBoxVisible =
true;
401 buttonBoxVisible = mButtonBox->
isVisible();
403 mButtonBox =
nullptr;
406 qDeleteAll( mWidgets );
409 while (
QWidget* w = this->findChild<QWidget*>() )
423 if ( file.open( QFile::ReadOnly ) )
429 formWidget = loader.
load( &file,
this );
434 mButtonBox = findChild<QDialogButtonBox*>();
451 tabWidget->
addTab( tabPage, widgDef->
name() );
464 tabPageLayout->
addWidget( createWidgetFromDef( widgDef, tabPage, mLayer, mContext, dummy1, dummy2 ) );
468 QgsDebugMsg(
"No support for fields in attribute editor on top level" );
471 formWidget = tabWidget;
478 formWidget =
new QWidget(
this );
504 if ( widgetType ==
"Hidden" )
513 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 ) );
519 addWidgetWrapper( eww );
523 gridLayout->
addWidget( l, row++, 0, 1, 2 );
524 gridLayout->
addWidget( w, row++, 0, 1, 2 );
546 gridLayout->
addItem( spacerItem, row++, 0 );
552 mButtonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
561 connect( mButtonBox, SIGNAL( accepted() ),
this, SLOT(
accept() ) );
564 connect( mLayer, SIGNAL( editingStarted() ),
this, SLOT( synchronizeEnabledState() ) );
565 connect( mLayer, SIGNAL( editingStopped() ),
this, SLOT( synchronizeEnabledState() ) );
574 void QgsAttributeForm::cleanPython()
576 if ( !mPyFormVarName.
isNull() )
578 QString expr =
QString(
"if locals().has_key('%1'): del %1\n" ).
arg( mPyFormVarName );
583 void QgsAttributeForm::initPython()
600 if ( ! initFilePath.
isEmpty() )
602 QFile inputFile( initFilePath );
604 if ( inputFile.
open( QFile::ReadOnly ) )
649 static int sFormId = 0;
650 mPyFormVarName =
QString(
"_qgis_featureform_%1_%2" ).
arg( mFormNr ).
arg( sFormId++ );
652 QString form =
QString(
"%1 = sip.wrapinstance( %2, qgis.gui.QgsAttributeForm )" )
653 .
arg( mPyFormVarName )
654 .
arg((
unsigned long )
this );
661 if ( numArgs ==
"3" )
669 msgBox.
setText(
tr(
"The python init function (<code>%1</code>) does not accept three arguments as expected!<br>Please check the function name in the <b>Fields</b> tab of the layer properties." ).arg( initFunction ) );
674 .arg( mPyFormVarName );
675 QgsAttributeFormInterface* iface = QgsPythonRunner::evalToSipObject<QgsAttributeFormInterface*>( expr,
"QgsAttributeFormInterface" );
685 msgBox.
setText(
tr(
"The python init function (<code>%1</code>) could not be found!<br>Please check the function name in the <b>Fields</b> tab of the layer properties." ).arg( initFunction ) );
695 switch ( widgetDef->
type() )
704 if ( fldIdx < vl->fields().count() && fldIdx >= 0 )
710 newWidget = eww->
widget();
711 addWidgetWrapper( eww );
730 newWidget = rww->
widget();
732 labelText = QString::null;
748 myContainer = groupBox;
749 newWidget = myContainer;
755 myContainer =
new QWidget( scrollArea );
761 newWidget = scrollArea;
775 QWidget* editor = createWidgetFromDef( childDef, myContainer, vl, context, labelText, labelOnTop );
779 gbLayout->
addWidget( editor, index, 0, 1, 2 );
786 gbLayout->
addWidget( mypLabel, index, 0, 1, 2 );
788 gbLayout->
addWidget( editor, index, 0, 1, 2 );
792 gbLayout->
addWidget( mypLabel, index, 0 );
800 spacer->
setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Preferred );
803 labelText = QString::null;
809 QgsDebugMsg(
"Unknown attribute editor widget type encountered..." );
835 void QgsAttributeForm::createWrappers()
840 Q_FOREACH (
QWidget* myWidget, myWidgets )
859 Q_FOREACH (
const QgsField& field, fields )
868 addWidgetWrapper( eww );
875 void QgsAttributeForm::connectWrappers()
877 bool isFirstEww =
true;
891 connect( eww, SIGNAL( valueChanged(
const QVariant& ) ),
this, SLOT( onAttributeChanged(
const QVariant& ) ) );
901 if ( e->
type() == QEvent::KeyPress )
904 if ( keyEvent && keyEvent->
key() == Qt::Key_Escape )
bool isValid() const
Returns the validity of this feature.
bool isValid() const
Returns the validity of this relation.
QgsAttributes attributes() const
Returns the feature's attributes.
int size() const
Return number of items.
This is an abstract base class for any elements of a drag and drop form.
void beginEditCommand(const QString &text)
Create edit command for undo/redo operations.
void setFrameShape(Shape)
This class contains context information for attribute editor widgets.
static void warning(const QString &msg)
Goes to qWarning.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
const QgsRelation & relation() const
Get the id of the relation which shall be embedded.
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.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
QgsRelationManager * relationManager() const
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.
QString tr(const char *sourceText, const char *disambiguation, int n)
AttributeEditorType type() const
The type of this element.
QString id() const
A (project-wide) unique id for this relation.
QString name() const
Gets the name of the field.
const QgsField & at(int i) const
Get field at particular index (must be in range 0..N-1)
QgsEditFormConfig * editFormConfig() const
Get the configuration of the form used to represent this vector layer.
QgsFields fields() const
Returns the list of fields of this layer.
const char * name() const
void append(const T &value)
const QgsFields * fields() const
Returns the field map associated with the feature.
QVariant property(const char *name) const
void installEventFilter(QObject *filterObj)
void setObjectName(const QString &name)
void setText(const QString &text)
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)
void destroyEditCommand()
Destroy active command and reverts all changes in it.
void restoreOverrideCursor()
int idx() const
Return the index of the field.
Encapsulate a field in an attribute table or data source.
virtual int capabilities() const
Returns a bitmask containing the supported capabilities Note, some capabilities may change depending ...
virtual bool open(QFlags< QIODevice::OpenModeFlag > mode)
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.
QgsFeatureId id() const
Get the feature ID for this feature.
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.
Q_DECL_DEPRECATED QString editFormInit() const
Get python function for edit form initialization.
const T & at(int i) const
int indexFromName(const QString &name) const
Look up field's index from name. Returns -1 on error.
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
QList< QgsField > toList() const
Utility function to return a list of QgsField instances.
int count(const T &value) const
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)
QList< QgsAttributeEditorElement * > children() const
Get a list of the children elements of this container.
virtual bool isGroupBox() const
Returns if this container is going to be rendered as a group box.
QgsVectorDataProvider * dataProvider()
Returns the data provider.
bool nextFeature(QgsFeature &f)
QgsRelation relation(const QString &id) const
Get access to a relation by its id.
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.
QVariant::Type type() const
Gets variant type of the field as it will be retrieved from data source.
QString name() const
Return the name of this element.
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QString attributeDisplayName(int attributeIndex) const
Convenience function that returns the attribute alias if defined or the field name else...
Allows modification of attribute values.
int fieldNameIndex(const QString &fieldName) const
Returns the index of a field name or -1 if the field does not exist.