QGIS API Documentation 4.3.0-Master (bf28115e945)
Loading...
Searching...
No Matches
qgskeyvaluewidgetfactory.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgskeyvaluewidgetfactory.cpp
3 --------------------------------------
4 Date : 08.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
18#include "qgsdummyconfigdlg.h"
19#include "qgsfields.h"
21#include "qgsvectorlayer.h"
22
23#include <QSettings>
24#include <QString>
25#include <QVariant>
26
27using namespace Qt::StringLiterals;
28
32
33QgsEditorWidgetWrapper *QgsKeyValueWidgetFactory::create( QgsVectorLayer *vl, int fieldIdx, QWidget *editor, QWidget *parent ) const
34{
35 return new QgsKeyValueWidgetWrapper( vl, fieldIdx, editor, parent );
36}
37
39{
40 Q_UNUSED( vl )
41 Q_UNUSED( fieldIdx )
42 Q_UNUSED( parent )
43 return new QgsDummyConfigDlg( vl, fieldIdx, parent, QObject::tr( "Key/Value field" ) );
44}
45
46unsigned int QgsKeyValueWidgetFactory::fieldScore( const QgsVectorLayer *vl, int fieldIdx ) const
47{
48 const QgsField field = vl->fields().field( fieldIdx );
49 // Handle the json field
50 if ( field.typeName().compare( u"json"_s, Qt::CaseInsensitive ) == 0 || field.typeName().compare( u"jsonb"_s, Qt::CaseInsensitive ) == 0 )
51 {
52 // Look for the values in the first 20 features check if it contains only maps
53 const int MAX_FEATURE_LIMIT { 20 };
56 req.setSubsetOfAttributes( { fieldIdx } );
57 req.setLimit( MAX_FEATURE_LIMIT );
58 QgsFeature f;
59 QgsFeatureIterator featureIt { vl->getFeatures( req ) };
60 // The counter is an extra safety measure in case the provider does not respect the limit
61 int featureCount = 0;
62 bool foundNotNull = false;
63 bool foundInvalidValue = false; // An invalid value is any value that is not a JSON object (map) or an object with nested or invalid values
64 while ( featureIt.nextFeature( f ) )
65 {
66 ++featureCount;
67 if ( featureCount > MAX_FEATURE_LIMIT )
68 {
69 break;
70 }
71 // Get attribute value and check if it is a valid JSON object
72 const QVariant value( f.attribute( fieldIdx ) );
73 if ( !value.isNull() )
74 {
75 foundNotNull = true;
76
77 // Read the object from string or map
78 QJsonObject jsonObject;
79 bool validObject = false;
80 if ( value.type() == QVariant::Type::Map )
81 {
82 validObject = true;
83 jsonObject = QJsonObject::fromVariantMap( value.toMap() );
84 }
85 else
86 {
87 const QJsonDocument doc = QJsonDocument::fromJson( value.toString().toUtf8() );
88 if ( doc.isObject() )
89 {
90 validObject = true;
91 jsonObject = doc.object();
92 }
93 }
94 if ( validObject ) // empty object {} counts as valid as well
95 {
96 // It's a map, check the first 20 entries if flat (not nested)
97 int count = 0;
98 for ( auto it = jsonObject.begin(); it != jsonObject.end(); ++it )
99 {
100 if ( count >= 20 )
101 {
102 break;
103 }
104 count++;
105 const QJsonValue childValue = it.value();
106 if ( childValue.isObject() || childValue.isArray() || childValue.isUndefined() )
107 {
108 // Stop when we find the first nested object
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 non-map value
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::QVariantMap && field.subType() != QMetaType::Type::UnknownType ? 20 : 0;
144}
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Definition qgis.h:2343
Configuration widget for dummy widgets.
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).
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.
unsigned int fieldScore(const QgsVectorLayer *vl, int fieldIdx) const override
This method allows disabling this editor widget type for a certain field.
QgsKeyValueWidgetFactory(const QString &name, const QIcon &icon=QIcon())
Constructor for QgsKeyValueWidgetFactory, where name is a human-readable name for the factory and ico...
Wraps a key/value 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.