mirror of
https://github.com/qgis/QGIS.git
synced 2025-12-10 00:08:20 -05:00
[feature][ui] Add a Show in Attribute Table action to the right click menu of legend class symbols (#49984)
This commit is contained in:
parent
ec51684f06
commit
b7e31d4508
@ -220,6 +220,12 @@ need to be filtered again (like on filter or on main model data change).
|
|||||||
.. versionadded:: 3.10.3
|
.. versionadded:: 3.10.3
|
||||||
%End
|
%End
|
||||||
|
|
||||||
|
QString filterExpression() const;
|
||||||
|
%Docstring
|
||||||
|
Returns the stored filter expression string.
|
||||||
|
|
||||||
|
.. versionadded:: 3.28.0
|
||||||
|
%End
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void sortColumnChanged( int column, Qt::SortOrder order );
|
void sortColumnChanged( int column, Qt::SortOrder order );
|
||||||
|
|||||||
@ -7747,7 +7747,7 @@ void QgisApp::fieldCalculator()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgisApp::attributeTable( QgsAttributeTableFilterModel::FilterMode filter )
|
void QgisApp::attributeTable( QgsAttributeTableFilterModel::FilterMode filter, const QString &filterExpression )
|
||||||
{
|
{
|
||||||
QgsVectorLayer *myLayer = qobject_cast<QgsVectorLayer *>( activeLayer() );
|
QgsVectorLayer *myLayer = qobject_cast<QgsVectorLayer *>( activeLayer() );
|
||||||
if ( !myLayer || !myLayer->dataProvider() )
|
if ( !myLayer || !myLayer->dataProvider() )
|
||||||
@ -7755,7 +7755,7 @@ void QgisApp::attributeTable( QgsAttributeTableFilterModel::FilterMode filter )
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsAttributeTableDialog *mDialog = new QgsAttributeTableDialog( myLayer, filter );
|
QgsAttributeTableDialog *mDialog = new QgsAttributeTableDialog( myLayer, filter, nullptr, Qt::Window, nullptr, filterExpression );
|
||||||
mDialog->show();
|
mDialog->show();
|
||||||
// the dialog will be deleted by itself on close
|
// the dialog will be deleted by itself on close
|
||||||
}
|
}
|
||||||
|
|||||||
@ -934,7 +934,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
|
|||||||
void layerProperties();
|
void layerProperties();
|
||||||
|
|
||||||
//! show the attribute table for the currently selected layer
|
//! show the attribute table for the currently selected layer
|
||||||
void attributeTable( QgsAttributeTableFilterModel::FilterMode filter = QgsAttributeTableFilterModel::ShowAll );
|
void attributeTable( QgsAttributeTableFilterModel::FilterMode filter = QgsAttributeTableFilterModel::ShowAll, const QString &filterExpression = QString() );
|
||||||
|
|
||||||
void fieldCalculator();
|
void fieldCalculator();
|
||||||
|
|
||||||
|
|||||||
@ -802,7 +802,6 @@ QMenu *QgsAppLayerTreeViewMenuProvider::createContextMenu()
|
|||||||
{
|
{
|
||||||
QAction *selectMatching = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "/mIconSelected.svg" ) ), tr( "Select Features" ), menu );
|
QAction *selectMatching = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "/mIconSelected.svg" ) ), tr( "Select Features" ), menu );
|
||||||
menu->addAction( selectMatching );
|
menu->addAction( selectMatching );
|
||||||
menu->addSeparator();
|
|
||||||
connect( selectMatching, &QAction::triggered, this, [layerId, ruleKey ]
|
connect( selectMatching, &QAction::triggered, this, [layerId, ruleKey ]
|
||||||
{
|
{
|
||||||
if ( QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( QgsProject::instance()->mapLayer( layerId ) ) )
|
if ( QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( QgsProject::instance()->mapLayer( layerId ) ) )
|
||||||
@ -836,6 +835,29 @@ QMenu *QgsAppLayerTreeViewMenuProvider::createContextMenu()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
QAction *showMatchingInAttributeTable = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "/propertyicons/attributes.svg" ) ), tr( "Show in Attribute Table" ), menu );
|
||||||
|
menu->addAction( showMatchingInAttributeTable );
|
||||||
|
connect( showMatchingInAttributeTable, &QAction::triggered, this, [layerId, ruleKey ]
|
||||||
|
{
|
||||||
|
if ( QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( QgsProject::instance()->mapLayer( layerId ) ) )
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
QString filterExp = layer->renderer() ? layer->renderer()->legendKeyToExpression( ruleKey, layer, ok ) : QString();
|
||||||
|
if ( ok )
|
||||||
|
{
|
||||||
|
const QString canvasFilter = QgsMapCanvasUtils::filterForLayer( QgisApp::instance()->mapCanvas(), layer );
|
||||||
|
if ( canvasFilter == QLatin1String( "FALSE" ) )
|
||||||
|
return;
|
||||||
|
else if ( !canvasFilter.isEmpty() )
|
||||||
|
filterExp = QStringLiteral( "(%1) AND (%2)" ).arg( filterExp, canvasFilter );
|
||||||
|
|
||||||
|
QgisApp::instance()->attributeTable( QgsAttributeTableFilterModel::ShowFilteredList, filterExp );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
menu->addSeparator();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( layer && layer->type() == QgsMapLayerType::VectorLayer && symbolNode->symbol() )
|
if ( layer && layer->type() == QgsMapLayerType::VectorLayer && symbolNode->symbol() )
|
||||||
|
|||||||
@ -108,7 +108,7 @@ void QgsAttributeTableDialog::updateMultiEditButtonState()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *layer, QgsAttributeTableFilterModel::FilterMode initialMode, QWidget *parent, Qt::WindowFlags flags, bool *initiallyDocked )
|
QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *layer, QgsAttributeTableFilterModel::FilterMode initialMode, QWidget *parent, Qt::WindowFlags flags, bool *initiallyDocked, const QString &filterExpression )
|
||||||
: QDialog( parent, flags )
|
: QDialog( parent, flags )
|
||||||
, mLayer( layer )
|
, mLayer( layer )
|
||||||
{
|
{
|
||||||
@ -221,6 +221,10 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *layer, QgsAttr
|
|||||||
{
|
{
|
||||||
r.setFilterFids( layer->editBuffer() ? layer->editBuffer()->allAddedOrEditedFeatures() : QgsFeatureIds() );
|
r.setFilterFids( layer->editBuffer() ? layer->editBuffer()->allAddedOrEditedFeatures() : QgsFeatureIds() );
|
||||||
}
|
}
|
||||||
|
else if ( !filterExpression.isEmpty() )
|
||||||
|
{
|
||||||
|
r.setFilterExpression( filterExpression );
|
||||||
|
}
|
||||||
if ( !needsGeom )
|
if ( !needsGeom )
|
||||||
r.setFlags( QgsFeatureRequest::NoGeometry );
|
r.setFlags( QgsFeatureRequest::NoGeometry );
|
||||||
|
|
||||||
@ -385,6 +389,10 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *layer, QgsAttr
|
|||||||
mFeatureFilterWidget->filterEdited();
|
mFeatureFilterWidget->filterEdited();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case QgsAttributeTableFilterModel::ShowFilteredList:
|
||||||
|
mFeatureFilterWidget->setFilterExpression( filterExpression );
|
||||||
|
break;
|
||||||
|
|
||||||
case QgsAttributeTableFilterModel::ShowAll:
|
case QgsAttributeTableFilterModel::ShowAll:
|
||||||
default:
|
default:
|
||||||
mFeatureFilterWidget->filterShowAll();
|
mFeatureFilterWidget->filterShowAll();
|
||||||
|
|||||||
@ -53,8 +53,12 @@ class APP_EXPORT QgsAttributeTableDialog : public QDialog, private Ui::QgsAttrib
|
|||||||
* \param parent parent object
|
* \param parent parent object
|
||||||
* \param flags window flags
|
* \param flags window flags
|
||||||
*/
|
*/
|
||||||
QgsAttributeTableDialog( QgsVectorLayer *layer, QgsAttributeTableFilterModel::FilterMode initialMode = QgsAttributeTableFilterModel::ShowAll, QWidget *parent = nullptr, Qt::WindowFlags flags = Qt::Window,
|
QgsAttributeTableDialog( QgsVectorLayer *layer,
|
||||||
bool *initiallyDocked = nullptr );
|
QgsAttributeTableFilterModel::FilterMode initialMode = QgsAttributeTableFilterModel::ShowAll,
|
||||||
|
QWidget *parent = nullptr,
|
||||||
|
Qt::WindowFlags flags = Qt::Window,
|
||||||
|
bool *initiallyDocked = nullptr,
|
||||||
|
const QString &filterExpression = QString() );
|
||||||
~QgsAttributeTableDialog() override;
|
~QgsAttributeTableDialog() override;
|
||||||
|
|
||||||
QgsExpressionContext createExpressionContext() const override;
|
QgsExpressionContext createExpressionContext() const override;
|
||||||
|
|||||||
@ -251,6 +251,13 @@ class GUI_EXPORT QgsAttributeTableFilterModel: public QSortFilterProxyModel, pub
|
|||||||
*/
|
*/
|
||||||
void setFilterExpression( const QgsExpression &expression, const QgsExpressionContext &context );
|
void setFilterExpression( const QgsExpression &expression, const QgsExpressionContext &context );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the stored filter expression string.
|
||||||
|
*
|
||||||
|
* \since QGIS 3.28.0
|
||||||
|
*/
|
||||||
|
QString filterExpression() const { return mFilterExpression; };
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -361,9 +361,14 @@ void QgsDualView::setFilterMode( QgsAttributeTableFilterModel::FilterMode filter
|
|||||||
|
|
||||||
case QgsAttributeTableFilterModel::ShowAll:
|
case QgsAttributeTableFilterModel::ShowAll:
|
||||||
case QgsAttributeTableFilterModel::ShowFilteredList:
|
case QgsAttributeTableFilterModel::ShowFilteredList:
|
||||||
|
{
|
||||||
|
const QString filterExpression = filterMode == QgsAttributeTableFilterModel::ShowFilteredList ? mFilterModel->filterExpression() : QString();
|
||||||
|
if ( !filterExpression.isEmpty() )
|
||||||
|
r.setFilterExpression( mFilterModel->filterExpression() );
|
||||||
connect( mFilterModel, &QgsAttributeTableFilterModel::featuresFiltered, this, &QgsDualView::filterChanged );
|
connect( mFilterModel, &QgsAttributeTableFilterModel::featuresFiltered, this, &QgsDualView::filterChanged );
|
||||||
connect( mFilterModel, &QgsAttributeTableFilterModel::filterError, this, &QgsDualView::filterError );
|
connect( mFilterModel, &QgsAttributeTableFilterModel::filterError, this, &QgsDualView::filterError );
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case QgsAttributeTableFilterModel::ShowSelected:
|
case QgsAttributeTableFilterModel::ShowSelected:
|
||||||
connect( masterModel()->layer(), &QgsVectorLayer::selectionChanged, this, &QgsDualView::updateSelectedFeatures );
|
connect( masterModel()->layer(), &QgsVectorLayer::selectionChanged, this, &QgsDualView::updateSelectedFeatures );
|
||||||
|
|||||||
@ -462,7 +462,6 @@ void QgsFeatureFilterWidget::setFilterExpression( const QString &filterString, Q
|
|||||||
}
|
}
|
||||||
|
|
||||||
mMainView->filterFeatures( filterExpression, context );
|
mMainView->filterFeatures( filterExpression, context );
|
||||||
|
|
||||||
mMainView->setFilterMode( QgsAttributeTableFilterModel::ShowFilteredList );
|
mMainView->setFilterMode( QgsAttributeTableFilterModel::ShowFilteredList );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -61,6 +61,7 @@ class TestQgsAttributeTable : public QObject
|
|||||||
void testSortByDisplayExpression();
|
void testSortByDisplayExpression();
|
||||||
void testOrderColumn();
|
void testOrderColumn();
|
||||||
void testFilteredFeatures();
|
void testFilteredFeatures();
|
||||||
|
void testOpenWithFilterExpression();
|
||||||
void testVisibleTemporal();
|
void testVisibleTemporal();
|
||||||
void testCopySelectedRows();
|
void testCopySelectedRows();
|
||||||
void testSortNumbers();
|
void testSortNumbers();
|
||||||
@ -757,5 +758,40 @@ void TestQgsAttributeTable::testCopySelectedRows()
|
|||||||
QCOMPARE( clipboard->crs().authid(), "EPSG:3111" );
|
QCOMPARE( clipboard->crs().authid(), "EPSG:3111" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestQgsAttributeTable::testOpenWithFilterExpression()
|
||||||
|
{
|
||||||
|
// test attribute table opening in show feature visible mode
|
||||||
|
std::unique_ptr< QgsVectorLayer> tempLayer( new QgsVectorLayer( QStringLiteral( "LineString?crs=epsg:4326&field=pk:int&field=col1:date" ), QStringLiteral( "vl" ), QStringLiteral( "memory" ) ) );
|
||||||
|
QVERIFY( tempLayer->isValid() );
|
||||||
|
|
||||||
|
QgsPolylineXY line;
|
||||||
|
line << QgsPointXY( 0, 0 ) << QgsPointXY( 1, 1 );
|
||||||
|
QgsGeometry geometry = QgsGeometry::fromPolylineXY( line ) ;
|
||||||
|
QgsFeature f1( tempLayer->dataProvider()->fields(), 1 );
|
||||||
|
f1.setGeometry( geometry );
|
||||||
|
f1.setAttributes( QgsAttributes() << 1 << QDate( 2020, 1, 1 ) );
|
||||||
|
QgsFeature f2( tempLayer->dataProvider()->fields(), 2 );
|
||||||
|
f2.setGeometry( geometry );
|
||||||
|
f2.setAttributes( QgsAttributes() << 2 << QDate( 2020, 3, 1 ) );
|
||||||
|
QgsFeature f3( tempLayer->dataProvider()->fields(), 3 );
|
||||||
|
line.clear();
|
||||||
|
line << QgsPointXY( -3, -3 ) << QgsPointXY( -2, -2 );
|
||||||
|
geometry = QgsGeometry::fromPolylineXY( line );
|
||||||
|
f3.setGeometry( geometry );
|
||||||
|
f3.setAttributes( QgsAttributes() << 3 << QDate( 2020, 1, 1 ) );
|
||||||
|
QVERIFY( tempLayer->dataProvider()->addFeatures( QgsFeatureList() << f1 << f2 << f3 ) );
|
||||||
|
|
||||||
|
const QString filterExpression = QStringLiteral( "col1 < to_date('2020-02-03')" );
|
||||||
|
std::unique_ptr< QgsAttributeTableDialog > dlg( new QgsAttributeTableDialog( tempLayer.get(),
|
||||||
|
QgsAttributeTableFilterModel::ShowFilteredList,
|
||||||
|
nullptr,
|
||||||
|
Qt::Window,
|
||||||
|
nullptr,
|
||||||
|
filterExpression ) );
|
||||||
|
|
||||||
|
// feature id 2 is filtered out due not matching the provided filter expression
|
||||||
|
QCOMPARE( dlg->mMainView->filteredFeatures(), QgsFeatureIds() << 1 << 3 );
|
||||||
|
}
|
||||||
|
|
||||||
QGSTEST_MAIN( TestQgsAttributeTable )
|
QGSTEST_MAIN( TestQgsAttributeTable )
|
||||||
#include "testqgsattributetable.moc"
|
#include "testqgsattributetable.moc"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user