do not use qaction in the result, build context menu in the widget

This commit is contained in:
Denis Rouzaud 2018-11-29 08:02:37 -04:00
parent c48a706e49
commit d272f3cf2a
10 changed files with 67 additions and 32 deletions

View File

@ -48,10 +48,23 @@ Constructor for QgsLocatorResult.
QString group;
QMap<int, QAction *> contextMenuActions = QMap<int, QAction *>();
struct ResultAction
{
public:
ResultAction();
%Docstring
Constructor for ResultAction
%End
ResultAction( int id, QString text );
int id;
QString text;
};
QList<ResultAction> actions;
};
class QgsLocatorFilter : QObject
{
%Docstring
@ -177,10 +190,10 @@ E.g. a file search filter would open file associated with the triggered
result.
%End
virtual void triggerResultFromContextMenu( const QgsLocatorResult &result, const int id );
virtual void triggerResultFromAction( const QgsLocatorResult &result, const int actionId );
%Docstring
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.
The entry is identified by its ``actionId`` as specified in the result of this filter.
.. seealso:: :py:func:`triggerResult`

View File

@ -36,7 +36,7 @@ in order to ensure correct sorting of results by priority and match level.
ResultScoreRole,
ResultFilterNameRole,
ResultFilterGroupSortingRole,
ResultContextMenuActionsRole,
ResultActionsRole,
};
QgsLocatorModel( QObject *parent /TransferThis/ = 0 );

View File

@ -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.insert( OpenForm, new QAction( tr( "Open form" ) ) );
result.actions << QgsLocatorResult::ResultAction( OpenForm, tr( "Open form" ) );
emit resultFetched( result );
foundInCurrentLayer++;
@ -417,10 +417,10 @@ void QgsAllLayersFeaturesLocatorFilter::fetchResults( const QString &string, con
void QgsAllLayersFeaturesLocatorFilter::triggerResult( const QgsLocatorResult &result )
{
triggerResultFromContextMenu( result, NoEntry );
triggerResultFromAction( result, NoEntry );
}
void QgsAllLayersFeaturesLocatorFilter::triggerResultFromContextMenu( const QgsLocatorResult &result, const int id )
void QgsAllLayersFeaturesLocatorFilter::triggerResultFromAction( const QgsLocatorResult &result, const int actionId )
{
QVariantList dataList = result.userData.toList();
QgsFeatureId fid = dataList.at( 0 ).toLongLong();
@ -429,7 +429,7 @@ void QgsAllLayersFeaturesLocatorFilter::triggerResultFromContextMenu( const QgsL
if ( !layer )
return;
if ( id == OpenForm )
if ( actionId == OpenForm )
{
QgsFeature f;
QgsFeatureRequest request;

View File

@ -146,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 int id ) override;
void triggerResultFromAction( const QgsLocatorResult &result, const int actionId ) override;
private:
int mMaxResultsPerLayer = 6;

View File

@ -33,10 +33,10 @@ QgsLocatorFilter::Flags QgsLocatorFilter::flags() const
return nullptr;
}
void QgsLocatorFilter::triggerResultFromContextMenu( const QgsLocatorResult &result, const int id )
void QgsLocatorFilter::triggerResultFromAction( const QgsLocatorResult &result, const int actionId )
{
Q_UNUSED( result );
Q_UNUSED( id );
Q_UNUSED( actionId );
}
bool QgsLocatorFilter::stringMatches( const QString &candidate, const QString &search )

View File

@ -94,17 +94,39 @@ class CORE_EXPORT QgsLocatorResult
QString group = QString();
/**
* 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.
* The ResultActions stores basic informations for additional
* actions to be used in a locator widget, in a context menu
* for instance.
* The \a id used to recognized the action when the result is triggered.
* It should be 0 or greater as otherwise, the result will be triggered
* normally.
* \since QGIS 3.6
*/
struct CORE_EXPORT ResultAction
{
public:
//! Constructor for ResultAction
ResultAction() = default;
ResultAction( int id, QString text )
: id( id )
, text( text )
{}
int id = -1;
QString text;
};
/**
* Additional actions to be used in a locator widget
* for the given result. They could be displayed in
* a context menu.
* \since QGIS 3.6
*/
QMap<int, QAction *> contextMenuActions = QMap<int, QAction *>();
QList<ResultAction> actions;
};
Q_DECLARE_METATYPE( QgsLocatorResult::ResultAction )
/**
* \class QgsLocatorFilter
* \ingroup core
@ -223,11 +245,11 @@ class CORE_EXPORT QgsLocatorFilter : public QObject
/**
* 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.
* The entry is identified by its \a actionId as specified in the result of this filter.
* \see triggerResult()
* \since QGIS 3.6
*/
virtual void triggerResultFromContextMenu( const QgsLocatorResult &result, const int id );
virtual void triggerResultFromAction( const QgsLocatorResult &result, const int actionId );
/**
* This method will be called on main thread on the original filter (not a clone)

View File

@ -161,8 +161,8 @@ QVariant QgsLocatorModel::data( const QModelIndex &index, int role ) const
else
return 0;
case ResultContextMenuActionsRole:
return QVariant::fromValue( mResults.at( index.row() ).result.contextMenuActions );
case ResultActionsRole:
return QVariant::fromValue( mResults.at( index.row() ).result.actions );
}
return QVariant();
@ -191,7 +191,7 @@ QHash<int, QByteArray> QgsLocatorModel::roleNames() const
roles[ResultScoreRole] = "ResultScore";
roles[ResultFilterNameRole] = "ResultFilterName";
roles[ResultFilterGroupSortingRole] = "ResultFilterGroupSorting";
roles[ResultContextMenuActionsRole] = "ResultContextMenuActions";
roles[ResultActionsRole] = "ResultContextMenuActions";
roles[Qt::DisplayRole] = "Text";
return roles;
}

View File

@ -56,7 +56,7 @@ class CORE_EXPORT QgsLocatorModel : public QAbstractTableModel
ResultScoreRole, //!< Result match score, used by QgsLocatorProxyModel for sorting roles.
ResultFilterNameRole, //!< Associated filter name which created the result
ResultFilterGroupSortingRole, //!< Group results within the same filter results
ResultContextMenuActionsRole, //!< The actions to be shown for the given result in a context menu
ResultActionsRole, //!< The actions to be shown for the given result in a context menu
};
/**

View File

@ -44,7 +44,7 @@ void QgsLocatorModelBridge::triggerResult( const QModelIndex &index, const int i
if ( result.filter )
{
if ( id >= 0 )
result.filter->triggerResultFromContextMenu( result, id );
result.filter->triggerResultFromAction( result, id );
else
result.filter->triggerResult( result );
}

View File

@ -181,14 +181,14 @@ void QgsLocatorWidget::showContextMenu( const QPoint &point )
if ( !index.isValid() )
return;
const QMap<int, QAction *> actions = mResultsView->model()->data( index, QgsLocatorModel::ResultContextMenuActionsRole ).value<QMap<int, QAction *>>();
QMap<int, QAction *>::const_iterator it = actions.constBegin();
for ( ; it != actions.constEnd(); ++it )
{
connect( it.value(), &QAction::triggered, this, [ = ]() {mModelBridge->triggerResult( index, it.key() );} );
}
const QList<QgsLocatorResult::ResultAction> actions = mResultsView->model()->data( index, QgsLocatorModel::ResultActionsRole ).value<QList<QgsLocatorResult::ResultAction>>();
QMenu *contextMenu = new QMenu( mResultsView );
contextMenu->addActions( actions.values() );
for ( auto action : actions )
{
QAction *menuAction = new QAction( action.text, contextMenu );
connect( menuAction, &QAction::triggered, this, [ = ]() {mModelBridge->triggerResult( index, action.id );} );
contextMenu->addAction( menuAction );
}
contextMenu->exec( mResultsView->viewport()->mapToGlobal( point ) );
}