Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fetch feature with geometry when opening a feature context menu in attribute table (fix #48964) #60658

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions python/PyQt6/core/auto_generated/vector/qgsvectorlayercache.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,25 @@ Considers the changed, added, deleted and permanent features
.. seealso:: :py:func:`featureAtId`

.. versionadded:: 3.32
%End

bool featureAtIdWithAllAttributesAndGeometry( QgsFeatureId featureId, QgsFeature &feature, bool skipCache = false );
%Docstring
Gets the feature at the given feature id with all attributes and geometry, if the cached feature
already contains all attributes and geometry, calling this function has the same effect as calling
:py:func:`~QgsVectorLayerCache.featureAtId`.

Considers the changed, added, deleted and permanent features

:param featureId: The id of the feature to query
:param feature: The result of the operation will be written to this feature
:param skipCache: Will query the layer regardless if the feature is in the cache already

:return: ``True`` in case of success

.. seealso:: :py:func:`featureAtId`

.. versionadded:: 3.42
%End

bool removeCachedFeature( QgsFeatureId fid );
Expand Down
1 change: 1 addition & 0 deletions python/PyQt6/gui/auto_additions/qgsfeaturelistmodel.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# The following has been generated automatically from src/gui/attributetable/qgsfeaturelistmodel.h
QgsFeatureListModel.FeatureInfoRole = QgsFeatureListModel.Role.FeatureInfoRole
QgsFeatureListModel.FeatureRole = QgsFeatureListModel.Role.FeatureRole
QgsFeatureListModel.FeatureWithGeometryRole = QgsFeatureListModel.Role.FeatureWithGeometryRole
try:
QgsFeatureListModel.FeatureInfo.__attribute_docs__ = {'isNew': 'True if feature is a newly added feature.', 'isEdited': 'True if feature has been edited.'}
QgsFeatureListModel.FeatureInfo.__group__ = ['attributetable']
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ class QgsFeatureListModel : QSortFilterProxyModel, QgsFeatureModel
enum Role /BaseType=IntEnum/
{
FeatureInfoRole,
FeatureRole
FeatureRole,
FeatureWithGeometryRole,
};

public:
Expand Down
19 changes: 19 additions & 0 deletions python/core/auto_generated/vector/qgsvectorlayercache.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,25 @@ Considers the changed, added, deleted and permanent features
.. seealso:: :py:func:`featureAtId`

.. versionadded:: 3.32
%End

bool featureAtIdWithAllAttributesAndGeometry( QgsFeatureId featureId, QgsFeature &feature, bool skipCache = false );
%Docstring
Gets the feature at the given feature id with all attributes and geometry, if the cached feature
already contains all attributes and geometry, calling this function has the same effect as calling
:py:func:`~QgsVectorLayerCache.featureAtId`.

Considers the changed, added, deleted and permanent features

:param featureId: The id of the feature to query
:param feature: The result of the operation will be written to this feature
:param skipCache: Will query the layer regardless if the feature is in the cache already

:return: ``True`` in case of success

.. seealso:: :py:func:`featureAtId`

.. versionadded:: 3.42
%End

bool removeCachedFeature( QgsFeatureId fid );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ class QgsFeatureListModel : QSortFilterProxyModel, QgsFeatureModel
enum Role
{
FeatureInfoRole,
FeatureRole
FeatureRole,
FeatureWithGeometryRole,
};

public:
Expand Down
31 changes: 31 additions & 0 deletions src/core/vector/qgsvectorlayercache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,33 @@ bool QgsVectorLayerCache::featureAtIdWithAllAttributes( QgsFeatureId featureId,
return featureFound;
}

bool QgsVectorLayerCache::featureAtIdWithAllAttributesAndGeometry( QgsFeatureId featureId, QgsFeature &feature, bool skipCache )
{
bool featureFound = false;

QgsCachedFeature *cachedFeature = nullptr;

if ( !skipCache )
{
cachedFeature = mCache[ featureId ];
}

if ( cachedFeature && cachedFeature->allAttributesFetched() && cachedFeature->geometryFetched() )
{
feature = QgsFeature( *cachedFeature->feature() );
featureFound = true;
}
else if ( mLayer->getFeatures( QgsFeatureRequest()
.setFilterFid( featureId ) )
.nextFeature( feature ) )
{
cacheFeature( feature, true, true );
featureFound = true;
}

return featureFound;
}

bool QgsVectorLayerCache::removeCachedFeature( QgsFeatureId fid )
{
bool removed = mCache.remove( fid );
Expand Down Expand Up @@ -561,3 +588,7 @@ bool QgsVectorLayerCache::QgsCachedFeature::allAttributesFetched() const
return mAllAttributesFetched;
}

bool QgsVectorLayerCache::QgsCachedFeature::geometryFetched() const
{
return mGeometryFetched;
}
26 changes: 23 additions & 3 deletions src/core/vector/qgsvectorlayercache.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,12 @@ class CORE_EXPORT QgsVectorLayerCache : public QObject
* \param feat The feature to cache. A copy will be made.
* \param vlCache The cache to inform when the feature has been removed from the cache.
* \param allAttributesFetched TRUE if the feature was fetched with all attributes (and not a subset)
* \param geometryFetched TRUE if the feature was fetched with geometry, \since QGIS 3.42
*/
QgsCachedFeature( const QgsFeature &feat, QgsVectorLayerCache *vlCache, bool allAttributesFetched )
QgsCachedFeature( const QgsFeature &feat, QgsVectorLayerCache *vlCache, bool allAttributesFetched, bool geometryFetched )
: mCache( vlCache )
, mAllAttributesFetched( allAttributesFetched )
, mGeometryFetched( geometryFetched )
{
mFeature = new QgsFeature( feat );
}
Expand All @@ -84,10 +86,13 @@ class CORE_EXPORT QgsVectorLayerCache : public QObject

bool allAttributesFetched() const;

bool geometryFetched() const;

private:
QgsFeature *mFeature = nullptr;
QgsVectorLayerCache *mCache = nullptr;
bool mAllAttributesFetched = true;
bool mGeometryFetched = false;

friend class QgsVectorLayerCache;
Q_DISABLE_COPY( QgsCachedFeature )
Expand Down Expand Up @@ -270,6 +275,21 @@ class CORE_EXPORT QgsVectorLayerCache : public QObject
*/
bool featureAtIdWithAllAttributes( QgsFeatureId featureId, QgsFeature &feature, bool skipCache = false );

/**
* Gets the feature at the given feature id with all attributes and geometry, if the cached feature
* already contains all attributes and geometry, calling this function has the same effect as calling
* featureAtId().
*
* Considers the changed, added, deleted and permanent features
* \param featureId The id of the feature to query
* \param feature The result of the operation will be written to this feature
* \param skipCache Will query the layer regardless if the feature is in the cache already
* \returns TRUE in case of success
* \see featureAtId()
* \since QGIS 3.42
*/
bool featureAtIdWithAllAttributesAndGeometry( QgsFeatureId featureId, QgsFeature &feature, bool skipCache = false );

/**
* Removes the feature identified by fid from the cache if present.
* \param fid The id of the feature to delete
Expand Down Expand Up @@ -417,9 +437,9 @@ class CORE_EXPORT QgsVectorLayerCache : public QObject

void connectJoinedLayers() const;

inline void cacheFeature( QgsFeature &feat, bool allAttributesFetched )
inline void cacheFeature( QgsFeature &feat, bool allAttributesFetched, bool geometryFetched = false )
{
QgsCachedFeature *cachedFeature = new QgsCachedFeature( feat, this, allAttributesFetched );
QgsCachedFeature *cachedFeature = new QgsCachedFeature( feat, this, allAttributesFetched, geometryFetched );
mCache.insert( feat.id(), cachedFeature );
if ( mCacheUnorderedKeys.find( feat.id() ) == mCacheUnorderedKeys.end() )
{
Expand Down
8 changes: 8 additions & 0 deletions src/gui/attributetable/qgsfeaturelistmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,14 @@ QVariant QgsFeatureListModel::data( const QModelIndex &index, int role ) const

return QVariant::fromValue( feat );
}
else if ( role == FeatureWithGeometryRole )
{
QgsFeature feat;

mFilterModel->layerCache()->featureAtIdWithAllAttributesAndGeometry( idxToFid( index ), feat );

return QVariant::fromValue( feat );
}
else if ( role == Qt::TextAlignmentRole )
{
return static_cast<Qt::Alignment::Int>( Qt::AlignLeft );
Expand Down
3 changes: 2 additions & 1 deletion src/gui/attributetable/qgsfeaturelistmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ class GUI_EXPORT QgsFeatureListModel : public QSortFilterProxyModel, public QgsF
enum Role
{
FeatureInfoRole = 0x1000, // Make sure no collisions with roles on QgsAttributeTableModel
FeatureRole
FeatureRole, //!< Feature with all attributes and no geometry
FeatureWithGeometryRole, //!< Feature with all attributes and geometry, \since QGIS 3.42
};

public:
Expand Down
2 changes: 1 addition & 1 deletion src/gui/attributetable/qgsfeaturelistview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ void QgsFeatureListView::contextMenuEvent( QContextMenuEvent *event )

if ( index.isValid() )
{
const QgsFeature feature = mModel->data( index, QgsFeatureListModel::FeatureRole ).value<QgsFeature>();
const QgsFeature feature = mModel->data( index, QgsFeatureListModel::FeatureWithGeometryRole ).value<QgsFeature>();

QgsActionMenu *menu = new QgsActionMenu( mModel->layerCache()->layer(), feature, QStringLiteral( "Feature" ), this );

Expand Down
Loading