Skip to content

Commit ae5988c

Browse files
committedApr 29, 2020
do not use template since they cannot be mixed with Q_OBJECT
1 parent 780b581 commit ae5988c

17 files changed

+576
-756
lines changed
 

‎python/core/auto_generated/qgsfeaturefiltermodel.sip.in

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,7 @@
88

99

1010

11-
12-
typedef QgsFeaturePickerModelBase<QgsFeatureByIdentifierFieldsExpressionValuesGatherer> QgsFeaturePickerModelBaseQgsFeatureByIdentifierFieldsExpressionValuesGathererBase;
13-
14-
class QgsFeatureFilterModel : QgsFeaturePickerModelBaseQgsFeatureByIdentifierFieldsExpressionValuesGathererBase
11+
class QgsFeatureFilterModel : QgsFeaturePickerModelBase
1512
{
1613
%Docstring
1714
Provides a list of features based on filter conditions.
@@ -22,18 +19,9 @@ Features are fetched asynchronously.
2219

2320
%TypeHeaderCode
2421
#include "qgsfeaturefiltermodel.h"
25-
#include "qgsfeaturepickermodelbase.h"
26-
typedef QgsFeaturePickerModelBase<QgsFeatureByIdentifierFieldsExpressionValuesGatherer> QgsFeaturePickerModelBaseQgsFeatureByIdentifierFieldsExpressionValuesGathererBase;
2722
%End
2823
public:
2924

30-
enum Role
31-
{
32-
IdentifierValueRole,
33-
IdentifierValuesRole,
34-
ValueRole
35-
};
36-
3725
explicit QgsFeatureFilterModel( QObject *parent = 0 );
3826
%Docstring
3927
Create a new QgsFeatureFilterModel, optionally specifying a ``parent``.
@@ -78,8 +66,21 @@ still be available in the model as NULL value(s).
7866
.. versionadded:: 3.10
7967
%End
8068

81-
virtual QVariantList extraIdentifierValue() const;
69+
QVariantList extraIdentifierValues() const;
70+
%Docstring
71+
Allows specifying one value that does not need to match the filter criteria but will
72+
still be available in the model.
73+
74+
.. versionadded:: 3.10
75+
%End
76+
77+
void setExtraIdentifierValues( const QVariantList &extraIdentifierValues );
78+
%Docstring
79+
Allows specifying one value that does not need to match the filter criteria but will
80+
still be available in the model.
8281

82+
.. versionadded:: 3.10
83+
%End
8384

8485

8586
signals:
@@ -90,10 +91,11 @@ The identifier field should be a unique field that can be used to identify indiv
9091
It is normally set to the primary key of the layer.
9192
%End
9293

93-
protected:
94-
virtual QgsFeatureByIdentifierFieldsExpressionValuesGatherer createValuesGatherer( const QgsFeatureRequest &request ) const;
95-
96-
94+
void extraIdentifierValuesChanged();
95+
%Docstring
96+
Allows specifying one value that does not need to match the filter criteria but will
97+
still be available in the model.
98+
%End
9799

98100
};
99101

‎python/core/auto_generated/qgsfeaturepickermodel.sip.in

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,7 @@
88

99

1010

11-
12-
typedef QgsFeaturePickerModelBase<QgsFeatureByIdExpressionValuesGatherer> QgsFeaturePickerModelBaseQgsFeatureByIdExpressionValuesGathererBase;
13-
14-
class QgsFeaturePickerModel : QgsFeaturePickerModelBaseQgsFeatureByIdExpressionValuesGathererBase
11+
class QgsFeaturePickerModel : QgsFeaturePickerModelBase
1512
{
1613
%Docstring
1714
Provides a list of features based on filter conditions.
@@ -22,16 +19,13 @@ Features are fetched asynchronously.
2219

2320
%TypeHeaderCode
2421
#include "qgsfeaturepickermodel.h"
25-
#include "qgsfeaturepickermodelbase.h"
26-
typedef QgsFeaturePickerModelBase<QgsFeatureByIdExpressionValuesGatherer> QgsFeaturePickerModelBaseQgsFeatureByIdExpressionValuesGathererBase;
2722
%End
2823
public:
2924

3025
explicit QgsFeaturePickerModel( QObject *parent = 0 );
3126
%Docstring
3227
Create a new QgsFeaturePickerModel, optionally specifying a ``parent``.
3328
%End
34-
~QgsFeaturePickerModel();
3529

3630
virtual void setExtraIdentifierValueToNull();
3731

@@ -42,6 +36,14 @@ still be available in the model as NULL value(s).
4236
.. versionadded:: 3.10
4337
%End
4438

39+
void setFeature( const QgsFeatureId &fid );
40+
%Docstring
41+
Set the feature to the given feature id
42+
%End
43+
44+
signals:
45+
void featureChanged( const QgsFeature &feature );
46+
4547

4648
};
4749

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
/************************************************************************
2+
* This file has been generated automatically from *
3+
* *
4+
* src/core/qgsfeaturepickermodelbase.h *
5+
* *
6+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
7+
************************************************************************/
8+
9+
10+
11+
class QgsFeaturePickerModelBase : QAbstractItemModel /Abstract/
12+
{
13+
%Docstring
14+
Provides a list of features based on filter conditions.
15+
Features are fetched asynchronously.
16+
17+
.. versionadded:: 3.0
18+
%End
19+
20+
%TypeHeaderCode
21+
#include "qgsfeaturepickermodelbase.h"
22+
%End
23+
public:
24+
25+
enum Role
26+
{
27+
IdentifierValueRole,
28+
IdentifierValuesRole,
29+
ValueRole,
30+
FeatureRole,
31+
FeatureIdRole
32+
};
33+
34+
explicit QgsFeaturePickerModelBase( QObject *parent = 0 );
35+
%Docstring
36+
Create a new QgsFeaturePickerModelBase, optionally specifying a ``parent``.
37+
%End
38+
~QgsFeaturePickerModelBase();
39+
40+
QgsVectorLayer *sourceLayer() const;
41+
%Docstring
42+
The source layer from which features will be fetched.
43+
%End
44+
45+
void setSourceLayer( QgsVectorLayer *sourceLayer );
46+
%Docstring
47+
The source layer from which features will be fetched.
48+
%End
49+
50+
QString displayExpression() const;
51+
%Docstring
52+
The display expression will be used for
53+
54+
- displaying values in the combobox
55+
- filtering based on filterValue
56+
%End
57+
58+
void setDisplayExpression( const QString &displayExpression );
59+
%Docstring
60+
The display expression will be used for
61+
62+
- displaying values in the combobox
63+
- filtering based on filterValue
64+
%End
65+
66+
QString filterValue() const;
67+
%Docstring
68+
This value will be used to filter the features available from
69+
this model. Whenever a substring of the displayExpression of a feature
70+
matches the filter value, it will be accessible by this model.
71+
%End
72+
73+
void setFilterValue( const QString &filterValue );
74+
%Docstring
75+
This value will be used to filter the features available from
76+
this model. Whenever a substring of the displayExpression of a feature
77+
matches the filter value, it will be accessible by this model.
78+
%End
79+
80+
virtual QModelIndex index( int row, int column, const QModelIndex &parent ) const;
81+
82+
virtual QModelIndex parent( const QModelIndex &child ) const;
83+
84+
virtual int rowCount( const QModelIndex &parent ) const;
85+
86+
virtual int columnCount( const QModelIndex &parent ) const;
87+
virtual QVariant data( const QModelIndex &index, int role ) const;
88+
89+
90+
QString filterExpression() const;
91+
%Docstring
92+
An additional filter expression to apply, next to the filterValue.
93+
Can be used for spatial filtering etc.
94+
%End
95+
96+
void setFilterExpression( const QString &filterExpression );
97+
%Docstring
98+
An additional filter expression to apply, next to the filterValue.
99+
Can be used for spatial filtering etc.
100+
%End
101+
102+
bool isLoading() const;
103+
%Docstring
104+
Indicator if the model is currently performing any feature iteration in the background.
105+
%End
106+
107+
virtual void setExtraIdentifierValueToNull() = 0;
108+
%Docstring
109+
Allows specifying one value that does not need to match the filter criteria but will
110+
still be available in the model as NULL value(s).
111+
112+
.. versionadded:: 3.10
113+
%End
114+
115+
int extraIdentifierValueIndex() const;
116+
%Docstring
117+
The index at which the extra identifier value is available within the model.
118+
%End
119+
120+
bool extraValueDoesNotExist() const;
121+
%Docstring
122+
Flag indicating that the extraIdentifierValue does not exist in the data.
123+
%End
124+
125+
bool allowNull() const;
126+
%Docstring
127+
Add a NULL entry to the list.
128+
%End
129+
130+
void setAllowNull( bool allowNull );
131+
%Docstring
132+
Add a NULL entry to the list.
133+
%End
134+
135+
signals:
136+
137+
void sourceLayerChanged();
138+
%Docstring
139+
The source layer from which features will be fetched.
140+
%End
141+
142+
void displayExpressionChanged();
143+
%Docstring
144+
The display expression will be used for
145+
146+
- displaying values in the combobox
147+
- filtering based on filterValue
148+
%End
149+
150+
void filterValueChanged();
151+
%Docstring
152+
This value will be used to filter the features available from
153+
this model. Whenever a substring of the displayExpression of a feature
154+
matches the filter value, it will be accessible by this model.
155+
%End
156+
157+
void filterExpressionChanged();
158+
%Docstring
159+
An additional filter expression to apply, next to the filterValue.
160+
Can be used for spatial filtering etc.
161+
%End
162+
163+
void isLoadingChanged();
164+
%Docstring
165+
Indicator if the model is currently performing any feature iteration in the background.
166+
%End
167+
168+
void filterJobCompleted();
169+
%Docstring
170+
Indicates that a filter job has been completed and new data may be available.
171+
%End
172+
173+
void extraIdentifierValueChanged();
174+
%Docstring
175+
Allows specifying one value that does not need to match the filter criteria but will
176+
still be available in the model.
177+
%End
178+
179+
void extraIdentifierValueIndexChanged( int index );
180+
%Docstring
181+
The index at which the extra identifier value is available within the model.
182+
%End
183+
184+
void extraValueDoesNotExistChanged();
185+
%Docstring
186+
Flag indicating that the extraIdentifierValue does not exist in the data.
187+
%End
188+
189+
void beginUpdate();
190+
%Docstring
191+
Notification that the model is about to be changed because a job was completed.
192+
%End
193+
194+
void endUpdate();
195+
%Docstring
196+
Notification that the model change is finished. Will always be emitted in sync with beginUpdate.
197+
%End
198+
199+
void allowNullChanged();
200+
%Docstring
201+
Add a NULL entry to the list.
202+
%End
203+
204+
protected:
205+
206+
QVariant extraIdentifierValue() const;
207+
%Docstring
208+
Allows specifying one value that does not need to match the filter criteria but will
209+
still be available in the model.
210+
%End
211+
212+
void setExtraIdentifierValue( const QVariant &extraIdentifierValue );
213+
%Docstring
214+
Allows specifying one value that does not need to match the filter criteria but will
215+
still be available in the model.
216+
%End
217+
218+
virtual void requestToReloadCurrentFeature( QgsFeatureRequest &request ) = 0;
219+
%Docstring
220+
Update the request to match the current feature to be reloaded
221+
%End
222+
223+
void setExtraIdentifierValueUnguarded( const QVariant &identifierValue );
224+
225+
226+
227+
228+
};
229+
230+
/************************************************************************
231+
* This file has been generated automatically from *
232+
* *
233+
* src/core/qgsfeaturepickermodelbase.h *
234+
* *
235+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
236+
************************************************************************/

‎python/core/core_auto.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
%Include auto_generated/qgsexpressionfieldbuffer.sip
6363
%Include auto_generated/qgsfeature.sip
6464
%Include auto_generated/qgsfeaturepickermodel.sip
65+
%Include auto_generated/qgsfeaturepickermodelbase.sip
6566
%Include auto_generated/qgsfeaturefiltermodel.sip
6667
%Include auto_generated/qgsfeaturefilterprovider.sip
6768
%Include auto_generated/qgsfeatureid.sip

‎python/gui/auto_generated/qgsfeaturepickerwidget.sip.in

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ The layer from which features should be listed.
4141
The layer from which features should be listed.
4242
%End
4343

44-
void setCurrentFeature( QgsFeatureId featureId );
44+
void setFeature( QgsFeatureId featureId );
4545
%Docstring
4646
Sets the current index by using the given feature
4747
%End
@@ -132,7 +132,7 @@ This can be used to integrate additional spatial or other constraints.
132132
Determines if a NULL value should be available in the list.
133133
%End
134134

135-
void currentFeatureChanged( const QgsFeature &feature );
135+
void featureChanged( const QgsFeature &feature );
136136
%Docstring
137137
Sends the feature as soon as it is chosen
138138
%End

‎scripts/sip_include.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ fi
3434
if [[ -n $1 ]]; then
3535
modules=("$1")
3636
else
37-
modules=(core gui analysis server 3d)
37+
modules=(core gui analysis server)
3838
fi
3939
sources=(HDRS MOC_HDRS SRCS)
4040

‎src/core/qgsfeatureexpressionvaluesgatherer.h

Lines changed: 23 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
*
3434
* \since QGIS 3.0
3535
*/
36-
template <class T>
3736
class QgsFeatureExpressionValuesGatherer: public QThread
3837
{
3938
Q_OBJECT
@@ -58,24 +57,36 @@ class QgsFeatureExpressionValuesGatherer: public QThread
5857
{
5958
}
6059

61-
//! The type to identify a feature (QgsFeatureId, QVariantList, …)
62-
using IdentifierType = T;
63-
6460
struct Entry
6561
{
66-
Entry( const T &_identifier, const QString &_value, const QgsFeature &_feature )
67-
: identifier( _identifier )
62+
Entry() = default;
63+
64+
Entry( const QVariantList &_identifierFields, const QString &_value, const QgsFeature &_feature )
65+
: identifierFields( _identifierFields )
66+
, featureId( _feature.isValid() ? _feature.id() : FID_NULL )
6867
, value( _value )
6968
, feature( _feature )
7069
{}
7170

72-
T identifier;
71+
Entry( const QgsFeatureId &_featureId, const QString &_value )
72+
: featureId( _featureId )
73+
, value( _value )
74+
, feature( QgsFeature() )
75+
{}
76+
77+
QVariantList identifierFields;
78+
QgsFeatureId featureId;
7379
QString value;
7480
QgsFeature feature;
7581

7682
bool operator()( const Entry &lhs, const Entry &rhs ) const;
7783
};
7884

85+
static Entry nullEntry()
86+
{
87+
return Entry( QVariantList(), QgsApplication::nullRepresentation(), QgsFeature() );
88+
}
89+
7990
void run() override
8091
{
8192
mWasCanceled = false;
@@ -84,40 +95,28 @@ class QgsFeatureExpressionValuesGatherer: public QThread
8495

8596
mDisplayExpression.prepare( &mExpressionContext );
8697

87-
QgsFeature feat;
98+
QgsFeature feature;
8899
QList<int> attributeIndexes;
89100
for ( const QString &fieldName : qgis::as_const( mIdentifierFields ) )
90101
attributeIndexes << mSource->fields().indexOf( fieldName );
91102

92-
while ( mIterator.nextFeature( feat ) )
103+
while ( mIterator.nextFeature( feature ) )
93104
{
94-
mExpressionContext.setFeature( feat );
105+
mExpressionContext.setFeature( feature );
95106
QVariantList attributes;
96107
for ( const int idx : attributeIndexes )
97-
attributes << feat.attribute( idx );
108+
attributes << feature.attribute( idx );
98109

99110
const QString expressionValue = mDisplayExpression.evaluate( &mExpressionContext ).toString();
100111

101-
addEntry( feat, attributes, expressionValue );
112+
mEntries.append( Entry( attributes, expressionValue, feature ) );
102113

103114
QMutexLocker locker( &mCancelMutex );
104115
if ( mWasCanceled )
105116
return;
106117
}
107118
}
108119

109-
//! Add an entry to the list
110-
virtual void addEntry( const QgsFeature &feature, const QVariantList &attributes, const QString &expressionValue ) = 0;
111-
112-
//! Returns TRUE if the 2 entries refers to the same feature
113-
virtual bool compareEntries( const Entry &a, const Entry &b ) {return a.identifier == b.identifier;}
114-
115-
//! Returns TRUE if the entry is null
116-
virtual bool identifierIsNull( const T &identifier ) = 0;
117-
118-
//! Returns a human reading representation of the identifier
119-
virtual QString identifierToString( const T &identifier ) = 0;
120-
121120
//! Informs the gatherer to immediately stop collecting values
122121
void stop()
123122
{
@@ -173,89 +172,6 @@ class QgsFeatureExpressionValuesGatherer: public QThread
173172
QVariant mData;
174173
};
175174

176-
177-
178-
class QgsFeatureByIdExpressionValuesGatherer : public QgsFeatureExpressionValuesGatherer<QgsFeatureId>
179-
{
180-
public:
181-
QgsFeatureByIdExpressionValuesGatherer( QgsVectorLayer *layer,
182-
const QString &displayExpression = QString(),
183-
const QgsFeatureRequest &request = QgsFeatureRequest() )
184-
: QgsFeatureExpressionValuesGatherer( layer, displayExpression, request )
185-
{}
186-
187-
static Entry nullEntry()
188-
{
189-
return Entry( QgsFeatureId( FID_NULL ), QgsApplication::nullRepresentation(), QgsFeature() );
190-
}
191-
192-
void addEntry( const QgsFeature &feature, const QVariantList &attributes, const QString &expressionValue ) override
193-
{
194-
Q_UNUSED( attributes )
195-
mEntries.append( Entry( feature.id(), expressionValue, feature ) );
196-
}
197-
198-
bool identifierIsNull( const QgsFeatureId &identifier ) override
199-
{
200-
return identifier == FID_NULL;
201-
}
202-
203-
QString identifierToString( const QgsFeatureId &identifier ) override
204-
{
205-
return QStringLiteral( "(%1)" ).arg( identifier );
206-
}
207-
};
208-
209-
210-
class QgsFeatureByIdentifierFieldsExpressionValuesGatherer : public QgsFeatureExpressionValuesGatherer<QVariantList>
211-
{
212-
public:
213-
QgsFeatureByIdentifierFieldsExpressionValuesGatherer( QgsVectorLayer *layer,
214-
const QString &displayExpression = QString(),
215-
const QgsFeatureRequest &request = QgsFeatureRequest(),
216-
const QStringList &identifierFields = QStringList() )
217-
: QgsFeatureExpressionValuesGatherer( layer, displayExpression, request, identifierFields )
218-
{}
219-
220-
bool compareEntries( const Entry &a, const Entry &b ) override {return qVariantListCompare( a.identifier, b.identifier );}
221-
222-
static Entry nullEntry()
223-
{
224-
return Entry( QVariantList(), QgsApplication::nullRepresentation(), QgsFeature() );
225-
}
226-
227-
void addEntry( const QgsFeature &feature, const QVariantList &attributes, const QString &expressionValue ) override
228-
{
229-
mEntries.append( Entry( attributes, expressionValue, feature ) );
230-
}
231-
232-
bool identifierIsNull( const QList<QVariant> &identifier ) override
233-
{
234-
return identifier.isEmpty();
235-
}
236-
237-
QString identifierToString( const QList<QVariant> &identifier ) override
238-
{
239-
QStringList values;
240-
for ( const QVariant &v : qgis::as_const( identifier ) )
241-
values << QStringLiteral( "(%1)" ).arg( v.toString() );
242-
return values.join( QStringLiteral( " " ) );
243-
}
244-
245-
private:
246-
bool qVariantListCompare( const QVariantList &a, const QVariantList &b )
247-
{
248-
if ( a.size() != b.size() )
249-
return false;
250-
251-
for ( int i = 0; i < a.size(); ++i )
252-
{
253-
if ( !qgsVariantEqual( a.at( i ), b.at( i ) ) )
254-
return false;
255-
}
256-
return true;
257-
}
258-
};
259175
///@endcond
260176

261177

‎src/core/qgsfeaturefiltermodel.cpp

Lines changed: 69 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,20 @@
2121
#include "qgssettings.h"
2222

2323

24+
bool qVariantListCompare( const QVariantList &a, const QVariantList &b )
25+
{
26+
if ( a.size() != b.size() )
27+
return false;
28+
29+
for ( int i = 0; i < a.size(); ++i )
30+
{
31+
if ( !qgsVariantEqual( a.at( i ), b.at( i ) ) )
32+
return false;
33+
}
34+
return true;
35+
}
36+
37+
2438
QgsFeatureFilterModel::QgsFeatureFilterModel( QObject *parent )
2539
: QgsFeaturePickerModelBase( parent )
2640
{
@@ -37,13 +51,13 @@ void QgsFeatureFilterModel::requestToReloadCurrentFeature( QgsFeatureRequest &re
3751
QStringList conditions;
3852
for ( int i = 0; i < mIdentifierFields.count(); i++ )
3953
{
40-
if ( i >= mExtraIdentifierValue.count() )
54+
if ( i >= mExtraIdentifierValue.toList().count() )
4155
{
4256
conditions << QgsExpression::createFieldEqualityExpression( mIdentifierFields.at( i ), QVariant() );
4357
}
4458
else
4559
{
46-
conditions << QgsExpression::createFieldEqualityExpression( mIdentifierFields.at( i ), mExtraIdentifierValue.at( i ) );
60+
conditions << QgsExpression::createFieldEqualityExpression( mIdentifierFields.at( i ), mExtraIdentifierValue.toList().at( i ) );
4761
}
4862
}
4963
request.setFilterExpression( conditions.join( QStringLiteral( " AND " ) ) );
@@ -54,6 +68,45 @@ QSet<QString> QgsFeatureFilterModel::requestedAttributes() const
5468
return QSet<QString>( mIdentifierFields.begin(), mIdentifierFields.end() );
5569
}
5670

71+
QVariant QgsFeatureFilterModel::entryIdentifier( const QgsFeatureExpressionValuesGatherer::Entry &entry ) const
72+
{
73+
return entry.featureId;
74+
}
75+
76+
QgsFeatureExpressionValuesGatherer::Entry QgsFeatureFilterModel::createEntry( const QVariant &identifier ) const
77+
{
78+
const QVariantList constValues = identifier.toList();
79+
80+
QStringList values;
81+
for ( const QVariant &v : constValues )
82+
values << QStringLiteral( "(%1)" ).arg( v.toString() );
83+
84+
return QgsFeatureExpressionValuesGatherer::Entry( constValues, values.join( QStringLiteral( " " ) ), QgsFeature() );
85+
}
86+
87+
bool QgsFeatureFilterModel::compareEntries( const QgsFeatureExpressionValuesGatherer::Entry &a, const QgsFeatureExpressionValuesGatherer::Entry &b ) const
88+
{
89+
return qVariantListCompare( a.identifierFields, b.identifierFields );
90+
}
91+
92+
bool QgsFeatureFilterModel::identifierIsNull( const QVariant &identifier ) const
93+
{
94+
const QVariantList values = identifier.toList();
95+
for ( const QVariant &value : values )
96+
{
97+
if ( !value.isNull() )
98+
{
99+
return false;
100+
}
101+
}
102+
return true;
103+
}
104+
105+
QVariant QgsFeatureFilterModel::nullIentifier() const
106+
{
107+
return QVariantList();
108+
}
109+
57110
QStringList QgsFeatureFilterModel::identifierFields() const
58111
{
59112
return mIdentifierFields;
@@ -70,25 +123,32 @@ void QgsFeatureFilterModel::setIdentifierFields( const QStringList &identifierFi
70123
setExtraIdentifierValueToNull();
71124
}
72125

126+
QgsFeatureExpressionValuesGatherer *QgsFeatureFilterModel::createValuesGatherer( const QgsFeatureRequest &request ) const
127+
{
128+
return new QgsFeatureExpressionValuesGatherer( sourceLayer(), displayExpression(), request, mIdentifierFields );
129+
}
73130

74-
QVariantList QgsFeatureFilterModel::extraIdentifierValue() const
131+
132+
QVariantList QgsFeatureFilterModel::extraIdentifierValues() const
75133
{
76-
if ( mExtraIdentifierValue.count() != mIdentifierFields.count() )
134+
QVariantList values = mExtraIdentifierValue.toList();
135+
if ( values.count() != mIdentifierFields.count() )
77136
{
78137
QVariantList nullValues;
79138
for ( int i = 0; i < mIdentifierFields.count(); i++ )
80139
nullValues << QVariant( QVariant::Int );
81140
return nullValues;
82141
}
83-
return mExtraIdentifierValue;
142+
return values;
84143
}
85144

86-
void QgsFeatureFilterModel::setExtraIdentifierValueToNull()
145+
void QgsFeatureFilterModel::setExtraIdentifierValues( const QVariantList &extraIdentifierValues )
87146
{
88-
setExtraIdentifierValue( QVariantList() );
147+
setExtraIdentifierValue( extraIdentifierValues );
89148
}
90149

91-
QgsFeatureByIdentifierFieldsExpressionValuesGatherer QgsFeatureFilterModel::createValuesGatherer( const QgsFeatureRequest &request ) const
150+
void QgsFeatureFilterModel::setExtraIdentifierValueToNull()
92151
{
93-
new QgsFeatureByIdentifierFieldsExpressionValuesGatherer( mSourceLayer, mDisplayExpression, request, mIdentifierFields );
152+
setExtraIdentifierValue( QVariantList() );
94153
}
154+

‎src/core/qgsfeaturefiltermodel.h

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
*
2626
* \since QGIS 3.0
2727
*/
28-
class CORE_EXPORT QgsFeatureFilterModel : public QgsFeaturePickerModelBase<QgsFeatureByIdentifierFieldsExpressionValuesGatherer>
28+
class CORE_EXPORT QgsFeatureFilterModel : public QgsFeaturePickerModelBase
2929
{
3030
Q_OBJECT
3131

@@ -34,19 +34,14 @@ class CORE_EXPORT QgsFeatureFilterModel : public QgsFeaturePickerModelBase<QgsFe
3434
* Normally the primary key field.
3535
* Needs to match the identifierValue.
3636
*/
37-
Q_PROPERTY( QString identifierFields READ identifierFields WRITE setIdentifierFields NOTIFY identifierFieldChangeds )
38-
39-
public:
37+
Q_PROPERTY( QStringList identifierFields READ identifierFields WRITE setIdentifierFields NOTIFY identifierFieldsChanged )
4038

4139
/**
42-
* Extra roles that can be used to fetch data from this model.
40+
* The value that identifies the current feature.
4341
*/
44-
enum Role
45-
{
46-
IdentifierValueRole = Qt::UserRole, //!< \deprecated Use IdentifierValuesRole instead
47-
IdentifierValuesRole, //!< Used to retrieve the identifierValues (primary keys) of a feature.
48-
ValueRole //!< Used to retrieve the displayExpression of a feature.
49-
};
42+
Q_PROPERTY( QVariantList extraIdentifierValues READ extraIdentifierValues WRITE setExtraIdentifierValues NOTIFY extraIdentifierValuesChanged )
43+
44+
public:
5045

5146
/**
5247
* Create a new QgsFeatureFilterModel, optionally specifying a \a parent.
@@ -83,7 +78,19 @@ class CORE_EXPORT QgsFeatureFilterModel : public QgsFeaturePickerModelBase<QgsFe
8378
*/
8479
void setExtraIdentifierValueToNull() override;
8580

86-
QVariantList extraIdentifierValue() const override;
81+
/**
82+
* Allows specifying one value that does not need to match the filter criteria but will
83+
* still be available in the model.
84+
* \since QGIS 3.10
85+
*/
86+
QVariantList extraIdentifierValues() const;
87+
88+
/**
89+
* Allows specifying one value that does not need to match the filter criteria but will
90+
* still be available in the model.
91+
* \since QGIS 3.10
92+
*/
93+
void setExtraIdentifierValues( const QVariantList &extraIdentifierValues );
8794

8895

8996
signals:
@@ -94,15 +101,29 @@ class CORE_EXPORT QgsFeatureFilterModel : public QgsFeaturePickerModelBase<QgsFe
94101
*/
95102
void identifierFieldsChanged();
96103

97-
protected:
98-
QgsFeatureByIdentifierFieldsExpressionValuesGatherer createValuesGatherer( const QgsFeatureRequest &request ) const override;
99-
104+
/**
105+
* Allows specifying one value that does not need to match the filter criteria but will
106+
* still be available in the model.
107+
*/
108+
void extraIdentifierValuesChanged();
100109

101110
private:
111+
QgsFeatureExpressionValuesGatherer *createValuesGatherer( const QgsFeatureRequest &request ) const override;
112+
102113
void requestToReloadCurrentFeature( QgsFeatureRequest &request ) override;
103114

104115
QSet<QString> requestedAttributes() const override;
105116

117+
QVariant entryIdentifier( const QgsFeatureExpressionValuesGatherer::Entry &entry ) const override;
118+
119+
QgsFeatureExpressionValuesGatherer::Entry createEntry( const QVariant &identifier ) const override;
120+
121+
bool compareEntries( const QgsFeatureExpressionValuesGatherer::Entry &a, const QgsFeatureExpressionValuesGatherer::Entry &b ) const override;
122+
123+
bool identifierIsNull( const QVariant &identifier ) const override;
124+
125+
QVariant nullIentifier() const override;
126+
106127
QStringList mIdentifierFields;
107128
};
108129

‎src/core/qgsfeaturepickermodel.cpp

Lines changed: 21 additions & 453 deletions
Large diffs are not rendered by default.

‎src/core/qgsfeaturepickermodel.h

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include "qgsconditionalstyle.h"
2121
#include "qgsfeatureexpressionvaluesgatherer.h"
22+
#include "qgsfeaturepickermodelbase.h"
2223

2324
/**
2425
* \ingroup core
@@ -27,7 +28,7 @@
2728
*
2829
* \since QGIS 3.0
2930
*/
30-
class CORE_EXPORT QgsFeaturePickerModel : public QgsFeaturePickerModelBase<QgsFeatureByIdExpressionValuesGatherer>
31+
class CORE_EXPORT QgsFeaturePickerModel : public QgsFeaturePickerModelBase
3132
{
3233
Q_OBJECT
3334

@@ -37,7 +38,6 @@ class CORE_EXPORT QgsFeaturePickerModel : public QgsFeaturePickerModelBase<QgsFe
3738
* Create a new QgsFeaturePickerModel, optionally specifying a \a parent.
3839
*/
3940
explicit QgsFeaturePickerModel( QObject *parent = nullptr );
40-
~QgsFeaturePickerModel() override;
4141

4242
/**
4343
* Allows specifying one value that does not need to match the filter criteria but will
@@ -46,14 +46,27 @@ class CORE_EXPORT QgsFeaturePickerModel : public QgsFeaturePickerModelBase<QgsFe
4646
*/
4747
void setExtraIdentifierValueToNull() override;
4848

49+
//! Set the feature to the given feature id
50+
void setFeature( const QgsFeatureId &fid );
51+
52+
signals:
53+
void featureChanged( const QgsFeature &feature );
54+
4955

5056
private:
57+
QgsFeatureExpressionValuesGatherer *createValuesGatherer( const QgsFeatureRequest &request ) const override;
58+
5159
void requestToReloadCurrentFeature( QgsFeatureRequest &request ) override;
5260

53-
void setCurrentFeatureUnguarded( const QgsFeatureId &featureId );
61+
QVariant entryIdentifier( const QgsFeatureExpressionValuesGatherer::Entry &entry ) const override;
62+
63+
QgsFeatureExpressionValuesGatherer::Entry createEntry( const QVariant &identifier ) const override;
64+
65+
bool compareEntries( const QgsFeatureExpressionValuesGatherer::Entry &a, const QgsFeatureExpressionValuesGatherer::Entry &b ) const override;
5466

55-
QgsFeatureId mFeatureFidToReload = FID_NULL;
67+
bool identifierIsNull( const QVariant &identifier ) const override;
5668

69+
QVariant nullIentifier() const override;
5770
};
5871

5972
#endif // QGSFEATUREPICKERMODEL_H

‎src/core/qgsfeaturepickermodelbase.cpp

Lines changed: 83 additions & 93 deletions
Large diffs are not rendered by default.

‎src/core/qgsfeaturepickermodelbase.h

Lines changed: 43 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,8 @@
2727
*
2828
* \since QGIS 3.0
2929
*/
30-
template <class T>
31-
class CORE_EXPORT QgsFeaturePickerModelBase : public QAbstractItemModel
30+
class CORE_EXPORT QgsFeaturePickerModelBase : public QAbstractItemModel SIP_ABSTRACT
3231
{
33-
using GathererType = T;
34-
using IdentifierType = typename GathererType::IdentifierType;
35-
3632
Q_OBJECT
3733

3834
Q_PROPERTY( QgsVectorLayer *sourceLayer READ sourceLayer WRITE setSourceLayer NOTIFY sourceLayerChanged )
@@ -42,11 +38,6 @@ class CORE_EXPORT QgsFeaturePickerModelBase : public QAbstractItemModel
4238
Q_PROPERTY( bool allowNull READ allowNull WRITE setAllowNull NOTIFY allowNullChanged )
4339
Q_PROPERTY( bool isLoading READ isLoading NOTIFY isLoadingChanged )
4440

45-
/**
46-
* The value that identifies the current feature.
47-
*/
48-
Q_PROPERTY( IdentifierType extraIdentifierValue READ extraIdentifierValue WRITE setExtraIdentifierValue NOTIFY extraIdentifierValueChanged )
49-
5041
Q_PROPERTY( int extraIdentifierValueIndex READ extraIdentifierValueIndex NOTIFY extraIdentifierValueIndexChanged )
5142

5243
public:
@@ -136,18 +127,6 @@ class CORE_EXPORT QgsFeaturePickerModelBase : public QAbstractItemModel
136127
*/
137128
bool isLoading() const;
138129

139-
/**
140-
* Allows specifying one value that does not need to match the filter criteria but will
141-
* still be available in the model.
142-
*/
143-
virtual IdentifierType extraIdentifierValue() const {return mExtraIdentifierValue;}
144-
145-
/**
146-
* Allows specifying one value that does not need to match the filter criteria but will
147-
* still be available in the model.
148-
*/
149-
virtual void setExtraIdentifierValue( const IdentifierType &extraIdentifierValue ) = 0;
150-
151130
/**
152131
* Allows specifying one value that does not need to match the filter criteria but will
153132
* still be available in the model as NULL value(s).
@@ -249,26 +228,62 @@ class CORE_EXPORT QgsFeaturePickerModelBase : public QAbstractItemModel
249228
void scheduledReload();
250229

251230
protected:
231+
232+
/**
233+
* Allows specifying one value that does not need to match the filter criteria but will
234+
* still be available in the model.
235+
*/
236+
QVariant extraIdentifierValue() const;
237+
238+
/**
239+
* Allows specifying one value that does not need to match the filter criteria but will
240+
* still be available in the model.
241+
*/
242+
void setExtraIdentifierValue( const QVariant &extraIdentifierValue );
243+
252244
//! Update the request to match the current feature to be reloaded
253245
virtual void requestToReloadCurrentFeature( QgsFeatureRequest &request ) = 0;
254246

247+
void setExtraIdentifierValueUnguarded( const QVariant &identifierValue );
248+
249+
#ifndef SIP_RUN
250+
255251
/**
256252
* Returns the attributes to be fetched in the request.
257253
* Returns an empty set if all attributes should be fetched.
258254
*/
259255
virtual QSet<QString> requestedAttributes() const {return {};}
260256

261-
virtual T createValuesGatherer( const QgsFeatureRequest &request ) const;
257+
virtual QgsFeatureExpressionValuesGatherer *createValuesGatherer( const QgsFeatureRequest &request ) const = 0;
262258

263-
void setExtraIdentifierValueUnguarded( const IdentifierType &identifierValue );
259+
//! Creates an entry with just the identifier so the feature can be retrieved in a next iteration
260+
virtual QgsFeatureExpressionValuesGatherer::Entry createEntry( const QVariant &identifer ) const = 0;
261+
262+
//! Returns the identifier of the given entry
263+
virtual QVariant entryIdentifier( const QgsFeatureExpressionValuesGatherer::Entry &entry ) const = 0;
264+
265+
//! Returns TRUE if the 2 entries refers to the same feature
266+
virtual bool compareEntries( const QgsFeatureExpressionValuesGatherer::Entry &a, const QgsFeatureExpressionValuesGatherer::Entry &b ) const = 0;
267+
268+
//! Returns a null identifier
269+
virtual QVariant nullIentifier() const = 0;
270+
271+
/**
272+
* Returns TRUE if the entry is null
273+
* The identifier can be either the feature ID or the list of identifier fields
274+
*/
275+
virtual bool identifierIsNull( const QVariant &identifier ) const = 0;
276+
277+
QVector<QgsFeatureExpressionValuesGatherer::Entry> mEntries;
278+
#endif
264279

265280
//! The current identifier value
266-
IdentifierType mExtraIdentifierValue;
281+
QVariant mExtraIdentifierValue;
267282

283+
//! The current index
284+
int mExtraValueIndex = -1;
268285

269286
private:
270-
using EntryType = typename GathererType::Entry;
271-
272287
void setExtraIdentifierValueIndex( int index, bool force = false );
273288
void setExtraValueDoesNotExist( bool extraValueDoesNotExist );
274289
void reload();
@@ -285,19 +300,13 @@ class CORE_EXPORT QgsFeaturePickerModelBase : public QAbstractItemModel
285300
mutable QgsExpressionContext mExpressionContext;
286301
mutable QMap< QgsFeatureId, QgsConditionalStyle > mEntryStylesMap;
287302

288-
QVector<EntryType> mEntries;
289-
290-
T *mGatherer = nullptr;
303+
QgsFeatureExpressionValuesGatherer *mGatherer = nullptr;
291304

292305
QTimer mReloadTimer;
293306
bool mShouldReloadCurrentFeature = false;
294307
bool mExtraValueDoesNotExist = false;
295308
bool mAllowNull = false;
296309
bool mIsSettingExtraIdentifierValue = false;
297-
298-
//! The current index
299-
int mExtraValueIndex = -1;
300-
301310
};
302311

303312
#endif // QGSFEATUREFILTERMODELBASE_H

‎src/gui/qgsexpressionpreviewwidget.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ QgsExpressionPreviewWidget::QgsExpressionPreviewWidget( QWidget *parent )
2828
setupUi( this );
2929
mPreviewLabel->clear();
3030

31-
connect( mFeatureChooserWidget, &QgsFeaturePickerWidget::currentFeatureChanged, this, &QgsExpressionPreviewWidget::setCurrentFeature );
31+
connect( mFeatureChooserWidget, &QgsFeaturePickerWidget::featureChanged, this, &QgsExpressionPreviewWidget::setCurrentFeature );
3232
connect( mPreviewLabel, &QLabel::linkActivated, this, &QgsExpressionPreviewWidget::linkActivated );
3333
}
3434

‎src/gui/qgsfeaturelistcombobox.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ QgsFeatureListComboBox::QgsFeatureListComboBox( QWidget *parent )
4141
connect( mModel, &QgsFeatureFilterModel::allowNullChanged, this, &QgsFeatureListComboBox::allowNullChanged );
4242
connect( mModel, &QgsFeatureFilterModel::extraIdentifierValueChanged, this, &QgsFeatureListComboBox::identifierValueChanged );
4343
connect( mModel, &QgsFeatureFilterModel::extraIdentifierValueIndexChanged, this, &QgsFeatureListComboBox::setCurrentIndex );
44-
connect( mModel, &QgsFeatureFilterModel::identifierFieldChanged, this, &QgsFeatureListComboBox::identifierFieldChanged );
44+
connect( mModel, &QgsFeatureFilterModel::identifierFieldsChanged, this, &QgsFeatureListComboBox::identifierFieldChanged );
4545
connect( mCompleter, static_cast<void( QCompleter::* )( const QModelIndex & )>( &QCompleter::highlighted ), this, &QgsFeatureListComboBox::onItemSelected );
4646
connect( mCompleter, static_cast<void( QCompleter::* )( const QModelIndex & )>( &QCompleter::activated ), this, &QgsFeatureListComboBox::onActivated );
4747
connect( mModel, &QgsFeatureFilterModel::beginUpdate, this, &QgsFeatureListComboBox::storeLineEditState );
@@ -242,7 +242,7 @@ void QgsFeatureListComboBox::setAllowNull( bool allowNull )
242242
QVariant QgsFeatureListComboBox::identifierValue() const
243243
{
244244
Q_NOWARN_DEPRECATED_PUSH
245-
return mModel->extraIdentifierValue();
245+
return mModel->extraIdentifierValues().at( 0 );
246246
Q_NOWARN_DEPRECATED_POP
247247
}
248248

‎src/gui/qgsfeaturepickerwidget.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ QgsFeaturePickerWidget::QgsFeaturePickerWidget( QWidget *parent )
4141
connect( mModel, &QgsFeaturePickerModel::isLoadingChanged, this, &QgsFeaturePickerWidget::onLoadingChanged );
4242
connect( mModel, &QgsFeaturePickerModel::filterJobCompleted, this, &QgsFeaturePickerWidget::onFilterUpdateCompleted );
4343
connect( mModel, &QgsFeaturePickerModel::allowNullChanged, this, &QgsFeaturePickerWidget::allowNullChanged );
44-
connect( mModel, &QgsFeaturePickerModel::currentIndexChanged, mComboBox, &QComboBox::setCurrentIndex );
45-
connect( mModel, &QgsFeaturePickerModel::currentFeatureChanged, this, &QgsFeaturePickerWidget::currentFeatureChanged );
44+
connect( mModel, &QgsFeaturePickerModel::extraIdentifierValueIndexChanged, mComboBox, &QComboBox::setCurrentIndex );
45+
connect( mModel, &QgsFeaturePickerModel::featureChanged, this, &QgsFeaturePickerWidget::featureChanged );
4646
connect( mCompleter, static_cast<void( QCompleter::* )( const QModelIndex & )>( &QCompleter::highlighted ), this, &QgsFeaturePickerWidget::onItemSelected );
4747
connect( mCompleter, static_cast<void( QCompleter::* )( const QModelIndex & )>( &QCompleter::activated ), this, &QgsFeaturePickerWidget::onActivated );
4848
connect( mModel, &QgsFeaturePickerModel::beginUpdate, this, &QgsFeaturePickerWidget::storeLineEditState );
@@ -75,9 +75,9 @@ void QgsFeaturePickerWidget::setLayer( QgsVectorLayer *sourceLayer )
7575
mModel->setSourceLayer( sourceLayer );
7676
}
7777

78-
void QgsFeaturePickerWidget::setCurrentFeature( QgsFeatureId featureId )
78+
void QgsFeaturePickerWidget::setFeature( QgsFeatureId featureId )
7979
{
80-
mModel->setCurrentFeature( featureId );
80+
mModel->setFeature( featureId );
8181
}
8282

8383
QString QgsFeaturePickerWidget::displayExpression() const
@@ -119,8 +119,10 @@ void QgsFeaturePickerWidget::onCurrentIndexChanged( int i )
119119
{
120120
if ( !mHasStoredEditState )
121121
mIsCurrentlyEdited = false;
122+
if ( i < 0 )
123+
return;
122124
QModelIndex modelIndex = mModel->index( i, 0, QModelIndex() );
123-
mModel->setCurrentFeature( mModel->data( modelIndex, QgsFeaturePickerModel::FeatureIdRole ).value<QgsFeatureId>() );
125+
mModel->setFeature( mModel->data( modelIndex, QgsFeaturePickerModel::FeatureIdRole ).value<QgsFeatureId>() );
124126
mLineEdit->setText( mModel->data( modelIndex, QgsFeaturePickerModel::ValueRole ).toString() );
125127
mLineEdit->setFont( mModel->data( modelIndex, Qt::FontRole ).value<QFont>() );
126128
QPalette palette = mLineEdit->palette();
@@ -130,7 +132,7 @@ void QgsFeaturePickerWidget::onCurrentIndexChanged( int i )
130132

131133
void QgsFeaturePickerWidget::onActivated( QModelIndex modelIndex )
132134
{
133-
setCurrentFeature( mModel->data( modelIndex, QgsFeaturePickerModel::FeatureIdRole ).value<QgsFeatureId>() );
135+
setFeature( mModel->data( modelIndex, QgsFeaturePickerModel::FeatureIdRole ).value<QgsFeatureId>() );
134136
mLineEdit->setText( mModel->data( modelIndex, QgsFeaturePickerModel::ValueRole ).toString() );
135137
}
136138

@@ -169,7 +171,7 @@ void QgsFeaturePickerWidget::onDataChanged( const QModelIndex &topLeft, const QM
169171
Q_UNUSED( roles )
170172
if ( !mIsCurrentlyEdited )
171173
{
172-
const int currentIndex = mModel->currentIndex();
174+
const int currentIndex = mModel->extraIdentifierValueIndex();
173175
if ( currentIndex >= topLeft.row() && currentIndex <= bottomRight.row() )
174176
{
175177
QModelIndex modelIndex = mModel->index( currentIndex, 0, QModelIndex() );
@@ -180,7 +182,7 @@ void QgsFeaturePickerWidget::onDataChanged( const QModelIndex &topLeft, const QM
180182

181183
QModelIndex QgsFeaturePickerWidget::currentModelIndex() const
182184
{
183-
return mModel->index( mModel->currentIndex(), 0, QModelIndex() );
185+
return mModel->index( mModel->extraIdentifierValueIndex(), 0, QModelIndex() );
184186
}
185187

186188
void QgsFeaturePickerWidget::focusOutEvent( QFocusEvent *event )

‎src/gui/qgsfeaturepickerwidget.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ class GUI_EXPORT QgsFeaturePickerWidget : public QWidget
6868
/**
6969
* Sets the current index by using the given feature
7070
*/
71-
void setCurrentFeature( QgsFeatureId featureId );
71+
void setFeature( QgsFeatureId featureId );
7272

7373
/**
7474
* The display expression will be used to display features as well as
@@ -155,7 +155,7 @@ class GUI_EXPORT QgsFeaturePickerWidget : public QWidget
155155
void allowNullChanged();
156156

157157
//! Sends the feature as soon as it is chosen
158-
void currentFeatureChanged( const QgsFeature &feature );
158+
void featureChanged( const QgsFeature &feature );
159159

160160
private slots:
161161
void onCurrentTextChanged( const QString &text );

0 commit comments

Comments
 (0)
Please sign in to comment.