diff --git a/python/core/auto_generated/locator/qgslocatorfilter.sip.in b/python/core/auto_generated/locator/qgslocatorfilter.sip.in index 3ca7b72bb45..5627771a1e5 100644 --- a/python/core/auto_generated/locator/qgslocatorfilter.sip.in +++ b/python/core/auto_generated/locator/qgslocatorfilter.sip.in @@ -48,7 +48,7 @@ Constructor for QgsLocatorResult. QString group; - QList contextMenuActions; + QMap contextMenuActions = QMap(); }; @@ -177,11 +177,10 @@ E.g. a file search filter would open file associated with the triggered result. %End - virtual void triggerResultFromContextMenu( const QgsLocatorResult &result, const QAction *action ); + virtual void triggerResultFromContextMenu( const QgsLocatorResult &result, const int id ); %Docstring -Triggers a filter ``result`` from this filter for a given action. -Actions are specified in the result given by this filter and shown -as context menu entries. +Triggers a filter ``result`` from this filter for an entry in the context menu. +The entry is identified by its \id as specified in the result of this filter. .. seealso:: :py:func:`triggerResult` diff --git a/python/core/auto_generated/locator/qgslocatormodelbridge.sip.in b/python/core/auto_generated/locator/qgslocatormodelbridge.sip.in index 55fe03ce2d5..6d4b4684fcd 100644 --- a/python/core/auto_generated/locator/qgslocatormodelbridge.sip.in +++ b/python/core/auto_generated/locator/qgslocatormodelbridge.sip.in @@ -57,7 +57,7 @@ Returns true if some text to be search is pending in the queue Returns true if the a search is currently running %End - void triggerResult( const QModelIndex &index, const QAction *action = 0 ); + void triggerResult( const QModelIndex &index, const int id = -1 ); %Docstring Triggers the result at given ``index`` and with optional ``action`` if context menu entry was triggered %End diff --git a/src/app/locator/qgsinbuiltlocatorfilters.cpp b/src/app/locator/qgsinbuiltlocatorfilters.cpp index d0885c7436c..381ce49c069 100644 --- a/src/app/locator/qgsinbuiltlocatorfilters.cpp +++ b/src/app/locator/qgsinbuiltlocatorfilters.cpp @@ -402,7 +402,7 @@ void QgsAllLayersFeaturesLocatorFilter::fetchResults( const QString &string, con result.icon = preparedLayer.layerIcon; result.score = static_cast< double >( string.length() ) / result.displayString.size(); - result.contextMenuActions << new QAction( tr( "Open form" ) ); + result.contextMenuActions.insert( OpenForm, new QAction( tr( "Open form" ) ) ); emit resultFetched( result ); foundInCurrentLayer++; @@ -417,28 +417,23 @@ void QgsAllLayersFeaturesLocatorFilter::fetchResults( const QString &string, con void QgsAllLayersFeaturesLocatorFilter::triggerResult( const QgsLocatorResult &result ) { - triggerResultFromContextMenu( result, nullptr ); + triggerResultFromContextMenu( result, NoEntry ); } -void QgsAllLayersFeaturesLocatorFilter::triggerResultFromContextMenu( const QgsLocatorResult &result, const QAction *action ) +void QgsAllLayersFeaturesLocatorFilter::triggerResultFromContextMenu( const QgsLocatorResult &result, const int id ) { QVariantList dataList = result.userData.toList(); - QgsFeatureId id = dataList.at( 0 ).toLongLong(); + QgsFeatureId fid = dataList.at( 0 ).toLongLong(); QString layerId = dataList.at( 1 ).toString(); QgsVectorLayer *layer = qobject_cast< QgsVectorLayer *>( QgsProject::instance()->mapLayer( layerId ) ); if ( !layer ) return; - if ( !action ) + if ( id == OpenForm ) { - QgisApp::instance()->mapCanvas()->zoomToFeatureIds( layer, QgsFeatureIds() << id ); - } - else - { - // no need to check for which action, since the filter shows only one QgsFeature f; QgsFeatureRequest request; - request.setFilterFid( id ); + request.setFilterFid( fid ); bool fetched = layer->getFeatures( request ).nextFeature( f ); if ( !fetched ) return; @@ -452,6 +447,10 @@ void QgsAllLayersFeaturesLocatorFilter::triggerResultFromContextMenu( const QgsL action.viewFeatureForm(); } } + else + { + QgisApp::instance()->mapCanvas()->zoomToFeatureIds( layer, QgsFeatureIds() << fid ); + } } // diff --git a/src/app/locator/qgsinbuiltlocatorfilters.h b/src/app/locator/qgsinbuiltlocatorfilters.h index f6ebedbc68d..48b0d31ff21 100644 --- a/src/app/locator/qgsinbuiltlocatorfilters.h +++ b/src/app/locator/qgsinbuiltlocatorfilters.h @@ -119,6 +119,12 @@ class APP_EXPORT QgsAllLayersFeaturesLocatorFilter : public QgsLocatorFilter Q_OBJECT public: + enum ContextMenuEntry + { + NoEntry, + OpenForm + }; + struct PreparedLayer { public: @@ -128,7 +134,7 @@ class APP_EXPORT QgsAllLayersFeaturesLocatorFilter : public QgsLocatorFilter QString layerName; QString layerId; QIcon layerIcon; - } ; + }; QgsAllLayersFeaturesLocatorFilter( QObject *parent = nullptr ); QgsAllLayersFeaturesLocatorFilter *clone() const override; @@ -140,7 +146,7 @@ class APP_EXPORT QgsAllLayersFeaturesLocatorFilter : public QgsLocatorFilter 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; - void triggerResultFromContextMenu( const QgsLocatorResult &result, const QAction *action ) override; + void triggerResultFromContextMenu( const QgsLocatorResult &result, const int id ) override; private: int mMaxResultsPerLayer = 6; diff --git a/src/core/locator/qgslocatorfilter.cpp b/src/core/locator/qgslocatorfilter.cpp index e04ccc67654..267ccf3ca6d 100644 --- a/src/core/locator/qgslocatorfilter.cpp +++ b/src/core/locator/qgslocatorfilter.cpp @@ -33,10 +33,10 @@ QgsLocatorFilter::Flags QgsLocatorFilter::flags() const return nullptr; } -void QgsLocatorFilter::triggerResultFromContextMenu( const QgsLocatorResult &result, const QAction *action ) +void QgsLocatorFilter::triggerResultFromContextMenu( const QgsLocatorResult &result, const int id ) { Q_UNUSED( result ); - Q_UNUSED( action ); + Q_UNUSED( id ); } bool QgsLocatorFilter::stringMatches( const QString &candidate, const QString &search ) diff --git a/src/core/locator/qgslocatorfilter.h b/src/core/locator/qgslocatorfilter.h index 2359699f6ce..f02e665aea0 100644 --- a/src/core/locator/qgslocatorfilter.h +++ b/src/core/locator/qgslocatorfilter.h @@ -89,14 +89,19 @@ class CORE_EXPORT QgsLocatorResult * If left as empty string, this means that results are all shown without being grouped. * If a group is given, the results will be grouped by \a group under a header. * \note This should be translated. - * \since 3.2 + * \since QGIS 3.2 */ QString group = QString(); /** - * Actions to be used in a context menu for the result + * Actions to be used in a context menu for the result. + * The key of the map is populated with IDs used to recognized + * entry when the result is triggered. The IDs should be 0 or greater + * otherwise, the result will be triggered normally. + * Entries in the context menu will be ordered by IDs. + * \since QGIS 3.6 */ - QList contextMenuActions = QList(); + QMap contextMenuActions = QMap(); }; @@ -217,13 +222,12 @@ class CORE_EXPORT QgsLocatorFilter : public QObject virtual void triggerResult( const QgsLocatorResult &result ) = 0; /** - * Triggers a filter \a result from this filter for a given action. - * Actions are specified in the result given by this filter and shown - * as context menu entries. + * Triggers a filter \a result from this filter for an entry in the context menu. + * The entry is identified by its \id as specified in the result of this filter. * \see triggerResult() * \since QGIS 3.6 */ - virtual void triggerResultFromContextMenu( const QgsLocatorResult &result, const QAction *action ); + virtual void triggerResultFromContextMenu( const QgsLocatorResult &result, const int id ); /** * This method will be called on main thread on the original filter (not a clone) diff --git a/src/core/locator/qgslocatormodelbridge.cpp b/src/core/locator/qgslocatormodelbridge.cpp index 6225d8f968e..0afa0cb30a8 100644 --- a/src/core/locator/qgslocatormodelbridge.cpp +++ b/src/core/locator/qgslocatormodelbridge.cpp @@ -37,14 +37,14 @@ bool QgsLocatorModelBridge::isRunning() const return mIsRunning; } -void QgsLocatorModelBridge::triggerResult( const QModelIndex &index, const QAction *action ) +void QgsLocatorModelBridge::triggerResult( const QModelIndex &index, const int id ) { mLocator->clearPreviousResults(); QgsLocatorResult result = mProxyModel->data( index, QgsLocatorModel::ResultDataRole ).value< QgsLocatorResult >(); if ( result.filter ) { - if ( action ) - result.filter->triggerResultFromContextMenu( result, action ); + if ( id >= 0 ) + result.filter->triggerResultFromContextMenu( result, id ); else result.filter->triggerResult( result ); } diff --git a/src/core/locator/qgslocatormodelbridge.h b/src/core/locator/qgslocatormodelbridge.h index 323d1fb6515..3865724ff8b 100644 --- a/src/core/locator/qgslocatormodelbridge.h +++ b/src/core/locator/qgslocatormodelbridge.h @@ -64,7 +64,7 @@ class CORE_EXPORT QgsLocatorModelBridge : public QObject bool isRunning() const; //! Triggers the result at given \a index and with optional \a action if context menu entry was triggered - void triggerResult( const QModelIndex &index, const QAction *action = nullptr ); + void triggerResult( const QModelIndex &index, const int id = -1 ); signals: //! Emitted when a result is added diff --git a/src/gui/locator/qgslocatorwidget.cpp b/src/gui/locator/qgslocatorwidget.cpp index 44c753926bd..f26118b8ada 100644 --- a/src/gui/locator/qgslocatorwidget.cpp +++ b/src/gui/locator/qgslocatorwidget.cpp @@ -181,14 +181,14 @@ void QgsLocatorWidget::showContextMenu( const QPoint &point ) if ( !index.isValid() ) return; - const QList actions = mResultsView->model()->data( index, QgsLocatorModel::ResultContextMenuActionsRole ).value>(); - for ( const QAction *action : actions ) + const QMap actions = mResultsView->model()->data( index, QgsLocatorModel::ResultContextMenuActionsRole ).value>(); + QMap::const_iterator it = actions.constBegin(); + for ( ; it != actions.constEnd(); ++it ) { - connect( action, &QAction::triggered, this, [ = ]() {mModelBridge->triggerResult( index, action );} ); + connect( it.value(), &QAction::triggered, this, [ = ]() {mModelBridge->triggerResult( index, it.key() );} ); } - QMenu *contextMenu = new QMenu( mResultsView ); - contextMenu->addActions( actions ); + contextMenu->addActions( actions.values() ); contextMenu->exec( mResultsView->viewport()->mapToGlobal( point ) ); }