31 : QAbstractTableModel( parent )
33 mDeferredClearTimer.setInterval( 100 );
34 mDeferredClearTimer.setSingleShot(
true );
40 mDeferredClearTimer.stop();
41 mDeferredClear =
false;
45 mFoundResultsFromFilterNames.clear();
46 mFoundResultsFilterGroups.clear();
52 mDeferredClear =
true;
53 mDeferredClearTimer.start();
58 return mResults.count();
68 if ( !index.isValid() || index.row() < 0 || index.column() < 0 ||
69 index.row() >=
rowCount( QModelIndex() ) || index.column() >=
columnCount( QModelIndex() ) )
72 const Entry &entry = mResults.at( index.row() );
78 switch (
static_cast<Column
>( index.column() ) )
85 case EntryType::Filter:
87 v = entry.filterTitle;
91 case EntryType::Group:
93 v = QStringLiteral(
" " ).append( entry.groupTitle );
97 case EntryType::Result:
99 v = entry.result.displayString;
108 if ( entry.type == EntryType::Result )
109 return entry.result.description;
117 if ( index.column() == Name && !entry.groupTitle.isEmpty() )
120 font.setItalic(
true );
129 case Qt::DecorationRole:
130 switch (
static_cast<Column
>( index.column() ) )
135 const QIcon &icon = entry.result.icon;
136 if ( !icon.isNull() )
148 if ( entry.type == EntryType::Result )
149 return QVariant::fromValue( entry.result );
154 return static_cast<int>( entry.type );
160 return ( entry.result.score );
164 return entry.result.filter->priority();
166 return entry.filter->priority();
170 return entry.result.filter->displayName();
172 return entry.filterTitle;
175 return entry.groupTitle;
178 return entry.groupScore;
181 return QVariant::fromValue( entry.result.actions );
189 if ( !index.isValid() || index.row() < 0 || index.column() < 0 ||
190 index.row() >=
rowCount( QModelIndex() ) || index.column() >=
columnCount( QModelIndex() ) )
191 return QAbstractTableModel::flags( index );
193 Qt::ItemFlags
flags = QAbstractTableModel::flags( index );
194 if ( mResults.at( index.row() ).type != QgsLocatorModel::EntryType::Result )
196 flags =
flags & ~( Qt::ItemIsSelectable | Qt::ItemIsEnabled );
203 QHash<int, QByteArray> roles;
213 roles[Qt::DisplayRole] =
"Text";
219 mDeferredClearTimer.stop();
220 if ( mDeferredClear )
222 mFoundResultsFromFilterNames.clear();
223 mFoundResultsFilterGroups.clear();
226 const int pos = mResults.size();
227 const bool addingFilter = !result.
filter->
displayName().isEmpty() && !mFoundResultsFromFilterNames.contains( result.
filter->
name() );
229 mFoundResultsFromFilterNames << result.
filter->
name();
231 const bool addingGroup = !result.
group.isEmpty() && ( !mFoundResultsFilterGroups.contains( result.
filter )
232 || !mFoundResultsFilterGroups.value( result.
filter ).contains( std::pair( result.
group, result.
groupScore ) ) );
235 if ( !mFoundResultsFilterGroups.contains( result.
filter ) )
236 mFoundResultsFilterGroups[result.
filter] = QList<std::pair<QString, double>>();
241 if ( mDeferredClear )
248 beginInsertRows( QModelIndex(), pos, pos + (
static_cast<int>( addingFilter ) +
static_cast<int>( addingGroup ) ) );
255 entry.type = EntryType::Filter;
257 entry.filter = result.
filter;
263 entry.type = EntryType::Group;
265 entry.groupTitle = result.
group;
266 entry.groupScore = groupScore;
267 entry.filter = result.
filter;
271 entry.type = EntryType::Result;
272 entry.filter = result.
filter;
274 entry.result = result;
275 entry.groupTitle = result.
group;
276 entry.groupScore = groupScore;
279 if ( mDeferredClear )
284 mDeferredClear =
false;
294 , mLocator( locator )
296 Q_ASSERT( mLocator );
314 mNextRequestedString = string;
315 mHasQueuedRequest =
true;
330void QgsLocatorAutomaticModel::searchFinished()
332 if ( mHasQueuedRequest )
335 const QString nextSearch = mNextRequestedString;
336 mNextRequestedString.clear();
337 mHasQueuedRequest =
false;
351 : QSortFilterProxyModel( parent )
353 setDynamicSortFilter(
true );
354 setSortLocaleAware(
true );
355 setFilterCaseSensitivity( Qt::CaseInsensitive );
364 const QAbstractItemModel *lSourceModel = sourceModel();
365 const int leftFilterPriority = lSourceModel->data( left,
static_cast< int >( CustomRole::ResultFilterPriority ) ).toInt();
366 const int rightFilterPriority = lSourceModel->data( right,
static_cast< int >( CustomRole::ResultFilterPriority ) ).toInt();
367 if ( leftFilterPriority != rightFilterPriority )
368 return leftFilterPriority < rightFilterPriority;
371 QString leftFilter = lSourceModel->data( left,
static_cast< int >( CustomRole::ResultFilterName ) ).toString();
372 QString rightFilter = lSourceModel->data( right,
static_cast< int >( CustomRole::ResultFilterName ) ).toString();
373 if ( leftFilter != rightFilter )
374 return QString::localeAwareCompare( leftFilter, rightFilter ) < 0;
377 const int leftTypeRole = lSourceModel->data( left,
static_cast< int >( CustomRole::ResultType ) ).toInt();
378 const int rightTypeRole = lSourceModel->data( right,
static_cast< int >( CustomRole::ResultType ) ).toInt();
379 if ( leftTypeRole != rightTypeRole && ( leftTypeRole == 0 || rightTypeRole == 0 ) )
380 return leftTypeRole < rightTypeRole;
383 const double leftGroupScoreRole = lSourceModel->data( left,
static_cast< double >( CustomRole::ResultFilterGroupScore ) ).toDouble();
384 const double rightGroupScoreRole = lSourceModel->data( right,
static_cast< double >( CustomRole::ResultFilterGroupScore ) ).toDouble();
385 if ( leftGroupScoreRole != rightGroupScoreRole )
386 return leftGroupScoreRole > rightGroupScoreRole;
389 QString leftGroupTitle = lSourceModel->data( left,
static_cast< int >( CustomRole::ResultFilterGroupTitle ) ).toString();
390 QString rightGroupTitle = lSourceModel->data( right,
static_cast< int >( CustomRole::ResultFilterGroupTitle ) ).toString();
391 if ( leftGroupTitle != rightGroupTitle )
392 return QString::localeAwareCompare( leftGroupTitle, rightGroupTitle ) < 0;
395 if ( leftTypeRole != rightTypeRole )
396 return leftTypeRole < rightTypeRole;
399 const double leftScore = lSourceModel->data( left,
static_cast< int >( CustomRole::ResultScore ) ).toDouble();
400 const double rightScore = lSourceModel->data( right,
static_cast< int >( CustomRole::ResultScore ) ).toDouble();
402 return leftScore > rightScore;
405 leftFilter = lSourceModel->data( left, Qt::DisplayRole ).toString();
406 rightFilter = lSourceModel->data( right, Qt::DisplayRole ).toString();
407 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)