mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
[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:
parent
016e1d728f
commit
b1a2bef1fc
@ -24,5 +24,5 @@ class QgsAttributeEditorContext
|
||||
*
|
||||
* @param layer The layer to adjust for.
|
||||
*/
|
||||
void adjustForLayer( QgsVectorLayer* layer );
|
||||
// void adjustForLayer( QgsVectorLayer* layer );
|
||||
};
|
||||
|
@ -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;
|
||||
|
||||
};
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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" ) );
|
||||
|
@ -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
|
||||
|
@ -116,7 +116,6 @@ qgisinterface.cpp
|
||||
qgsannotationitem.cpp
|
||||
qgsattributedialog.cpp
|
||||
qgsattributeeditor.cpp
|
||||
qgsattributeeditorcontext.cpp
|
||||
qgsattributeform.cpp
|
||||
qgsattributeforminterface.cpp
|
||||
qgsattributeformlegacyinterface.cpp
|
||||
|
@ -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" );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 ) ) );
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -63,7 +63,10 @@ void QgsUniqueValuesWidgetWrapper::initWidget( QWidget* editor )
|
||||
mComboBox->addItem( v.toString(), v );
|
||||
}
|
||||
|
||||
sValues << v.toString();
|
||||
if ( mLineEdit )
|
||||
{
|
||||
sValues << v.toString();
|
||||
}
|
||||
}
|
||||
|
||||
if ( mLineEdit )
|
||||
|
@ -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 )
|
||||
|
@ -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() );
|
||||
}
|
@ -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
|
||||
|
@ -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 );
|
||||
|
||||
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user