1 /***************************************************************************
2   qgsfeaturefiltermodel.cpp - QgsFeatureFilterModel
3  ---------------------
4  begin                : 10.3.2017
5  copyright            : (C) 2017 by Matthias Kuhn
6  email                : matthias@opengis.ch
7  ***************************************************************************
8  *                                                                         *
9  *   This program is free software; you can redistribute it and/or modify  *
10  *   it under the terms of the GNU General Public License as published by  *
11  *   the Free Software Foundation; either version 2 of the License, or     *
12  *   (at your option) any later version.                                   *
13  *                                                                         *
14  ***************************************************************************/
15 #include "qgsfeaturefiltermodel.h"
16 #include "qgsfeatureexpressionvaluesgatherer.h"
17 
18 #include "qgsvectorlayer.h"
19 #include "qgsconditionalstyle.h"
20 #include "qgsapplication.h"
21 #include "qgssettings.h"
22 
23 
qVariantListCompare(const QVariantList & a,const QVariantList & b)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 
QgsFeatureFilterModel(QObject * parent)38 QgsFeatureFilterModel::QgsFeatureFilterModel( QObject *parent )
39   : QgsFeaturePickerModelBase( parent )
40 {
41   setFetchGeometry( false );
42   setFetchLimit( QgsSettings().value( QStringLiteral( "maxEntriesRelationWidget" ), 100, QgsSettings::Gui ).toInt() );
43   setExtraIdentifierValueUnguarded( nullIdentifier() );
44 }
45 
identifierField() const46 QString QgsFeatureFilterModel::identifierField() const
47 {
48   return mIdentifierFields.value( 0 );
49 }
50 
requestToReloadCurrentFeature(QgsFeatureRequest & request)51 void QgsFeatureFilterModel::requestToReloadCurrentFeature( QgsFeatureRequest &request )
52 {
53   QStringList conditions;
54   for ( int i = 0; i < mIdentifierFields.count(); i++ )
55   {
56     if ( i >= mExtraIdentifierValue.toList().count() )
57     {
58       conditions << QgsExpression::createFieldEqualityExpression( mIdentifierFields.at( i ), QVariant() );
59     }
60     else
61     {
62       conditions << QgsExpression::createFieldEqualityExpression( mIdentifierFields.at( i ), mExtraIdentifierValue.toList().at( i ) );
63     }
64   }
65   request.setFilterExpression( conditions.join( QLatin1String( " AND " ) ) );
66 }
67 
requestedAttributes() const68 QSet<QString> QgsFeatureFilterModel::requestedAttributes() const
69 {
70   return qgis::listToSet( mIdentifierFields );
71 }
72 
entryIdentifier(const QgsFeatureExpressionValuesGatherer::Entry & entry) const73 QVariant QgsFeatureFilterModel::entryIdentifier( const QgsFeatureExpressionValuesGatherer::Entry &entry ) const
74 {
75   return entry.featureId;
76 }
77 
createEntry(const QVariant & identifier) const78 QgsFeatureExpressionValuesGatherer::Entry QgsFeatureFilterModel::createEntry( const QVariant &identifier ) const
79 {
80   const QVariantList constValues = identifier.toList();
81 
82   QStringList values;
83   for ( const QVariant &v : constValues )
84     values << QStringLiteral( "(%1)" ).arg( v.toString() );
85 
86   return QgsFeatureExpressionValuesGatherer::Entry( constValues, values.join( QLatin1Char( ' ' ) ), QgsFeature( sourceLayer() ? sourceLayer()->fields() : QgsFields() ) );
87 }
88 
compareEntries(const QgsFeatureExpressionValuesGatherer::Entry & a,const QgsFeatureExpressionValuesGatherer::Entry & b) const89 bool QgsFeatureFilterModel::compareEntries( const QgsFeatureExpressionValuesGatherer::Entry &a, const QgsFeatureExpressionValuesGatherer::Entry &b ) const
90 {
91   return qVariantListCompare( a.identifierFields, b.identifierFields );
92 }
93 
identifierIsNull(const QVariant & identifier) const94 bool QgsFeatureFilterModel::identifierIsNull( const QVariant &identifier ) const
95 {
96   const QVariantList values = identifier.toList();
97   for ( const QVariant &value : values )
98   {
99     if ( !value.isNull() )
100     {
101       return false;
102     }
103   }
104   return true;
105 }
106 
nullIdentifier() const107 QVariant QgsFeatureFilterModel::nullIdentifier() const
108 {
109   QVariantList nullValues;
110   for ( int i = 0; i < mIdentifierFields.count(); i++ )
111     nullValues << QVariant( QVariant::Int );
112   return nullValues;
113 }
114 
identifierFields() const115 QStringList QgsFeatureFilterModel::identifierFields() const
116 {
117   return mIdentifierFields;
118 }
119 
120 
setIdentifierFields(const QStringList & identifierFields)121 void QgsFeatureFilterModel::setIdentifierFields( const QStringList &identifierFields )
122 {
123   if ( mIdentifierFields == identifierFields )
124     return;
125 
126   mIdentifierFields = identifierFields;
127   emit identifierFieldsChanged();
128   setExtraIdentifierValueToNull();
129 }
130 
createValuesGatherer(const QgsFeatureRequest & request) const131 QgsFeatureExpressionValuesGatherer *QgsFeatureFilterModel::createValuesGatherer( const QgsFeatureRequest &request ) const
132 {
133   return new QgsFeatureExpressionValuesGatherer( sourceLayer(), displayExpression(), request, mIdentifierFields );
134 }
135 
136 
extraIdentifierValues() const137 QVariantList QgsFeatureFilterModel::extraIdentifierValues() const
138 {
139   QVariantList values = mExtraIdentifierValue.toList();
140   if ( values.count() != mIdentifierFields.count() )
141   {
142     return nullIdentifier().toList();
143   }
144   return values;
145 }
146 
setExtraIdentifierValues(const QVariantList & extraIdentifierValues)147 void QgsFeatureFilterModel::setExtraIdentifierValues( const QVariantList &extraIdentifierValues )
148 {
149   setExtraIdentifierValue( extraIdentifierValues );
150 }
151 
setExtraIdentifierValueToNull()152 void QgsFeatureFilterModel::setExtraIdentifierValueToNull()
153 {
154   setExtraIdentifierValue( nullIdentifier() );
155 }
156 
157