QGIS API Documentation 4.3.0-Master (bf28115e945)
Loading...
Searching...
No Matches
qgslistwidgetfactory.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgslistwidgetfactory.cpp
3 --------------------------------------
4 Date : 09.2016
5 Copyright : (C) 2016 Patrick Valsecchi
6 Email : patrick.valsecchi@camptocamp.com
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
17
19#include "qgsfields.h"
20#include "qgslistconfigdlg.h"
22#include "qgsvectorlayer.h"
23
24#include <QSettings>
25#include <QString>
26#include <QVariant>
27#include <qjsonarray.h>
28
29using namespace Qt::StringLiterals;
30
34
35QgsEditorWidgetWrapper *QgsListWidgetFactory::create( QgsVectorLayer *vl, int fieldIdx, QWidget *editor, QWidget *parent ) const
36{
37 return new QgsListWidgetWrapper( vl, fieldIdx, editor, parent );
38}
39
41{
42 return new QgsListConfigDlg( vl, fieldIdx, parent );
43}
44
45unsigned int QgsListWidgetFactory::fieldScore( const QgsVectorLayer *vl, int fieldIdx ) const
46{
47 const QgsField field = vl->fields().field( fieldIdx );
48 // Handle the json field
49 if ( field.typeName().compare( u"json"_s, Qt::CaseInsensitive ) == 0 || field.typeName().compare( u"jsonb"_s, Qt::CaseInsensitive ) == 0 )
50 {
51 // Look the first not-null value (limiting to the first 20 features) and check if it is really an array
52 const int MAX_FEATURE_LIMIT { 20 };
55 req.setSubsetOfAttributes( { fieldIdx } );
56 req.setLimit( MAX_FEATURE_LIMIT );
57 QgsFeature f;
58 QgsFeatureIterator featureIt { vl->getFeatures( req ) };
59 // The counter is an extra safety measure in case the provider does not respect the limit
60 int featureCount = 0;
61 bool foundNotNull = false;
62 bool foundInvalidValue = false; // An invalid value is any value that is not a JSON list or a list with nested or invalid values
63 while ( featureIt.nextFeature( f ) )
64 {
65 ++featureCount;
66 if ( featureCount > MAX_FEATURE_LIMIT )
67 {
68 break;
69 }
70 // Get attribute value and check if it is a valid JSON array
71 const QVariant value( f.attribute( fieldIdx ) );
72 if ( !value.isNull() )
73 {
74 foundNotNull = true;
75
76 // Read the list from a string or a list
77 QJsonArray jsonArray;
78 bool validArray = false;
79 if ( value.type() == QVariant::Type::List )
80 {
81 validArray = true;
82 jsonArray = QJsonArray::fromVariantList( value.toList() );
83 }
84 else
85 {
86 const QJsonDocument doc = QJsonDocument::fromJson( value.toString().toUtf8() );
87 if ( doc.isArray() )
88 {
89 validArray = true;
90 jsonArray = doc.array();
91 }
92 }
93
94 if ( validArray ) // empty array [] counts as valid as well
95 {
96 // It's a array(list), check the first 20 entries if flat (not nested)
97 int count = 0;
98 for ( auto it = jsonArray.begin(); it != jsonArray.end(); ++it )
99 {
100 if ( count >= 20 )
101 {
102 break;
103 }
104 count++;
105
106 QJsonValue childValue = *it;
107 if ( childValue.isObject() || childValue.isArray() || childValue.isUndefined() )
108 {
109 foundInvalidValue = true;
110 break;
111 }
112 }
113 if ( foundInvalidValue )
114 {
115 break;
116 }
117 }
118 else
119 {
120 // Stop when we find the first not-array
121 foundInvalidValue = true;
122 break;
123 }
124 }
125 }
126 if ( foundNotNull )
127 {
128 if ( !foundInvalidValue )
129 {
130 return 20;
131 }
132 else
133 {
134 return 5;
135 }
136 }
137 else
138 {
139 return 10;
140 }
141 }
142
143 return ( field.type() == QMetaType::Type::QVariantList || field.type() == QMetaType::Type::QStringList || field.type() == QMetaType::Type::QVariantMap )
144 && field.subType() != QMetaType::Type::UnknownType
145 ? 20
146 : 0;
147}
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Definition qgis.h:2343
Base class for widgets which configure editor widget types.
QgsEditorWidgetFactory(const QString &name, const QIcon &icon=QIcon())
Constructor.
QIcon icon() const
Returns the icon of this widget type.
QString name() const
Returns the human readable identifier name of this widget type.
Manages an editor widget.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
Wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setLimit(long long limit)
Set the maximum number of features to request.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:60
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Encapsulate a field in an attribute table or data source.
Definition qgsfield.h:56
QMetaType::Type type
Definition qgsfield.h:63
QString typeName() const
Gets the field type.
Definition qgsfield.cpp:158
QMetaType::Type subType() const
If the field is a collection, gets its element's type.
Definition qgsfield.cpp:153
QgsField field(int fieldIdx) const
Returns the field at particular index (must be in range 0..N-1).
A configuration dialog for the List Widget class.
unsigned int fieldScore(const QgsVectorLayer *vl, int fieldIdx) const override
This method allows disabling this editor widget type for a certain field.
QgsListWidgetFactory(const QString &name, const QIcon &icon=QIcon()=QIcon())
Constructor for QgsListWidgetFactory, where name is a human-readable name for the factory and icon pr...
QgsEditorConfigWidget * configWidget(QgsVectorLayer *vl, int fieldIdx, QWidget *parent) const override
Override this in your implementation.
QgsEditorWidgetWrapper * create(QgsVectorLayer *vl, int fieldIdx, QWidget *editor, QWidget *parent) const override
Override this in your implementation.
Wraps a list widget.
Represents a vector layer which manages a vector based dataset.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const final
Queries the layer for features specified in request.