Skip to content

Commit 1f7875e

Browse files
committed
[FEATURE][locator] Add bookmark search to locator bar
Allows search for spatial bookmarks. Double clicking a search result will zoom to the bookmark. Short video: https://www.youtube.com/watch?v=ymW4TU8QWy4 The new filter presents itself with a prefix of "b" and with tr( "Spatial bookmarks" ) as displayname. A bookmark locator filter is added to the built in locator filters (class QgsBookmarkLocatorFilter is added to qgsinbuiltlocatorfilters.cpp). The wiring between the the new filter and QgsBookmarks has been implemented in * QgisApp::getBookmarkIndexMap() (For reading bookmarks), and * QgisApp::zoomToBookmarkIndex(const QModelIndex &index) (For navigating to a bookmark) QgsBookmarks has been slightly refactored
1 parent 871132e commit 1f7875e

File tree

7 files changed

+121
-8
lines changed

7 files changed

+121
-8
lines changed

src/app/locator/qgsinbuiltlocatorfilters.cpp

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
/***************************************************************************
2-
qgsinbuiltlocatorfilters.cpp
3-
----------------------------
4-
begin : May 2017
5-
copyright : (C) 2017 by Nyall Dawson
6-
email : nyall dot dawson at gmail dot com
7-
***************************************************************************/
2+
qgsinbuiltlocatorfilters.cpp
3+
----------------------------
4+
begin : May 2017
5+
copyright : (C) 2017 by Nyall Dawson
6+
email : nyall dot dawson at gmail dot com
7+
***************************************************************************/
88

99
/***************************************************************************
1010
* *
@@ -320,3 +320,50 @@ void QgsExpressionCalculatorLocatorFilter::triggerResult( const QgsLocatorResult
320320
{
321321
QApplication::clipboard()->setText( result.userData.toString() );
322322
}
323+
// QgBookmarkLocatorFilter
324+
//
325+
326+
QgsBookmarkLocatorFilter::QgsBookmarkLocatorFilter( QObject *parent )
327+
: QgsLocatorFilter( parent )
328+
{}
329+
330+
QgsBookmarkLocatorFilter *QgsBookmarkLocatorFilter::clone() const
331+
{
332+
return new QgsBookmarkLocatorFilter();
333+
}
334+
335+
void QgsBookmarkLocatorFilter::fetchResults( const QString &string, const QgsLocatorContext &, QgsFeedback *feedback )
336+
{
337+
QMap<QString, QModelIndex> bookmarkMap = QgisApp::instance()->getBookmarkIndexMap();
338+
339+
QMapIterator<QString, QModelIndex> i( bookmarkMap );
340+
341+
while ( i.hasNext() )
342+
{
343+
i.next();
344+
if ( feedback->isCanceled() )
345+
return;
346+
347+
QString name = i.key();
348+
349+
if ( stringMatches( name, string ) )
350+
{
351+
QModelIndex index = i.value();
352+
QgsLocatorResult result;
353+
result.filter = this;
354+
result.displayString = name;
355+
result.userData = index;
356+
//TODO Create svg for "Bookmark"?
357+
//result.icon = TBD
358+
result.score = static_cast< double >( string.length() ) / name.length();
359+
emit resultFetched( result );
360+
}
361+
}
362+
363+
}
364+
365+
void QgsBookmarkLocatorFilter::triggerResult( const QgsLocatorResult &result )
366+
{
367+
QModelIndex index = qvariant_cast<QModelIndex>( result.userData );
368+
QgisApp::instance()->zoomToBookmarkIndex( index );
369+
}

src/app/locator/qgsinbuiltlocatorfilters.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,25 @@ class APP_EXPORT QgsExpressionCalculatorLocatorFilter : public QgsLocatorFilter
132132
};
133133

134134

135+
class QgsBookmarkLocatorFilter : public QgsLocatorFilter
136+
{
137+
Q_OBJECT
138+
139+
public:
140+
141+
QgsBookmarkLocatorFilter( QObject *parent = nullptr );
142+
QgsBookmarkLocatorFilter *clone() const override;
143+
QString name() const override { return QStringLiteral( "bookmarks" ); }
144+
QString displayName() const override { return tr( "Spatial bookmarks" ); }
145+
Priority priority() const override { return Highest; }
146+
QString prefix() const override { return QStringLiteral( "b" ); }
147+
QgsLocatorFilter::Flags flags() const override { return QgsLocatorFilter::FlagFast; }
148+
149+
void fetchResults( const QString &string, const QgsLocatorContext &context, QgsFeedback *feedback ) override;
150+
void triggerResult( const QgsLocatorResult &result ) override;
151+
152+
};
153+
135154
#endif // QGSINBUILTLOCATORFILTERS_H
136155

137156

src/app/qgisapp.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2946,6 +2946,7 @@ void QgisApp::createStatusBar()
29462946
mLocatorWidget->locator()->registerFilter( new QgsActionLocatorFilter( actionObjects ) );
29472947
mLocatorWidget->locator()->registerFilter( new QgsActiveLayerFeaturesLocatorFilter() );
29482948
mLocatorWidget->locator()->registerFilter( new QgsExpressionCalculatorLocatorFilter() );
2949+
mLocatorWidget->locator()->registerFilter( new QgsBookmarkLocatorFilter() );
29492950
}
29502951

29512952
void QgisApp::setIconSizes( int size )
@@ -12343,6 +12344,16 @@ void QgisApp::showBookmarks( bool show )
1234312344
mBookMarksDockWidget->setUserVisible( show );
1234412345
}
1234512346

12347+
QMap<QString, QModelIndex> QgisApp::getBookmarkIndexMap()
12348+
{
12349+
return mBookMarksDockWidget->getIndexMap();
12350+
}
12351+
12352+
void QgisApp::zoomToBookmarkIndex( const QModelIndex &index )
12353+
{
12354+
mBookMarksDockWidget->zoomToBookmarkIndex( index );
12355+
}
12356+
1234612357
// Slot that gets called when the project file was saved with an older
1234712358
// version of QGIS
1234812359

src/app/qgisapp.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,11 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
685685
*/
686686
bool askUserForDatumTransform( const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs );
687687

688+
//! Get map of bookmarks
689+
QMap<QString, QModelIndex> getBookmarkIndexMap();
690+
//! Zoom to a bookmark
691+
void zoomToBookmarkIndex( const QModelIndex & );
692+
688693
public slots:
689694
//! save current vector layer
690695
void saveAsFile( QgsMapLayer *layer = nullptr );

src/app/qgsbookmarks.cpp

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,11 @@ void QgsBookmarks::zoomToBookmark()
236236
QModelIndex index = lstBookmarks->currentIndex();
237237
if ( !index.isValid() )
238238
return;
239+
zoomToBookmarkIndex( index );
240+
}
239241

242+
void QgsBookmarks::zoomToBookmarkIndex( const QModelIndex &index )
243+
{
240244
double xmin = index.sibling( index.row(), 3 ).data().toDouble();
241245
double ymin = index.sibling( index.row(), 4 ).data().toDouble();
242246
double xmax = index.sibling( index.row(), 5 ).data().toDouble();
@@ -254,7 +258,7 @@ void QgsBookmarks::zoomToBookmark()
254258
rect = ct.transform( rect );
255259
if ( rect.isEmpty() )
256260
{
257-
QMessageBox::warning( this, tr( "Zoom to Bookmark" ), tr( "Reprojected extent is empty." ) );
261+
QMessageBox::warning( this, tr( "Empty Extent" ), tr( "Reprojected extent is empty." ) );
258262
return;
259263
}
260264
}
@@ -340,6 +344,30 @@ void QgsBookmarks::importFromXml()
340344
mProxyModel->_resetModel();
341345
}
342346

347+
QMap<QString, QModelIndex> QgsBookmarks::getIndexMap()
348+
{
349+
QMap<QString, QModelIndex> map;
350+
int rowCount = mMergedModel->rowCount();
351+
352+
for ( int i = 0; i < rowCount; ++i )
353+
{
354+
QModelIndex idx = mMergedModel->index( i, 1 ); //Name col
355+
if ( idx.isValid() )
356+
{
357+
QString name = idx.data( Qt::DisplayRole ).toString();
358+
QString project = idx.sibling( idx.row(), 2 ).data().toString();
359+
if ( !project.isEmpty() )
360+
{
361+
name = name + " (" + project + ")";
362+
}
363+
map.insert( name, idx ); //Duplicate name/project pairs are overwritten by subsequent bookmarks
364+
}
365+
}
366+
367+
return map;
368+
369+
}
370+
343371
void QgsBookmarks::exportToXml()
344372
{
345373
QgsSettings settings;

src/app/qgsbookmarks.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ class APP_EXPORT QgsBookmarks : public QgsDockWidget, private Ui::QgsBookmarksBa
145145
public:
146146
QgsBookmarks( QWidget *parent = nullptr );
147147
~QgsBookmarks() override;
148+
QMap<QString, QModelIndex> getIndexMap();
149+
void zoomToBookmarkIndex( const QModelIndex & );
148150

149151
public slots:
150152
void addClicked();

src/core/locator/qgslocator.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ void QgsLocator::registerFilter( QgsLocatorFilter *filter )
6161
{
6262
if ( filter->name() == QStringLiteral( "actions" ) || filter->name() == QStringLiteral( "processing_alg" )
6363
|| filter->name() == QStringLiteral( "layertree" ) || filter->name() == QStringLiteral( "layouts" )
64-
|| filter->name() == QStringLiteral( "features" ) || filter->name() == QStringLiteral( "calculator" ) )
64+
|| filter->name() == QStringLiteral( "features" ) || filter->name() == QStringLiteral( "calculator" )
65+
|| filter->name() == QStringLiteral( "bookmarks" ) )
6566
{
6667
//inbuilt filter, no prefix check
6768
mPrefixedFilters.insert( filter->prefix(), filter );

0 commit comments

Comments
 (0)