Skip to content

Commit

Permalink
handle list of features to attributedialog on feature fix process
Browse files Browse the repository at this point in the history
  • Loading branch information
signedav committed Jan 9, 2020
1 parent 104598b commit c4dc133
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 54 deletions.
12 changes: 12 additions & 0 deletions python/gui/auto_generated/qgsattributedialog.sip.in
Expand Up @@ -28,6 +28,16 @@ Create an attribute dialog for a given layer and feature
:param parent: A parent widget for the dialog
:param showDialogButtons: ``True``: Show the dialog buttons accept/cancel
:param context: The context in which this dialog is created
%End

QgsAttributeDialog( QgsVectorLayer *vl, QgsFeatureList *features, QWidget *parent /TransferThis/ = 0, const QgsAttributeEditorContext &context = QgsAttributeEditorContext() );
%Docstring
Create an attribute dialog for a given layer and a feature list

:param vl: The layer for which the dialog will be generated
:param features: A list of features handled in the dialog
:param parent: A parent widget for the dialog
:param context: The context in which this dialog is created
%End

~QgsAttributeDialog();
Expand Down Expand Up @@ -75,6 +85,8 @@ Intercept window activate/deactivate events to show/hide the highlighted feature
:return: The same as the parent QDialog
%End

QgsFeatureList validFeatures();

public slots:
virtual void accept();

Expand Down
59 changes: 20 additions & 39 deletions src/app/qgisapp.cpp
Expand Up @@ -9609,46 +9609,27 @@ void QgisApp::pasteFromClipboard( QgsMapLayer *destinationLayer )
}
}

for ( const QgsFeature &f : qgis::as_const( invalidFeatures ) )
{
// open attribute form to fix invalid features and offer the options:
// - fix part of invalid features and save (without the unfixed) -> on cancel invalid or all fixed
// - fix part of invalid features and save (with the unfixed as invalid) -> on store invalid
// - cancel everything
QgsFeature feature = f;
QgsAttributeDialog *dialog = new QgsAttributeDialog( pasteVectorLayer, &feature, false, nullptr, true, QgsAttributeEditorContext(), true );

int feedback = dialog->exec();
// open attribute form to fix invalid features and offer the options:
// - fix part of invalid features and save (without the unfixed) -> on cancel invalid or all fixed
// - fix part of invalid features and save (with the unfixed as invalid) -> on store invalid
// - cancel everything
QgsAttributeDialog *dialog = new QgsAttributeDialog( pasteVectorLayer, &invalidFeatures, nullptr, QgsAttributeEditorContext() );
dialog->setMode( QgsAttributeEditorContext::AddFeatureMode );
int feedback = dialog->exec();

if ( feedback == 0 )
{
//feature unfixed
continue;
}
else if ( feedback == 1 )
{
//feature fixed
feature.setAttributes( dialog->feature()->attributes() );
validFeatures << feature;
invalidFeatures.removeOne( f );
}
else if ( feedback == 10 )
{
//cancel all
break;
}
else if ( feedback == 11 )
{
//cancel all invalid
newFeatures << validFeatures;
break;
}
else if ( feedback == 12 )
{
//store all invalid
newFeatures << validFeatures << invalidFeatures;
break;
}
if ( feedback == 10 )
{
//cancel all
}
else if ( feedback == 11 )
{
//cancel all invalid
newFeatures << validFeatures << dialog->validFeatures();
}
else if ( feedback == 12 )
{
//store all invalid
newFeatures << validFeatures << invalidFeatures;
}

pasteVectorLayer->addFeatures( newFeatures );
Expand Down
112 changes: 98 additions & 14 deletions src/gui/qgsattributedialog.cpp
Expand Up @@ -21,13 +21,21 @@
#include "qgshighlight.h"
#include "qgsapplication.h"
#include "qgssettings.h"

#include <QtWidgets/QProgressBar>
#include <QtWidgets/QPushButton>

QgsAttributeDialog::QgsAttributeDialog( QgsVectorLayer *vl, QgsFeature *thepFeature, bool featureOwner, QWidget *parent, bool showDialogButtons, const QgsAttributeEditorContext &context, bool showFixFeatureDialogButtons )
: QDialog( parent )
, mOwnedFeature( featureOwner ? thepFeature : nullptr )
{
init( vl, thepFeature, context, showDialogButtons, showFixFeatureDialogButtons );
init( vl, thepFeature, context, showDialogButtons );
}

QgsAttributeDialog::QgsAttributeDialog( QgsVectorLayer *vl, QgsFeatureList *features, QWidget *parent, const QgsAttributeEditorContext &context )
: QDialog( parent )
{
initList( vl, features, context );
}

QgsAttributeDialog::~QgsAttributeDialog()
Expand Down Expand Up @@ -86,7 +94,7 @@ void QgsAttributeDialog::reject()
QDialog::reject();
}

void QgsAttributeDialog::init( QgsVectorLayer *layer, QgsFeature *feature, const QgsAttributeEditorContext &context, bool showDialogButtons, bool showFixFeatureDialogButtons )
void QgsAttributeDialog::init( QgsVectorLayer *layer, QgsFeature *feature, const QgsAttributeEditorContext &context, bool showDialogButtons )
{
QgsAttributeEditorContext trackedContext = context;
setWindowTitle( tr( "%1 - Feature Attributes" ).arg( layer->name() ) );
Expand All @@ -101,21 +109,97 @@ void QgsAttributeDialog::init( QgsVectorLayer *layer, QgsFeature *feature, const
mAttributeForm->disconnectButtonBox();
layout()->addWidget( mAttributeForm );
QDialogButtonBox *buttonBox = mAttributeForm->findChild<QDialogButtonBox *>();
connect( buttonBox, &QDialogButtonBox::rejected, this, &QgsAttributeDialog::reject );
connect( buttonBox, &QDialogButtonBox::accepted, this, &QgsAttributeDialog::accept );
connect( layer, &QObject::destroyed, this, &QWidget::close );

if ( showFixFeatureDialogButtons )
mMenu = new QgsActionMenu( layer, mAttributeForm->feature(), QStringLiteral( "Feature" ), this );
if ( !mMenu->actions().isEmpty() )
{
QPushButton *cancelAllBtn = new QPushButton( tr( "Cancel all" ) );
QPushButton *cancelAllInvalidBtn = new QPushButton( tr( "Cancel all invalid" ) );
QPushButton *storeAllInvalidBtn = new QPushButton( tr( "Store all (even invalid)" ) );
buttonBox->addButton( cancelAllBtn, QDialogButtonBox::RejectRole );
buttonBox->addButton( cancelAllInvalidBtn, QDialogButtonBox::RejectRole );
buttonBox->addButton( storeAllInvalidBtn, QDialogButtonBox::RejectRole );
connect( cancelAllBtn, &QAbstractButton::clicked, this, [ = ]() { done( 10 ); } );
connect( cancelAllInvalidBtn, &QAbstractButton::clicked, this, [ = ]() { done( 11 ); } );
connect( storeAllInvalidBtn, &QAbstractButton::clicked, this, [ = ]() { done( 12 ); } );
QMenuBar *menuBar = new QMenuBar( this );
menuBar->addMenu( mMenu );
layout()->setMenuBar( menuBar );
}
connect( buttonBox, &QDialogButtonBox::rejected, this, &QgsAttributeDialog::reject );
connect( buttonBox, &QDialogButtonBox::accepted, this, &QgsAttributeDialog::accept );

restoreGeometry();
focusNextChild();
}

void QgsAttributeDialog::initList( QgsVectorLayer *layer, QgsFeatureList *features, const QgsAttributeEditorContext &context )
{

QgsAttributeEditorContext trackedContext = context;
setWindowTitle( tr( "%1 - Fix Feature Attributes" ).arg( layer->name() ) );
setLayout( new QGridLayout() );
layout()->setMargin( 0 );
mTrackedVectorLayerTools.setVectorLayerTools( trackedContext.vectorLayerTools() );
trackedContext.setVectorLayerTools( &mTrackedVectorLayerTools );
trackedContext.setFormMode( QgsAttributeEditorContext::StandaloneDialog );

mCurrentIndex = 0;
QLabel *description = new QLabel( tr( "%1 features do not fullfill the constraints. Please fix or cancel them." ).arg( features->count() ) );
layout()->addWidget( description );
QProgressBar *progressBar = new QProgressBar();
progressBar->setOrientation( Qt::Horizontal );
progressBar->setRange( 0, features->count() );

layout()->addWidget( progressBar );
mAttributeForm = new QgsAttributeForm( layer, features->at( mCurrentIndex ), trackedContext, this );
mAttributeForm->disconnectButtonBox();
layout()->addWidget( mAttributeForm );
QDialogButtonBox *buttonBox = mAttributeForm->findChild<QDialogButtonBox *>();

QPushButton *cancelAllBtn = new QPushButton( tr( "Cancel all" ) );
QPushButton *cancelAllInvalidBtn = new QPushButton( tr( "Cancel all invalid" ) );
QPushButton *storeAllInvalidBtn = new QPushButton( tr( "Store all (even invalid)" ) );
buttonBox->addButton( cancelAllBtn, QDialogButtonBox::RejectRole );
buttonBox->addButton( cancelAllInvalidBtn, QDialogButtonBox::RejectRole );
buttonBox->addButton( storeAllInvalidBtn, QDialogButtonBox::RejectRole );
connect( cancelAllBtn, &QAbstractButton::clicked, this, [ = ]()
{
done( 10 );
} );
connect( cancelAllInvalidBtn, &QAbstractButton::clicked, this, [ = ]()
{
done( 11 );
} );
connect( storeAllInvalidBtn, &QAbstractButton::clicked, this, [ = ]()
{
done( 12 );
} );
connect( buttonBox, &QDialogButtonBox::rejected, this, [ = ]()
{
//next feature
mCurrentIndex++;
progressBar->setValue( mCurrentIndex );
if ( mCurrentIndex < features->count() )
{
mAttributeForm->setFeature( features->at( mCurrentIndex ) );
}
else
{
done( 11 );
}
} );
connect( buttonBox, &QDialogButtonBox::accepted, this, [ = ]()
{
mAttributeForm->save();
QgsFeature feature;
feature.setAttributes( mAttributeForm->feature().attributes() );
mValidFeatures << feature;
//next feature
mCurrentIndex++;
progressBar->setValue( mCurrentIndex );
if ( mCurrentIndex < features->count() )
{
mAttributeForm->setFeature( features->at( mCurrentIndex ) );
}
else
{
done( 11 );
}
} );

connect( layer, &QObject::destroyed, this, &QWidget::close );

mMenu = new QgsActionMenu( layer, mAttributeForm->feature(), QStringLiteral( "Feature" ), this );
Expand Down
19 changes: 18 additions & 1 deletion src/gui/qgsattributedialog.h
Expand Up @@ -53,6 +53,17 @@ class GUI_EXPORT QgsAttributeDialog : public QDialog
*/
QgsAttributeDialog( QgsVectorLayer *vl, QgsFeature *thepFeature, bool featureOwner, QWidget *parent SIP_TRANSFERTHIS = nullptr, bool showDialogButtons = true, const QgsAttributeEditorContext &context = QgsAttributeEditorContext(), bool showFixFeatureDialogButtons = false );

/**
* Create an attribute dialog for a given layer and a feature list
*
* \param vl The layer for which the dialog will be generated
* \param features A list of features handled in the dialog
* \param parent A parent widget for the dialog
* \param context The context in which this dialog is created
*
*/
QgsAttributeDialog( QgsVectorLayer *vl, QgsFeatureList *features, QWidget *parent SIP_TRANSFERTHIS = nullptr, const QgsAttributeEditorContext &context = QgsAttributeEditorContext() );

~QgsAttributeDialog() override;

/**
Expand Down Expand Up @@ -95,6 +106,8 @@ class GUI_EXPORT QgsAttributeDialog : public QDialog
*/
bool event( QEvent *e ) override;

QgsFeatureList validFeatures() { return mValidFeatures; }

public slots:
void accept() override;
void reject() override;
Expand All @@ -103,7 +116,8 @@ class GUI_EXPORT QgsAttributeDialog : public QDialog
void show();

private:
void init( QgsVectorLayer *layer, QgsFeature *feature, const QgsAttributeEditorContext &context, bool showDialogButtons, bool showFixFeatureDialogButtons );
void init( QgsVectorLayer *layer, QgsFeature *feature, const QgsAttributeEditorContext &context, bool showDialogButtons );
void initList( QgsVectorLayer *layer, QgsFeatureList *features, const QgsAttributeEditorContext &context );

QString mSettingsPath;
// Used to sync multiple widgets for the same field
Expand All @@ -121,6 +135,9 @@ class GUI_EXPORT QgsAttributeDialog : public QDialog

QgsActionMenu *mMenu;

int mCurrentIndex = 0;
QgsFeatureList mValidFeatures;

static int sFormCounter;

void saveGeometry();
Expand Down

0 comments on commit c4dc133

Please sign in to comment.