21#include "moc_qgslocatormodel.cpp"
32 : QAbstractTableModel( parent )
34 mDeferredClearTimer.setInterval( 100 );
35 mDeferredClearTimer.setSingleShot(
true );
41 mDeferredClearTimer.stop();
42 mDeferredClear =
false;
46 mFoundResultsFromFilterNames.clear();
47 mFoundResultsFilterGroups.clear();
53 mDeferredClear =
true;
54 mDeferredClearTimer.start();
59 return mResults.count();
69 if ( !index.isValid() || index.row() < 0 || index.column() < 0 ||
70 index.row() >=
rowCount( QModelIndex() ) || index.column() >=
columnCount( QModelIndex() ) )
73 const Entry &entry = mResults.at( index.row() );
79 switch (
static_cast<Column
>( index.column() ) )
86 case EntryType::Filter:
88 v = entry.filterTitle;
92 case EntryType::Group:
94 v = QStringLiteral(
" " ).append( entry.groupTitle );
98 case EntryType::Result:
100 v = entry.result.displayString;
109 if ( entry.type == EntryType::Result )
110 return entry.result.description;
118 if ( index.column() == Name && !entry.groupTitle.isEmpty() )
121 font.setItalic(
true );
130 case Qt::DecorationRole:
131 switch (
static_cast<Column
>( index.column() ) )
134 if ( entry.type == EntryType::Result )
136 const QIcon &icon = entry.result.icon;
137 if ( !icon.isNull() )
149 if ( entry.type == EntryType::Result )
150 return QVariant::fromValue( entry.result );
155 return static_cast<int>( entry.type );
161 return ( entry.result.score );
164 return entry.filter->priority();
167 return entry.filterTitle;
170 return entry.groupTitle;
173 return entry.groupScore;
176 return QVariant::fromValue( entry.result.actions );
184 if ( !index.isValid() || index.row() < 0 || index.column() < 0 ||
185 index.row() >=
rowCount( QModelIndex() ) || index.column() >=
columnCount( QModelIndex() ) )
186 return QAbstractTableModel::flags( index );
188 Qt::ItemFlags
flags = QAbstractTableModel::flags( index );
189 if ( mResults.at( index.row() ).type != QgsLocatorModel::EntryType::Result )
191 flags =
flags & ~( Qt::ItemIsSelectable | Qt::ItemIsEnabled );
198 QHash<int, QByteArray> roles;
208 roles[Qt::DisplayRole] =
"Text";
214 mDeferredClearTimer.stop();
215 if ( mDeferredClear )
217 mFoundResultsFromFilterNames.clear();
218 mFoundResultsFilterGroups.clear();
221 const int pos = mResults.size();
222 const bool addingFilter = !result.
filter->
displayName().isEmpty() && !mFoundResultsFromFilterNames.contains( result.
filter->
name() );
224 mFoundResultsFromFilterNames << result.
filter->
name();
226 const bool addingGroup = !result.
group.isEmpty() && ( !mFoundResultsFilterGroups.contains( result.
filter )
227 || !mFoundResultsFilterGroups.value( result.
filter ).contains( std::pair( result.
group, result.
groupScore ) ) );
230 if ( !mFoundResultsFilterGroups.contains( result.
filter ) )
231 mFoundResultsFilterGroups[result.
filter] = QList<std::pair<QString, double>>();
236 if ( mDeferredClear )
243 beginInsertRows( QModelIndex(), pos, pos + (
static_cast<int>( addingFilter ) +
static_cast<int>( addingGroup ) ) );
250 entry.type = EntryType::Filter;
252 entry.filter = result.
filter;
258 entry.type = EntryType::Group;
260 entry.groupTitle = result.
group;
261 entry.groupScore = groupScore;
262 entry.filter = result.
filter;
266 entry.type = EntryType::Result;
267 entry.filter = result.
filter;
269 entry.result = result;
270 entry.groupTitle = result.
group;
271 entry.groupScore = groupScore;
274 if ( mDeferredClear )
279 mDeferredClear =
false;
289 , mLocator( locator )
291 Q_ASSERT( mLocator );
309 mNextRequestedString = string;
310 mHasQueuedRequest =
true;
325void QgsLocatorAutomaticModel::searchFinished()
327 if ( mHasQueuedRequest )
330 const QString nextSearch = mNextRequestedString;
331 mNextRequestedString.clear();
332 mHasQueuedRequest =
false;
346 : QSortFilterProxyModel( parent )
348 setDynamicSortFilter(
true );
349 setSortLocaleAware(
true );
350 setFilterCaseSensitivity( Qt::CaseInsensitive );
359 const QAbstractItemModel *lSourceModel = sourceModel();
360 const int leftFilterPriority = lSourceModel->data( left,
static_cast< int >( CustomRole::ResultFilterPriority ) ).toInt();
361 const int rightFilterPriority = lSourceModel->data( right,
static_cast< int >( CustomRole::ResultFilterPriority ) ).toInt();
362 if ( leftFilterPriority != rightFilterPriority )
363 return leftFilterPriority < rightFilterPriority;
366 QString leftFilter = lSourceModel->data( left,
static_cast< int >( CustomRole::ResultFilterName ) ).toString();
367 QString rightFilter = lSourceModel->data( right,
static_cast< int >( CustomRole::ResultFilterName ) ).toString();
368 if ( leftFilter != rightFilter )
369 return QString::localeAwareCompare( leftFilter, rightFilter ) < 0;
372 const int leftTypeRole = lSourceModel->data( left,
static_cast< int >( CustomRole::ResultType ) ).toInt();
373 const int rightTypeRole = lSourceModel->data( right,
static_cast< int >( CustomRole::ResultType ) ).toInt();
374 if ( leftTypeRole != rightTypeRole && ( leftTypeRole == 0 || rightTypeRole == 0 ) )
375 return leftTypeRole < rightTypeRole;
378 const double leftGroupScoreRole = lSourceModel->data( left,
static_cast< double >( CustomRole::ResultFilterGroupScore ) ).toDouble();
379 const double rightGroupScoreRole = lSourceModel->data( right,
static_cast< double >( CustomRole::ResultFilterGroupScore ) ).toDouble();
380 if ( leftGroupScoreRole != rightGroupScoreRole )
381 return leftGroupScoreRole > rightGroupScoreRole;
384 QString leftGroupTitle = lSourceModel->data( left,
static_cast< int >( CustomRole::ResultFilterGroupTitle ) ).toString();
385 QString rightGroupTitle = lSourceModel->data( right,
static_cast< int >( CustomRole::ResultFilterGroupTitle ) ).toString();
386 if ( leftGroupTitle != rightGroupTitle )
387 return QString::localeAwareCompare( leftGroupTitle, rightGroupTitle ) < 0;
390 if ( leftTypeRole != rightTypeRole )
391 return leftTypeRole < rightTypeRole;
394 const double leftScore = lSourceModel->data( left,
static_cast< int >( CustomRole::ResultScore ) ).toDouble();
395 const double rightScore = lSourceModel->data( right,
static_cast< int >( CustomRole::ResultScore ) ).toDouble();
397 return leftScore > rightScore;
400 leftFilter = lSourceModel->data( left, Qt::DisplayRole ).toString();
401 rightFilter = lSourceModel->data( right, Qt::DisplayRole ).toString();
402 return QString::localeAwareCompare( leftFilter, rightFilter ) < 0;
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
QgsLocator * locator()
Returns a pointer to the locator utilized by this model.
QgsLocatorAutomaticModel(QgsLocator *locator)
Constructor for QgsLocatorAutomaticModel, linked with the specified locator.
void search(const QString &string)
Enqueues a search for a specified string within the model.
virtual QgsLocatorContext createContext()
Returns a new locator context for searches.
Encapsulates the properties relating to the context of a locator search.
virtual QString displayName() const =0
Returns a translated, user-friendly name for the filter.
virtual QString name() const =0
Returns the unique name for the filter.
An abstract list model for displaying the results of locator searches.
int columnCount(const QModelIndex &parent=QModelIndex()) const override
void deferredClear()
Resets the model and clears all existing results after a short delay, or whenever the next result is ...
CustomRole
Custom model roles.
@ ResultFilterGroupTitle
Group title.
@ ResultScore
Result match score, used by QgsLocatorProxyModel for sorting roles.
@ ResultFilterPriority
Result priority, used by QgsLocatorProxyModel for sorting roles.
@ ResultFilterGroupScore
Group score.
@ ResultFilterName
Associated filter name which created the result.
@ ResultData
QgsLocatorResult data.
@ ResultFilterGroupSorting
Custom value for sorting.
@ ResultActions
The actions to be shown for the given result in a context menu.
Qt::ItemFlags flags(const QModelIndex &index) const override
QHash< int, QByteArray > roleNames() const override
void addResult(const QgsLocatorResult &result)
Adds a new result to the model.
QgsLocatorModel(QObject *parent=nullptr)
Constructor for QgsLocatorModel.
void clear()
Resets the model and clears all existing results.
int rowCount(const QModelIndex &parent=QModelIndex()) const override
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override
QgsLocatorProxyModel(QObject *parent=nullptr)
Constructor for QgsLocatorProxyModel, with the specified parent object.
Encapsulates properties of an individual matching result found by a QgsLocatorFilter.
double groupScore
Specifies the score of the group to allow ordering.
QString group
Group the results by categories If left as empty string, this means that results are all shown withou...
QgsLocatorFilter * filter
Filter from which the result was obtained.
Handles the management of QgsLocatorFilter objects and async collection of search results from them.
void finished()
Emitted when locator has finished a query, either as a result of successful completion or early cance...
void foundResult(const QgsLocatorResult &result)
Emitted whenever a filter encounters a matching result after the fetchResults() method is called.
void fetchResults(const QString &string, const QgsLocatorContext &context, QgsFeedback *feedback=nullptr)
Triggers the background fetching of filter results for a specified search string.
bool isRunning() const
Returns true if a query is currently being executed by the locator.
void cancelWithoutBlocking()
Triggers cancellation of any current running query without blocking.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)