Skip to content

Commit

Permalink
quick add reuse last value option
Browse files Browse the repository at this point in the history
  • Loading branch information
tomasMizera authored and wonder-sk committed Feb 2, 2021
1 parent 46dbd8b commit 5475a05
Show file tree
Hide file tree
Showing 11 changed files with 276 additions and 33 deletions.
5 changes: 5 additions & 0 deletions src/quickgui/attributes/qgsquickattributeformmodel.cpp
Expand Up @@ -77,6 +77,11 @@ void QgsQuickAttributeFormModel::forceClean()
mSourceModel->forceClean();
}

void QgsQuickAttributeFormModel::setRememberValuesAllowed( bool rememberValuesAllowed )
{
mSourceModel->setRememberValuesAllowed( rememberValuesAllowed );
}

bool QgsQuickAttributeFormModel::filterAcceptsRow( int source_row, const QModelIndex &source_parent ) const
{
return mSourceModel->data( mSourceModel->index( source_row, 0, source_parent ), CurrentlyVisible ).toBool();
Expand Down
8 changes: 8 additions & 0 deletions src/quickgui/attributes/qgsquickattributeformmodel.h
Expand Up @@ -51,9 +51,13 @@ class QUICK_EXPORT QgsQuickAttributeFormModel : public QSortFilterProxyModel

//! Returns TRUE if all hard constraints defined on fields are satisfied with the current attribute values
Q_PROPERTY( bool constraintsHardValid READ constraintsHardValid NOTIFY constraintsHardValidChanged )

//! Returns TRUE if all soft constraints defined on fields are satisfied with the current attribute values
Q_PROPERTY( bool constraintsSoftValid READ constraintsSoftValid NOTIFY constraintsSoftValidChanged )

//! Returns TRUE if remembering values is allowed
Q_PROPERTY( bool rememberValuesAllowed WRITE setRememberValuesAllowed )

public:

//! Feature fields's roles
Expand Down Expand Up @@ -111,6 +115,10 @@ class QUICK_EXPORT QgsQuickAttributeFormModel : public QSortFilterProxyModel
//! Resets the model
Q_INVOKABLE void forceClean();

public slots:
//! Allows or forbids attribute model to reuse last entered values
void setRememberValuesAllowed( bool rememberValuesAllowed );

signals:
//! \copydoc QgsQuickAttributeFormModel::attributeModel
void attributeModelChanged();
Expand Down
11 changes: 10 additions & 1 deletion src/quickgui/attributes/qgsquickattributeformmodelbase.cpp
Expand Up @@ -252,14 +252,18 @@ void QgsQuickAttributeFormModelBase::flatten( QgsAttributeEditorContainer *conta

QgsField field = mLayer->fields().at( fieldIndex );

Qt::CheckState rememberFlag = Qt::Unchecked;
if ( mAttributeModel->rememberValuesAllowed() && mAttributeModel->isFieldRemembered( fieldIndex ) )
rememberFlag = Qt::Checked;

QStandardItem *item = new QStandardItem();
item->setData( mLayer->attributeDisplayName( fieldIndex ), QgsQuickAttributeFormModel::Name );
item->setData( mAttributeModel->featureLayerPair().feature().attribute( fieldIndex ), QgsQuickAttributeFormModel::AttributeValue );
item->setData( !mLayer->editFormConfig().readOnly( fieldIndex ), QgsQuickAttributeFormModel::AttributeEditable );
QgsEditorWidgetSetup setup = mLayer->editorWidgetSetup( fieldIndex );
item->setData( setup.type(), QgsQuickAttributeFormModel::EditorWidget );
item->setData( setup.config(), QgsQuickAttributeFormModel::EditorWidgetConfig );
item->setData( mAttributeModel->rememberedAttributes().at( fieldIndex ) ? Qt::Checked : Qt::Unchecked, QgsQuickAttributeFormModel::RememberValue );
item->setData( rememberFlag, QgsQuickAttributeFormModel::RememberValue );
item->setData( mLayer->fields().at( fieldIndex ), QgsQuickAttributeFormModel::Field );
item->setData( QStringLiteral( "field" ), QgsQuickAttributeFormModel::ElementType );
item->setData( fieldIndex, QgsQuickAttributeFormModel::FieldIndex );
Expand Down Expand Up @@ -428,6 +432,11 @@ void QgsQuickAttributeFormModelBase::forceClean()
mConstraintsSoftValid = false;
}

void QgsQuickAttributeFormModelBase::setRememberValuesAllowed( bool rememberValuesAllowed )
{
mAttributeModel->setRememberValuesAllowed( rememberValuesAllowed );
}

bool QgsQuickAttributeFormModelBase::hasTabs() const
{
return mHasTabs;
Expand Down
3 changes: 3 additions & 0 deletions src/quickgui/attributes/qgsquickattributeformmodelbase.h
Expand Up @@ -108,6 +108,9 @@ class QgsQuickAttributeFormModelBase : public QStandardItemModel
//! Resets the model
Q_INVOKABLE void forceClean();

//! Allows or forbids attribute model to reuse last entered values
void setRememberValuesAllowed( bool rememberValuesAllowed );

signals:
//! \copydoc QgsQuickAttributeFormModelBase::attributeModel
void attributeModelChanged();
Expand Down
100 changes: 84 additions & 16 deletions src/quickgui/attributes/qgsquickattributemodel.cpp
Expand Up @@ -25,6 +25,8 @@ QgsQuickAttributeModel::QgsQuickAttributeModel( QObject *parent )
connect( this, &QgsQuickAttributeModel::modelReset, this, &QgsQuickAttributeModel::featureLayerPairChanged );
connect( this, &QgsQuickAttributeModel::featureChanged, this, &QgsQuickAttributeModel::featureLayerPairChanged );
connect( this, &QgsQuickAttributeModel::layerChanged, this, &QgsQuickAttributeModel::featureLayerPairChanged );
connect( this, &QgsQuickAttributeModel::featureCreated, this, &QgsQuickAttributeModel::onFeatureCreated );
connect( this, &QgsQuickAttributeModel::rememberValuesAllowChanged, this, &QgsQuickAttributeModel::onRememberValuesAllowChanged );
}

QgsQuickFeatureLayerPair QgsQuickAttributeModel::featureLayerPair() const
Expand All @@ -40,10 +42,34 @@ void QgsQuickAttributeModel::setFeatureLayerPair( const QgsQuickFeatureLayerPair

void QgsQuickAttributeModel::forceClean()
{
mRememberedAttributes.clear();
mRememberedValues.clear();
mFeatureLayerPair = QgsQuickFeatureLayerPair();
}

void QgsQuickAttributeModel::onFeatureCreated( const QgsFeature &feature )
{
if ( mRememberValuesAllowed )
{
QString layerName = mFeatureLayerPair.layer()->id();

// save created feature to remember values
if ( mRememberedValues.contains( layerName ) )
{
mRememberedValues[layerName].feature = feature;
}
}
}

void QgsQuickAttributeModel::onRememberValuesAllowChanged()
{
if ( mRememberValuesAllowed ) // add current layer
{
if ( mFeatureLayerPair.layer() )
mRememberedValues[mFeatureLayerPair.layer()->id()].attributeFilter.fill( false, mFeatureLayerPair.layer()->fields().size() );
}
else
mRememberedValues.clear();
}

void QgsQuickAttributeModel::setVectorLayer( QgsVectorLayer *layer )
{
Expand All @@ -53,30 +79,44 @@ void QgsQuickAttributeModel::setVectorLayer( QgsVectorLayer *layer )
beginResetModel();
mFeatureLayerPair = QgsQuickFeatureLayerPair( mFeatureLayerPair.feature(), layer );


if ( const QgsVectorLayer *lLayer = mFeatureLayerPair.layer() )
{
mRememberedAttributes.resize( lLayer->fields().size() );
mRememberedAttributes.fill( false );
}
else
if ( mRememberValuesAllowed )
{
mRememberedAttributes.clear();
if ( layer && !mRememberedValues.contains( layer->id() ) )
{
mRememberedValues[layer->id()].attributeFilter.fill( false, layer->fields().size() );
}
}

endResetModel();
emit layerChanged();
}

void QgsQuickAttributeModel::prefillRememberedValues()
{
RememberedValues from = mRememberedValues[mFeatureLayerPair.layer()->id()];
if ( !from.feature.isValid() )
return;

QgsAttributes fromAttributes = from.feature.attributes();
for ( int i = 0; i < fromAttributes.length(); i++ )
{
if ( from.attributeFilter.at( i ) )
mFeatureLayerPair.featureRef().setAttribute( i, fromAttributes.at( i ) );
}
}

void QgsQuickAttributeModel::setFeature( const QgsFeature &feature )
{
if ( mFeatureLayerPair.feature() == feature )
return;

beginResetModel();
mFeatureLayerPair = QgsQuickFeatureLayerPair( feature, mFeatureLayerPair.layer() );
endResetModel();

if ( mRememberValuesAllowed && FID_IS_NULL( mFeatureLayerPair.feature().id() ) ) // this is a new feature
prefillRememberedValues();

endResetModel();
emit featureChanged();
}

Expand Down Expand Up @@ -117,7 +157,10 @@ QVariant QgsQuickAttributeModel::data( const QModelIndex &index, int role ) cons
break;

case RememberAttribute:
return mRememberedAttributes.at( index.row() );
if ( mRememberValuesAllowed )
return mRememberedValues[mFeatureLayerPair.layer()->id()].attributeFilter.at( index.row() );
else
return QVariant( false );
break;
}

Expand Down Expand Up @@ -150,8 +193,11 @@ bool QgsQuickAttributeModel::setData( const QModelIndex &index, const QVariant &

case RememberAttribute:
{
mRememberedAttributes[ index.row() ] = value.toBool();
emit dataChanged( index, index, QVector<int>() << role );
if ( mRememberValuesAllowed )
{
mRememberedValues[mFeatureLayerPair.layer()->id()].attributeFilter[index.row()] = value.toBool();
emit dataChanged( index, index, QVector<int>() << role );
}
break;
}
}
Expand Down Expand Up @@ -251,7 +297,7 @@ void QgsQuickAttributeModel::resetAttributes()
beginResetModel();
for ( int i = 0; i < fields.count(); ++i )
{
if ( !mRememberedAttributes.at( i ) )
if ( !mRememberValuesAllowed || !mRememberedValues[mFeatureLayerPair.layer()->id()].attributeFilter.at( i ) )
{
if ( !fields.at( i ).defaultValueDefinition().expression().isEmpty() )
{
Expand Down Expand Up @@ -300,6 +346,8 @@ void QgsQuickAttributeModel::create()
Qgis::Critical );
}
commit();

emit featureCreated( mFeatureLayerPair.featureRef() );
}

bool QgsQuickAttributeModel::commit()
Expand Down Expand Up @@ -337,7 +385,27 @@ bool QgsQuickAttributeModel::startEditing()
}
}

QVector<bool> QgsQuickAttributeModel::rememberedAttributes() const
void QgsQuickAttributeModel::setRememberValuesAllowed( bool allowed )
{
return mRememberedAttributes;
if ( allowed == mRememberValuesAllowed )
return;

mRememberValuesAllowed = allowed;
emit rememberValuesAllowChanged();
}

bool QgsQuickAttributeModel::rememberValuesAllowed() const
{
return mRememberValuesAllowed;
}

bool QgsQuickAttributeModel::isFieldRemembered( const int fieldIndex ) const
{
if ( !mRememberValuesAllowed || !mFeatureLayerPair.layer() || !mRememberedValues.contains( mFeatureLayerPair.layer()->id() ) )
return false;

if ( fieldIndex < 0 || fieldIndex > mRememberedValues[mFeatureLayerPair.layer()->id()].attributeFilter.size() )
return false;

return mRememberedValues[mFeatureLayerPair.layer()->id()].attributeFilter.at( fieldIndex );
}
47 changes: 40 additions & 7 deletions src/quickgui/attributes/qgsquickattributemodel.h
Expand Up @@ -33,10 +33,10 @@
* related to layer and feature pair.
*
* On top of the QgsFeature attributes, support for "remember"
* attribute is added. Remember attribute is used for
* quick addition of the multiple features to the same layer.
* A new feature can use "remembered" attribute values from
* the last feature added.
* values is added. When model is allowed to remember values, it reuses
* values for last created features. However, this only work for attributes
* that passes filter (\see RememberedValues struct). This feature is used for quick addition
* of multiple features to the same layer.
*
*
* \note QML Type: AttributeModel
Expand Down Expand Up @@ -67,6 +67,13 @@ class QUICK_EXPORT QgsQuickAttributeModel : public QAbstractListModel
RememberAttribute //!< Remember attribute value for next feature
};

//! Remembered values struct contains last created feature instance and a boolean vector masking attributes that should be remembered
struct RememberedValues
{
QgsFeature feature;
QVector<bool> attributeFilter;
};

//! Creates a new feature attribute model
explicit QgsQuickAttributeModel( QObject *parent = nullptr );

Expand Down Expand Up @@ -115,8 +122,8 @@ class QUICK_EXPORT QgsQuickAttributeModel : public QAbstractListModel
//! Resets remembered attributes
Q_INVOKABLE virtual void resetAttributes();

//! Gets remembered attributes
QVector<bool> rememberedAttributes() const;
//! Gives information whether field with given index is remembered or not
bool isFieldRemembered( const int fieldIndex ) const;

//! Gets current featureLayerPair
QgsQuickFeatureLayerPair featureLayerPair() const;
Expand All @@ -127,8 +134,20 @@ class QUICK_EXPORT QgsQuickAttributeModel : public QAbstractListModel
//! Resets the model
Q_INVOKABLE void forceClean();

//! Allows or forbids model to reuse last entered values
void setRememberValuesAllowed( bool allowed );

//! Returns whether model is remembering last entered values
bool rememberValuesAllowed() const;

public slots:

//! Handles feature creation
void onFeatureCreated( const QgsFeature &feature );

//! Handles changing allowance of reusing last entered values
void onRememberValuesAllowChanged();

signals:
//! Feature or layer changed in feature layer pair
void featureLayerPairChanged();
Expand All @@ -139,17 +158,31 @@ class QUICK_EXPORT QgsQuickAttributeModel : public QAbstractListModel
//! Layer changed, feature is the same
void layerChanged();

//! Feature has been created
void featureCreated( const QgsFeature &feature );

//! Emitted when user allows reusing last entered values
void rememberValuesAllowChanged();

protected:
//! Commits model changes
bool commit();
//! Starts editing model
bool startEditing();

QgsQuickFeatureLayerPair mFeatureLayerPair;
QVector<bool> mRememberedAttributes;

private:
void setFeature( const QgsFeature &feature );
void setVectorLayer( QgsVectorLayer *layer );

//! Fills remembered attributes from last created feature (mRememberedValues) to current feature (mFeatureLayerPair)
void prefillRememberedValues();

//! Remembered last created feature for each layer (key)
QHash<QString, RememberedValues> mRememberedValues;

bool mRememberValuesAllowed;
};

#endif // QGSQUICKATTRIBUTEMODEL_H
1 change: 1 addition & 0 deletions src/quickgui/plugin/CMakeLists.txt
Expand Up @@ -11,6 +11,7 @@ set(QGIS_QUICK_PLUGIN_SRC

set(QGIS_QUICK_PLUGIN_RESOURCES
components/qgsquickicontextitem.qml
components/qgsquickcheckboxcomponent.qml
editor/qgsquickeditorwidgetcombobox.qml
editor/qgsquickcheckbox.qml
editor/qgsquickdatetime.qml
Expand Down

0 comments on commit 5475a05

Please sign in to comment.