Skip to content

Commit

Permalink
Don't clear locator model immediately when a new search triggers
Browse files Browse the repository at this point in the history
Instead delay the search until either a tiny timeout (100ms) or
the first new results come in, whichever happens first.

This avoids the list view clearing too frequently and giving
a distracting "flashing" appearance when users type quickly
into to locator bar.
  • Loading branch information
nyalldawson committed May 21, 2017
1 parent d55fa22 commit 1577a57
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 5 deletions.
41 changes: 36 additions & 5 deletions src/gui/locator/qgslocatorwidget.cpp
Expand Up @@ -304,7 +304,7 @@ void QgsLocatorWidget::updateResults( const QString &text )
else
{
mHasSelectedResult = false;
mLocatorModel->clear();
mLocatorModel->deferredClear();
mLocator->fetchResults( text, createContext() );
}
}
Expand Down Expand Up @@ -350,16 +350,29 @@ QgsLocatorContext QgsLocatorWidget::createContext()

QgsLocatorModel::QgsLocatorModel( QObject *parent )
: QAbstractTableModel( parent )
{}
{
mDeferredClearTimer.setInterval( 100 );
mDeferredClearTimer.setSingleShot( true );
connect( &mDeferredClearTimer, &QTimer::timeout, this, &QgsLocatorModel::clear );
}

void QgsLocatorModel::clear()
{
mDeferredClearTimer.stop();
mDeferredClear = false;

beginResetModel();
mResults.clear();
mFoundResultsFromFilterNames.clear();
endResetModel();
}

void QgsLocatorModel::deferredClear()
{
mDeferredClear = true;
mDeferredClearTimer.start();
}

int QgsLocatorModel::rowCount( const QModelIndex & ) const
{
return mResults.size();
Expand Down Expand Up @@ -459,17 +472,29 @@ Qt::ItemFlags QgsLocatorModel::flags( const QModelIndex &index ) const
flags = flags & ~( Qt::ItemIsSelectable | Qt::ItemIsEnabled );
}
return flags;

}

void QgsLocatorModel::addResult( const QgsLocatorResult &result )
{
mDeferredClearTimer.stop();
if ( mDeferredClear )
{
mFoundResultsFromFilterNames.clear();
}

int pos = mResults.size();
bool addingFilter = !result.filter->displayName().isEmpty() && !mFoundResultsFromFilterNames.contains( result.filter->name() );
if ( addingFilter )
mFoundResultsFromFilterNames << result.filter->name();

beginInsertRows( QModelIndex(), pos, pos + ( addingFilter ? 1 : 0 ) );
if ( mDeferredClear )
{
beginResetModel();
mResults.clear();
}
else
beginInsertRows( QModelIndex(), pos, pos + ( addingFilter ? 1 : 0 ) );

if ( addingFilter )
{
Entry entry;
Expand All @@ -480,7 +505,13 @@ void QgsLocatorModel::addResult( const QgsLocatorResult &result )
Entry entry;
entry.result = result;
mResults << entry;
endInsertRows();

if ( mDeferredClear )
endResetModel();
else
endInsertRows();

mDeferredClear = false;
}


Expand Down
11 changes: 11 additions & 0 deletions src/gui/locator/qgslocatorwidget.h
Expand Up @@ -180,9 +180,18 @@ class QgsLocatorModel : public QAbstractTableModel

/**
* Resets the model and clears all existing results.
* \see deferredClear()
*/
void clear();

/**
* Resets the model and clears all existing results after a short delay, or whenever the next result is added to the model
* (whichever occurs first). Using deferredClear() instead of clear() can avoid the visually distracting frequent clears
* which may occur if the model is being updated quickly multiple times as a result of users typing in a search query.
* \see deferredClear()
*/
void deferredClear();

int rowCount( const QModelIndex &parent = QModelIndex() ) const override;
int columnCount( const QModelIndex &parent = QModelIndex() ) const override;
QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const override;
Expand All @@ -206,6 +215,8 @@ class QgsLocatorModel : public QAbstractTableModel

QList<Entry> mResults;
QSet<QString> mFoundResultsFromFilterNames;
bool mDeferredClear = false;
QTimer mDeferredClearTimer;
};

class QgsLocatorProxyModel : public QSortFilterProxyModel
Expand Down

0 comments on commit 1577a57

Please sign in to comment.