22#include "moc_qgslocatormodel.cpp" 
   33  : QAbstractTableModel( parent )
 
   35  mDeferredClearTimer.setInterval( 100 );
 
   36  mDeferredClearTimer.setSingleShot( 
true );
 
 
   42  mDeferredClearTimer.stop();
 
   43  mDeferredClear = 
false;
 
   47  mFoundResultsFromFilterNames.clear();
 
   48  mFoundResultsFilterGroups.clear();
 
 
   54  mDeferredClear = 
true;
 
   55  mDeferredClearTimer.start();
 
 
   60  return mResults.count();
 
 
   70  if ( !index.isValid() || index.row() < 0 || index.column() < 0 ||
 
   71       index.row() >= 
rowCount( QModelIndex() ) || index.column() >= 
columnCount( QModelIndex() ) )
 
   74  const Entry &entry = mResults.at( index.row() );
 
   80      switch ( 
static_cast<Column
>( index.column() ) )
 
   87            case EntryType::Filter:
 
   89              v = entry.filterTitle;
 
   93            case EntryType::Group:
 
   95              v = QStringLiteral( 
"  " ).append( entry.groupTitle );
 
   99            case EntryType::Result:
 
  101              v = entry.result.displayString;
 
  110          if ( entry.type == EntryType::Result )
 
  111            return entry.result.description;
 
  120      if ( index.column() == Name )
 
  123        font.setBold( entry.type == EntryType::Filter );
 
  124        font.setItalic( entry.type == EntryType::Group );
 
  134    case Qt::BackgroundRole:
 
  136      return entry.type == EntryType::Result ? QPalette().base() : QPalette().alternateBase();
 
  139    case Qt::ForegroundRole:
 
  141      return QPalette().text();
 
  145    case Qt::DecorationRole:
 
  146      switch ( 
static_cast<Column
>( index.column() ) )
 
  149          if ( entry.type == EntryType::Result )
 
  151            const QIcon &icon = entry.result.icon;
 
  152            if ( !icon.isNull() )
 
  164      if ( entry.type == EntryType::Result )
 
  165        return QVariant::fromValue( entry.result );
 
  170      return static_cast<int>( entry.type );
 
  176        return ( entry.result.score );
 
  179      return entry.filter->priority();
 
  182      return entry.filterTitle;
 
  185      return entry.groupTitle;
 
  188      return entry.groupScore;
 
  191      return QVariant::fromValue( entry.result.actions );
 
 
  199  if ( !index.isValid() || index.row() < 0 || index.column() < 0 ||
 
  200       index.row() >= 
rowCount( QModelIndex() ) || index.column() >= 
columnCount( QModelIndex() ) )
 
  201    return QAbstractTableModel::flags( index );
 
  203  Qt::ItemFlags 
flags = QAbstractTableModel::flags( index );
 
  204  if ( mResults.at( index.row() ).type != QgsLocatorModel::EntryType::Result )
 
  206    flags = 
flags & ~( Qt::ItemIsSelectable | Qt::ItemIsEnabled );
 
 
  213  QHash<int, QByteArray> roles;
 
  223  roles[Qt::DisplayRole] = 
"Text";
 
 
  229  mDeferredClearTimer.stop();
 
  230  if ( mDeferredClear )
 
  232    mFoundResultsFromFilterNames.clear();
 
  233    mFoundResultsFilterGroups.clear();
 
  236  const int pos = mResults.size();
 
  237  const bool addingFilter = !result.
filter->
displayName().isEmpty() && !mFoundResultsFromFilterNames.contains( result.
filter->
name() );
 
  239    mFoundResultsFromFilterNames << result.
filter->
name();
 
  241  const bool addingGroup = !result.
group.isEmpty() && ( !mFoundResultsFilterGroups.contains( result.
filter )
 
  242                           || !mFoundResultsFilterGroups.value( result.
filter ).contains( std::pair( result.
group, result.
groupScore ) ) );
 
  245    if ( !mFoundResultsFilterGroups.contains( result.
filter ) )
 
  246      mFoundResultsFilterGroups[result.
filter] = QList<std::pair<QString, double>>();
 
  251  if ( mDeferredClear )
 
  258    beginInsertRows( QModelIndex(), pos, pos + ( 
static_cast<int>( addingFilter ) + 
static_cast<int>( addingGroup ) ) );
 
  265    entry.type = EntryType::Filter;
 
  267    entry.filter = result.
filter;
 
  273    entry.type = EntryType::Group;
 
  275    entry.groupTitle = result.
group;
 
  276    entry.groupScore = groupScore;
 
  277    entry.filter = result.
filter;
 
  281  entry.type = EntryType::Result;
 
  282  entry.filter = result.
filter;
 
  284  entry.result = result;
 
  285  entry.groupTitle = result.
group;
 
  286  entry.groupScore = groupScore;
 
  289  if ( mDeferredClear )
 
  294  mDeferredClear = 
false;
 
 
  304  , mLocator( locator )
 
  306  Q_ASSERT( mLocator );
 
 
  324    mNextRequestedString = string;
 
  325    mHasQueuedRequest = 
true;
 
 
  340void QgsLocatorAutomaticModel::searchFinished()
 
  342  if ( mHasQueuedRequest )
 
  345    const QString nextSearch = mNextRequestedString;
 
  346    mNextRequestedString.clear();
 
  347    mHasQueuedRequest = 
false;
 
  361  : QSortFilterProxyModel( parent )
 
  363  setDynamicSortFilter( 
true );
 
  364  setSortLocaleAware( 
true );
 
  365  setFilterCaseSensitivity( Qt::CaseInsensitive );
 
 
  374  const QAbstractItemModel *lSourceModel = sourceModel();
 
  375  const int leftFilterPriority = lSourceModel->data( left, 
static_cast< int >( CustomRole::ResultFilterPriority ) ).toInt();
 
  376  const int rightFilterPriority  = lSourceModel->data( right, 
static_cast< int >( CustomRole::ResultFilterPriority ) ).toInt();
 
  377  if ( leftFilterPriority != rightFilterPriority )
 
  378    return leftFilterPriority < rightFilterPriority;
 
  381  QString leftFilter = lSourceModel->data( left, 
static_cast< int >( CustomRole::ResultFilterName ) ).toString();
 
  382  QString rightFilter = lSourceModel->data( right, 
static_cast< int >( CustomRole::ResultFilterName ) ).toString();
 
  383  if ( leftFilter != rightFilter )
 
  384    return QString::localeAwareCompare( leftFilter, rightFilter ) < 0;
 
  387  const int leftTypeRole = lSourceModel->data( left, 
static_cast< int >( CustomRole::ResultType ) ).toInt();
 
  388  const int rightTypeRole = lSourceModel->data( right, 
static_cast< int >( CustomRole::ResultType ) ).toInt();
 
  389  if ( leftTypeRole != rightTypeRole && ( leftTypeRole == 0 || rightTypeRole == 0 ) )
 
  390    return leftTypeRole < rightTypeRole;
 
  393  const double leftGroupScoreRole = lSourceModel->data( left, 
static_cast< double >( CustomRole::ResultFilterGroupScore ) ).toDouble();
 
  394  const double rightGroupScoreRole = lSourceModel->data( right, 
static_cast< double >( CustomRole::ResultFilterGroupScore ) ).toDouble();
 
  395  if ( leftGroupScoreRole != rightGroupScoreRole )
 
  396    return leftGroupScoreRole > rightGroupScoreRole;
 
  399  QString leftGroupTitle = lSourceModel->data( left, 
static_cast< int >( CustomRole::ResultFilterGroupTitle ) ).toString();
 
  400  QString rightGroupTitle = lSourceModel->data( right, 
static_cast< int >( CustomRole::ResultFilterGroupTitle ) ).toString();
 
  401  if ( leftGroupTitle != rightGroupTitle )
 
  402    return QString::localeAwareCompare( leftGroupTitle, rightGroupTitle ) < 0;
 
  405  if ( leftTypeRole != rightTypeRole )
 
  406    return leftTypeRole < rightTypeRole;
 
  409  const double leftScore = lSourceModel->data( left, 
static_cast< int >( CustomRole::ResultScore ) ).toDouble();
 
  410  const double rightScore = lSourceModel->data( right, 
static_cast< int >( CustomRole::ResultScore ) ).toDouble();
 
  412    return leftScore > rightScore;
 
  415  leftFilter = lSourceModel->data( left, Qt::DisplayRole ).toString();
 
  416  rightFilter = lSourceModel->data( right, Qt::DisplayRole ).toString();
 
  417  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)