From ea86049c5e9f8b0d21f20c431a04e7c4ada21121 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Fri, 12 May 2017 12:13:01 +1000 Subject: [PATCH] Show a list of shortcut prefixes in locator bar if no text is entered --- python/gui/locator/qgslocator.sip | 9 ++++ src/app/locator/qgsinbuiltlocatorfilters.h | 4 +- src/gui/locator/qgslocator.cpp | 5 +++ src/gui/locator/qgslocator.h | 8 ++++ src/gui/locator/qgslocatorwidget.cpp | 51 +++++++++++++++++++--- src/gui/locator/qgslocatorwidget.h | 17 ++++++++ 6 files changed, 86 insertions(+), 8 deletions(-) diff --git a/python/gui/locator/qgslocator.sip b/python/gui/locator/qgslocator.sip index 205367dab32..f51b0c92eca 100644 --- a/python/gui/locator/qgslocator.sip +++ b/python/gui/locator/qgslocator.sip @@ -71,9 +71,18 @@ class QgsLocator : QObject QList< QgsLocatorFilter *> filters(); %Docstring Returns the list of filters registered in the locator. +.. seealso:: prefixedFilters() :rtype: list of QgsLocatorFilter %End + QMap< QString, QgsLocatorFilter *> prefixedFilters() const; +%Docstring + Returns a map of prefix to filter, for all registered filters + with valid prefixes. +.. seealso:: filters() + :rtype: QMap< str, QgsLocatorFilter *> +%End + void fetchResults( const QString &string, const QgsLocatorContext &context, QgsFeedback *feedback = 0 ); %Docstring Triggers the background fetching of filter results for a specified search ``string``. diff --git a/src/app/locator/qgsinbuiltlocatorfilters.h b/src/app/locator/qgsinbuiltlocatorfilters.h index e0d05b2abc6..683a98e16b9 100644 --- a/src/app/locator/qgsinbuiltlocatorfilters.h +++ b/src/app/locator/qgsinbuiltlocatorfilters.h @@ -29,7 +29,7 @@ class QgsLayerTreeLocatorFilter : public QgsLocatorFilter QgsLayerTreeLocatorFilter( QObject *parent = nullptr ); virtual QString name() const override { return QStringLiteral( "layertree" ); } - virtual QString displayName() const override { return tr( "Project layers" ); } + virtual QString displayName() const override { return tr( "Project Layers" ); } virtual Priority priority() const override { return Highest; } QString prefix() const override { return QStringLiteral( "l" ); } @@ -46,7 +46,7 @@ class QgsLayoutLocatorFilter : public QgsLocatorFilter QgsLayoutLocatorFilter( QObject *parent = nullptr ); virtual QString name() const override { return QStringLiteral( "layouts" ); } - virtual QString displayName() const override { return tr( "Project layouts" ); } + virtual QString displayName() const override { return tr( "Project Layouts" ); } virtual Priority priority() const override { return Highest; } QString prefix() const override { return QStringLiteral( "pl" ); } diff --git a/src/gui/locator/qgslocator.cpp b/src/gui/locator/qgslocator.cpp index f90bbb1d258..ef1bee19849 100644 --- a/src/gui/locator/qgslocator.cpp +++ b/src/gui/locator/qgslocator.cpp @@ -48,6 +48,11 @@ QList QgsLocator::filters() return mFilters; } +QMap QgsLocator::prefixedFilters() const +{ + return mPrefixedFilters; +} + void QgsLocator::registerFilter( QgsLocatorFilter *filter ) { mFilters.append( filter ); diff --git a/src/gui/locator/qgslocator.h b/src/gui/locator/qgslocator.h index 8a356c2b6e1..ca5f11ae51c 100644 --- a/src/gui/locator/qgslocator.h +++ b/src/gui/locator/qgslocator.h @@ -89,9 +89,17 @@ class GUI_EXPORT QgsLocator : public QObject /** * Returns the list of filters registered in the locator. + * \see prefixedFilters() */ QList< QgsLocatorFilter *> filters(); + /** + * Returns a map of prefix to filter, for all registered filters + * with valid prefixes. + * \see filters() + */ + QMap< QString, QgsLocatorFilter *> prefixedFilters() const; + /** * Triggers the background fetching of filter results for a specified search \a string. * The \a context argument encapsulates the context relating to the search (such as a map diff --git a/src/gui/locator/qgslocatorwidget.cpp b/src/gui/locator/qgslocatorwidget.cpp index f2f059da8fe..40f207c0e2d 100644 --- a/src/gui/locator/qgslocatorwidget.cpp +++ b/src/gui/locator/qgslocatorwidget.cpp @@ -83,6 +83,8 @@ QgsLocatorWidget::QgsLocatorWidget( QWidget *parent ) mResultsView->installEventFilter( this ); installEventFilter( this ); window()->installEventFilter( this ); + + mLocator->registerFilter( new QgsLocatorFilterFilter( this, this ) ); } QgsLocator *QgsLocatorWidget::locator() @@ -204,7 +206,10 @@ void QgsLocatorWidget::addResult( const QgsLocatorResult &result ) bool selectFirst = !mHasSelectedResult || mProxyModel->rowCount() == 0; mLocatorModel->addResult( result ); if ( selectFirst ) - mResultsView->setCurrentIndex( mProxyModel->index( 1, 0 ) ); + { + int row = mProxyModel->flags( mProxyModel->index( 0, 0 ) ) & Qt::ItemIsSelectable ? 0 : 1; + mResultsView->setCurrentIndex( mProxyModel->index( row, 0 ) ); + } } void QgsLocatorWidget::updateResults( const QString &text ) @@ -223,10 +228,7 @@ void QgsLocatorWidget::updateResults( const QString &text ) { mHasSelectedResult = false; mLocatorModel->clear(); - if ( !text.isEmpty() ) - { - mLocator->fetchResults( text, createContext() ); - } + mLocator->fetchResults( text, createContext() ); } } @@ -366,7 +368,7 @@ Qt::ItemFlags QgsLocatorModel::flags( const QModelIndex &index ) const void QgsLocatorModel::addResult( const QgsLocatorResult &result ) { int pos = mResults.size(); - bool addingFilter = !mFoundResultsFromFilterNames.contains( result.filter->name() ); + bool addingFilter = !result.filter->displayName().isEmpty() && !mFoundResultsFromFilterNames.contains( result.filter->name() ); if ( addingFilter ) mFoundResultsFromFilterNames << result.filter->name(); @@ -469,3 +471,40 @@ bool QgsLocatorProxyModel::lessThan( const QModelIndex &left, const QModelIndex rightFilter = sourceModel()->data( right, Qt::DisplayRole ).toString(); return QString::localeAwareCompare( leftFilter, rightFilter ) < 0; } + +QgsLocatorFilterFilter::QgsLocatorFilterFilter( QgsLocatorWidget *locator, QObject *parent ) + : QgsLocatorFilter( parent ) + , mLocator( locator ) +{} + +void QgsLocatorFilterFilter::fetchResults( const QString &string, const QgsLocatorContext &context, QgsFeedback *feedback ) +{ + if ( !string.isEmpty() ) + { + //only shows results when nothing typed + return; + } + + QMap< QString, QgsLocatorFilter *> filters = mLocator->locator()->prefixedFilters(); + QMap< QString, QgsLocatorFilter *>::const_iterator fIt = filters.constBegin(); + for ( ; fIt != filters.constEnd(); ++fIt ) + { + if ( feedback->isCanceled() ) + return; + + if ( fIt.value() == this || !fIt.value() ) + continue; + + QgsLocatorResult result; + result.filter = this; + result.displayString = QString( "%1 (%2)" ).arg( fIt.key(), fIt.value()->displayName() ); + result.userData = fIt.key() + ' '; + //result.icon = action->icon(); + emit resultFetched( result ); + } +} + +void QgsLocatorFilterFilter::triggerResult( const QgsLocatorResult &result ) +{ + mLocator->search( result.userData.toString() ); +} diff --git a/src/gui/locator/qgslocatorwidget.h b/src/gui/locator/qgslocatorwidget.h index 334c92ae836..2da5f3d63bf 100644 --- a/src/gui/locator/qgslocatorwidget.h +++ b/src/gui/locator/qgslocatorwidget.h @@ -111,6 +111,23 @@ class GUI_EXPORT QgsLocatorWidget : public QWidget ///@cond PRIVATE +class QgsLocatorFilterFilter : public QgsLocatorFilter +{ + public: + + QgsLocatorFilterFilter( QgsLocatorWidget *widget, QObject *parent = nullptr ); + + virtual QString name() const override { return QStringLiteral( "filters" );} + virtual QString displayName() const override { return QString(); } + virtual Priority priority() const { return static_cast< QgsLocatorFilter::Priority>( -1 ); /** shh, we cheat!**/ } + virtual void fetchResults( const QString &string, const QgsLocatorContext &context, QgsFeedback *feedback ) override; + virtual void triggerResult( const QgsLocatorResult &result ) override; + + private: + + QgsLocatorWidget *mLocator = nullptr; +}; + /** * \class QgsLocatorModel * \ingroup gui