mirror of
https://github.com/qgis/QGIS.git
synced 2025-11-27 00:07:16 -05:00
[QgsLocator] add the capability of adding group for elements within the same filter
This commit is contained in:
parent
56104bcd12
commit
c1e16969f3
@ -45,6 +45,8 @@ Constructor for QgsLocatorResult.
|
||||
|
||||
double score;
|
||||
|
||||
QString group;
|
||||
|
||||
};
|
||||
|
||||
class QgsLocatorFilter : QObject
|
||||
|
||||
@ -26,6 +26,8 @@ in order to ensure correct sorting of results by priority and match level.
|
||||
%End
|
||||
public:
|
||||
|
||||
static const int NoGroup;
|
||||
|
||||
enum Role
|
||||
{
|
||||
ResultDataRole,
|
||||
@ -33,6 +35,7 @@ in order to ensure correct sorting of results by priority and match level.
|
||||
ResultFilterPriorityRole,
|
||||
ResultScoreRole,
|
||||
ResultFilterNameRole,
|
||||
ResultFilterGroupSortingRole,
|
||||
};
|
||||
|
||||
QgsLocatorModel( QObject *parent /TransferThis/ = 0 );
|
||||
|
||||
@ -409,9 +409,9 @@ sub detect_comment_block{
|
||||
}
|
||||
|
||||
# Detect if line is a non method member declaration
|
||||
# https://regex101.com/r/gUBZUk/13
|
||||
# https://regex101.com/r/gUBZUk/14
|
||||
sub detect_non_method_member{
|
||||
return 1 if $LINE =~ m/^\s*(?:template\s*<\w+>\s+)?(?:(const|mutable|static|friend|unsigned)\s+)*\w+(::\w+)?(<([\w<> *&,()]|::)+>)?(,?\s+\*?\w+( = (-?\d+(\.\d+)?|((QMap|QList)<[^()]+>\(\))|(\w+::)*\w+(\([^()]+\))?)|\[\d+\])?)+;/;
|
||||
return 1 if $LINE =~ m/^\s*(?:template\s*<\w+>\s+)?(?:(const|mutable|static|friend|unsigned)\s+)*\w+(::\w+)?(<([\w<> *&,()]|::)+>)?(,?\s+\*?\w+( = (-?\d+(\.\d+)?|((QMap|QList)<[^()]+>\(\))|(\w+::)*\w+(\([^()]?\))?)|\[\d+\])?)+;/;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -82,6 +82,15 @@ class CORE_EXPORT QgsLocatorResult
|
||||
*/
|
||||
double score = 0.5;
|
||||
|
||||
/**
|
||||
* Group the results by categories
|
||||
* 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
|
||||
*/
|
||||
QString group = QString();
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -15,12 +15,14 @@
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include <QFont>
|
||||
|
||||
#include "qgslocatormodel.h"
|
||||
#include "qgslocator.h"
|
||||
#include "qgsapplication.h"
|
||||
#include "qgslogger.h"
|
||||
|
||||
|
||||
//
|
||||
// QgsLocatorModel
|
||||
//
|
||||
@ -41,6 +43,7 @@ void QgsLocatorModel::clear()
|
||||
beginResetModel();
|
||||
mResults.clear();
|
||||
mFoundResultsFromFilterNames.clear();
|
||||
mFoundResultsFilterGroups.clear();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
@ -76,8 +79,14 @@ QVariant QgsLocatorModel::data( const QModelIndex &index, int role ) const
|
||||
case Name:
|
||||
if ( !mResults.at( index.row() ).filter )
|
||||
return mResults.at( index.row() ).result.displayString;
|
||||
else
|
||||
else if ( mResults.at( index.row() ).filter && mResults.at( index.row() ).groupSorting == 0 )
|
||||
return mResults.at( index.row() ).filterTitle;
|
||||
else
|
||||
{
|
||||
QString groupTitle = mResults.at( index.row() ).groupTitle;
|
||||
groupTitle.prepend( " " );
|
||||
return groupTitle;
|
||||
}
|
||||
case Description:
|
||||
if ( !mResults.at( index.row() ).filter )
|
||||
return mResults.at( index.row() ).result.description;
|
||||
@ -87,6 +96,19 @@ QVariant QgsLocatorModel::data( const QModelIndex &index, int role ) const
|
||||
break;
|
||||
}
|
||||
|
||||
case Qt::FontRole:
|
||||
if ( index.column() == Name && !mResults.at( index.row() ).groupTitle.isEmpty() )
|
||||
{
|
||||
QFont font;
|
||||
font.setItalic( true );
|
||||
return font;
|
||||
}
|
||||
else
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::DecorationRole:
|
||||
switch ( index.column() )
|
||||
{
|
||||
@ -112,10 +134,8 @@ QVariant QgsLocatorModel::data( const QModelIndex &index, int role ) const
|
||||
return QVariant();
|
||||
|
||||
case ResultTypeRole:
|
||||
if ( mResults.at( index.row() ).filter )
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
// 0 for filter title, the group otherwise, 9999 if no group
|
||||
return mResults.at( index.row() ).groupSorting;
|
||||
|
||||
case ResultScoreRole:
|
||||
if ( mResults.at( index.row() ).filter )
|
||||
@ -134,6 +154,12 @@ QVariant QgsLocatorModel::data( const QModelIndex &index, int role ) const
|
||||
return mResults.at( index.row() ).result.filter->displayName();
|
||||
else
|
||||
return mResults.at( index.row() ).filterTitle;
|
||||
|
||||
case ResultFilterGroupSortingRole:
|
||||
if ( mResults.at( index.row() ).groupTitle.isEmpty() )
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
@ -146,7 +172,7 @@ Qt::ItemFlags QgsLocatorModel::flags( const QModelIndex &index ) const
|
||||
return QAbstractTableModel::flags( index );
|
||||
|
||||
Qt::ItemFlags flags = QAbstractTableModel::flags( index );
|
||||
if ( !mResults.at( index.row() ).filterTitle.isEmpty() )
|
||||
if ( mResults.at( index.row() ).filter )
|
||||
{
|
||||
flags = flags & ~( Qt::ItemIsSelectable | Qt::ItemIsEnabled );
|
||||
}
|
||||
@ -159,6 +185,7 @@ void QgsLocatorModel::addResult( const QgsLocatorResult &result )
|
||||
if ( mDeferredClear )
|
||||
{
|
||||
mFoundResultsFromFilterNames.clear();
|
||||
mFoundResultsFilterGroups.clear();
|
||||
}
|
||||
|
||||
int pos = mResults.size();
|
||||
@ -166,13 +193,21 @@ void QgsLocatorModel::addResult( const QgsLocatorResult &result )
|
||||
if ( addingFilter )
|
||||
mFoundResultsFromFilterNames << result.filter->name();
|
||||
|
||||
bool addingGroup = !result.group.isEmpty() && ( !mFoundResultsFilterGroups.contains( result.filter )
|
||||
|| !mFoundResultsFilterGroups.value( result.filter ).contains( result.group ) );
|
||||
if ( addingGroup )
|
||||
{
|
||||
if ( !mFoundResultsFilterGroups.contains( result.filter ) )
|
||||
mFoundResultsFilterGroups[result.filter] = QStringList();
|
||||
mFoundResultsFilterGroups[result.filter] << result.group ;
|
||||
}
|
||||
if ( mDeferredClear )
|
||||
{
|
||||
beginResetModel();
|
||||
mResults.clear();
|
||||
}
|
||||
else
|
||||
beginInsertRows( QModelIndex(), pos, pos + ( addingFilter ? 1 : 0 ) );
|
||||
beginInsertRows( QModelIndex(), pos, pos + ( static_cast<int>( addingFilter ) + static_cast<int>( addingGroup ) ) );
|
||||
|
||||
if ( addingFilter )
|
||||
{
|
||||
@ -181,8 +216,21 @@ void QgsLocatorModel::addResult( const QgsLocatorResult &result )
|
||||
entry.filter = result.filter;
|
||||
mResults << entry;
|
||||
}
|
||||
if ( addingGroup )
|
||||
{
|
||||
Entry entry;
|
||||
entry.filterTitle = result.filter->displayName();
|
||||
entry.groupTitle = result.group;
|
||||
// the sorting of groups will be achieved by order of adding groups
|
||||
// this could be customized by adding the extra info to QgsLocatorResult
|
||||
entry.groupSorting = mFoundResultsFilterGroups[result.filter].count();
|
||||
entry.filter = result.filter;
|
||||
mResults << entry;
|
||||
}
|
||||
Entry entry;
|
||||
entry.result = result;
|
||||
// keep the group title empty to allow differecing group title from results
|
||||
entry.groupSorting = result.group.isEmpty() ? NoGroup : mFoundResultsFilterGroups[result.filter].count();
|
||||
mResults << entry;
|
||||
|
||||
if ( mDeferredClear )
|
||||
@ -279,12 +327,18 @@ bool QgsLocatorProxyModel::lessThan( const QModelIndex &left, const QModelIndex
|
||||
if ( leftFilter != rightFilter )
|
||||
return QString::localeAwareCompare( leftFilter, rightFilter ) < 0;
|
||||
|
||||
// then make sure filter title appears before filter's results
|
||||
// then make sure filter title or group appears before filter's results
|
||||
int leftTypeRole = sourceModel()->data( left, QgsLocatorModel::ResultTypeRole ).toInt();
|
||||
int rightTypeRole = sourceModel()->data( right, QgsLocatorModel::ResultTypeRole ).toInt();
|
||||
if ( leftTypeRole != rightTypeRole )
|
||||
return leftTypeRole < rightTypeRole;
|
||||
|
||||
// make sure group title are above
|
||||
int leftGroupRole = sourceModel()->data( left, QgsLocatorModel::ResultFilterGroupSortingRole ).toInt();
|
||||
int rightGroupRole = sourceModel()->data( right, QgsLocatorModel::ResultFilterGroupSortingRole ).toInt();
|
||||
if ( leftGroupRole != rightGroupRole )
|
||||
return leftGroupRole < rightGroupRole;
|
||||
|
||||
// sort filter's results by score
|
||||
double leftScore = sourceModel()->data( left, QgsLocatorModel::ResultScoreRole ).toDouble();
|
||||
double rightScore = sourceModel()->data( right, QgsLocatorModel::ResultScoreRole ).toDouble();
|
||||
|
||||
@ -45,6 +45,8 @@ class CORE_EXPORT QgsLocatorModel : public QAbstractTableModel
|
||||
|
||||
public:
|
||||
|
||||
static const int NoGroup = 9999;
|
||||
|
||||
//! Custom model roles
|
||||
enum Role
|
||||
{
|
||||
@ -53,6 +55,7 @@ class CORE_EXPORT QgsLocatorModel : public QAbstractTableModel
|
||||
ResultFilterPriorityRole, //!< Result priority, used by QgsLocatorProxyModel for sorting roles.
|
||||
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
|
||||
};
|
||||
|
||||
/**
|
||||
@ -99,10 +102,13 @@ class CORE_EXPORT QgsLocatorModel : public QAbstractTableModel
|
||||
QgsLocatorResult result;
|
||||
QString filterTitle;
|
||||
QgsLocatorFilter *filter = nullptr;
|
||||
QString groupTitle = QString();
|
||||
int groupSorting = 0;
|
||||
};
|
||||
|
||||
QList<Entry> mResults;
|
||||
QSet<QString> mFoundResultsFromFilterNames;
|
||||
QMap<QgsLocatorFilter *, QStringList> mFoundResultsFilterGroups;
|
||||
bool mDeferredClear = false;
|
||||
QTimer mDeferredClearTimer;
|
||||
};
|
||||
|
||||
@ -252,8 +252,15 @@ void QgsLocatorWidget::addResult( const QgsLocatorResult &result )
|
||||
mLocatorModel->addResult( result );
|
||||
if ( selectFirst )
|
||||
{
|
||||
int row = mProxyModel->flags( mProxyModel->index( 0, 0 ) ) & Qt::ItemIsSelectable ? 0 : 1;
|
||||
mResultsView->setCurrentIndex( mProxyModel->index( row, 0 ) );
|
||||
int row = -1;
|
||||
bool selectable = false;
|
||||
while ( !selectable && row < mProxyModel->rowCount() )
|
||||
{
|
||||
row++;
|
||||
selectable = mProxyModel->flags( mProxyModel->index( row, 0 ) ).testFlag( Qt::ItemIsSelectable );
|
||||
}
|
||||
if ( selectable )
|
||||
mResultsView->setCurrentIndex( mProxyModel->index( row, 0 ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user