[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
This commit is contained in:
Matthias Kuhn 2014-09-01 23:37:30 +02:00
parent 016e1d728f
commit b1a2bef1fc
26 changed files with 318 additions and 217 deletions

View File

@ -24,5 +24,5 @@ class QgsAttributeEditorContext
*
* @param layer The layer to adjust for.
*/
void adjustForLayer( QgsVectorLayer* layer );
// void adjustForLayer( QgsVectorLayer* layer );
};

View File

@ -13,7 +13,7 @@ class QgsVectorLayerTools
* @param defaultGeometry A default geometry to add to the feature
* @return True in case of success, False if the operation failed/was aborted
*/
virtual bool addFeature( QgsVectorLayer* layer, QgsAttributeMap defaultValues = QgsAttributeMap(), const QgsGeometry& defaultGeometry = QgsGeometry() ) = 0;
virtual bool addFeature( QgsVectorLayer* layer, QgsAttributeMap defaultValues = QgsAttributeMap(), const QgsGeometry& defaultGeometry = QgsGeometry() ) const = 0;
/**
@ -25,7 +25,7 @@ class QgsVectorLayerTools
*
* @return True, if the editing session was started
*/
virtual bool startEditing( QgsVectorLayer* layer ) = 0;
virtual bool startEditing( QgsVectorLayer* layer ) const = 0;
/**
* Will be called, when an editing session is ended and the features should be commited.
@ -35,6 +35,6 @@ class QgsVectorLayerTools
* @param allowCancel True if a cancel button should be offered
* @return True if successful
*/
virtual bool stopEditing( QgsVectorLayer* layer, bool allowCancel = true ) = 0;
virtual bool stopEditing( QgsVectorLayer* layer, bool allowCancel = true ) const = 0;
};

View File

@ -666,8 +666,6 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, QWidget * parent,
// Init the editor widget types
QgsEditorWidgetRegistry* editorWidgetRegistry = QgsEditorWidgetRegistry::instance();
QgsAttributeEditorContext context;
context.setVectorLayerTools( vectorLayerTools() );
editorWidgetRegistry->registerWidget( "Classification", new QgsClassificationWidgetWrapperFactory( tr( "Classification" ) ) );
editorWidgetRegistry->registerWidget( "Range", new QgsRangeWidgetFactory( tr( "Range" ) ) );
editorWidgetRegistry->registerWidget( "UniqueValues", new QgsUniqueValueWidgetFactory( tr( "Unique Values" ) ) );
@ -682,7 +680,7 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, QWidget * parent,
editorWidgetRegistry->registerWidget( "Photo", new QgsPhotoWidgetFactory( tr( "Photo" ) ) );
editorWidgetRegistry->registerWidget( "WebView", new QgsWebViewWidgetFactory( tr( "Web View" ) ) );
editorWidgetRegistry->registerWidget( "Color", new QgsColorWidgetFactory( tr( "Color" ) ) );
editorWidgetRegistry->registerWidget( "RelationReference", new QgsRelationReferenceFactory( tr( "Relation Reference" ), context, mMapCanvas, mInfoBar ) );
editorWidgetRegistry->registerWidget( "RelationReference", new QgsRelationReferenceFactory( tr( "Relation Reference" ), mMapCanvas, mInfoBar ) );
editorWidgetRegistry->registerWidget( "DateTime", new QgsDateTimeEditFactory( tr( "Date/Time" ) ) );
mInternalClipboard = new QgsClipboard; // create clipboard
@ -935,6 +933,8 @@ QgisApp::~QgisApp()
delete mComposerManager;
delete mVectorLayerTools;
deletePrintComposers();
removeAnnotationItems();

View File

@ -629,7 +629,10 @@ QgsAttributeDialog* QgisAppInterface::getFeatureForm( QgsVectorLayer *l, QgsFeat
myDa.setEllipsoidalMode( QgisApp::instance()->mapCanvas()->mapSettings().hasCrsTransformEnabled() );
myDa.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) );
QgsAttributeDialog *dialog = new QgsAttributeDialog( l, &feature, false, NULL, true );
QgsAttributeEditorContext context;
context.setDistanceArea( myDa );
context.setVectorLayerTools( qgis->vectorLayerTools() );
QgsAttributeDialog *dialog = new QgsAttributeDialog( l, &feature, false, NULL, true, context );
return dialog;
}

View File

@ -32,7 +32,7 @@ QgsGuiVectorLayerTools::QgsGuiVectorLayerTools()
: QObject( NULL )
{}
bool QgsGuiVectorLayerTools::addFeature( QgsVectorLayer* layer, QgsAttributeMap defaultValues, const QgsGeometry& defaultGeometry )
bool QgsGuiVectorLayerTools::addFeature( QgsVectorLayer* layer, QgsAttributeMap defaultValues, const QgsGeometry& defaultGeometry ) const
{
QgsFeature f;
f.setGeometry( defaultGeometry );
@ -40,7 +40,7 @@ bool QgsGuiVectorLayerTools::addFeature( QgsVectorLayer* layer, QgsAttributeMap
return a.addFeature( defaultValues );
}
bool QgsGuiVectorLayerTools::startEditing( QgsVectorLayer* layer )
bool QgsGuiVectorLayerTools::startEditing( QgsVectorLayer* layer ) const
{
if ( !layer )
{
@ -65,7 +65,7 @@ bool QgsGuiVectorLayerTools::startEditing( QgsVectorLayer* layer )
return res;
}
bool QgsGuiVectorLayerTools::stopEditing( QgsVectorLayer* layer, bool allowCancel )
bool QgsGuiVectorLayerTools::stopEditing( QgsVectorLayer* layer, bool allowCancel ) const
{
bool res = true;
@ -127,7 +127,7 @@ bool QgsGuiVectorLayerTools::stopEditing( QgsVectorLayer* layer, bool allowCance
return res;
}
void QgsGuiVectorLayerTools::commitError( QgsVectorLayer* vlayer )
void QgsGuiVectorLayerTools::commitError( QgsVectorLayer* vlayer ) const
{
QgsMessageViewer *mv = new QgsMessageViewer();
mv->setWindowTitle( tr( "Commit errors" ) );

View File

@ -37,7 +37,7 @@ class QgsGuiVectorLayerTools : public QgsVectorLayerTools, public QObject
*
* @return True in case of success, False if the operation failed/was aborted
*/
bool addFeature( QgsVectorLayer *layer, QgsAttributeMap defaultValues, const QgsGeometry &defaultGeometry );
bool addFeature( QgsVectorLayer *layer, QgsAttributeMap defaultValues, const QgsGeometry &defaultGeometry ) const;
/**
* 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
*
* @return True, if the editing session was started
*/
bool startEditing( QgsVectorLayer* layer );
bool startEditing( QgsVectorLayer* layer ) const;
/**
* 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
*
* @return True if successful
*/
bool stopEditing( QgsVectorLayer* layer , bool allowCancel = true );
bool stopEditing( QgsVectorLayer* layer , bool allowCancel = true ) const;
private:
void commitError( QgsVectorLayer* vlayer );
void commitError( QgsVectorLayer* vlayer ) const;
};
#endif // QGSGUIVECTORLAYERTOOLS_H

View File

@ -116,7 +116,6 @@ qgisinterface.cpp
qgsannotationitem.cpp
qgsattributedialog.cpp
qgsattributeeditor.cpp
qgsattributeeditorcontext.cpp
qgsattributeform.cpp
qgsattributeforminterface.cpp
qgsattributeformlegacyinterface.cpp

View File

@ -34,9 +34,10 @@
QgsFeatureListView::QgsFeatureListView( QWidget *parent )
: QListView( parent )
, mCurrentEditSelectionModel( NULL )
, mFeatureSelectionModel( NULL )
, mItemDelegate( NULL )
, mModel( 0 )
, mCurrentEditSelectionModel( 0 )
, mFeatureSelectionModel( 0 )
, mItemDelegate( 0 )
, mEditSelectionDrag( false )
{
setSelectionMode( QAbstractItemView::ExtendedSelection );
@ -100,7 +101,7 @@ QString QgsFeatureListView::parserErrorString()
QgsFeatureIds QgsFeatureListView::currentEditSelection()
{
QgsFeatureIds selection;
Q_FOREACH ( QModelIndex idx, mCurrentEditSelectionModel->selectedIndexes() )
Q_FOREACH( QModelIndex idx, mCurrentEditSelectionModel->selectedIndexes() )
{
selection << idx.data( QgsAttributeTableModel::FeatureIdRole ).value<QgsFeatureId>();
}
@ -115,20 +116,27 @@ void QgsFeatureListView::setCurrentFeatureEdited( bool state )
void QgsFeatureListView::mousePressEvent( QMouseEvent *event )
{
QPoint pos = event->pos();
QModelIndex index = indexAt( pos );
if ( QgsFeatureListViewDelegate::EditElement == mItemDelegate->positionToElement( event->pos() ) )
if ( mModel )
{
mEditSelectionDrag = true;
setEditSelection( mModel->mapToMaster( index ), QItemSelectionModel::ClearAndSelect );
QPoint pos = event->pos();
QModelIndex index = indexAt( pos );
if ( QgsFeatureListViewDelegate::EditElement == mItemDelegate->positionToElement( event->pos() ) )
{
mEditSelectionDrag = true;
setEditSelection( mModel->mapToMaster( index ), QItemSelectionModel::ClearAndSelect );
}
else
{
mFeatureSelectionModel->enableSync( false );
selectRow( index, true );
repaintRequested();
}
}
else
{
mFeatureSelectionModel->enableSync( false );
selectRow( index, true );
repaintRequested();
QgsDebugMsg( "No model assigned to this view" );
}
}

View File

@ -42,9 +42,10 @@ QgsEditorWidgetWrapper* QgsEditorWidgetWrapper::fromWidget( QWidget* widget )
void QgsEditorWidgetWrapper::setEnabled( bool enabled )
{
if ( widget() )
QWidget* wdg = widget();
if ( wdg )
{
widget()->setEnabled( enabled );
wdg->setEnabled( enabled );
}
}

View File

@ -47,7 +47,7 @@ void QgsWidgetWrapper::setConfig( const QgsEditorWidgetConfig& config )
mConfig = config;
}
void QgsWidgetWrapper::setContext( const QgsAttributeEditorContext& context )
void QgsWidgetWrapper::setContext( const QgsAttributeEditorContext context )
{
mContext = context;
}

View File

@ -77,7 +77,7 @@ class GUI_EXPORT QgsWidgetWrapper : public QObject
*
* @param context context information
*/
void setContext( const QgsAttributeEditorContext& context );
void setContext( const QgsAttributeEditorContext context );
/**
* Use this inside your overriden classes to access the configuration.

View File

@ -18,9 +18,8 @@
#include "qgsrelationreferencewidgetwrapper.h"
#include "qgsrelreferenceconfigdlg.h"
QgsRelationReferenceFactory::QgsRelationReferenceFactory( QString name, QgsAttributeEditorContext context, QgsMapCanvas* canvas, QgsMessageBar* messageBar )
QgsRelationReferenceFactory::QgsRelationReferenceFactory( QString name, QgsMapCanvas* canvas, QgsMessageBar* messageBar )
: QgsEditorWidgetFactory( name )
, mEditorContext( context )
, mCanvas( canvas )
, mMessageBar( messageBar )
{
@ -28,7 +27,7 @@ QgsRelationReferenceFactory::QgsRelationReferenceFactory( QString name, QgsAttri
QgsEditorWidgetWrapper* QgsRelationReferenceFactory::create( QgsVectorLayer* vl, int fieldIdx, QWidget* editor, QWidget* parent ) const
{
return new QgsRelationReferenceWidgetWrapper( vl, fieldIdx, editor, mEditorContext, mCanvas, mMessageBar, parent );
return new QgsRelationReferenceWidgetWrapper( vl, fieldIdx, editor, mCanvas, mMessageBar, parent );
}
QgsEditorConfigWidget* QgsRelationReferenceFactory::configWidget( QgsVectorLayer* vl, int fieldIdx, QWidget* parent ) const

View File

@ -25,7 +25,7 @@ class QgsMessageBar;
class GUI_EXPORT QgsRelationReferenceFactory : public QgsEditorWidgetFactory
{
public:
QgsRelationReferenceFactory( QString name, QgsAttributeEditorContext context, QgsMapCanvas* canvas, QgsMessageBar* messageBar );
QgsRelationReferenceFactory( QString name, QgsMapCanvas* canvas, QgsMessageBar* messageBar );
/**
* Override this in your implementation.

View File

@ -20,6 +20,7 @@
#include <QHBoxLayout>
#include <QTimer>
#include "qgsattributeform.h"
#include "qgsattributedialog.h"
#include "qgsapplication.h"
#include "qgscollapsiblegroupbox.h"
@ -43,14 +44,14 @@ QgsRelationReferenceWidget::QgsRelationReferenceWidget( QWidget* parent )
, mFkeyFieldIdx( -1 )
, mAllowNull( true )
, mHighlight( NULL )
, mInitialValueAssigned( false )
, mMapTool( NULL )
, mMessageBarItem( NULL )
, mRelationName( "" )
, mReferencedAttributeDialog( NULL )
, mReferencedAttributeForm( NULL )
, mReferencedLayer( NULL )
, mReferencingLayer( NULL )
, mWindowWidget( NULL )
, mShown( false )
, mEmbedForm( false )
, mReadOnlySelector( false )
, mAllowMapIdentification( false )
@ -74,7 +75,7 @@ QgsRelationReferenceWidget::QgsRelationReferenceWidget( QWidget* parent )
// open form button
mOpenFormButton = new QToolButton( this );
mOpenFormAction = new QAction( QgsApplication::getThemeIcon( "/mActionToggleEditing.svg" ), tr( "Open related feature form" ), this );
mOpenFormAction = new QAction( QgsApplication::getThemeIcon( "/mActionPropertyItem.png" ), tr( "Open related feature form" ), this );
mOpenFormButton->addAction( mOpenFormAction );
mOpenFormButton->setDefaultAction( mOpenFormAction );
connect( mOpenFormButton, SIGNAL( triggered( QAction* ) ), this, SLOT( openForm() ) );
@ -112,10 +113,9 @@ QgsRelationReferenceWidget::QgsRelationReferenceWidget( QWidget* parent )
// embed form
mAttributeEditorFrame = new QgsCollapsibleGroupBox( this );
mAttributeEditorFrame->setCollapsed( true );
mAttributeEditorLayout = new QVBoxLayout( mAttributeEditorFrame );
mAttributeEditorFrame->setLayout( mAttributeEditorLayout );
mAttributeEditorFrame->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
mAttributeEditorFrame->setSizePolicy( mAttributeEditorFrame->sizePolicy().horizontalPolicy(), QSizePolicy::Expanding );
mTopLayout->addWidget( mAttributeEditorFrame );
// default mode is combobox, no geometric relation and no embed form
@ -146,43 +146,21 @@ void QgsRelationReferenceWidget::setRelation( QgsRelation relation, bool allowNu
if ( relation.isValid() )
{
mRelation = relation;
mReferencingLayer = relation.referencingLayer();
mRelationName = relation.name();
mReferencedLayer = relation.referencedLayer();
mFkeyFieldIdx = mReferencedLayer->fieldNameIndex( relation.fieldPairs().first().second );
if ( !mReadOnlySelector )
QgsAttributeEditorContext context( mEditorContext, relation, QgsAttributeEditorContext::EmbedSingle );
if ( mEmbedForm )
{
mComboBox->clear();
if ( allowNullValue )
{
const QString nullValue = QSettings().value( "qgis/nullValue", "NULL" ).toString();
mComboBox->addItem( tr( "%1 (no selection)" ).arg( nullValue ) );
mComboBox->setItemData( mComboBox->count() - 1, Qt::gray, Qt::ForegroundRole );
}
QgsFeatureIterator fit = mReferencedLayer->getFeatures( QgsFeatureRequest() );
QgsExpression exp( mReferencedLayer->displayExpression() );
exp.prepare( mReferencedLayer->pendingFields() );
QgsFeature f;
while ( fit.nextFeature( f ) )
{
QString txt = exp.evaluate( &f ).toString();
mComboBox->addItem( txt, f.id() );
mFidFkMap.insert( f.id(), f.attribute( mFkeyFieldIdx ) );
}
// Only connect after iterating, to have only one iterator on the referenced table at once
connect( mComboBox, SIGNAL( activated( int ) ), this, SLOT( comboReferenceChanged( int ) ) );
}
else
{
mForeignKey = QVariant();
mFeatureId = QgsFeatureId();
mAttributeEditorFrame->setTitle( mReferencedLayer->name() );
mReferencedAttributeForm = new QgsAttributeForm( relation.referencedLayer(), QgsFeature(), context, this );
mReferencedAttributeForm->hideButtonBox();
mAttributeEditorLayout->addWidget( mReferencedAttributeForm );
}
}
else
@ -194,6 +172,11 @@ void QgsRelationReferenceWidget::setRelation( QgsRelation relation, bool allowNu
lbl->setFont( font );
mTopLayout->addWidget( lbl, 1, 0 );
}
if ( mShown && isVisible() )
{
init();
}
}
void QgsRelationReferenceWidget::setRelationEditable( bool editable )
@ -215,6 +198,7 @@ void QgsRelationReferenceWidget::setRelatedFeature( const QVariant& value )
if ( !mReferencedLayer )
return;
// TODO: Rewrite using expression
QgsFeatureIterator fit = mReferencedLayer->getFeatures( QgsFeatureRequest() );
while ( fit.nextFeature( f ) )
{
@ -230,10 +214,11 @@ void QgsRelationReferenceWidget::setRelatedFeature( const QVariant& value )
return;
}
mForeignKey = f.attribute( mFkeyFieldIdx );
if ( mReadOnlySelector )
{
mLineEdit->setText( f.attribute( mFkeyFieldIdx ).toString() );
mForeignKey = f.attribute( mFkeyFieldIdx );
mFeatureId = f.id();
}
else
@ -301,16 +286,19 @@ void QgsRelationReferenceWidget::mapToolDeactivated()
QgsFeature QgsRelationReferenceWidget::relatedFeature()
{
QgsFeature f;
QgsFeatureId fid;
if ( mReadOnlySelector )
if ( mReferencedLayer )
{
fid = mFeatureId;
QgsFeatureId fid;
if ( mReadOnlySelector )
{
fid = mFeatureId;
}
else
{
fid = mComboBox->itemData( mComboBox->currentIndex() ).value<QgsFeatureId>();
}
mReferencedLayer->getFeatures( QgsFeatureRequest().setFilterFid( fid ) ).nextFeature( f );
}
else
{
fid = mComboBox->itemData( mComboBox->currentIndex() ).value<QgsFeatureId>();
}
mReferencedLayer->getFeatures( QgsFeatureRequest().setFilterFid( fid ) ).nextFeature( f );
return f;
}
@ -361,6 +349,53 @@ void QgsRelationReferenceWidget::setAllowMapIdentification( bool allowMapIdentif
mAllowMapIdentification = allowMapIdentification;
}
void QgsRelationReferenceWidget::showEvent( QShowEvent* e )
{
Q_UNUSED( e )
mShown = true;
init();
}
void QgsRelationReferenceWidget::init()
{
if ( !mReadOnlySelector && mComboBox->count() == 0 && mReferencedLayer )
{
if ( mAllowNull )
{
const QString nullValue = QSettings().value( "qgis/nullValue", "NULL" ).toString();
mComboBox->addItem( tr( "%1 (no selection)" ).arg( nullValue ), QVariant( QVariant::Int ) );
mComboBox->setItemData( 0, QColor( Qt::gray ), Qt::ForegroundRole );
}
QgsExpression exp( mReferencedLayer->displayExpression() );
QStringList attrs = exp.referencedColumns();
attrs << mRelation.fieldPairs().first().second;
QgsFeatureIterator fit = mReferencedLayer->getFeatures( QgsFeatureRequest().setFlags( QgsFeatureRequest::NoGeometry ).setSubsetOfAttributes( attrs, mReferencedLayer->pendingFields() ) );
exp.prepare( mReferencedLayer->pendingFields() );
QgsFeature f;
while ( fit.nextFeature( f ) )
{
QString txt = exp.evaluate( &f ).toString();
mComboBox->addItem( txt, f.id() );
if ( f.attribute( mFkeyFieldIdx ) == mForeignKey )
mComboBox->setCurrentIndex( mComboBox->count() - 1 );
mFidFkMap.insert( f.id(), f.attribute( mFkeyFieldIdx ) );
}
// Only connect after iterating, to have only one iterator on the referenced table at once
connect( mComboBox, SIGNAL( activated( int ) ), this, SLOT( comboReferenceChanged( int ) ) );
}
}
void QgsRelationReferenceWidget::highlightActionTriggered( QAction* action )
{
if ( action == mHighlightFeatureAction )
@ -384,10 +419,9 @@ void QgsRelationReferenceWidget::openForm()
if ( !feat.isValid() )
return;
// TODO: Get a proper QgsDistanceArea thingie
mReferencedAttributeDialog = new QgsAttributeDialog( mReferencedLayer, new QgsFeature( feat ), true, this, true, mEditorContext );
mReferencedAttributeDialog->exec();
delete mReferencedAttributeDialog;
QgsAttributeEditorContext context( mEditorContext, mRelation, QgsAttributeEditorContext::StandaloneSingle );
QgsAttributeDialog attributeDialog( mReferencedLayer, new QgsFeature( feat ), true, this, true, context );
attributeDialog.exec();
}
void QgsRelationReferenceWidget::highlightFeature( QgsFeature f, CanvasExtent canvasExtent )
@ -473,7 +507,7 @@ void QgsRelationReferenceWidget::mapIdentificationTriggered( QAction* action )
if ( !mReferencedLayer )
return;
QgsVectorLayerTools* tools = mEditorContext.vectorLayerTools();
const QgsVectorLayerTools* tools = mEditorContext.vectorLayerTools();
if ( !tools )
return;
if ( !mCanvas )
@ -511,17 +545,9 @@ void QgsRelationReferenceWidget::updateAttributeEditorFrame( const QgsFeature fe
// Check if we're running with an embedded frame we need to update
if ( mAttributeEditorFrame )
{
if ( feature.isValid() )
if ( feature.isValid() && mReferencedAttributeForm )
{
if ( mReferencedAttributeDialog )
{
mAttributeEditorLayout->removeWidget( mReferencedAttributeDialog );
}
// TODO: Get a proper QgsDistanceArea thingie
mReferencedAttributeDialog = new QgsAttributeDialog( mReferencedLayer, new QgsFeature( feature ), true, mAttributeEditorFrame, false, mEditorContext );
mReferencedAttributeDialog->setWindowFlags( Qt::Widget ); // Embed instead of opening as window
mAttributeEditorLayout->addWidget( mReferencedAttributeDialog );
mReferencedAttributeDialog->show();
mReferencedAttributeForm->setFeature( feature );
}
}
}

View File

@ -27,7 +27,7 @@
#include <QLineEdit>
#include <QVBoxLayout>
class QgsAttributeDialog;
class QgsAttributeForm;
class QgsVectorLayerTools;
class GUI_EXPORT QgsRelationReferenceWidget : public QWidget
@ -67,6 +67,11 @@ class GUI_EXPORT QgsRelationReferenceWidget : public QWidget
bool allowMapIdentification() {return mAllowMapIdentification;}
void setAllowMapIdentification( bool allowMapIdentification );
protected:
virtual void showEvent( QShowEvent* e );
void init();
signals:
void relatedFeatureChanged( QVariant );
@ -95,14 +100,15 @@ class GUI_EXPORT QgsRelationReferenceWidget : public QWidget
int mFkeyFieldIdx;
bool mAllowNull;
QgsHighlight* mHighlight;
bool mInitialValueAssigned;
QgsMapToolIdentifyFeature* mMapTool;
QgsMessageBarItem* mMessageBarItem;
QString mRelationName;
QgsAttributeDialog* mReferencedAttributeDialog;
QgsAttributeForm* mReferencedAttributeForm;
QgsVectorLayer* mReferencedLayer;
QgsVectorLayer* mReferencingLayer;
QWidget* mWindowWidget;
bool mShown;
QgsRelation mRelation;
// Q_PROPERTY
bool mEmbedForm;

View File

@ -19,9 +19,8 @@
#include "qgsrelationmanager.h"
QgsRelationReferenceWidgetWrapper::QgsRelationReferenceWidgetWrapper( QgsVectorLayer* vl, int fieldIdx, QWidget* editor, QgsAttributeEditorContext context, QgsMapCanvas* canvas, QgsMessageBar* messageBar, QWidget* parent )
QgsRelationReferenceWidgetWrapper::QgsRelationReferenceWidgetWrapper( QgsVectorLayer* vl, int fieldIdx, QWidget* editor, QgsMapCanvas* canvas, QgsMessageBar* messageBar, QWidget* parent )
: QgsEditorWidgetWrapper( vl, fieldIdx, editor, parent )
, mEditorContext( context )
, mCanvas( canvas )
, mMessageBar( messageBar )
{
@ -29,7 +28,9 @@ QgsRelationReferenceWidgetWrapper::QgsRelationReferenceWidgetWrapper( QgsVectorL
QWidget* QgsRelationReferenceWidgetWrapper::createWidget( QWidget* parent )
{
return new QgsRelationReferenceWidget( parent );
QgsRelationReferenceWidget* w = new QgsRelationReferenceWidget( parent );
w->setSizePolicy( w->sizePolicy().horizontalPolicy(), QSizePolicy::Expanding );
return w;
}
void QgsRelationReferenceWidgetWrapper::initWidget( QWidget* editor )
@ -42,16 +43,32 @@ void QgsRelationReferenceWidgetWrapper::initWidget( QWidget* editor )
mWidget = w;
mWidget->setEditorContext( mEditorContext, mCanvas, mMessageBar );
mWidget->setEditorContext( context(), mCanvas, mMessageBar );
bool showForm = config( "ShowForm", true ).toBool();
bool mapIdent = config( "MapIdentification", false ).toBool();
bool readOnlyWidget = config( "ReadOnly", false ).toBool();
mWidget->setEmbedForm( showForm );
mWidget->setAllowMapIdentification( mapIdent );
mWidget->setReadOnlySelector( readOnlyWidget );
mWidget->setAllowMapIdentification( mapIdent );
QgsRelation relation = QgsProject::instance()->relationManager()->relation( config( "Relation" ).toString() );
// If this widget is already embedded by the same relation, reduce functionality
const QgsAttributeEditorContext* ctx = &context();
do
{
if ( ctx->relation().name() == relation.name() )
{
mWidget->setEmbedForm( false );
mWidget->setReadOnlySelector( false );
mWidget->setAllowMapIdentification( false );
}
ctx = ctx->parentContext();
}
while ( ctx );
mWidget->setRelation( relation, config( "AllowNULL" ).toBool() );
connect( mWidget, SIGNAL( relatedFeatureChanged( QVariant ) ), this, SLOT( relatedFeatureChanged( QVariant ) ) );

View File

@ -26,7 +26,6 @@ class GUI_EXPORT QgsRelationReferenceWidgetWrapper : public QgsEditorWidgetWrapp
explicit QgsRelationReferenceWidgetWrapper( QgsVectorLayer* vl,
int fieldIdx,
QWidget* editor,
QgsAttributeEditorContext context,
QgsMapCanvas* canvas,
QgsMessageBar* messageBar,
QWidget* parent = 0 );
@ -44,7 +43,6 @@ class GUI_EXPORT QgsRelationReferenceWidgetWrapper : public QgsEditorWidgetWrapp
private:
QgsRelationReferenceWidget* mWidget;
QgsAttributeEditorContext mEditorContext;
QgsMapCanvas* mCanvas;
QgsMessageBar* mMessageBar;
};

View File

@ -16,6 +16,7 @@
#include "qgsrelationwidgetwrapper.h"
#include "qgsrelationeditorwidget.h"
#include "qgsattributeeditorcontext.h"
#include <QWidget>
@ -24,7 +25,6 @@ QgsRelationWidgetWrapper::QgsRelationWidgetWrapper( QgsVectorLayer* vl, const Qg
, mRelation( relation )
, mWidget( NULL )
{
initWidget( editor );
}
QWidget* QgsRelationWidgetWrapper::createWidget( QWidget* parent )
@ -35,7 +35,7 @@ QWidget* QgsRelationWidgetWrapper::createWidget( QWidget* parent )
void QgsRelationWidgetWrapper::setFeature( const QgsFeature& feature )
{
if ( mWidget )
mWidget->setRelationFeature( mRelation, feature, context() );
mWidget->setRelationFeature( mRelation, feature );
}
void QgsRelationWidgetWrapper::initWidget( QWidget* editor )
@ -48,5 +48,23 @@ void QgsRelationWidgetWrapper::initWidget( QWidget* editor )
w = new QgsRelationEditorWidget( editor );
}
QgsAttributeEditorContext myContext( QgsAttributeEditorContext( context(), mRelation, QgsAttributeEditorContext::EmbedMultiple ) );
w->setEditorContext( myContext );
// If this widget is already embedded by the same relation, reduce functionality
const QgsAttributeEditorContext* ctx = &context();
do
{
if ( ctx->relation().name() == mRelation.name() && ctx->relationMode() == QgsAttributeEditorContext::EmbedMultiple )
{
w->setSaveCollapsedState( false );
w->setCollapsed( true );
break;
}
ctx = ctx->parentContext();
}
while ( ctx );
mWidget = w;
}

View File

@ -63,7 +63,10 @@ void QgsUniqueValuesWidgetWrapper::initWidget( QWidget* editor )
mComboBox->addItem( v.toString(), v );
}
sValues << v.toString();
if ( mLineEdit )
{
sValues << v.toString();
}
}
if ( mLineEdit )

View File

@ -19,6 +19,7 @@
#include "qgsattributeform.h"
#include "qgshighlight.h"
#include "qgsapplication.h"
#include <QSettings>
#include <QGridLayout>
@ -30,6 +31,7 @@ QgsAttributeDialog::QgsAttributeDialog( QgsVectorLayer* vl, QgsFeature* thepFeat
{
QgsAttributeEditorContext context;
context.setDistanceArea( myDa );
init( vl, thepFeature, context, parent );
if ( !showDialogButtons )

View File

@ -1,27 +0,0 @@
/***************************************************************************
qgsattributeeditorcontext.cpp
--------------------------------------
Date : 30.7.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsattributeeditorcontext.h"
QgsAttributeEditorContext::QgsAttributeEditorContext()
: mVectorLayerTools( NULL )
{
}
void QgsAttributeEditorContext::adjustForLayer( QgsVectorLayer* layer )
{
mDistanceArea.setSourceCrs( layer->crs() );
}

View File

@ -33,34 +33,63 @@
class GUI_EXPORT QgsAttributeEditorContext
{
public:
QgsAttributeEditorContext();
QWidget* proxyWidget( QgsVectorLayer* vl, int fieldIdx );
//! @note not available in python bindings
void addProxyWidgets( QgsVectorLayer* vl, QMap<int, QWidget*> proxyWidgets );
void addProxyWidget( QgsVectorLayer* vl, int idx, QWidget* widget );
void setDistanceArea( const QgsDistanceArea& distanceArea ) { mDistanceArea = distanceArea; }
inline const QgsDistanceArea& distanceArea() { return mDistanceArea; }
void setVectorLayerTools( QgsVectorLayerTools* vlTools ) { mVectorLayerTools = vlTools; }
QgsVectorLayerTools* vectorLayerTools() { return mVectorLayerTools; }
/**
* When copying the context for another layer, call this.
* Will adjast the distance area for this layer
*
* @param layer The layer to adjust for.
* Determines in which direction a relation was resolved.
*/
void adjustForLayer( QgsVectorLayer* layer );
enum RelationMode
{
Undefined, //!< This context is not defined by a relation
EmbedMultiple, //!< When embedding a list of features (e.g. houses as an embedded form in a district form)
EmbedSingle, //!< When embedding a single feature (e.g. district information when looking at the form of a house)
StandaloneSingle //!< When showing a new dialog for a single feature (e.g. district information when looking at the form of a house)
};
public:
QgsAttributeEditorContext()
: mParentContext( 0 )
, mLayer( 0 )
, mVectorLayerTools( 0 )
, mRelationMode( Undefined )
{}
QgsAttributeEditorContext( const QgsAttributeEditorContext& parentContext, const QgsRelation& relation, RelationMode mode )
: mParentContext( &parentContext )
, mLayer( 0 )
, mVectorLayerTools( parentContext.mVectorLayerTools )
, mDistanceArea( parentContext.mDistanceArea )
, mRelation( relation )
, mRelationMode( mode )
{
Q_ASSERT( parentContext.vectorLayerTools() );
}
inline void setDistanceArea( const QgsDistanceArea& distanceArea )
{
if ( mLayer )
{
mDistanceArea = distanceArea;
mDistanceArea.setSourceCrs( mLayer->crs() );
}
}
inline const QgsDistanceArea& distanceArea() const { return mDistanceArea; }
inline void setVectorLayerTools( QgsVectorLayerTools* vlTools ) { mVectorLayerTools = vlTools; }
inline const QgsVectorLayerTools* vectorLayerTools() const { return mVectorLayerTools; }
inline void setRelation( const QgsRelation& relation, RelationMode mode ) { mRelation = relation; mRelationMode = mode; }
inline const QgsRelation& relation() const { return mRelation; }
inline RelationMode relationMode() const { return mRelationMode; }
inline const QgsAttributeEditorContext* parentContext() const { return mParentContext; }
private:
const QgsAttributeEditorContext* mParentContext;
QgsVectorLayer* mLayer;
QgsVectorLayerTools* mVectorLayerTools;
//! vectorlayer => ( fieldIdx, proxyWidget )
QMap<QgsVectorLayer*, QMap<int, QWidget*> > mProxyWidgets;
QgsDistanceArea mDistanceArea;
QgsRelation mRelation;
RelationMode mRelationMode;
};
#endif // QGSATTRIBUTEEDITORCONTEXT_H

View File

@ -41,6 +41,7 @@ QgsAttributeForm::QgsAttributeForm( QgsVectorLayer* vl, const QgsFeature feature
: QWidget( parent )
, mLayer( vl )
, mContext( context )
, mButtonBox( 0 )
, mFormNr( sFormCounter++ )
, mIsSaving( false )
, mIsAddDialog( false )
@ -101,7 +102,7 @@ void QgsAttributeForm::setIsAddDialog( bool isAddDialog )
void QgsAttributeForm::changeAttribute( const QString& field, const QVariant& value )
{
Q_FOREACH ( QgsWidgetWrapper* ww, mWidgets )
Q_FOREACH( QgsWidgetWrapper* ww, mWidgets )
{
QgsEditorWidgetWrapper* eww = qobject_cast<QgsEditorWidgetWrapper*>( ww );
if ( eww && eww->field().name() == field )
@ -119,7 +120,7 @@ void QgsAttributeForm::setFeature( const QgsFeature& feature )
synchronizeEnabledState();
Q_FOREACH ( QgsAttributeFormInterface* iface, mInterfaces )
Q_FOREACH( QgsAttributeFormInterface* iface, mInterfaces )
{
iface->featureChanged();
}
@ -154,7 +155,7 @@ bool QgsAttributeForm::save()
QgsAttributes src = mFeature.attributes();
QgsAttributes dst = mFeature.attributes();
Q_FOREACH ( QgsWidgetWrapper* ww, mWidgets )
Q_FOREACH( QgsWidgetWrapper* ww, mWidgets )
{
QgsEditorWidgetWrapper* eww = qobject_cast<QgsEditorWidgetWrapper*>( ww );
if ( eww )
@ -174,7 +175,7 @@ bool QgsAttributeForm::save()
updatedFeature.setAttributes( dst );
Q_FOREACH ( QgsAttributeFormInterface* iface, mInterfaces )
Q_FOREACH( QgsAttributeFormInterface* iface, mInterfaces )
{
if ( !iface->acceptChanges( updatedFeature ) )
{
@ -242,7 +243,7 @@ bool QgsAttributeForm::save()
void QgsAttributeForm::resetValues()
{
Q_FOREACH ( QgsWidgetWrapper* ww, mWidgets )
Q_FOREACH( QgsWidgetWrapper* ww, mWidgets )
{
ww->setFeature( mFeature );
}
@ -289,7 +290,7 @@ void QgsAttributeForm::synchronizeEnabledState()
{
bool isEditable = ( mFeature.isValid() || mIsAddDialog ) && mLayer->isEditable();
Q_FOREACH ( QgsWidgetWrapper* ww, mWidgets )
Q_FOREACH( QgsWidgetWrapper* ww, mWidgets )
{
bool fieldEditable = true;
QgsEditorWidgetWrapper* eww = qobject_cast<QgsEditorWidgetWrapper*>( ww );
@ -337,6 +338,7 @@ void QgsAttributeForm::init()
layout()->addWidget( formWidget );
formWidget->show();
file.close();
mButtonBox = findChild<QDialogButtonBox*>();
createWrappers();
formWidget->installEventFilter( this );
@ -349,7 +351,7 @@ void QgsAttributeForm::init()
QTabWidget* tabWidget = new QTabWidget( this );
layout()->addWidget( tabWidget );
Q_FOREACH ( QgsAttributeEditorElement *widgDef, mLayer->attributeEditorElements() )
Q_FOREACH( QgsAttributeEditorElement *widgDef, mLayer->attributeEditorElements() )
{
QWidget* tabPage = new QWidget( tabWidget );
@ -391,7 +393,7 @@ void QgsAttributeForm::init()
layout()->addWidget( scrollArea );
int row = 0;
Q_FOREACH ( const QgsField& field, mLayer->pendingFields().toList() )
Q_FOREACH( const QgsField& field, mLayer->pendingFields().toList() )
{
int idx = mLayer->fieldNameIndex( field.name() );
//show attribute alias if available
@ -428,7 +430,7 @@ void QgsAttributeForm::init()
}
}
Q_FOREACH ( const QgsRelation& rel, QgsProject::instance()->relationManager()->referencedRelations( mLayer ) )
Q_FOREACH( const QgsRelation& rel, QgsProject::instance()->relationManager()->referencedRelations( mLayer ) )
{
QgsRelationWidgetWrapper* rww = new QgsRelationWidgetWrapper( mLayer, rel, 0, this );
rww->setContext( mContext );
@ -437,8 +439,6 @@ void QgsAttributeForm::init()
}
}
mButtonBox = findChild<QDialogButtonBox*>();
if ( !mButtonBox )
{
mButtonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
@ -454,7 +454,7 @@ void QgsAttributeForm::init()
connect( mLayer, SIGNAL( editingStarted() ), this, SLOT( synchronizeEnabledState() ) );
connect( mLayer, SIGNAL( editingStopped() ), this, SLOT( synchronizeEnabledState() ) );
Q_FOREACH ( QgsAttributeFormInterface* iface, mInterfaces )
Q_FOREACH( QgsAttributeFormInterface* iface, mInterfaces )
{
iface->initForm();
}
@ -598,7 +598,7 @@ QWidget* QgsAttributeForm::createWidgetFromDef( const QgsAttributeEditorElement
QList<QgsAttributeEditorElement*> children = container->children();
Q_FOREACH ( QgsAttributeEditorElement* childDef, children )
Q_FOREACH( QgsAttributeEditorElement* childDef, children )
{
QString labelText;
bool labelOnTop;
@ -643,7 +643,7 @@ QWidget* QgsAttributeForm::createWidgetFromDef( const QgsAttributeEditorElement
void QgsAttributeForm::addWidgetWrapper( QgsEditorWidgetWrapper* eww )
{
Q_FOREACH ( QgsWidgetWrapper* ww, mWidgets )
Q_FOREACH( QgsWidgetWrapper* ww, mWidgets )
{
QgsEditorWidgetWrapper* meww = qobject_cast<QgsEditorWidgetWrapper*>( ww );
if ( meww )
@ -665,7 +665,7 @@ void QgsAttributeForm::createWrappers()
QList<QWidget*> myWidgets = findChildren<QWidget*>();
const QList<QgsField> fields = mLayer->pendingFields().toList();
Q_FOREACH ( QWidget* myWidget, myWidgets )
Q_FOREACH( QWidget* myWidget, myWidgets )
{
// Check the widget's properties for a relation definition
QVariant vRel = myWidget->property( "qgisRelation" );
@ -678,12 +678,13 @@ void QgsAttributeForm::createWrappers()
QgsRelationWidgetWrapper* rww = new QgsRelationWidgetWrapper( mLayer, relation, myWidget, this );
rww->setConfig( QgsEditorWidgetConfig() );
rww->setContext( mContext );
rww->widget(); // Will initialize the widget
mWidgets.append( rww );
}
}
else
{
Q_FOREACH ( const QgsField& field, fields )
Q_FOREACH( const QgsField& field, fields )
{
if ( field.name() == myWidget->objectName() )
{
@ -703,7 +704,7 @@ void QgsAttributeForm::connectWrappers()
{
bool isFirstEww = true;
Q_FOREACH ( QgsWidgetWrapper* ww, mWidgets )
Q_FOREACH( QgsWidgetWrapper* ww, mWidgets )
{
QgsEditorWidgetWrapper* eww = qobject_cast<QgsEditorWidgetWrapper*>( ww );

View File

@ -34,6 +34,7 @@ QgsRelationEditorWidget::QgsRelationEditorWidget( QWidget* parent )
, mEditorContext( QgsAttributeEditorContext() )
, mRelation( QgsRelation() )
, mFeature( QgsFeature() )
, mInitialized( false )
{
QVBoxLayout* topLayout = new QVBoxLayout( this );
topLayout->setContentsMargins( 0, 9, 0, 0 );
@ -47,6 +48,8 @@ QgsRelationEditorWidget::QgsRelationEditorWidget( QWidget* parent )
QAction* toggleEditingAction = new QAction( QgsApplication::getThemeIcon( "/mActionToggleEditing.svg" ), tr( "Toggle editing" ), this );
mToggleEditingButton->addAction( toggleEditingAction );
mToggleEditingButton->setDefaultAction( toggleEditingAction );
mToggleEditingButton->setEnabled( false );
mToggleEditingButton->setCheckable( true );
buttonLayout->addWidget( mToggleEditingButton );
// add feature
mAddFeatureButton = new QToolButton( this );
@ -110,13 +113,20 @@ QgsRelationEditorWidget::QgsRelationEditorWidget( QWidget* parent )
mDualView = new QgsDualView( this );
mDualView->setView( mViewMode );
mFeatureSelectionMgr = new QgsGenericFeatureSelectionManager( mDualView );
mDualView->setFeatureSelectionManager( mFeatureSelectionMgr );
mRelationLayout->addWidget( mDualView );
connect( this, SIGNAL( collapsedStateChanged( bool ) ), this, SLOT( onCollapsedStateChanged( bool ) ) );
connect( mViewModeButtonGroup, SIGNAL( buttonClicked( int ) ), this, SLOT( setViewMode( int ) ) );
connect( mToggleEditingButton, SIGNAL( clicked( bool ) ), this, SLOT( toggleEditing( bool ) ) );
connect( mAddFeatureButton, SIGNAL( clicked() ), this, SLOT( addFeature() ) );
connect( mDeleteFeatureButton, SIGNAL( clicked() ), this, SLOT( deleteFeature() ) );
connect( mLinkFeatureButton, SIGNAL( clicked() ), this, SLOT( linkFeature() ) );
connect( mUnlinkFeatureButton, SIGNAL( clicked() ), this, SLOT( unlinkFeature() ) );
}
void QgsRelationEditorWidget::setRelationFeature( const QgsRelation& relation, const QgsFeature& feature, const QgsAttributeEditorContext& context )
void QgsRelationEditorWidget::setRelationFeature( const QgsRelation& relation, const QgsFeature& feature )
{
if ( mRelation.isValid() )
{
@ -126,7 +136,6 @@ void QgsRelationEditorWidget::setRelationFeature( const QgsRelation& relation, c
mRelation = relation;
mFeature = feature;
mEditorContext = context;
connect( mRelation.referencingLayer(), SIGNAL( editingStarted() ), this, SLOT( referencingLayerEditingToggled() ) );
connect( mRelation.referencingLayer(), SIGNAL( editingStopped() ), this, SLOT( referencingLayerEditingToggled() ) );
@ -137,13 +146,11 @@ void QgsRelationEditorWidget::setRelationFeature( const QgsRelation& relation, c
bool canChangeAttributes = lyr->dataProvider()->capabilities() & QgsVectorDataProvider::ChangeAttributeValues;
mToggleEditingButton->setEnabled( canChangeAttributes && !lyr->isReadOnly() );
}
mDualView->setFeatureSelectionManager( mFeatureSelectionMgr );
QgsFeatureRequest myRequest = relation.getRelatedFeaturesRequest( feature );
mDualView->init( relation.referencingLayer(), NULL, myRequest, context );
void QgsRelationEditorWidget::setEditorContext( const QgsAttributeEditorContext& context )
{
mEditorContext = context;
}
void QgsRelationEditorWidget::setViewMode( QgsDualView::ViewMode mode )
@ -154,14 +161,6 @@ void QgsRelationEditorWidget::setViewMode( QgsDualView::ViewMode mode )
mFormViewButton->setChecked( mViewMode == QgsDualView::AttributeEditor );
}
void QgsRelationEditorWidget::onCollapsedStateChanged( bool state )
{
if ( state && !mDualView->masterModel() )
{
// TODO: Lazy init dual view if collapsed on init
}
}
void QgsRelationEditorWidget::referencingLayerEditingToggled()
{
bool editable = false;
@ -177,13 +176,13 @@ void QgsRelationEditorWidget::referencingLayerEditingToggled()
mToggleEditingButton->setChecked( editable );
}
void QgsRelationEditorWidget::on_mAddFeatureButton_clicked()
void QgsRelationEditorWidget::addFeature()
{
QgsAttributeMap keyAttrs;
QgsFields fields = mRelation.referencingLayer()->pendingFields();
foreach ( QgsRelation::FieldPair fieldPair, mRelation.fieldPairs() )
Q_FOREACH( QgsRelation::FieldPair fieldPair, mRelation.fieldPairs() )
{
keyAttrs.insert( fields.indexFromName( fieldPair.referencingField() ), mFeature.attribute( fieldPair.referencedField() ) );
}
@ -191,21 +190,21 @@ void QgsRelationEditorWidget::on_mAddFeatureButton_clicked()
mEditorContext.vectorLayerTools()->addFeature( mDualView->masterModel()->layer(), keyAttrs );
}
void QgsRelationEditorWidget::on_mLinkFeatureButton_clicked()
void QgsRelationEditorWidget::linkFeature()
{
QgsFeatureSelectionDlg selectionDlg( mRelation.referencingLayer(), this );
if ( selectionDlg.exec() )
{
QMap<int, QVariant> keys;
foreach ( const QgsRelation::FieldPair fieldPair, mRelation.fieldPairs() )
Q_FOREACH( const QgsRelation::FieldPair fieldPair, mRelation.fieldPairs() )
{
int idx = mRelation.referencingLayer()->fieldNameIndex( fieldPair.referencingField() );
QVariant val = mFeature.attribute( fieldPair.referencedField() );
keys.insert( idx, val );
}
foreach ( QgsFeatureId fid, selectionDlg.selectedFeatures() )
Q_FOREACH( QgsFeatureId fid, selectionDlg.selectedFeatures() )
{
QMapIterator<int, QVariant> it( keys );
while ( it.hasNext() )
@ -217,25 +216,25 @@ void QgsRelationEditorWidget::on_mLinkFeatureButton_clicked()
}
}
void QgsRelationEditorWidget::on_mDeleteFeatureButton_clicked()
void QgsRelationEditorWidget::deleteFeature()
{
foreach ( QgsFeatureId fid, mFeatureSelectionMgr->selectedFeaturesIds() )
Q_FOREACH( QgsFeatureId fid, mFeatureSelectionMgr->selectedFeaturesIds() )
{
mRelation.referencingLayer()->deleteFeature( fid );
}
}
void QgsRelationEditorWidget::on_mUnlinkFeatureButton_clicked()
void QgsRelationEditorWidget::unlinkFeature()
{
QMap<int, QgsField> keyFields;
foreach ( const QgsRelation::FieldPair fieldPair, mRelation.fieldPairs() )
Q_FOREACH( const QgsRelation::FieldPair fieldPair, mRelation.fieldPairs() )
{
int idx = mRelation.referencingLayer()->fieldNameIndex( fieldPair.referencingField() );
QgsField fld = mRelation.referencingLayer()->pendingFields().at( idx );
keyFields.insert( idx, fld );
}
foreach ( QgsFeatureId fid, mFeatureSelectionMgr->selectedFeaturesIds() )
Q_FOREACH( QgsFeatureId fid, mFeatureSelectionMgr->selectedFeaturesIds() )
{
QMapIterator<int, QgsField> it( keyFields );
while ( it.hasNext() )
@ -246,14 +245,26 @@ void QgsRelationEditorWidget::on_mUnlinkFeatureButton_clicked()
}
}
void QgsRelationEditorWidget::on_mToggleEditingButton_toggled( bool state )
void QgsRelationEditorWidget::toggleEditing( bool state )
{
if ( state )
{
mEditorContext.vectorLayerTools()->startEditing( mRelation.referencingLayer() );
mEditorContext.vectorLayerTools()->stopEditing( mRelation.referencingLayer() );
}
else
{
mEditorContext.vectorLayerTools()->stopEditing( mRelation.referencingLayer() );
mEditorContext.vectorLayerTools()->startEditing( mRelation.referencingLayer() );
}
}
void QgsRelationEditorWidget::onCollapsedStateChanged( bool collapsed )
{
if ( !mInitialized && !collapsed && mRelation.isValid() )
{
mInitialized = true;
QgsFeatureRequest myRequest = mRelation.getRelatedFeaturesRequest( mFeature );
mDualView->init( mRelation.referencingLayer(), 0, myRequest, mEditorContext );
}
}

View File

@ -52,18 +52,20 @@ class GUI_EXPORT QgsRelationEditorWidget : public QgsCollapsibleGroupBox
void setQgisRelation( QString qgisRelationId ) { mRelationId = qgisRelationId; }
QString qgisRelation() { return mRelationId; } //property( "qgisRelation" ).toString()
void setRelationFeature( const QgsRelation& relation, const QgsFeature& feature, const QgsAttributeEditorContext& context );
void setRelationFeature( const QgsRelation& relation, const QgsFeature& feature );
void setEditorContext( const QgsAttributeEditorContext& context );
private slots:
void setViewMode( int mode ) {setViewMode( static_cast<QgsDualView::ViewMode>( mode ) );}
void onCollapsedStateChanged( bool state );
void referencingLayerEditingToggled();
void on_mAddFeatureButton_clicked();
void on_mLinkFeatureButton_clicked();
void on_mDeleteFeatureButton_clicked();
void on_mUnlinkFeatureButton_clicked();
void on_mToggleEditingButton_toggled( bool state );
void addFeature();
void linkFeature();
void deleteFeature();
void unlinkFeature();
void toggleEditing( bool state );
void onCollapsedStateChanged( bool collapsed );
private:
QgsDualView* mDualView;
@ -83,6 +85,8 @@ class GUI_EXPORT QgsRelationEditorWidget : public QgsCollapsibleGroupBox
QToolButton* mTableViewButton;
QGridLayout* mRelationLayout;
QButtonGroup* mViewModeButtonGroup;
bool mInitialized;
};
#endif // QGSRELATIONEDITOR_H

View File

@ -36,6 +36,9 @@ class GUI_EXPORT QgsVectorLayerTools
QgsVectorLayerTools()
{}
virtual ~QgsVectorLayerTools()
{}
/**
* This method should/will be called, whenever a new feature will be added to the layer
*
@ -44,7 +47,7 @@ class GUI_EXPORT QgsVectorLayerTools
* @param defaultGeometry A default geometry to add to the feature
* @return True in case of success, False if the operation failed/was aborted
*/
virtual bool addFeature( QgsVectorLayer* layer, QgsAttributeMap defaultValues = QgsAttributeMap(), const QgsGeometry& defaultGeometry = QgsGeometry() ) = 0;
virtual bool addFeature( QgsVectorLayer* layer, QgsAttributeMap defaultValues = QgsAttributeMap(), const QgsGeometry& defaultGeometry = QgsGeometry() ) const = 0;
/**
@ -56,7 +59,7 @@ class GUI_EXPORT QgsVectorLayerTools
*
* @return True, if the editing session was started
*/
virtual bool startEditing( QgsVectorLayer* layer ) = 0;
virtual bool startEditing( QgsVectorLayer* layer ) const = 0;
/**
* Will be called, when an editing session is ended and the features should be commited.
@ -66,7 +69,7 @@ class GUI_EXPORT QgsVectorLayerTools
* @param allowCancel True if a cancel button should be offered
* @return True if successful
*/
virtual bool stopEditing( QgsVectorLayer* layer, bool allowCancel = true ) = 0;
virtual bool stopEditing( QgsVectorLayer* layer, bool allowCancel = true ) const = 0;
};