use int as IDs to recognize context menu entries

This commit is contained in:
Denis Rouzaud 2018-11-28 08:12:20 -04:00
parent 91736fd9f6
commit c48a706e49
9 changed files with 45 additions and 37 deletions

View File

@ -48,7 +48,7 @@ Constructor for QgsLocatorResult.
QString group; QString group;
QList<QAction *> contextMenuActions; QMap<int, QAction *> contextMenuActions = QMap<int, QAction *>();
}; };
@ -177,11 +177,10 @@ E.g. a file search filter would open file associated with the triggered
result. result.
%End %End
virtual void triggerResultFromContextMenu( const QgsLocatorResult &result, const QAction *action ); virtual void triggerResultFromContextMenu( const QgsLocatorResult &result, const int id );
%Docstring %Docstring
Triggers a filter ``result`` from this filter for a given action. Triggers a filter ``result`` from this filter for an entry in the context menu.
Actions are specified in the result given by this filter and shown The entry is identified by its \id as specified in the result of this filter.
as context menu entries.
.. seealso:: :py:func:`triggerResult` .. seealso:: :py:func:`triggerResult`

View File

@ -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 Returns true if the a search is currently running
%End %End
void triggerResult( const QModelIndex &index, const QAction *action = 0 ); void triggerResult( const QModelIndex &index, const int id = -1 );
%Docstring %Docstring
Triggers the result at given ``index`` and with optional ``action`` if context menu entry was triggered Triggers the result at given ``index`` and with optional ``action`` if context menu entry was triggered
%End %End

View File

@ -402,7 +402,7 @@ void QgsAllLayersFeaturesLocatorFilter::fetchResults( const QString &string, con
result.icon = preparedLayer.layerIcon; result.icon = preparedLayer.layerIcon;
result.score = static_cast< double >( string.length() ) / result.displayString.size(); 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 ); emit resultFetched( result );
foundInCurrentLayer++; foundInCurrentLayer++;
@ -417,28 +417,23 @@ void QgsAllLayersFeaturesLocatorFilter::fetchResults( const QString &string, con
void QgsAllLayersFeaturesLocatorFilter::triggerResult( const QgsLocatorResult &result ) 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(); QVariantList dataList = result.userData.toList();
QgsFeatureId id = dataList.at( 0 ).toLongLong(); QgsFeatureId fid = dataList.at( 0 ).toLongLong();
QString layerId = dataList.at( 1 ).toString(); QString layerId = dataList.at( 1 ).toString();
QgsVectorLayer *layer = qobject_cast< QgsVectorLayer *>( QgsProject::instance()->mapLayer( layerId ) ); QgsVectorLayer *layer = qobject_cast< QgsVectorLayer *>( QgsProject::instance()->mapLayer( layerId ) );
if ( !layer ) if ( !layer )
return; 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; QgsFeature f;
QgsFeatureRequest request; QgsFeatureRequest request;
request.setFilterFid( id ); request.setFilterFid( fid );
bool fetched = layer->getFeatures( request ).nextFeature( f ); bool fetched = layer->getFeatures( request ).nextFeature( f );
if ( !fetched ) if ( !fetched )
return; return;
@ -452,6 +447,10 @@ void QgsAllLayersFeaturesLocatorFilter::triggerResultFromContextMenu( const QgsL
action.viewFeatureForm(); action.viewFeatureForm();
} }
} }
else
{
QgisApp::instance()->mapCanvas()->zoomToFeatureIds( layer, QgsFeatureIds() << fid );
}
} }
// //

View File

@ -119,6 +119,12 @@ class APP_EXPORT QgsAllLayersFeaturesLocatorFilter : public QgsLocatorFilter
Q_OBJECT Q_OBJECT
public: public:
enum ContextMenuEntry
{
NoEntry,
OpenForm
};
struct PreparedLayer struct PreparedLayer
{ {
public: public:
@ -128,7 +134,7 @@ class APP_EXPORT QgsAllLayersFeaturesLocatorFilter : public QgsLocatorFilter
QString layerName; QString layerName;
QString layerId; QString layerId;
QIcon layerIcon; QIcon layerIcon;
} ; };
QgsAllLayersFeaturesLocatorFilter( QObject *parent = nullptr ); QgsAllLayersFeaturesLocatorFilter( QObject *parent = nullptr );
QgsAllLayersFeaturesLocatorFilter *clone() const override; QgsAllLayersFeaturesLocatorFilter *clone() const override;
@ -140,7 +146,7 @@ class APP_EXPORT QgsAllLayersFeaturesLocatorFilter : public QgsLocatorFilter
void prepare( const QString &string, const QgsLocatorContext &context ) override; void prepare( const QString &string, const QgsLocatorContext &context ) override;
void fetchResults( const QString &string, const QgsLocatorContext &context, QgsFeedback *feedback ) override; void fetchResults( const QString &string, const QgsLocatorContext &context, QgsFeedback *feedback ) override;
void triggerResult( const QgsLocatorResult &result ) 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: private:
int mMaxResultsPerLayer = 6; int mMaxResultsPerLayer = 6;

View File

@ -33,10 +33,10 @@ QgsLocatorFilter::Flags QgsLocatorFilter::flags() const
return nullptr; 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( result );
Q_UNUSED( action ); Q_UNUSED( id );
} }
bool QgsLocatorFilter::stringMatches( const QString &candidate, const QString &search ) bool QgsLocatorFilter::stringMatches( const QString &candidate, const QString &search )

View File

@ -89,14 +89,19 @@ class CORE_EXPORT QgsLocatorResult
* If left as empty string, this means that results are all shown without being grouped. * 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. * If a group is given, the results will be grouped by \a group under a header.
* \note This should be translated. * \note This should be translated.
* \since 3.2 * \since QGIS 3.2
*/ */
QString group = QString(); 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<QAction *> contextMenuActions = QList<QAction *>(); QMap<int, QAction *> contextMenuActions = QMap<int, QAction *>();
}; };
@ -217,13 +222,12 @@ class CORE_EXPORT QgsLocatorFilter : public QObject
virtual void triggerResult( const QgsLocatorResult &result ) = 0; virtual void triggerResult( const QgsLocatorResult &result ) = 0;
/** /**
* Triggers a filter \a result from this filter for a given action. * Triggers a filter \a result from this filter for an entry in the context menu.
* Actions are specified in the result given by this filter and shown * The entry is identified by its \id as specified in the result of this filter.
* as context menu entries.
* \see triggerResult() * \see triggerResult()
* \since QGIS 3.6 * \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) * This method will be called on main thread on the original filter (not a clone)

View File

@ -37,14 +37,14 @@ bool QgsLocatorModelBridge::isRunning() const
return mIsRunning; return mIsRunning;
} }
void QgsLocatorModelBridge::triggerResult( const QModelIndex &index, const QAction *action ) void QgsLocatorModelBridge::triggerResult( const QModelIndex &index, const int id )
{ {
mLocator->clearPreviousResults(); mLocator->clearPreviousResults();
QgsLocatorResult result = mProxyModel->data( index, QgsLocatorModel::ResultDataRole ).value< QgsLocatorResult >(); QgsLocatorResult result = mProxyModel->data( index, QgsLocatorModel::ResultDataRole ).value< QgsLocatorResult >();
if ( result.filter ) if ( result.filter )
{ {
if ( action ) if ( id >= 0 )
result.filter->triggerResultFromContextMenu( result, action ); result.filter->triggerResultFromContextMenu( result, id );
else else
result.filter->triggerResult( result ); result.filter->triggerResult( result );
} }

View File

@ -64,7 +64,7 @@ class CORE_EXPORT QgsLocatorModelBridge : public QObject
bool isRunning() const; bool isRunning() const;
//! Triggers the result at given \a index and with optional \a action if context menu entry was triggered //! 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: signals:
//! Emitted when a result is added //! Emitted when a result is added

View File

@ -181,14 +181,14 @@ void QgsLocatorWidget::showContextMenu( const QPoint &point )
if ( !index.isValid() ) if ( !index.isValid() )
return; return;
const QList<QAction *> actions = mResultsView->model()->data( index, QgsLocatorModel::ResultContextMenuActionsRole ).value<QList<QAction *>>(); const QMap<int, QAction *> actions = mResultsView->model()->data( index, QgsLocatorModel::ResultContextMenuActionsRole ).value<QMap<int, QAction *>>();
for ( const QAction *action : actions ) QMap<int, QAction *>::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 ); QMenu *contextMenu = new QMenu( mResultsView );
contextMenu->addActions( actions ); contextMenu->addActions( actions.values() );
contextMenu->exec( mResultsView->viewport()->mapToGlobal( point ) ); contextMenu->exec( mResultsView->viewport()->mapToGlobal( point ) );
} }