Skip to content

Commit ebab649

Browse files
committed
Fix some locator filters show results when no string is entered
and filter prefix is not used
1 parent ccb72eb commit ebab649

File tree

8 files changed

+101
-10
lines changed

8 files changed

+101
-10
lines changed

python/core/locator/qgslocatorcontext.sip.in

+2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ Constructor for QgsLocatorContext.
3131

3232
QgsCoordinateReferenceSystem targetExtentCrs;
3333

34+
bool usingPrefix;
35+
3436
};
3537

3638

python/plugins/processing/gui/AlgorithmLocatorFilter.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ def fetchResults(self, string, context, feedback):
6565
if a.flags() & QgsProcessingAlgorithm.FlagHideFromToolbox:
6666
continue
6767

68-
if QgsLocatorFilter.stringMatches(a.displayName(), string) or [t for t in a.tags() if QgsLocatorFilter.stringMatches(t, string)]:
68+
if QgsLocatorFilter.stringMatches(a.displayName(), string) or [t for t in a.tags() if QgsLocatorFilter.stringMatches(t, string)] or \
69+
(context.usingPrefix and not string):
6970
result = QgsLocatorResult()
7071
result.filter = self
7172
result.displayString = a.displayName()

src/app/locator/qgsinbuiltlocatorfilters.cpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,13 @@ QgsLayerTreeLocatorFilter *QgsLayerTreeLocatorFilter::clone() const
3737
return new QgsLayerTreeLocatorFilter();
3838
}
3939

40-
void QgsLayerTreeLocatorFilter::fetchResults( const QString &string, const QgsLocatorContext &, QgsFeedback * )
40+
void QgsLayerTreeLocatorFilter::fetchResults( const QString &string, const QgsLocatorContext &context, QgsFeedback * )
4141
{
4242
QgsLayerTree *tree = QgsProject::instance()->layerTreeRoot();
4343
const QList<QgsLayerTreeLayer *> layers = tree->findLayers();
4444
for ( QgsLayerTreeLayer *layer : layers )
4545
{
46-
if ( layer->layer() && stringMatches( layer->layer()->name(), string ) )
46+
if ( layer->layer() && ( stringMatches( layer->layer()->name(), string ) || ( context.usingPrefix && string.isEmpty() ) ) )
4747
{
4848
QgsLocatorResult result;
4949
result.displayString = layer->layer()->name();
@@ -75,12 +75,12 @@ QgsLayoutLocatorFilter *QgsLayoutLocatorFilter::clone() const
7575
return new QgsLayoutLocatorFilter();
7676
}
7777

78-
void QgsLayoutLocatorFilter::fetchResults( const QString &string, const QgsLocatorContext &, QgsFeedback * )
78+
void QgsLayoutLocatorFilter::fetchResults( const QString &string, const QgsLocatorContext &context, QgsFeedback * )
7979
{
8080
const QList< QgsMasterLayoutInterface * > layouts = QgsProject::instance()->layoutManager()->layouts();
8181
for ( QgsMasterLayoutInterface *layout : layouts )
8282
{
83-
if ( layout && stringMatches( layout->name(), string ) )
83+
if ( layout && ( stringMatches( layout->name(), string ) || ( context.usingPrefix && string.isEmpty() ) ) )
8484
{
8585
QgsLocatorResult result;
8686
result.displayString = layout->name();
@@ -332,7 +332,7 @@ QgsBookmarkLocatorFilter *QgsBookmarkLocatorFilter::clone() const
332332
return new QgsBookmarkLocatorFilter();
333333
}
334334

335-
void QgsBookmarkLocatorFilter::fetchResults( const QString &string, const QgsLocatorContext &, QgsFeedback *feedback )
335+
void QgsBookmarkLocatorFilter::fetchResults( const QString &string, const QgsLocatorContext &context, QgsFeedback *feedback )
336336
{
337337
QMap<QString, QModelIndex> bookmarkMap = QgisApp::instance()->getBookmarkIndexMap();
338338

@@ -346,7 +346,7 @@ void QgsBookmarkLocatorFilter::fetchResults( const QString &string, const QgsLoc
346346

347347
QString name = i.key();
348348

349-
if ( stringMatches( name, string ) )
349+
if ( stringMatches( name, string ) || ( context.usingPrefix && string.isEmpty() ) )
350350
{
351351
QModelIndex index = i.value();
352352
QgsLocatorResult result;

src/core/locator/qgslocator.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,9 @@ void QgsLocator::registerFilter( QgsLocatorFilter *filter )
8282
filter->setUseWithoutPrefix( byDefault );
8383
}
8484

85-
void QgsLocator::fetchResults( const QString &string, const QgsLocatorContext &context, QgsFeedback *feedback )
85+
void QgsLocator::fetchResults( const QString &string, const QgsLocatorContext &c, QgsFeedback *feedback )
8686
{
87+
QgsLocatorContext context( c );
8788
// ideally this should not be required, as well behaved callers
8889
// will NOT fire up a new fetchResults call while an existing one is
8990
// operating/waiting to be canceled...
@@ -112,6 +113,7 @@ void QgsLocator::fetchResults( const QString &string, const QgsLocatorContext &c
112113
activeFilters << mPrefixedFilters.value( prefix );
113114
searchString = searchString.mid( prefix.length() + 1 );
114115
}
116+
context.usingPrefix = !activeFilters.empty();
115117
}
116118
if ( activeFilters.isEmpty() )
117119
{

src/core/locator/qgslocatorcontext.h

+5
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ class CORE_EXPORT QgsLocatorContext
5151
*/
5252
QgsCoordinateReferenceSystem targetExtentCrs;
5353

54+
/**
55+
* Will be true if search is being conducted using a filter prefix.
56+
*/
57+
bool usingPrefix = false;
58+
5459
};
5560

5661
#endif // QGSLOCATORCONTEXT_H

src/core/locator/qgslocatorfilter.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ QgsLocatorFilter::Flags QgsLocatorFilter::flags() const
3434

3535
bool QgsLocatorFilter::stringMatches( const QString &candidate, const QString &search )
3636
{
37-
return candidate.contains( search, Qt::CaseInsensitive );
37+
return !search.isEmpty() && candidate.contains( search, Qt::CaseInsensitive );
3838
}
3939

4040
bool QgsLocatorFilter::enabled() const

tests/src/app/testqgsapplocatorfilters.cpp

+76-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#include "qgisapp.h"
1717
#include "qgslocatorfilter.h"
1818
#include "qgslocator.h"
19+
#include "qgsprintlayout.h"
20+
#include "qgslayoutmanager.h"
1921
#include "locator/qgsinbuiltlocatorfilters.h"
2022
#include <QSignalSpy>
2123
#include <QClipboard>
@@ -32,6 +34,8 @@ class TestQgsAppLocatorFilters : public QObject
3234
void initTestCase();// will be called before the first testfunction is executed.
3335
void cleanupTestCase();// will be called after the last testfunction was executed.
3436
void testCalculator();
37+
void testLayers();
38+
void testLayouts();
3539

3640
private:
3741
QgisApp *mQgisApp = nullptr;
@@ -70,6 +74,77 @@ void TestQgsAppLocatorFilters::testCalculator()
7074
// invalid expression
7175
results = gatherResults( &filter, QStringLiteral( "1+" ), QgsLocatorContext() );
7276
QVERIFY( results.empty() );
77+
}
78+
79+
void TestQgsAppLocatorFilters::testLayers()
80+
{
81+
QgsVectorLayer *l1 = new QgsVectorLayer( QStringLiteral( "Point" ), QStringLiteral( "aaaaa" ), QStringLiteral( "memory" ) );
82+
QgsVectorLayer *l2 = new QgsVectorLayer( QStringLiteral( "Point" ), QStringLiteral( "abc" ), QStringLiteral( "memory" ) );
83+
QgsVectorLayer *l3 = new QgsVectorLayer( QStringLiteral( "Point" ), QStringLiteral( "ccccc" ), QStringLiteral( "memory" ) );
84+
QgsProject::instance()->addMapLayers( QList< QgsMapLayer *>() << l1 << l2 << l3 );
85+
86+
QgsLayerTreeLocatorFilter filter;
87+
88+
QList< QgsLocatorResult > results = gatherResults( &filter, QStringLiteral( "xxxxx" ), QgsLocatorContext() );
89+
QCOMPARE( results.count(), 0 );
90+
91+
results = gatherResults( &filter, QStringLiteral( "aa" ), QgsLocatorContext() );
92+
QCOMPARE( results.count(), 1 );
93+
QCOMPARE( results.at( 0 ).userData.toString(), l1->id() );
94+
95+
results = gatherResults( &filter, QStringLiteral( "A" ), QgsLocatorContext() );
96+
QCOMPARE( results.count(), 2 );
97+
QCOMPARE( results.at( 0 ).userData.toString(), l1->id() );
98+
QCOMPARE( results.at( 1 ).userData.toString(), l2->id() );
99+
100+
results = gatherResults( &filter, QString(), QgsLocatorContext() );
101+
QCOMPARE( results.count(), 0 );
102+
103+
QgsLocatorContext context;
104+
context.usingPrefix = true;
105+
results = gatherResults( &filter, QString(), context );
106+
QCOMPARE( results.count(), 3 );
107+
QCOMPARE( results.at( 0 ).userData.toString(), l1->id() );
108+
QCOMPARE( results.at( 1 ).userData.toString(), l2->id() );
109+
QCOMPARE( results.at( 2 ).userData.toString(), l3->id() );
110+
}
111+
112+
void TestQgsAppLocatorFilters::testLayouts()
113+
{
114+
QgsPrintLayout *pl1 = new QgsPrintLayout( QgsProject::instance() );
115+
pl1->setName( QStringLiteral( "aaaaaa" ) );
116+
QgsProject::instance()->layoutManager()->addLayout( pl1 );
117+
QgsPrintLayout *pl2 = new QgsPrintLayout( QgsProject::instance() );
118+
pl2->setName( QStringLiteral( "abc" ) );
119+
QgsProject::instance()->layoutManager()->addLayout( pl2 );
120+
QgsPrintLayout *pl3 = new QgsPrintLayout( QgsProject::instance() );
121+
pl3->setName( QStringLiteral( "ccccc" ) );
122+
QgsProject::instance()->layoutManager()->addLayout( pl3 );
123+
124+
QgsLayoutLocatorFilter filter;
125+
126+
QList< QgsLocatorResult > results = gatherResults( &filter, QStringLiteral( "xxxxx" ), QgsLocatorContext() );
127+
QCOMPARE( results.count(), 0 );
128+
129+
results = gatherResults( &filter, QStringLiteral( "aa" ), QgsLocatorContext() );
130+
QCOMPARE( results.count(), 1 );
131+
QCOMPARE( results.at( 0 ).userData.toString(), pl1->name() );
132+
133+
results = gatherResults( &filter, QStringLiteral( "A" ), QgsLocatorContext() );
134+
QCOMPARE( results.count(), 2 );
135+
QCOMPARE( results.at( 0 ).userData.toString(), pl1->name() );
136+
QCOMPARE( results.at( 1 ).userData.toString(), pl2->name() );
137+
138+
results = gatherResults( &filter, QString(), QgsLocatorContext() );
139+
QCOMPARE( results.count(), 0 );
140+
141+
QgsLocatorContext context;
142+
context.usingPrefix = true;
143+
results = gatherResults( &filter, QString(), context );
144+
QCOMPARE( results.count(), 3 );
145+
QCOMPARE( results.at( 0 ).userData.toString(), pl1->name() );
146+
QCOMPARE( results.at( 1 ).userData.toString(), pl2->name() );
147+
QCOMPARE( results.at( 2 ).userData.toString(), pl3->name() );
73148

74149
}
75150

@@ -82,7 +157,7 @@ QList<QgsLocatorResult> TestQgsAppLocatorFilters::gatherResults( QgsLocatorFilte
82157
QList< QgsLocatorResult > results;
83158
for ( int i = 0; i < spy.count(); ++ i )
84159
{
85-
QVariant v = spy.at( i ).at( i );
160+
QVariant v = spy.at( i ).at( 0 );
86161
QgsLocatorResult result = v.value<QgsLocatorResult>();
87162
results.append( result );
88163
}

tests/src/python/test_qgslocator.py

+6
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,12 @@ def testAutoModel(self):
260260
self.assertEqual(m.data(m.index(2, 0)), 'a1')
261261
self.assertEqual(m.data(m.index(3, 0)), 'a2')
262262

263+
def testStringMatches(self):
264+
self.assertFalse(QgsLocatorFilter.stringMatches('xxx', 'yyyy'))
265+
self.assertTrue(QgsLocatorFilter.stringMatches('axxxy', 'xxx'))
266+
self.assertTrue(QgsLocatorFilter.stringMatches('aXXXXy', 'xxx'))
267+
self.assertFalse(QgsLocatorFilter.stringMatches('aXXXXy', ''))
268+
263269

264270
if __name__ == '__main__':
265271
unittest.main()

0 commit comments

Comments
 (0)