mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-25 00:58:06 -05:00
[FEATURE] add new locator filter searching across all layers in display expression
This commit is contained in:
parent
d6b2537e1e
commit
d54b7b1d4d
@ -191,6 +191,10 @@ void QgsActionLocatorFilter::searchActions( const QString &string, QWidget *pare
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// QgsActiveLayerFeaturesLocatorFilter
|
||||
//
|
||||
|
||||
QgsActiveLayerFeaturesLocatorFilter::QgsActiveLayerFeaturesLocatorFilter( QObject *parent )
|
||||
: QgsLocatorFilter( parent )
|
||||
{
|
||||
@ -298,6 +302,106 @@ void QgsActiveLayerFeaturesLocatorFilter::triggerResult( const QgsLocatorResult
|
||||
QgisApp::instance()->mapCanvas()->zoomToFeatureIds( layer, QgsFeatureIds() << id );
|
||||
}
|
||||
|
||||
//
|
||||
// QgsAllLayersFeaturesLocatorFilter
|
||||
//
|
||||
|
||||
QgsAllLayersFeaturesLocatorFilter::QgsAllLayersFeaturesLocatorFilter( QObject *parent )
|
||||
: QgsLocatorFilter( parent )
|
||||
{
|
||||
setUseWithoutPrefix( false );
|
||||
}
|
||||
|
||||
QgsAllLayersFeaturesLocatorFilter *QgsAllLayersFeaturesLocatorFilter::clone() const
|
||||
{
|
||||
return new QgsAllLayersFeaturesLocatorFilter();
|
||||
}
|
||||
|
||||
void QgsAllLayersFeaturesLocatorFilter::prepare( const QString &string, const QgsLocatorContext & )
|
||||
{
|
||||
if ( string.length() < 3 )
|
||||
return;
|
||||
|
||||
const QMap<QString, QgsMapLayer *> layers = QgsProject::instance()->mapLayers();
|
||||
for ( auto it = layers.constBegin(); it != layers.constEnd(); ++it )
|
||||
{
|
||||
QgsVectorLayer *layer = qobject_cast< QgsVectorLayer *>( it.value() );
|
||||
if ( !layer )
|
||||
continue;
|
||||
|
||||
QgsExpression expression( layer->displayExpression() );
|
||||
QgsExpressionContext context;
|
||||
context.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( layer ) );
|
||||
expression.prepare( &context );
|
||||
|
||||
QgsFeatureRequest req;
|
||||
req.setFlags( QgsFeatureRequest::NoGeometry );
|
||||
req.setFilterExpression( QStringLiteral( "%1 ILIKE '%%2%'" )
|
||||
.arg( layer->displayExpression() )
|
||||
.arg( string ) );
|
||||
req.setLimit( 30 );
|
||||
|
||||
PreparedLayer preparedLayer;
|
||||
preparedLayer.expression = expression;
|
||||
preparedLayer.context = context;
|
||||
preparedLayer.layerId = layer->id();
|
||||
preparedLayer.layerName = layer->name();
|
||||
preparedLayer.iterator = layer->getFeatures( req );
|
||||
preparedLayer.layerIcon = QgsMapLayerModel::iconForLayer( layer );
|
||||
|
||||
mPreparedLayers.append( preparedLayer );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsAllLayersFeaturesLocatorFilter::fetchResults( const QString &string, const QgsLocatorContext &, QgsFeedback *feedback )
|
||||
{
|
||||
int foundInCurrentLayer;
|
||||
int foundInTotal = 0;
|
||||
QgsFeature f;
|
||||
|
||||
// we cannot used const loop since iterator::nextFeature is not const
|
||||
for ( PreparedLayer preparedLayer : mPreparedLayers )
|
||||
{
|
||||
foundInCurrentLayer = 0;
|
||||
while ( preparedLayer.iterator.nextFeature( f ) )
|
||||
{
|
||||
if ( feedback->isCanceled() )
|
||||
return;
|
||||
|
||||
QgsLocatorResult result;
|
||||
result.group = preparedLayer.layerName;
|
||||
|
||||
preparedLayer.context.setFeature( f );
|
||||
|
||||
result.displayString = preparedLayer.expression.evaluate( &( preparedLayer.context ) ).toString();
|
||||
|
||||
result.userData = QVariantList() << f.id() << preparedLayer.layerId;
|
||||
result.icon = preparedLayer.layerIcon;
|
||||
result.score = static_cast< double >( string.length() ) / result.displayString.size();
|
||||
emit resultFetched( result );
|
||||
|
||||
foundInCurrentLayer++;
|
||||
foundInTotal++;
|
||||
if ( foundInCurrentLayer >= mMaxResultsPerLayer )
|
||||
break;
|
||||
}
|
||||
if ( foundInTotal >= mMaxTotalResults )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void QgsAllLayersFeaturesLocatorFilter::triggerResult( const QgsLocatorResult &result )
|
||||
{
|
||||
QVariantList dataList = result.userData.toList();
|
||||
QgsFeatureId id = dataList.at( 0 ).toLongLong();
|
||||
QString layerId = dataList.at( 1 ).toString();
|
||||
QgsVectorLayer *layer = qobject_cast< QgsVectorLayer *>( QgsProject::instance()->mapLayer( layerId ) );
|
||||
if ( !layer )
|
||||
return;
|
||||
|
||||
QgisApp::instance()->mapCanvas()->zoomToFeatureIds( layer, QgsFeatureIds() << id );
|
||||
}
|
||||
|
||||
//
|
||||
// QgsExpressionCalculatorLocatorFilter
|
||||
//
|
||||
|
@ -113,6 +113,41 @@ class QgsActiveLayerFeaturesLocatorFilter : public QgsLocatorFilter
|
||||
QIcon mLayerIcon;
|
||||
};
|
||||
|
||||
class QgsAllLayersFeaturesLocatorFilter : public QgsLocatorFilter
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
struct PreparedLayer
|
||||
{
|
||||
public:
|
||||
QgsExpression expression;
|
||||
QgsExpressionContext context;
|
||||
QgsFeatureIterator iterator;
|
||||
QString layerName;
|
||||
QString layerId;
|
||||
QIcon layerIcon;
|
||||
} ;
|
||||
|
||||
QgsAllLayersFeaturesLocatorFilter( QObject *parent = nullptr );
|
||||
QgsAllLayersFeaturesLocatorFilter *clone() const override;
|
||||
QString name() const override { return QStringLiteral( "allfeatures" ); }
|
||||
QString displayName() const override { return tr( "Features In All Layers" ); }
|
||||
Priority priority() const override { return Medium; }
|
||||
QString prefix() const override { return QStringLiteral( "a" ); }
|
||||
|
||||
void prepare( const QString &string, const QgsLocatorContext &context ) override;
|
||||
void fetchResults( const QString &string, const QgsLocatorContext &context, QgsFeedback *feedback ) override;
|
||||
void triggerResult( const QgsLocatorResult &result ) override;
|
||||
|
||||
private:
|
||||
int mMaxResultsPerLayer = 6;
|
||||
int mMaxTotalResults = 12;
|
||||
QList<PreparedLayer> mPreparedLayers;
|
||||
|
||||
|
||||
};
|
||||
|
||||
class APP_EXPORT QgsExpressionCalculatorLocatorFilter : public QgsLocatorFilter
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -3121,6 +3121,7 @@ void QgisApp::createStatusBar()
|
||||
|
||||
mLocatorWidget->locator()->registerFilter( new QgsActionLocatorFilter( actionObjects ) );
|
||||
mLocatorWidget->locator()->registerFilter( new QgsActiveLayerFeaturesLocatorFilter() );
|
||||
mLocatorWidget->locator()->registerFilter( new QgsAllLayersFeaturesLocatorFilter() );
|
||||
mLocatorWidget->locator()->registerFilter( new QgsExpressionCalculatorLocatorFilter() );
|
||||
mLocatorWidget->locator()->registerFilter( new QgsBookmarkLocatorFilter() );
|
||||
mLocatorWidget->locator()->registerFilter( new QgsSettingsLocatorFilter() );
|
||||
|
@ -25,6 +25,7 @@ const QList<QString> QgsLocator::CORE_FILTERS = QList<QString>() << QStringLiter
|
||||
<< QStringLiteral( "layertree" )
|
||||
<< QStringLiteral( "layouts" )
|
||||
<< QStringLiteral( "features" )
|
||||
<< QStringLiteral( "allfeatures" )
|
||||
<< QStringLiteral( "calculator" )
|
||||
<< QStringLiteral( "bookmarks" )
|
||||
<< QStringLiteral( "optionpages" );
|
||||
|
Loading…
x
Reference in New Issue
Block a user