18 #include "qgseditorwidgetwrapper.h"
31 #include <QTableWidgetItem>
35 #include <QScrollArea>
39 #include <QDialogButtonBox>
42 #include <QVBoxLayout>
45 #include <QPushButton>
55 , mFeature( thepFeature )
56 , mFeatureOwner( featureOwner )
58 , mFormNr( sFormCounter++ )
59 , mShowDialogButtons( showDialogButtons )
70 , mFeature( thepFeature )
71 , mFeatureOwner( featureOwner )
73 , mFormNr( sFormCounter++ )
74 , mShowDialogButtons( showDialogButtons )
90 QDialogButtonBox *buttonBox = NULL;
97 if (
file.open( QFile::ReadOnly ) )
102 loader.setWorkingDirectory( fi.dir() );
103 QWidget *myWidget = loader.load( &
file, qobject_cast<QWidget*>( parent() ) );
106 mDialog = qobject_cast<QDialog*>( myWidget );
107 buttonBox = myWidget->findChild<QDialogButtonBox*>();
113 mDialog =
new QDialog( qobject_cast<QWidget*>( parent() ) );
115 QGridLayout *gridLayout;
116 QTabWidget *tabWidget;
119 gridLayout =
new QGridLayout(
mDialog );
120 gridLayout->setObjectName( QString::fromUtf8(
"gridLayout" ) );
122 tabWidget =
new QTabWidget(
mDialog );
123 gridLayout->addWidget( tabWidget );
127 QWidget* tabPage =
new QWidget( tabWidget );
129 tabWidget->addTab( tabPage, widgDef->
name() );
130 QGridLayout *tabPageLayout =
new QGridLayout( tabPage );
140 QgsDebugMsg(
"No support for fields in attribute editor on top level" );
144 buttonBox =
new QDialogButtonBox(
mDialog );
145 buttonBox->setObjectName( QString::fromUtf8(
"buttonBox" ) );
146 gridLayout->addWidget( buttonBox );
152 mDialog =
new QDialog( qobject_cast<QWidget*>( parent() ) );
154 QGridLayout *gridLayout;
158 gridLayout =
new QGridLayout(
mDialog );
159 gridLayout->setSpacing( 6 );
160 gridLayout->setMargin( 2 );
161 gridLayout->setObjectName( QString::fromUtf8(
"gridLayout" ) );
162 mFrame =
new QFrame(
mDialog );
163 mFrame->setObjectName( QString::fromUtf8(
"mFrame" ) );
164 mFrame->setFrameShape( QFrame::NoFrame );
165 mFrame->setFrameShadow( QFrame::Plain );
167 gridLayout->addWidget( mFrame, 0, 0, 1, 1 );
169 buttonBox =
new QDialogButtonBox(
mDialog );
170 buttonBox->setObjectName( QString::fromUtf8(
"buttonBox" ) );
171 gridLayout->addWidget( buttonBox, 2, 0, 1, 1 );
176 QVBoxLayout *mypOuterLayout =
new QVBoxLayout();
177 mypOuterLayout->setContentsMargins( 0, 0, 0, 0 );
180 mFrame->setLayout( mypOuterLayout );
182 QScrollArea *mypScrollArea =
new QScrollArea();
183 mypScrollArea->setFrameShape( QFrame::NoFrame );
184 mypScrollArea->setFrameShadow( QFrame::Plain );
187 mypOuterLayout->addWidget( mypScrollArea );
189 QFrame *mypInnerFrame =
new QFrame();
190 mypInnerFrame->setFrameShape( QFrame::NoFrame );
191 mypInnerFrame->setFrameShadow( QFrame::Plain );
194 mypScrollArea->setWidget( mypInnerFrame );
196 mypScrollArea->setWidgetResizable(
true );
197 QGridLayout *mypInnerLayout =
new QGridLayout( mypInnerFrame );
200 for (
int fldIdx = 0; fldIdx < theFields.
count(); ++fldIdx )
206 const QgsField &myField = theFields[fldIdx];
216 QLabel *mypLabel =
new QLabel( myFieldName, mypInnerFrame );
222 myWidget->setEnabled(
true );
226 foreach ( QWidget *w, myWidget->findChildren<QWidget *>() )
228 w->setEnabled( qobject_cast<QLabel *>( w ) ?
true :
false );
233 foreach ( QWidget *w, myWidget->findChildren<QWidget *>() )
235 if ( qobject_cast<QWebView *>( w ) )
236 w->setEnabled(
true );
237 else if ( qobject_cast<QPushButton *>( w ) && w->objectName() ==
"openUrl" )
238 w->setEnabled(
true );
240 w->setEnabled(
false );
245 QgsEditorWidgetWrapper* ww = QgsEditorWidgetWrapper::fromWidget( myWidget );
248 ww->setEnabled(
false );
253 myWidget->setEnabled(
false );
259 mypInnerLayout->addWidget( mypLabel, index++, 0, 1, 2 );
260 mypInnerLayout->addWidget( myWidget, index++, 0, 1, 2 );
264 mypInnerLayout->addWidget( mypLabel, index, 0 );
265 mypInnerLayout->addWidget( myWidget, index, 1 );
278 myWidget->setProperty(
"qgisRelation", relation.
id() );
279 myWidget->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
280 mypInnerLayout->addWidget( myWidget, index, 0, 1, 2 );
281 mypInnerLayout->setRowStretch( index, 2 );
286 if ( mypInnerLayout->rowCount() > 0 )
288 QWidget* widget = mypInnerLayout->itemAtPosition( 0, 1 )->widget();
290 widget->setFocus( Qt::OtherFocusReason );
293 QSpacerItem *mypSpacer =
new QSpacerItem( 0, 0, QSizePolicy::Fixed, QSizePolicy::MinimumExpanding );
294 mypInnerLayout->addItem( mypSpacer, mypInnerLayout->rowCount() + 1, 0 );
302 myDa.
setEllipsoidalMode( QgisApp::instance()->mapCanvas()->mapRenderer()->hasCrsTransformEnabled() );
307 QList<QWidget *> myWidgets =
mDialog->findChildren<QWidget*>();
308 Q_FOREACH( QWidget* myWidget, myWidgets )
311 QVariant vRel = myWidget->property(
"qgisRelation" );
312 if ( vRel.isValid() )
319 if ( !myWidget->layout() )
321 myWidget->setLayout(
new QHBoxLayout() );
323 myWidget->layout()->addWidget( relWdg );
330 for (
int fldIdx = 0; fldIdx < theFields.
count(); ++fldIdx )
332 if ( myWidget->objectName() == theFields[fldIdx].name() )
340 myWidget->setEnabled(
true );
344 foreach ( QWidget *w, myWidget->findChildren<QWidget *>() )
346 w->setEnabled( qobject_cast<QLabel *>( w ) ?
true :
false );
351 foreach ( QWidget *w, myWidget->findChildren<QWidget *>() )
353 w->setEnabled( qobject_cast<QWebView *>( w ) ?
true :
false );
358 QgsEditorWidgetWrapper* ww = QgsEditorWidgetWrapper::fromWidget( myWidget );
361 ww->setEnabled(
false );
366 myWidget->setEnabled(
false );
374 foreach ( QLineEdit *le,
mDialog->findChildren<QLineEdit*>() )
376 if ( !le->objectName().startsWith(
"expr_" ) )
379 le->setReadOnly(
true );
380 QString expr = le->text();
381 le->setText(
tr(
"Error" ) );
404 switch ( value.type() )
406 case QVariant::Invalid: text =
"NULL";
break;
407 case QVariant::Int: text = QString::number( value.toInt() );
break;
408 case QVariant::LongLong: text = QString::number( value.toLongLong() );
break;
409 case QVariant::Double: text = QString::number( value.toDouble() );
break;
410 case QVariant::String:
411 default: text = value.toString();
426 if (
mDialog->objectName().isEmpty() )
427 mDialog->setObjectName(
"QgsAttributeDialogBase" );
429 if (
mDialog->windowTitle().isEmpty() )
441 buttonBox->setStandardButtons( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
442 connect( buttonBox, SIGNAL( accepted() ),
mDialog, SLOT(
accept() ) );
443 connect( buttonBox, SIGNAL( accepted() ),
this, SLOT(
accept() ) );
447 buttonBox->setStandardButtons( QDialogButtonBox::Cancel );
450 connect( buttonBox, SIGNAL( rejected() ),
mDialog, SLOT( reject() ) );
462 buttonBox->setStandardButtons( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
463 connect( buttonBox, SIGNAL( accepted() ),
mDialog, SLOT(
accept() ) );
464 connect( buttonBox, SIGNAL( accepted() ),
this, SLOT(
accept() ) );
467 buttonBox->setVisible(
false );
471 QMetaObject::connectSlotsByName(
mDialog );
479 vl->setProperty(
"featureForm.dialog", QVariant::fromValue( qobject_cast<QObject*>(
mDialog ) ) );
480 vl->setProperty(
"featureForm.id", QVariant( mpFeature->id() ) );
484 int pos = module.lastIndexOf(
"." );
493 QString reload = QString(
"if hasattr(%1,'DEBUGMODE') and %1.DEBUGMODE:"
494 " reload(%1)" ).arg( module.left( pos ) );
498 QString form = QString(
"_qgis_featureform_%1 = sip.wrapinstance( %2, QtGui.QDialog )" )
500 .arg((
unsigned long )
mDialog );
502 QString layer = QString(
"_qgis_layer_%1 = sip.wrapinstance( %2, qgis.core.QgsVectorLayer )" )
504 .arg((
unsigned long )
mLayer );
508 QDateTime dt = QDateTime::currentDateTime();
509 QString featurevarname = QString(
"_qgis_feature_%1" ).arg( dt.toString(
"yyyyMMddhhmmsszzz" ) );
510 QString
feature = QString(
"%1 = sip.wrapinstance( %2, qgis.core.QgsFeature )" )
511 .arg( featurevarname )
518 mReturnvarname = QString(
"_qgis_feature_form_%1" ).arg( dt.toString(
"yyyyMMddhhmmsszzz" ) );
519 QString expr = QString(
"%5 = %1(_qgis_featureform_%2, _qgis_layer_%3, %4)" )
523 .arg( featurevarname )
526 QgsDebugMsg( QString(
"running featureForm init: %1" ).arg( expr ) );
570 for (
int idx = 0; idx < fields.
count(); ++idx )
588 return QDialog::Accepted;
596 mDialog->setAttribute( Qt::WA_DeleteOnClose );
600 mDialog->installEventFilter(
this );
636 mLayer->setProperty(
"featureForm.dialog", QVariant() );
637 mLayer->setProperty(
"featureForm.id", QVariant() );
641 QString expr = QString(
"if locals().has_key('_qgis_featureform_%1'): del _qgis_featureform_%1\n" ).arg(
mFormNr );
647 QString expr = QString(
"if locals().has_key('%1'): del %1\n" ).arg(
mReturnvarname );
661 case QEvent::WindowActivate:
664 case QEvent::WindowDeactivate:
QgsFeatureId id() const
Get the feature id for this feature.
Class for parsing and evaluation of expressions (formerly called "search strings").
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
bool isValid() const
Returns the validity of this relation.
bool fieldEditable(int idx)
is edit widget editable
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
QWidget * proxyWidget(QgsVectorLayer *vl, int fieldIdx)
EditorLayout editorLayout()
get the active layout for the attribute editor for this layer (added in 1.9)
void restoreGeometry()
Restores the size and position from the last time this dialog box was used.
static bool retrieveValue(QWidget *widget, QgsVectorLayer *vl, int idx, QVariant &value)
QVariant evaluate(const QgsFeature *f=NULL)
Evaluate the feature and return the result.
The attribute value should not be changed in the attribute form.
This class contains context information for attribute editor widgets.
void saveGeometry()
Saves the size and position for the next time this dialog box will be used.
void setSourceCrs(long srsid)
sets source spatial reference system (by QGIS CRS)
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
QgsGeometry * geometry() const
Get the geometry object associated with this feature.
QgsHighlight * mHighlight
Container of fields for a vector layer.
bool setAttribute(int field, const QVariant &attr)
Set an attribute by id.
void setHighlight(QgsHighlight *h)
QgsAttributeDialog(QgsVectorLayer *vl, QgsFeature *thepFeature, bool featureOwner, QgsDistanceArea myDa, QWidget *parent=0, bool showDialogButtons=true)
Create an attribute dialog for a given layer and feature.
bool setEllipsoid(const QString &ellipsoid)
sets ellipsoid by its acronym
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
static QWidget * createWidgetFromDef(const QgsAttributeEditorElement *widgetDef, QWidget *parent, QgsVectorLayer *vl, const QgsFeature &feat, QgsAttributeEditorContext &context, QString &labelText, bool &labelOnTop)
Creates a widget form a QgsAttributeEditorElement definition.
QString editForm()
get edit form (added in 1.4)
const QString & name() const
Get the display name of the layer.
void setGeometry(const QgsGeometry &geom)
Set this feature's geometry from another QgsGeometry object (deep copy)
QList< QgsRelation > referencedRelations(QgsVectorLayer *layer=0) const
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
EditType editType(int idx)
get edit type
const QString & id() const
The id.
void adjustForLayer(QgsVectorLayer *layer)
When copying the context for another layer, call this.
bool eventFilter(QObject *obj, QEvent *event)
A class for highlight features on the map.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
QList< int > QgsAttributeList
AttributeEditorType type() const
QString & dateFormat(int idx)
access date format
QString id() const
Get this layer's unique ID, this ID is used to access this layer from map layer registry.
int count() const
Return number of items.
static QString sSettingsPath
void setDistanceArea(const QgsDistanceArea &distanceArea)
Encapsulate a field in an attribute table or data source.
QString attributeAlias(int attributeIndex) const
Returns the alias of an attribute name or an empty string if there is no alias.
bool labelOnTop(int idx)
label widget on top
bool needsGeometry()
Returns true if the expression uses feature geometry for some computation.
General purpose distance and area calculator.
static QWidget * createAttributeEditor(QWidget *parent, QWidget *editor, QgsVectorLayer *vl, int idx, const QVariant &value, QMap< int, QWidget * > &proxyWidgets)
Creates or prepares a attribute editor widget.
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
This class manages a set of relations between layers.
static QgsProject * instance()
access to canonical QgsProject instance
const CORE_EXPORT QString GEO_NONE
Constant that holds the string representation for "No ellips/No CRS".
QList< QgsAttributeEditorElement * > & attributeEditorElements()
Returns a list of tabs holding groups and fields.
void setGeomCalculator(const QgsDistanceArea &calc)
Sets the geometry calculator used in evaluation of expressions,.
QgsAttributeEditorContext mContext
const QgsFields & pendingFields() const
returns field list in the to-be-committed state
QgsVectorDataProvider * dataProvider()
Returns the data provider.
QString editFormInit()
get python function for edit form initialization (added in 1.4)
bool nextFeature(QgsFeature &f)
virtual bool isEditable() const
Returns true if the provider is in editing mode.
Represents a vector layer which manages a vector based data sets.
bool isEmpty() const
Check whether the container is empty.
QgsRelationManager * relationManager() const
QString evalErrorString() const
Returns evaluation error.
void setEllipsoidalMode(bool flag)
sets whether coordinates must be projected to ellipsoid before measuring
QVariant::Type type() const
Gets variant type of the field as it will be retrieved from data source.
const QgsDistanceArea & distanceArea()