Skip to content

Commit b1a2bef

Browse files
committedSep 12, 2014
[relation widgets] General update
* Improve speed (lazy loading) * Loop detection for circular dependencies (Fix #10850) * Some memory leaks fixed * More const-correctness * Fix the attribute editor context
1 parent 016e1d7 commit b1a2bef

26 files changed

+313
-212
lines changed
 

‎python/gui/qgsattributeeditorcontext.sip

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,5 @@ class QgsAttributeEditorContext
2424
*
2525
* @param layer The layer to adjust for.
2626
*/
27-
void adjustForLayer( QgsVectorLayer* layer );
27+
// void adjustForLayer( QgsVectorLayer* layer );
2828
};

‎python/gui/qgsvectorlayertools.sip

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class QgsVectorLayerTools
1313
* @param defaultGeometry A default geometry to add to the feature
1414
* @return True in case of success, False if the operation failed/was aborted
1515
*/
16-
virtual bool addFeature( QgsVectorLayer* layer, QgsAttributeMap defaultValues = QgsAttributeMap(), const QgsGeometry& defaultGeometry = QgsGeometry() ) = 0;
16+
virtual bool addFeature( QgsVectorLayer* layer, QgsAttributeMap defaultValues = QgsAttributeMap(), const QgsGeometry& defaultGeometry = QgsGeometry() ) const = 0;
1717

1818

1919
/**
@@ -25,7 +25,7 @@ class QgsVectorLayerTools
2525
*
2626
* @return True, if the editing session was started
2727
*/
28-
virtual bool startEditing( QgsVectorLayer* layer ) = 0;
28+
virtual bool startEditing( QgsVectorLayer* layer ) const = 0;
2929

3030
/**
3131
* Will be called, when an editing session is ended and the features should be commited.
@@ -35,6 +35,6 @@ class QgsVectorLayerTools
3535
* @param allowCancel True if a cancel button should be offered
3636
* @return True if successful
3737
*/
38-
virtual bool stopEditing( QgsVectorLayer* layer, bool allowCancel = true ) = 0;
38+
virtual bool stopEditing( QgsVectorLayer* layer, bool allowCancel = true ) const = 0;
3939

4040
};

‎src/app/qgisapp.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -666,8 +666,6 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, QWidget * parent,
666666

667667
// Init the editor widget types
668668
QgsEditorWidgetRegistry* editorWidgetRegistry = QgsEditorWidgetRegistry::instance();
669-
QgsAttributeEditorContext context;
670-
context.setVectorLayerTools( vectorLayerTools() );
671669
editorWidgetRegistry->registerWidget( "Classification", new QgsClassificationWidgetWrapperFactory( tr( "Classification" ) ) );
672670
editorWidgetRegistry->registerWidget( "Range", new QgsRangeWidgetFactory( tr( "Range" ) ) );
673671
editorWidgetRegistry->registerWidget( "UniqueValues", new QgsUniqueValueWidgetFactory( tr( "Unique Values" ) ) );
@@ -682,7 +680,7 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, QWidget * parent,
682680
editorWidgetRegistry->registerWidget( "Photo", new QgsPhotoWidgetFactory( tr( "Photo" ) ) );
683681
editorWidgetRegistry->registerWidget( "WebView", new QgsWebViewWidgetFactory( tr( "Web View" ) ) );
684682
editorWidgetRegistry->registerWidget( "Color", new QgsColorWidgetFactory( tr( "Color" ) ) );
685-
editorWidgetRegistry->registerWidget( "RelationReference", new QgsRelationReferenceFactory( tr( "Relation Reference" ), context, mMapCanvas, mInfoBar ) );
683+
editorWidgetRegistry->registerWidget( "RelationReference", new QgsRelationReferenceFactory( tr( "Relation Reference" ), mMapCanvas, mInfoBar ) );
686684
editorWidgetRegistry->registerWidget( "DateTime", new QgsDateTimeEditFactory( tr( "Date/Time" ) ) );
687685

688686
mInternalClipboard = new QgsClipboard; // create clipboard
@@ -935,6 +933,8 @@ QgisApp::~QgisApp()
935933

936934
delete mComposerManager;
937935

936+
delete mVectorLayerTools;
937+
938938
deletePrintComposers();
939939
removeAnnotationItems();
940940

‎src/app/qgisappinterface.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -629,7 +629,10 @@ QgsAttributeDialog* QgisAppInterface::getFeatureForm( QgsVectorLayer *l, QgsFeat
629629
myDa.setEllipsoidalMode( QgisApp::instance()->mapCanvas()->mapSettings().hasCrsTransformEnabled() );
630630
myDa.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) );
631631

632-
QgsAttributeDialog *dialog = new QgsAttributeDialog( l, &feature, false, NULL, true );
632+
QgsAttributeEditorContext context;
633+
context.setDistanceArea( myDa );
634+
context.setVectorLayerTools( qgis->vectorLayerTools() );
635+
QgsAttributeDialog *dialog = new QgsAttributeDialog( l, &feature, false, NULL, true, context );
633636
return dialog;
634637
}
635638

‎src/app/qgsguivectorlayertools.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,15 @@ QgsGuiVectorLayerTools::QgsGuiVectorLayerTools()
3232
: QObject( NULL )
3333
{}
3434

35-
bool QgsGuiVectorLayerTools::addFeature( QgsVectorLayer* layer, QgsAttributeMap defaultValues, const QgsGeometry& defaultGeometry )
35+
bool QgsGuiVectorLayerTools::addFeature( QgsVectorLayer* layer, QgsAttributeMap defaultValues, const QgsGeometry& defaultGeometry ) const
3636
{
3737
QgsFeature f;
3838
f.setGeometry( defaultGeometry );
3939
QgsFeatureAction a( tr( "Add feature" ), f, layer );
4040
return a.addFeature( defaultValues );
4141
}
4242

43-
bool QgsGuiVectorLayerTools::startEditing( QgsVectorLayer* layer )
43+
bool QgsGuiVectorLayerTools::startEditing( QgsVectorLayer* layer ) const
4444
{
4545
if ( !layer )
4646
{
@@ -65,7 +65,7 @@ bool QgsGuiVectorLayerTools::startEditing( QgsVectorLayer* layer )
6565
return res;
6666
}
6767

68-
bool QgsGuiVectorLayerTools::stopEditing( QgsVectorLayer* layer, bool allowCancel )
68+
bool QgsGuiVectorLayerTools::stopEditing( QgsVectorLayer* layer, bool allowCancel ) const
6969
{
7070
bool res = true;
7171

@@ -127,7 +127,7 @@ bool QgsGuiVectorLayerTools::stopEditing( QgsVectorLayer* layer, bool allowCance
127127
return res;
128128
}
129129

130-
void QgsGuiVectorLayerTools::commitError( QgsVectorLayer* vlayer )
130+
void QgsGuiVectorLayerTools::commitError( QgsVectorLayer* vlayer ) const
131131
{
132132
QgsMessageViewer *mv = new QgsMessageViewer();
133133
mv->setWindowTitle( tr( "Commit errors" ) );

‎src/app/qgsguivectorlayertools.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class QgsGuiVectorLayerTools : public QgsVectorLayerTools, public QObject
3737
*
3838
* @return True in case of success, False if the operation failed/was aborted
3939
*/
40-
bool addFeature( QgsVectorLayer *layer, QgsAttributeMap defaultValues, const QgsGeometry &defaultGeometry );
40+
bool addFeature( QgsVectorLayer *layer, QgsAttributeMap defaultValues, const QgsGeometry &defaultGeometry ) const;
4141

4242
/**
4343
* This should be called, whenever a vector layer should be switched to edit mode. If successful
@@ -47,7 +47,7 @@ class QgsGuiVectorLayerTools : public QgsVectorLayerTools, public QObject
4747
*
4848
* @return True, if the editing session was started
4949
*/
50-
bool startEditing( QgsVectorLayer* layer );
50+
bool startEditing( QgsVectorLayer* layer ) const;
5151

5252
/**
5353
* Should be called, when an editing session is ended and the features should be commited.
@@ -59,10 +59,10 @@ class QgsGuiVectorLayerTools : public QgsVectorLayerTools, public QObject
5959
*
6060
* @return True if successful
6161
*/
62-
bool stopEditing( QgsVectorLayer* layer , bool allowCancel = true );
62+
bool stopEditing( QgsVectorLayer* layer , bool allowCancel = true ) const;
6363

6464
private:
65-
void commitError( QgsVectorLayer* vlayer );
65+
void commitError( QgsVectorLayer* vlayer ) const;
6666
};
6767

6868
#endif // QGSGUIVECTORLAYERTOOLS_H

‎src/gui/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,6 @@ qgisinterface.cpp
116116
qgsannotationitem.cpp
117117
qgsattributedialog.cpp
118118
qgsattributeeditor.cpp
119-
qgsattributeeditorcontext.cpp
120119
qgsattributeform.cpp
121120
qgsattributeforminterface.cpp
122121
qgsattributeformlegacyinterface.cpp

‎src/gui/attributetable/qgsfeaturelistview.cpp

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,10 @@
3434

3535
QgsFeatureListView::QgsFeatureListView( QWidget *parent )
3636
: QListView( parent )
37-
, mCurrentEditSelectionModel( NULL )
38-
, mFeatureSelectionModel( NULL )
39-
, mItemDelegate( NULL )
37+
, mModel( 0 )
38+
, mCurrentEditSelectionModel( 0 )
39+
, mFeatureSelectionModel( 0 )
40+
, mItemDelegate( 0 )
4041
, mEditSelectionDrag( false )
4142
{
4243
setSelectionMode( QAbstractItemView::ExtendedSelection );
@@ -100,7 +101,7 @@ QString QgsFeatureListView::parserErrorString()
100101
QgsFeatureIds QgsFeatureListView::currentEditSelection()
101102
{
102103
QgsFeatureIds selection;
103-
Q_FOREACH ( QModelIndex idx, mCurrentEditSelectionModel->selectedIndexes() )
104+
Q_FOREACH( QModelIndex idx, mCurrentEditSelectionModel->selectedIndexes() )
104105
{
105106
selection << idx.data( QgsAttributeTableModel::FeatureIdRole ).value<QgsFeatureId>();
106107
}
@@ -115,20 +116,27 @@ void QgsFeatureListView::setCurrentFeatureEdited( bool state )
115116

116117
void QgsFeatureListView::mousePressEvent( QMouseEvent *event )
117118
{
118-
QPoint pos = event->pos();
119+
if ( mModel )
120+
{
121+
QPoint pos = event->pos();
119122

120-
QModelIndex index = indexAt( pos );
123+
QModelIndex index = indexAt( pos );
121124

122-
if ( QgsFeatureListViewDelegate::EditElement == mItemDelegate->positionToElement( event->pos() ) )
123-
{
124-
mEditSelectionDrag = true;
125-
setEditSelection( mModel->mapToMaster( index ), QItemSelectionModel::ClearAndSelect );
125+
if ( QgsFeatureListViewDelegate::EditElement == mItemDelegate->positionToElement( event->pos() ) )
126+
{
127+
mEditSelectionDrag = true;
128+
setEditSelection( mModel->mapToMaster( index ), QItemSelectionModel::ClearAndSelect );
129+
}
130+
else
131+
{
132+
mFeatureSelectionModel->enableSync( false );
133+
selectRow( index, true );
134+
repaintRequested();
135+
}
126136
}
127137
else
128138
{
129-
mFeatureSelectionModel->enableSync( false );
130-
selectRow( index, true );
131-
repaintRequested();
139+
QgsDebugMsg( "No model assigned to this view" );
132140
}
133141
}
134142

‎src/gui/editorwidgets/core/qgseditorwidgetwrapper.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,10 @@ QgsEditorWidgetWrapper* QgsEditorWidgetWrapper::fromWidget( QWidget* widget )
4242

4343
void QgsEditorWidgetWrapper::setEnabled( bool enabled )
4444
{
45-
if ( widget() )
45+
QWidget* wdg = widget();
46+
if ( wdg )
4647
{
47-
widget()->setEnabled( enabled );
48+
wdg->setEnabled( enabled );
4849
}
4950
}
5051

‎src/gui/editorwidgets/core/qgswidgetwrapper.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ void QgsWidgetWrapper::setConfig( const QgsEditorWidgetConfig& config )
4747
mConfig = config;
4848
}
4949

50-
void QgsWidgetWrapper::setContext( const QgsAttributeEditorContext& context )
50+
void QgsWidgetWrapper::setContext( const QgsAttributeEditorContext context )
5151
{
5252
mContext = context;
5353
}

‎src/gui/editorwidgets/core/qgswidgetwrapper.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ class GUI_EXPORT QgsWidgetWrapper : public QObject
7777
*
7878
* @param context context information
7979
*/
80-
void setContext( const QgsAttributeEditorContext& context );
80+
void setContext( const QgsAttributeEditorContext context );
8181

8282
/**
8383
* Use this inside your overriden classes to access the configuration.

‎src/gui/editorwidgets/qgsrelationreferencefactory.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,16 @@
1818
#include "qgsrelationreferencewidgetwrapper.h"
1919
#include "qgsrelreferenceconfigdlg.h"
2020

21-
QgsRelationReferenceFactory::QgsRelationReferenceFactory( QString name, QgsAttributeEditorContext context, QgsMapCanvas* canvas, QgsMessageBar* messageBar )
21+
QgsRelationReferenceFactory::QgsRelationReferenceFactory( QString name, QgsMapCanvas* canvas, QgsMessageBar* messageBar )
2222
: QgsEditorWidgetFactory( name )
23-
, mEditorContext( context )
2423
, mCanvas( canvas )
2524
, mMessageBar( messageBar )
2625
{
2726
}
2827

2928
QgsEditorWidgetWrapper* QgsRelationReferenceFactory::create( QgsVectorLayer* vl, int fieldIdx, QWidget* editor, QWidget* parent ) const
3029
{
31-
return new QgsRelationReferenceWidgetWrapper( vl, fieldIdx, editor, mEditorContext, mCanvas, mMessageBar, parent );
30+
return new QgsRelationReferenceWidgetWrapper( vl, fieldIdx, editor, mCanvas, mMessageBar, parent );
3231
}
3332

3433
QgsEditorConfigWidget* QgsRelationReferenceFactory::configWidget( QgsVectorLayer* vl, int fieldIdx, QWidget* parent ) const

‎src/gui/editorwidgets/qgsrelationreferencefactory.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class QgsMessageBar;
2525
class GUI_EXPORT QgsRelationReferenceFactory : public QgsEditorWidgetFactory
2626
{
2727
public:
28-
QgsRelationReferenceFactory( QString name, QgsAttributeEditorContext context, QgsMapCanvas* canvas, QgsMessageBar* messageBar );
28+
QgsRelationReferenceFactory( QString name, QgsMapCanvas* canvas, QgsMessageBar* messageBar );
2929

3030
/**
3131
* Override this in your implementation.

‎src/gui/editorwidgets/qgsrelationreferencewidget.cpp

Lines changed: 84 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <QHBoxLayout>
2121
#include <QTimer>
2222

23+
#include "qgsattributeform.h"
2324
#include "qgsattributedialog.h"
2425
#include "qgsapplication.h"
2526
#include "qgscollapsiblegroupbox.h"
@@ -43,14 +44,14 @@ QgsRelationReferenceWidget::QgsRelationReferenceWidget( QWidget* parent )
4344
, mFkeyFieldIdx( -1 )
4445
, mAllowNull( true )
4546
, mHighlight( NULL )
46-
, mInitialValueAssigned( false )
4747
, mMapTool( NULL )
4848
, mMessageBarItem( NULL )
4949
, mRelationName( "" )
50-
, mReferencedAttributeDialog( NULL )
50+
, mReferencedAttributeForm( NULL )
5151
, mReferencedLayer( NULL )
5252
, mReferencingLayer( NULL )
5353
, mWindowWidget( NULL )
54+
, mShown( false )
5455
, mEmbedForm( false )
5556
, mReadOnlySelector( false )
5657
, mAllowMapIdentification( false )
@@ -74,7 +75,7 @@ QgsRelationReferenceWidget::QgsRelationReferenceWidget( QWidget* parent )
7475

7576
// open form button
7677
mOpenFormButton = new QToolButton( this );
77-
mOpenFormAction = new QAction( QgsApplication::getThemeIcon( "/mActionToggleEditing.svg" ), tr( "Open related feature form" ), this );
78+
mOpenFormAction = new QAction( QgsApplication::getThemeIcon( "/mActionPropertyItem.png" ), tr( "Open related feature form" ), this );
7879
mOpenFormButton->addAction( mOpenFormAction );
7980
mOpenFormButton->setDefaultAction( mOpenFormAction );
8081
connect( mOpenFormButton, SIGNAL( triggered( QAction* ) ), this, SLOT( openForm() ) );
@@ -112,10 +113,9 @@ QgsRelationReferenceWidget::QgsRelationReferenceWidget( QWidget* parent )
112113

113114
// embed form
114115
mAttributeEditorFrame = new QgsCollapsibleGroupBox( this );
115-
mAttributeEditorFrame->setCollapsed( true );
116116
mAttributeEditorLayout = new QVBoxLayout( mAttributeEditorFrame );
117117
mAttributeEditorFrame->setLayout( mAttributeEditorLayout );
118-
mAttributeEditorFrame->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
118+
mAttributeEditorFrame->setSizePolicy( mAttributeEditorFrame->sizePolicy().horizontalPolicy(), QSizePolicy::Expanding );
119119
mTopLayout->addWidget( mAttributeEditorFrame );
120120

121121
// default mode is combobox, no geometric relation and no embed form
@@ -146,43 +146,21 @@ void QgsRelationReferenceWidget::setRelation( QgsRelation relation, bool allowNu
146146

147147
if ( relation.isValid() )
148148
{
149+
mRelation = relation;
149150
mReferencingLayer = relation.referencingLayer();
150151
mRelationName = relation.name();
151152
mReferencedLayer = relation.referencedLayer();
152153
mFkeyFieldIdx = mReferencedLayer->fieldNameIndex( relation.fieldPairs().first().second );
153154

154-
if ( !mReadOnlySelector )
155-
{
156-
mComboBox->clear();
157-
if ( allowNullValue )
158-
{
159-
const QString nullValue = QSettings().value( "qgis/nullValue", "NULL" ).toString();
160-
mComboBox->addItem( tr( "%1 (no selection)" ).arg( nullValue ) );
161-
mComboBox->setItemData( mComboBox->count() - 1, Qt::gray, Qt::ForegroundRole );
162-
}
163-
164-
QgsFeatureIterator fit = mReferencedLayer->getFeatures( QgsFeatureRequest() );
165-
166-
QgsExpression exp( mReferencedLayer->displayExpression() );
167-
exp.prepare( mReferencedLayer->pendingFields() );
168155

169-
QgsFeature f;
170-
while ( fit.nextFeature( f ) )
171-
{
172-
QString txt = exp.evaluate( &f ).toString();
156+
QgsAttributeEditorContext context( mEditorContext, relation, QgsAttributeEditorContext::EmbedSingle );
173157

174-
mComboBox->addItem( txt, f.id() );
175-
176-
mFidFkMap.insert( f.id(), f.attribute( mFkeyFieldIdx ) );
177-
}
178-
179-
// Only connect after iterating, to have only one iterator on the referenced table at once
180-
connect( mComboBox, SIGNAL( activated( int ) ), this, SLOT( comboReferenceChanged( int ) ) );
181-
}
182-
else
158+
if ( mEmbedForm )
183159
{
184-
mForeignKey = QVariant();
185-
mFeatureId = QgsFeatureId();
160+
mAttributeEditorFrame->setTitle( mReferencedLayer->name() );
161+
mReferencedAttributeForm = new QgsAttributeForm( relation.referencedLayer(), QgsFeature(), context, this );
162+
mReferencedAttributeForm->hideButtonBox();
163+
mAttributeEditorLayout->addWidget( mReferencedAttributeForm );
186164
}
187165
}
188166
else
@@ -194,6 +172,11 @@ void QgsRelationReferenceWidget::setRelation( QgsRelation relation, bool allowNu
194172
lbl->setFont( font );
195173
mTopLayout->addWidget( lbl, 1, 0 );
196174
}
175+
176+
if ( mShown && isVisible() )
177+
{
178+
init();
179+
}
197180
}
198181

199182
void QgsRelationReferenceWidget::setRelationEditable( bool editable )
@@ -215,6 +198,7 @@ void QgsRelationReferenceWidget::setRelatedFeature( const QVariant& value )
215198
if ( !mReferencedLayer )
216199
return;
217200

201+
// TODO: Rewrite using expression
218202
QgsFeatureIterator fit = mReferencedLayer->getFeatures( QgsFeatureRequest() );
219203
while ( fit.nextFeature( f ) )
220204
{
@@ -230,10 +214,11 @@ void QgsRelationReferenceWidget::setRelatedFeature( const QVariant& value )
230214
return;
231215
}
232216

217+
mForeignKey = f.attribute( mFkeyFieldIdx );
218+
233219
if ( mReadOnlySelector )
234220
{
235221
mLineEdit->setText( f.attribute( mFkeyFieldIdx ).toString() );
236-
mForeignKey = f.attribute( mFkeyFieldIdx );
237222
mFeatureId = f.id();
238223
}
239224
else
@@ -301,16 +286,19 @@ void QgsRelationReferenceWidget::mapToolDeactivated()
301286
QgsFeature QgsRelationReferenceWidget::relatedFeature()
302287
{
303288
QgsFeature f;
304-
QgsFeatureId fid;
305-
if ( mReadOnlySelector )
306-
{
307-
fid = mFeatureId;
308-
}
309-
else
289+
if ( mReferencedLayer )
310290
{
311-
fid = mComboBox->itemData( mComboBox->currentIndex() ).value<QgsFeatureId>();
291+
QgsFeatureId fid;
292+
if ( mReadOnlySelector )
293+
{
294+
fid = mFeatureId;
295+
}
296+
else
297+
{
298+
fid = mComboBox->itemData( mComboBox->currentIndex() ).value<QgsFeatureId>();
299+
}
300+
mReferencedLayer->getFeatures( QgsFeatureRequest().setFilterFid( fid ) ).nextFeature( f );
312301
}
313-
mReferencedLayer->getFeatures( QgsFeatureRequest().setFilterFid( fid ) ).nextFeature( f );
314302
return f;
315303
}
316304

@@ -361,6 +349,53 @@ void QgsRelationReferenceWidget::setAllowMapIdentification( bool allowMapIdentif
361349
mAllowMapIdentification = allowMapIdentification;
362350
}
363351

352+
void QgsRelationReferenceWidget::showEvent( QShowEvent* e )
353+
{
354+
Q_UNUSED( e )
355+
356+
mShown = true;
357+
358+
init();
359+
}
360+
361+
void QgsRelationReferenceWidget::init()
362+
{
363+
if ( !mReadOnlySelector && mComboBox->count() == 0 && mReferencedLayer )
364+
{
365+
if ( mAllowNull )
366+
{
367+
const QString nullValue = QSettings().value( "qgis/nullValue", "NULL" ).toString();
368+
369+
mComboBox->addItem( tr( "%1 (no selection)" ).arg( nullValue ), QVariant( QVariant::Int ) );
370+
mComboBox->setItemData( 0, QColor( Qt::gray ), Qt::ForegroundRole );
371+
}
372+
373+
QgsExpression exp( mReferencedLayer->displayExpression() );
374+
375+
QStringList attrs = exp.referencedColumns();
376+
attrs << mRelation.fieldPairs().first().second;
377+
378+
QgsFeatureIterator fit = mReferencedLayer->getFeatures( QgsFeatureRequest().setFlags( QgsFeatureRequest::NoGeometry ).setSubsetOfAttributes( attrs, mReferencedLayer->pendingFields() ) );
379+
380+
exp.prepare( mReferencedLayer->pendingFields() );
381+
382+
QgsFeature f;
383+
while ( fit.nextFeature( f ) )
384+
{
385+
QString txt = exp.evaluate( &f ).toString();
386+
mComboBox->addItem( txt, f.id() );
387+
388+
if ( f.attribute( mFkeyFieldIdx ) == mForeignKey )
389+
mComboBox->setCurrentIndex( mComboBox->count() - 1 );
390+
391+
mFidFkMap.insert( f.id(), f.attribute( mFkeyFieldIdx ) );
392+
}
393+
394+
// Only connect after iterating, to have only one iterator on the referenced table at once
395+
connect( mComboBox, SIGNAL( activated( int ) ), this, SLOT( comboReferenceChanged( int ) ) );
396+
}
397+
}
398+
364399
void QgsRelationReferenceWidget::highlightActionTriggered( QAction* action )
365400
{
366401
if ( action == mHighlightFeatureAction )
@@ -384,10 +419,9 @@ void QgsRelationReferenceWidget::openForm()
384419
if ( !feat.isValid() )
385420
return;
386421

387-
// TODO: Get a proper QgsDistanceArea thingie
388-
mReferencedAttributeDialog = new QgsAttributeDialog( mReferencedLayer, new QgsFeature( feat ), true, this, true, mEditorContext );
389-
mReferencedAttributeDialog->exec();
390-
delete mReferencedAttributeDialog;
422+
QgsAttributeEditorContext context( mEditorContext, mRelation, QgsAttributeEditorContext::StandaloneSingle );
423+
QgsAttributeDialog attributeDialog( mReferencedLayer, new QgsFeature( feat ), true, this, true, context );
424+
attributeDialog.exec();
391425
}
392426

393427
void QgsRelationReferenceWidget::highlightFeature( QgsFeature f, CanvasExtent canvasExtent )
@@ -473,7 +507,7 @@ void QgsRelationReferenceWidget::mapIdentificationTriggered( QAction* action )
473507
if ( !mReferencedLayer )
474508
return;
475509

476-
QgsVectorLayerTools* tools = mEditorContext.vectorLayerTools();
510+
const QgsVectorLayerTools* tools = mEditorContext.vectorLayerTools();
477511
if ( !tools )
478512
return;
479513
if ( !mCanvas )
@@ -511,17 +545,9 @@ void QgsRelationReferenceWidget::updateAttributeEditorFrame( const QgsFeature fe
511545
// Check if we're running with an embedded frame we need to update
512546
if ( mAttributeEditorFrame )
513547
{
514-
if ( feature.isValid() )
548+
if ( feature.isValid() && mReferencedAttributeForm )
515549
{
516-
if ( mReferencedAttributeDialog )
517-
{
518-
mAttributeEditorLayout->removeWidget( mReferencedAttributeDialog );
519-
}
520-
// TODO: Get a proper QgsDistanceArea thingie
521-
mReferencedAttributeDialog = new QgsAttributeDialog( mReferencedLayer, new QgsFeature( feature ), true, mAttributeEditorFrame, false, mEditorContext );
522-
mReferencedAttributeDialog->setWindowFlags( Qt::Widget ); // Embed instead of opening as window
523-
mAttributeEditorLayout->addWidget( mReferencedAttributeDialog );
524-
mReferencedAttributeDialog->show();
550+
mReferencedAttributeForm->setFeature( feature );
525551
}
526552
}
527553
}

‎src/gui/editorwidgets/qgsrelationreferencewidget.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
#include <QLineEdit>
2828
#include <QVBoxLayout>
2929

30-
class QgsAttributeDialog;
30+
class QgsAttributeForm;
3131
class QgsVectorLayerTools;
3232

3333
class GUI_EXPORT QgsRelationReferenceWidget : public QWidget
@@ -67,6 +67,11 @@ class GUI_EXPORT QgsRelationReferenceWidget : public QWidget
6767
bool allowMapIdentification() {return mAllowMapIdentification;}
6868
void setAllowMapIdentification( bool allowMapIdentification );
6969

70+
protected:
71+
virtual void showEvent( QShowEvent* e );
72+
73+
void init();
74+
7075
signals:
7176
void relatedFeatureChanged( QVariant );
7277

@@ -95,14 +100,15 @@ class GUI_EXPORT QgsRelationReferenceWidget : public QWidget
95100
int mFkeyFieldIdx;
96101
bool mAllowNull;
97102
QgsHighlight* mHighlight;
98-
bool mInitialValueAssigned;
99103
QgsMapToolIdentifyFeature* mMapTool;
100104
QgsMessageBarItem* mMessageBarItem;
101105
QString mRelationName;
102-
QgsAttributeDialog* mReferencedAttributeDialog;
106+
QgsAttributeForm* mReferencedAttributeForm;
103107
QgsVectorLayer* mReferencedLayer;
104108
QgsVectorLayer* mReferencingLayer;
105109
QWidget* mWindowWidget;
110+
bool mShown;
111+
QgsRelation mRelation;
106112

107113
// Q_PROPERTY
108114
bool mEmbedForm;

‎src/gui/editorwidgets/qgsrelationreferencewidgetwrapper.cpp

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,18 @@
1919
#include "qgsrelationmanager.h"
2020

2121

22-
QgsRelationReferenceWidgetWrapper::QgsRelationReferenceWidgetWrapper( QgsVectorLayer* vl, int fieldIdx, QWidget* editor, QgsAttributeEditorContext context, QgsMapCanvas* canvas, QgsMessageBar* messageBar, QWidget* parent )
22+
QgsRelationReferenceWidgetWrapper::QgsRelationReferenceWidgetWrapper( QgsVectorLayer* vl, int fieldIdx, QWidget* editor, QgsMapCanvas* canvas, QgsMessageBar* messageBar, QWidget* parent )
2323
: QgsEditorWidgetWrapper( vl, fieldIdx, editor, parent )
24-
, mEditorContext( context )
2524
, mCanvas( canvas )
2625
, mMessageBar( messageBar )
2726
{
2827
}
2928

3029
QWidget* QgsRelationReferenceWidgetWrapper::createWidget( QWidget* parent )
3130
{
32-
return new QgsRelationReferenceWidget( parent );
31+
QgsRelationReferenceWidget* w = new QgsRelationReferenceWidget( parent );
32+
w->setSizePolicy( w->sizePolicy().horizontalPolicy(), QSizePolicy::Expanding );
33+
return w;
3334
}
3435

3536
void QgsRelationReferenceWidgetWrapper::initWidget( QWidget* editor )
@@ -42,16 +43,32 @@ void QgsRelationReferenceWidgetWrapper::initWidget( QWidget* editor )
4243

4344
mWidget = w;
4445

45-
mWidget->setEditorContext( mEditorContext, mCanvas, mMessageBar );
46+
mWidget->setEditorContext( context(), mCanvas, mMessageBar );
4647

4748
bool showForm = config( "ShowForm", true ).toBool();
4849
bool mapIdent = config( "MapIdentification", false ).toBool();
4950
bool readOnlyWidget = config( "ReadOnly", false ).toBool();
51+
5052
mWidget->setEmbedForm( showForm );
51-
mWidget->setAllowMapIdentification( mapIdent );
5253
mWidget->setReadOnlySelector( readOnlyWidget );
54+
mWidget->setAllowMapIdentification( mapIdent );
5355

5456
QgsRelation relation = QgsProject::instance()->relationManager()->relation( config( "Relation" ).toString() );
57+
58+
// If this widget is already embedded by the same relation, reduce functionality
59+
const QgsAttributeEditorContext* ctx = &context();
60+
do
61+
{
62+
if ( ctx->relation().name() == relation.name() )
63+
{
64+
mWidget->setEmbedForm( false );
65+
mWidget->setReadOnlySelector( false );
66+
mWidget->setAllowMapIdentification( false );
67+
}
68+
ctx = ctx->parentContext();
69+
}
70+
while ( ctx );
71+
5572
mWidget->setRelation( relation, config( "AllowNULL" ).toBool() );
5673

5774
connect( mWidget, SIGNAL( relatedFeatureChanged( QVariant ) ), this, SLOT( relatedFeatureChanged( QVariant ) ) );

‎src/gui/editorwidgets/qgsrelationreferencewidgetwrapper.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ class GUI_EXPORT QgsRelationReferenceWidgetWrapper : public QgsEditorWidgetWrapp
2626
explicit QgsRelationReferenceWidgetWrapper( QgsVectorLayer* vl,
2727
int fieldIdx,
2828
QWidget* editor,
29-
QgsAttributeEditorContext context,
3029
QgsMapCanvas* canvas,
3130
QgsMessageBar* messageBar,
3231
QWidget* parent = 0 );
@@ -44,7 +43,6 @@ class GUI_EXPORT QgsRelationReferenceWidgetWrapper : public QgsEditorWidgetWrapp
4443

4544
private:
4645
QgsRelationReferenceWidget* mWidget;
47-
QgsAttributeEditorContext mEditorContext;
4846
QgsMapCanvas* mCanvas;
4947
QgsMessageBar* mMessageBar;
5048
};

‎src/gui/editorwidgets/qgsrelationwidgetwrapper.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "qgsrelationwidgetwrapper.h"
1717

1818
#include "qgsrelationeditorwidget.h"
19+
#include "qgsattributeeditorcontext.h"
1920

2021
#include <QWidget>
2122

@@ -24,7 +25,6 @@ QgsRelationWidgetWrapper::QgsRelationWidgetWrapper( QgsVectorLayer* vl, const Qg
2425
, mRelation( relation )
2526
, mWidget( NULL )
2627
{
27-
initWidget( editor );
2828
}
2929

3030
QWidget* QgsRelationWidgetWrapper::createWidget( QWidget* parent )
@@ -35,7 +35,7 @@ QWidget* QgsRelationWidgetWrapper::createWidget( QWidget* parent )
3535
void QgsRelationWidgetWrapper::setFeature( const QgsFeature& feature )
3636
{
3737
if ( mWidget )
38-
mWidget->setRelationFeature( mRelation, feature, context() );
38+
mWidget->setRelationFeature( mRelation, feature );
3939
}
4040

4141
void QgsRelationWidgetWrapper::initWidget( QWidget* editor )
@@ -48,5 +48,23 @@ void QgsRelationWidgetWrapper::initWidget( QWidget* editor )
4848
w = new QgsRelationEditorWidget( editor );
4949
}
5050

51+
QgsAttributeEditorContext myContext( QgsAttributeEditorContext( context(), mRelation, QgsAttributeEditorContext::EmbedMultiple ) );
52+
53+
w->setEditorContext( myContext );
54+
55+
// If this widget is already embedded by the same relation, reduce functionality
56+
const QgsAttributeEditorContext* ctx = &context();
57+
do
58+
{
59+
if ( ctx->relation().name() == mRelation.name() && ctx->relationMode() == QgsAttributeEditorContext::EmbedMultiple )
60+
{
61+
w->setSaveCollapsedState( false );
62+
w->setCollapsed( true );
63+
break;
64+
}
65+
ctx = ctx->parentContext();
66+
}
67+
while ( ctx );
68+
5169
mWidget = w;
5270
}

‎src/gui/editorwidgets/qgsuniquevaluewidgetwrapper.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,10 @@ void QgsUniqueValuesWidgetWrapper::initWidget( QWidget* editor )
6363
mComboBox->addItem( v.toString(), v );
6464
}
6565

66-
sValues << v.toString();
66+
if ( mLineEdit )
67+
{
68+
sValues << v.toString();
69+
}
6770
}
6871

6972
if ( mLineEdit )

‎src/gui/qgsattributedialog.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include "qgsattributeform.h"
2121
#include "qgshighlight.h"
22+
#include "qgsapplication.h"
2223

2324
#include <QSettings>
2425
#include <QGridLayout>
@@ -30,6 +31,7 @@ QgsAttributeDialog::QgsAttributeDialog( QgsVectorLayer* vl, QgsFeature* thepFeat
3031
{
3132
QgsAttributeEditorContext context;
3233
context.setDistanceArea( myDa );
34+
3335
init( vl, thepFeature, context, parent );
3436

3537
if ( !showDialogButtons )

‎src/gui/qgsattributeeditorcontext.cpp

Lines changed: 0 additions & 27 deletions
This file was deleted.

‎src/gui/qgsattributeeditorcontext.h

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,34 +33,63 @@
3333
class GUI_EXPORT QgsAttributeEditorContext
3434
{
3535
public:
36-
QgsAttributeEditorContext();
36+
/**
37+
* Determines in which direction a relation was resolved.
38+
*/
39+
enum RelationMode
40+
{
41+
Undefined, //!< This context is not defined by a relation
42+
EmbedMultiple, //!< When embedding a list of features (e.g. houses as an embedded form in a district form)
43+
EmbedSingle, //!< When embedding a single feature (e.g. district information when looking at the form of a house)
44+
StandaloneSingle //!< When showing a new dialog for a single feature (e.g. district information when looking at the form of a house)
45+
};
3746

38-
QWidget* proxyWidget( QgsVectorLayer* vl, int fieldIdx );
39-
//! @note not available in python bindings
40-
void addProxyWidgets( QgsVectorLayer* vl, QMap<int, QWidget*> proxyWidgets );
41-
void addProxyWidget( QgsVectorLayer* vl, int idx, QWidget* widget );
47+
public:
48+
QgsAttributeEditorContext()
49+
: mParentContext( 0 )
50+
, mLayer( 0 )
51+
, mVectorLayerTools( 0 )
52+
, mRelationMode( Undefined )
53+
{}
4254

43-
void setDistanceArea( const QgsDistanceArea& distanceArea ) { mDistanceArea = distanceArea; }
44-
inline const QgsDistanceArea& distanceArea() { return mDistanceArea; }
55+
QgsAttributeEditorContext( const QgsAttributeEditorContext& parentContext, const QgsRelation& relation, RelationMode mode )
56+
: mParentContext( &parentContext )
57+
, mLayer( 0 )
58+
, mVectorLayerTools( parentContext.mVectorLayerTools )
59+
, mDistanceArea( parentContext.mDistanceArea )
60+
, mRelation( relation )
61+
, mRelationMode( mode )
62+
{
63+
Q_ASSERT( parentContext.vectorLayerTools() );
64+
}
4565

46-
void setVectorLayerTools( QgsVectorLayerTools* vlTools ) { mVectorLayerTools = vlTools; }
47-
QgsVectorLayerTools* vectorLayerTools() { return mVectorLayerTools; }
66+
inline void setDistanceArea( const QgsDistanceArea& distanceArea )
67+
{
68+
if ( mLayer )
69+
{
70+
mDistanceArea = distanceArea;
71+
mDistanceArea.setSourceCrs( mLayer->crs() );
72+
}
73+
}
4874

49-
/**
50-
* When copying the context for another layer, call this.
51-
* Will adjast the distance area for this layer
52-
*
53-
* @param layer The layer to adjust for.
54-
*/
55-
void adjustForLayer( QgsVectorLayer* layer );
75+
inline const QgsDistanceArea& distanceArea() const { return mDistanceArea; }
5676

57-
private:
58-
QgsVectorLayerTools* mVectorLayerTools;
77+
inline void setVectorLayerTools( QgsVectorLayerTools* vlTools ) { mVectorLayerTools = vlTools; }
78+
inline const QgsVectorLayerTools* vectorLayerTools() const { return mVectorLayerTools; }
79+
80+
inline void setRelation( const QgsRelation& relation, RelationMode mode ) { mRelation = relation; mRelationMode = mode; }
81+
inline const QgsRelation& relation() const { return mRelation; }
82+
inline RelationMode relationMode() const { return mRelationMode; }
5983

60-
//! vectorlayer => ( fieldIdx, proxyWidget )
61-
QMap<QgsVectorLayer*, QMap<int, QWidget*> > mProxyWidgets;
84+
inline const QgsAttributeEditorContext* parentContext() const { return mParentContext; }
6285

86+
private:
87+
const QgsAttributeEditorContext* mParentContext;
88+
QgsVectorLayer* mLayer;
89+
QgsVectorLayerTools* mVectorLayerTools;
6390
QgsDistanceArea mDistanceArea;
91+
QgsRelation mRelation;
92+
RelationMode mRelationMode;
6493
};
6594

6695
#endif // QGSATTRIBUTEEDITORCONTEXT_H

‎src/gui/qgsattributeform.cpp

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ QgsAttributeForm::QgsAttributeForm( QgsVectorLayer* vl, const QgsFeature feature
4141
: QWidget( parent )
4242
, mLayer( vl )
4343
, mContext( context )
44+
, mButtonBox( 0 )
4445
, mFormNr( sFormCounter++ )
4546
, mIsSaving( false )
4647
, mIsAddDialog( false )
@@ -101,7 +102,7 @@ void QgsAttributeForm::setIsAddDialog( bool isAddDialog )
101102

102103
void QgsAttributeForm::changeAttribute( const QString& field, const QVariant& value )
103104
{
104-
Q_FOREACH ( QgsWidgetWrapper* ww, mWidgets )
105+
Q_FOREACH( QgsWidgetWrapper* ww, mWidgets )
105106
{
106107
QgsEditorWidgetWrapper* eww = qobject_cast<QgsEditorWidgetWrapper*>( ww );
107108
if ( eww && eww->field().name() == field )
@@ -119,7 +120,7 @@ void QgsAttributeForm::setFeature( const QgsFeature& feature )
119120

120121
synchronizeEnabledState();
121122

122-
Q_FOREACH ( QgsAttributeFormInterface* iface, mInterfaces )
123+
Q_FOREACH( QgsAttributeFormInterface* iface, mInterfaces )
123124
{
124125
iface->featureChanged();
125126
}
@@ -154,7 +155,7 @@ bool QgsAttributeForm::save()
154155
QgsAttributes src = mFeature.attributes();
155156
QgsAttributes dst = mFeature.attributes();
156157

157-
Q_FOREACH ( QgsWidgetWrapper* ww, mWidgets )
158+
Q_FOREACH( QgsWidgetWrapper* ww, mWidgets )
158159
{
159160
QgsEditorWidgetWrapper* eww = qobject_cast<QgsEditorWidgetWrapper*>( ww );
160161
if ( eww )
@@ -174,7 +175,7 @@ bool QgsAttributeForm::save()
174175

175176
updatedFeature.setAttributes( dst );
176177

177-
Q_FOREACH ( QgsAttributeFormInterface* iface, mInterfaces )
178+
Q_FOREACH( QgsAttributeFormInterface* iface, mInterfaces )
178179
{
179180
if ( !iface->acceptChanges( updatedFeature ) )
180181
{
@@ -242,7 +243,7 @@ bool QgsAttributeForm::save()
242243

243244
void QgsAttributeForm::resetValues()
244245
{
245-
Q_FOREACH ( QgsWidgetWrapper* ww, mWidgets )
246+
Q_FOREACH( QgsWidgetWrapper* ww, mWidgets )
246247
{
247248
ww->setFeature( mFeature );
248249
}
@@ -289,7 +290,7 @@ void QgsAttributeForm::synchronizeEnabledState()
289290
{
290291
bool isEditable = ( mFeature.isValid() || mIsAddDialog ) && mLayer->isEditable();
291292

292-
Q_FOREACH ( QgsWidgetWrapper* ww, mWidgets )
293+
Q_FOREACH( QgsWidgetWrapper* ww, mWidgets )
293294
{
294295
bool fieldEditable = true;
295296
QgsEditorWidgetWrapper* eww = qobject_cast<QgsEditorWidgetWrapper*>( ww );
@@ -337,6 +338,7 @@ void QgsAttributeForm::init()
337338
layout()->addWidget( formWidget );
338339
formWidget->show();
339340
file.close();
341+
mButtonBox = findChild<QDialogButtonBox*>();
340342
createWrappers();
341343

342344
formWidget->installEventFilter( this );
@@ -349,7 +351,7 @@ void QgsAttributeForm::init()
349351
QTabWidget* tabWidget = new QTabWidget( this );
350352
layout()->addWidget( tabWidget );
351353

352-
Q_FOREACH ( QgsAttributeEditorElement *widgDef, mLayer->attributeEditorElements() )
354+
Q_FOREACH( QgsAttributeEditorElement *widgDef, mLayer->attributeEditorElements() )
353355
{
354356
QWidget* tabPage = new QWidget( tabWidget );
355357

@@ -391,7 +393,7 @@ void QgsAttributeForm::init()
391393
layout()->addWidget( scrollArea );
392394

393395
int row = 0;
394-
Q_FOREACH ( const QgsField& field, mLayer->pendingFields().toList() )
396+
Q_FOREACH( const QgsField& field, mLayer->pendingFields().toList() )
395397
{
396398
int idx = mLayer->fieldNameIndex( field.name() );
397399
//show attribute alias if available
@@ -428,7 +430,7 @@ void QgsAttributeForm::init()
428430
}
429431
}
430432

431-
Q_FOREACH ( const QgsRelation& rel, QgsProject::instance()->relationManager()->referencedRelations( mLayer ) )
433+
Q_FOREACH( const QgsRelation& rel, QgsProject::instance()->relationManager()->referencedRelations( mLayer ) )
432434
{
433435
QgsRelationWidgetWrapper* rww = new QgsRelationWidgetWrapper( mLayer, rel, 0, this );
434436
rww->setContext( mContext );
@@ -437,8 +439,6 @@ void QgsAttributeForm::init()
437439
}
438440
}
439441

440-
mButtonBox = findChild<QDialogButtonBox*>();
441-
442442
if ( !mButtonBox )
443443
{
444444
mButtonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
@@ -454,7 +454,7 @@ void QgsAttributeForm::init()
454454
connect( mLayer, SIGNAL( editingStarted() ), this, SLOT( synchronizeEnabledState() ) );
455455
connect( mLayer, SIGNAL( editingStopped() ), this, SLOT( synchronizeEnabledState() ) );
456456

457-
Q_FOREACH ( QgsAttributeFormInterface* iface, mInterfaces )
457+
Q_FOREACH( QgsAttributeFormInterface* iface, mInterfaces )
458458
{
459459
iface->initForm();
460460
}
@@ -598,7 +598,7 @@ QWidget* QgsAttributeForm::createWidgetFromDef( const QgsAttributeEditorElement
598598

599599
QList<QgsAttributeEditorElement*> children = container->children();
600600

601-
Q_FOREACH ( QgsAttributeEditorElement* childDef, children )
601+
Q_FOREACH( QgsAttributeEditorElement* childDef, children )
602602
{
603603
QString labelText;
604604
bool labelOnTop;
@@ -643,7 +643,7 @@ QWidget* QgsAttributeForm::createWidgetFromDef( const QgsAttributeEditorElement
643643

644644
void QgsAttributeForm::addWidgetWrapper( QgsEditorWidgetWrapper* eww )
645645
{
646-
Q_FOREACH ( QgsWidgetWrapper* ww, mWidgets )
646+
Q_FOREACH( QgsWidgetWrapper* ww, mWidgets )
647647
{
648648
QgsEditorWidgetWrapper* meww = qobject_cast<QgsEditorWidgetWrapper*>( ww );
649649
if ( meww )
@@ -665,7 +665,7 @@ void QgsAttributeForm::createWrappers()
665665
QList<QWidget*> myWidgets = findChildren<QWidget*>();
666666
const QList<QgsField> fields = mLayer->pendingFields().toList();
667667

668-
Q_FOREACH ( QWidget* myWidget, myWidgets )
668+
Q_FOREACH( QWidget* myWidget, myWidgets )
669669
{
670670
// Check the widget's properties for a relation definition
671671
QVariant vRel = myWidget->property( "qgisRelation" );
@@ -678,12 +678,13 @@ void QgsAttributeForm::createWrappers()
678678
QgsRelationWidgetWrapper* rww = new QgsRelationWidgetWrapper( mLayer, relation, myWidget, this );
679679
rww->setConfig( QgsEditorWidgetConfig() );
680680
rww->setContext( mContext );
681+
rww->widget(); // Will initialize the widget
681682
mWidgets.append( rww );
682683
}
683684
}
684685
else
685686
{
686-
Q_FOREACH ( const QgsField& field, fields )
687+
Q_FOREACH( const QgsField& field, fields )
687688
{
688689
if ( field.name() == myWidget->objectName() )
689690
{
@@ -703,7 +704,7 @@ void QgsAttributeForm::connectWrappers()
703704
{
704705
bool isFirstEww = true;
705706

706-
Q_FOREACH ( QgsWidgetWrapper* ww, mWidgets )
707+
Q_FOREACH( QgsWidgetWrapper* ww, mWidgets )
707708
{
708709
QgsEditorWidgetWrapper* eww = qobject_cast<QgsEditorWidgetWrapper*>( ww );
709710

‎src/gui/qgsrelationeditorwidget.cpp

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ QgsRelationEditorWidget::QgsRelationEditorWidget( QWidget* parent )
3434
, mEditorContext( QgsAttributeEditorContext() )
3535
, mRelation( QgsRelation() )
3636
, mFeature( QgsFeature() )
37+
, mInitialized( false )
3738
{
3839
QVBoxLayout* topLayout = new QVBoxLayout( this );
3940
topLayout->setContentsMargins( 0, 9, 0, 0 );
@@ -47,6 +48,8 @@ QgsRelationEditorWidget::QgsRelationEditorWidget( QWidget* parent )
4748
QAction* toggleEditingAction = new QAction( QgsApplication::getThemeIcon( "/mActionToggleEditing.svg" ), tr( "Toggle editing" ), this );
4849
mToggleEditingButton->addAction( toggleEditingAction );
4950
mToggleEditingButton->setDefaultAction( toggleEditingAction );
51+
mToggleEditingButton->setEnabled( false );
52+
mToggleEditingButton->setCheckable( true );
5053
buttonLayout->addWidget( mToggleEditingButton );
5154
// add feature
5255
mAddFeatureButton = new QToolButton( this );
@@ -110,13 +113,20 @@ QgsRelationEditorWidget::QgsRelationEditorWidget( QWidget* parent )
110113
mDualView = new QgsDualView( this );
111114
mDualView->setView( mViewMode );
112115
mFeatureSelectionMgr = new QgsGenericFeatureSelectionManager( mDualView );
116+
mDualView->setFeatureSelectionManager( mFeatureSelectionMgr );
117+
113118
mRelationLayout->addWidget( mDualView );
114119

115120
connect( this, SIGNAL( collapsedStateChanged( bool ) ), this, SLOT( onCollapsedStateChanged( bool ) ) );
116121
connect( mViewModeButtonGroup, SIGNAL( buttonClicked( int ) ), this, SLOT( setViewMode( int ) ) );
122+
connect( mToggleEditingButton, SIGNAL( clicked( bool ) ), this, SLOT( toggleEditing( bool ) ) );
123+
connect( mAddFeatureButton, SIGNAL( clicked() ), this, SLOT( addFeature() ) );
124+
connect( mDeleteFeatureButton, SIGNAL( clicked() ), this, SLOT( deleteFeature() ) );
125+
connect( mLinkFeatureButton, SIGNAL( clicked() ), this, SLOT( linkFeature() ) );
126+
connect( mUnlinkFeatureButton, SIGNAL( clicked() ), this, SLOT( unlinkFeature() ) );
117127
}
118128

119-
void QgsRelationEditorWidget::setRelationFeature( const QgsRelation& relation, const QgsFeature& feature, const QgsAttributeEditorContext& context )
129+
void QgsRelationEditorWidget::setRelationFeature( const QgsRelation& relation, const QgsFeature& feature )
120130
{
121131
if ( mRelation.isValid() )
122132
{
@@ -126,7 +136,6 @@ void QgsRelationEditorWidget::setRelationFeature( const QgsRelation& relation, c
126136

127137
mRelation = relation;
128138
mFeature = feature;
129-
mEditorContext = context;
130139

131140
connect( mRelation.referencingLayer(), SIGNAL( editingStarted() ), this, SLOT( referencingLayerEditingToggled() ) );
132141
connect( mRelation.referencingLayer(), SIGNAL( editingStopped() ), this, SLOT( referencingLayerEditingToggled() ) );
@@ -137,13 +146,11 @@ void QgsRelationEditorWidget::setRelationFeature( const QgsRelation& relation, c
137146

138147
bool canChangeAttributes = lyr->dataProvider()->capabilities() & QgsVectorDataProvider::ChangeAttributeValues;
139148
mToggleEditingButton->setEnabled( canChangeAttributes && !lyr->isReadOnly() );
149+
}
140150

141-
142-
mDualView->setFeatureSelectionManager( mFeatureSelectionMgr );
143-
144-
QgsFeatureRequest myRequest = relation.getRelatedFeaturesRequest( feature );
145-
146-
mDualView->init( relation.referencingLayer(), NULL, myRequest, context );
151+
void QgsRelationEditorWidget::setEditorContext( const QgsAttributeEditorContext& context )
152+
{
153+
mEditorContext = context;
147154
}
148155

149156
void QgsRelationEditorWidget::setViewMode( QgsDualView::ViewMode mode )
@@ -154,14 +161,6 @@ void QgsRelationEditorWidget::setViewMode( QgsDualView::ViewMode mode )
154161
mFormViewButton->setChecked( mViewMode == QgsDualView::AttributeEditor );
155162
}
156163

157-
void QgsRelationEditorWidget::onCollapsedStateChanged( bool state )
158-
{
159-
if ( state && !mDualView->masterModel() )
160-
{
161-
// TODO: Lazy init dual view if collapsed on init
162-
}
163-
}
164-
165164
void QgsRelationEditorWidget::referencingLayerEditingToggled()
166165
{
167166
bool editable = false;
@@ -177,35 +176,35 @@ void QgsRelationEditorWidget::referencingLayerEditingToggled()
177176
mToggleEditingButton->setChecked( editable );
178177
}
179178

180-
void QgsRelationEditorWidget::on_mAddFeatureButton_clicked()
179+
void QgsRelationEditorWidget::addFeature()
181180
{
182181
QgsAttributeMap keyAttrs;
183182

184183
QgsFields fields = mRelation.referencingLayer()->pendingFields();
185184

186-
foreach ( QgsRelation::FieldPair fieldPair, mRelation.fieldPairs() )
185+
Q_FOREACH( QgsRelation::FieldPair fieldPair, mRelation.fieldPairs() )
187186
{
188187
keyAttrs.insert( fields.indexFromName( fieldPair.referencingField() ), mFeature.attribute( fieldPair.referencedField() ) );
189188
}
190189

191190
mEditorContext.vectorLayerTools()->addFeature( mDualView->masterModel()->layer(), keyAttrs );
192191
}
193192

194-
void QgsRelationEditorWidget::on_mLinkFeatureButton_clicked()
193+
void QgsRelationEditorWidget::linkFeature()
195194
{
196195
QgsFeatureSelectionDlg selectionDlg( mRelation.referencingLayer(), this );
197196

198197
if ( selectionDlg.exec() )
199198
{
200199
QMap<int, QVariant> keys;
201-
foreach ( const QgsRelation::FieldPair fieldPair, mRelation.fieldPairs() )
200+
Q_FOREACH( const QgsRelation::FieldPair fieldPair, mRelation.fieldPairs() )
202201
{
203202
int idx = mRelation.referencingLayer()->fieldNameIndex( fieldPair.referencingField() );
204203
QVariant val = mFeature.attribute( fieldPair.referencedField() );
205204
keys.insert( idx, val );
206205
}
207206

208-
foreach ( QgsFeatureId fid, selectionDlg.selectedFeatures() )
207+
Q_FOREACH( QgsFeatureId fid, selectionDlg.selectedFeatures() )
209208
{
210209
QMapIterator<int, QVariant> it( keys );
211210
while ( it.hasNext() )
@@ -217,25 +216,25 @@ void QgsRelationEditorWidget::on_mLinkFeatureButton_clicked()
217216
}
218217
}
219218

220-
void QgsRelationEditorWidget::on_mDeleteFeatureButton_clicked()
219+
void QgsRelationEditorWidget::deleteFeature()
221220
{
222-
foreach ( QgsFeatureId fid, mFeatureSelectionMgr->selectedFeaturesIds() )
221+
Q_FOREACH( QgsFeatureId fid, mFeatureSelectionMgr->selectedFeaturesIds() )
223222
{
224223
mRelation.referencingLayer()->deleteFeature( fid );
225224
}
226225
}
227226

228-
void QgsRelationEditorWidget::on_mUnlinkFeatureButton_clicked()
227+
void QgsRelationEditorWidget::unlinkFeature()
229228
{
230229
QMap<int, QgsField> keyFields;
231-
foreach ( const QgsRelation::FieldPair fieldPair, mRelation.fieldPairs() )
230+
Q_FOREACH( const QgsRelation::FieldPair fieldPair, mRelation.fieldPairs() )
232231
{
233232
int idx = mRelation.referencingLayer()->fieldNameIndex( fieldPair.referencingField() );
234233
QgsField fld = mRelation.referencingLayer()->pendingFields().at( idx );
235234
keyFields.insert( idx, fld );
236235
}
237236

238-
foreach ( QgsFeatureId fid, mFeatureSelectionMgr->selectedFeaturesIds() )
237+
Q_FOREACH( QgsFeatureId fid, mFeatureSelectionMgr->selectedFeaturesIds() )
239238
{
240239
QMapIterator<int, QgsField> it( keyFields );
241240
while ( it.hasNext() )
@@ -246,14 +245,26 @@ void QgsRelationEditorWidget::on_mUnlinkFeatureButton_clicked()
246245
}
247246
}
248247

249-
void QgsRelationEditorWidget::on_mToggleEditingButton_toggled( bool state )
248+
void QgsRelationEditorWidget::toggleEditing( bool state )
250249
{
251250
if ( state )
252251
{
253-
mEditorContext.vectorLayerTools()->startEditing( mRelation.referencingLayer() );
252+
mEditorContext.vectorLayerTools()->stopEditing( mRelation.referencingLayer() );
254253
}
255254
else
256255
{
257-
mEditorContext.vectorLayerTools()->stopEditing( mRelation.referencingLayer() );
256+
mEditorContext.vectorLayerTools()->startEditing( mRelation.referencingLayer() );
257+
}
258+
}
259+
260+
void QgsRelationEditorWidget::onCollapsedStateChanged( bool collapsed )
261+
{
262+
if ( !mInitialized && !collapsed && mRelation.isValid() )
263+
{
264+
mInitialized = true;
265+
266+
QgsFeatureRequest myRequest = mRelation.getRelatedFeaturesRequest( mFeature );
267+
268+
mDualView->init( mRelation.referencingLayer(), 0, myRequest, mEditorContext );
258269
}
259270
}

‎src/gui/qgsrelationeditorwidget.h

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,18 +52,20 @@ class GUI_EXPORT QgsRelationEditorWidget : public QgsCollapsibleGroupBox
5252
void setQgisRelation( QString qgisRelationId ) { mRelationId = qgisRelationId; }
5353
QString qgisRelation() { return mRelationId; } //property( "qgisRelation" ).toString()
5454

55-
void setRelationFeature( const QgsRelation& relation, const QgsFeature& feature, const QgsAttributeEditorContext& context );
55+
void setRelationFeature( const QgsRelation& relation, const QgsFeature& feature );
56+
57+
void setEditorContext( const QgsAttributeEditorContext& context );
5658

5759
private slots:
5860
void setViewMode( int mode ) {setViewMode( static_cast<QgsDualView::ViewMode>( mode ) );}
59-
void onCollapsedStateChanged( bool state );
6061
void referencingLayerEditingToggled();
6162

62-
void on_mAddFeatureButton_clicked();
63-
void on_mLinkFeatureButton_clicked();
64-
void on_mDeleteFeatureButton_clicked();
65-
void on_mUnlinkFeatureButton_clicked();
66-
void on_mToggleEditingButton_toggled( bool state );
63+
void addFeature();
64+
void linkFeature();
65+
void deleteFeature();
66+
void unlinkFeature();
67+
void toggleEditing( bool state );
68+
void onCollapsedStateChanged( bool collapsed );
6769

6870
private:
6971
QgsDualView* mDualView;
@@ -83,6 +85,8 @@ class GUI_EXPORT QgsRelationEditorWidget : public QgsCollapsibleGroupBox
8385
QToolButton* mTableViewButton;
8486
QGridLayout* mRelationLayout;
8587
QButtonGroup* mViewModeButtonGroup;
88+
89+
bool mInitialized;
8690
};
8791

8892
#endif // QGSRELATIONEDITOR_H

‎src/gui/qgsvectorlayertools.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ class GUI_EXPORT QgsVectorLayerTools
3636
QgsVectorLayerTools()
3737
{}
3838

39+
virtual ~QgsVectorLayerTools()
40+
{}
41+
3942
/**
4043
* This method should/will be called, whenever a new feature will be added to the layer
4144
*
@@ -44,7 +47,7 @@ class GUI_EXPORT QgsVectorLayerTools
4447
* @param defaultGeometry A default geometry to add to the feature
4548
* @return True in case of success, False if the operation failed/was aborted
4649
*/
47-
virtual bool addFeature( QgsVectorLayer* layer, QgsAttributeMap defaultValues = QgsAttributeMap(), const QgsGeometry& defaultGeometry = QgsGeometry() ) = 0;
50+
virtual bool addFeature( QgsVectorLayer* layer, QgsAttributeMap defaultValues = QgsAttributeMap(), const QgsGeometry& defaultGeometry = QgsGeometry() ) const = 0;
4851

4952

5053
/**
@@ -56,7 +59,7 @@ class GUI_EXPORT QgsVectorLayerTools
5659
*
5760
* @return True, if the editing session was started
5861
*/
59-
virtual bool startEditing( QgsVectorLayer* layer ) = 0;
62+
virtual bool startEditing( QgsVectorLayer* layer ) const = 0;
6063

6164
/**
6265
* Will be called, when an editing session is ended and the features should be commited.
@@ -66,7 +69,7 @@ class GUI_EXPORT QgsVectorLayerTools
6669
* @param allowCancel True if a cancel button should be offered
6770
* @return True if successful
6871
*/
69-
virtual bool stopEditing( QgsVectorLayer* layer, bool allowCancel = true ) = 0;
72+
virtual bool stopEditing( QgsVectorLayer* layer, bool allowCancel = true ) const = 0;
7073

7174
};
7275

0 commit comments

Comments
 (0)
Please sign in to comment.