QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
qgseditorwidgetregistry.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgseditorwidgetregistry.cpp
3 --------------------------------------
4 Date : 24.4.2013
5 Copyright : (C) 2013 Matthias Kuhn
6 Email : matthias at opengis dot 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
17
19#include "qgsmessagelog.h"
20#include "qgsproject.h"
21#include "qgsvectorlayer.h"
24#include "qgsapplication.h"
25
26// Editors
46
48{
49 mFallbackWidgetFactory.reset( new QgsTextEditWidgetFactory( tr( "Text Edit" ) ) );
50}
51
53{
54 registerWidget( QStringLiteral( "TextEdit" ), new QgsTextEditWidgetFactory( tr( "Text Edit" ) ) );
55 registerWidget( QStringLiteral( "Classification" ), new QgsClassificationWidgetWrapperFactory( tr( "Classification" ) ) );
56 registerWidget( QStringLiteral( "Range" ), new QgsRangeWidgetFactory( tr( "Range" ) ) );
57 registerWidget( QStringLiteral( "UniqueValues" ), new QgsUniqueValueWidgetFactory( tr( "Unique Values" ) ) );
58 registerWidget( QStringLiteral( "ValueMap" ), new QgsValueMapWidgetFactory( tr( "Value Map" ) ) );
59 registerWidget( QStringLiteral( "Enumeration" ), new QgsEnumerationWidgetFactory( tr( "Enumeration" ) ) );
60 registerWidget( QStringLiteral( "Hidden" ), new QgsHiddenWidgetFactory( tr( "Hidden" ) ) );
61 registerWidget( QStringLiteral( "CheckBox" ), new QgsCheckboxWidgetFactory( tr( "Checkbox" ) ) );
62 registerWidget( QStringLiteral( "ValueRelation" ), new QgsValueRelationWidgetFactory( tr( "Value Relation" ) ) );
63 registerWidget( QStringLiteral( "UuidGenerator" ), new QgsUuidWidgetFactory( tr( "Uuid Generator" ) ) );
64 registerWidget( QStringLiteral( "Color" ), new QgsColorWidgetFactory( tr( "Color" ) ) );
65 registerWidget( QStringLiteral( "RelationReference" ), new QgsRelationReferenceFactory( tr( "Relation Reference" ), mapCanvas, messageBar ) );
66 registerWidget( QStringLiteral( "DateTime" ), new QgsDateTimeEditFactory( tr( "Date/Time" ) ) );
67 registerWidget( QStringLiteral( "ExternalResource" ), new QgsExternalResourceWidgetFactory( tr( "Attachment" ), messageBar ) );
68 registerWidget( QStringLiteral( "KeyValue" ), new QgsKeyValueWidgetFactory( tr( "Key/Value" ) ) );
69 registerWidget( QStringLiteral( "List" ), new QgsListWidgetFactory( tr( "List" ) ) );
70 registerWidget( QStringLiteral( "Binary" ), new QgsBinaryWidgetFactory( tr( "Binary (BLOB)" ), messageBar ) );
71 registerWidget( QStringLiteral( "JsonEdit" ), new QgsJsonEditWidgetFactory( tr( "Json View" ) ) );
72 registerWidget( QStringLiteral( "Geometry" ), new QgsGeometryWidgetFactory( tr( "Geometry" ), messageBar ) );
73}
74
76{
77 qDeleteAll( mWidgetFactories );
78}
79
80QgsEditorWidgetSetup QgsEditorWidgetRegistry::findBest( const QgsVectorLayer *vl, const QString &fieldName ) const
81{
82 const QgsFields fields = vl->fields();
83 const int index = fields.indexOf( fieldName );
84
85 if ( index > -1 )
86 {
87 QgsEditorWidgetSetup setup = fields.at( index ).editorWidgetSetup();
88 if ( !setup.isNull() )
89 return setup;
90 }
91 return mAutoConf.editorWidgetSetup( vl, fieldName );
92}
93
94QgsEditorWidgetWrapper *QgsEditorWidgetRegistry::create( QgsVectorLayer *vl, int fieldIdx, QWidget *editor, QWidget *parent, const QgsAttributeEditorContext &context )
95{
96 const QString fieldName = vl->fields().field( fieldIdx ).name();
97 const QgsEditorWidgetSetup setup = findBest( vl, fieldName );
98 return create( setup.type(), vl, fieldIdx, setup.config(), editor, parent, context );
99}
100
101QgsEditorWidgetWrapper *QgsEditorWidgetRegistry::create( const QString &widgetId, QgsVectorLayer *vl, int fieldIdx, const QVariantMap &config, QWidget *editor, QWidget *parent, const QgsAttributeEditorContext &context )
102{
103 if ( mWidgetFactories.contains( widgetId ) )
104 {
105 QgsEditorWidgetWrapper *ww = mWidgetFactories[widgetId]->create( vl, fieldIdx, editor, parent );
106
107 if ( ww )
108 {
109 ww->setConfig( config );
110 ww->setContext( context );
111 // Make sure that there is a widget created at this point
112 // so setValue() et al won't crash
113 ww->widget();
114
115 // If we tried to set a widget which is not supported by this wrapper
116 if ( !ww->valid() )
117 {
118 delete ww;
119 const QString wid = findSuitableWrapper( editor, QStringLiteral( "TextEdit" ) );
120 ww = mWidgetFactories[wid]->create( vl, fieldIdx, editor, parent );
121 ww->setConfig( config );
122 ww->setContext( context );
123 }
124
125 return ww;
126 }
127 }
128
129 return nullptr;
130}
131
132QgsSearchWidgetWrapper *QgsEditorWidgetRegistry::createSearchWidget( const QString &widgetId, QgsVectorLayer *vl, int fieldIdx, const QVariantMap &config, QWidget *parent, const QgsAttributeEditorContext &context )
133{
134 if ( mWidgetFactories.contains( widgetId ) )
135 {
136 QgsSearchWidgetWrapper *ww = mWidgetFactories[widgetId]->createSearchWidget( vl, fieldIdx, parent );
137
138 if ( ww )
139 {
140 ww->setConfig( config );
141 ww->setContext( context );
142 // Make sure that there is a widget created at this point
143 // so setValue() et al won't crash
144 ww->widget();
145 ww->clearWidget();
146 return ww;
147 }
148 }
149 return nullptr;
150}
151
152QgsEditorConfigWidget *QgsEditorWidgetRegistry::createConfigWidget( const QString &widgetId, QgsVectorLayer *vl, int fieldIdx, QWidget *parent )
153{
154 if ( mWidgetFactories.contains( widgetId ) )
155 {
156 return mWidgetFactories[widgetId]->configWidget( vl, fieldIdx, parent );
157 }
158 return nullptr;
159}
160
161QString QgsEditorWidgetRegistry::name( const QString &widgetId )
162{
163 if ( mWidgetFactories.contains( widgetId ) )
164 {
165 return mWidgetFactories[widgetId]->name();
166 }
167
168 return QString();
169}
170
171QMap<QString, QgsEditorWidgetFactory *> QgsEditorWidgetRegistry::factories()
172{
173 return mWidgetFactories;
174}
175
177{
178 return mWidgetFactories.value( widgetId, mFallbackWidgetFactory.get() );
179}
180
181bool QgsEditorWidgetRegistry::registerWidget( const QString &widgetId, QgsEditorWidgetFactory *widgetFactory )
182{
183 if ( !widgetFactory )
184 {
185 QgsMessageLog::logMessage( tr( "QgsEditorWidgetRegistry: Factory not valid." ) );
186 return false;
187 }
188 else if ( mWidgetFactories.contains( widgetId ) )
189 {
190 QgsMessageLog::logMessage( tr( "QgsEditorWidgetRegistry: Factory with id %1 already registered." ).arg( widgetId ) );
191 return false;
192 }
193 else
194 {
195 mWidgetFactories.insert( widgetId, widgetFactory );
196
197 // Use this factory as default where it provides the highest priority
198 const QHash<const char *, int> types = widgetFactory->supportedWidgetTypes();
199 QHash<const char *, int>::ConstIterator it;
200 it = types.constBegin();
201
202 for ( ; it != types.constEnd(); ++it )
203 {
204 if ( it.value() > mFactoriesByType[it.key()].first )
205 {
206 mFactoriesByType[it.key()] = qMakePair( it.value(), widgetId );
207 }
208 }
209
210 return true;
211 }
212}
213
214QString QgsEditorWidgetRegistry::findSuitableWrapper( QWidget *editor, const QString &defaultWidget )
215{
216 QMap<const char *, QPair<int, QString> >::ConstIterator it;
217
218 QString widgetid;
219
220 // Editor can be null
221 if ( editor )
222 {
223 int weight = 0;
224
225 it = mFactoriesByType.constBegin();
226 for ( ; it != mFactoriesByType.constEnd(); ++it )
227 {
228 if ( QWidget::staticMetaObject.className() == it.key() )
229 {
230 // if it's a perfect match: return it directly
231 return it.value().second;
232 }
233 else if ( editor->inherits( it.key() ) )
234 {
235 // if it's a subclass, continue evaluating, maybe we find a more-specific or one with more weight
236 if ( it.value().first > weight )
237 {
238 weight = it.value().first;
239 widgetid = it.value().second;
240 }
241 }
242 }
243 }
244
245 if ( widgetid.isNull() )
246 widgetid = defaultWidget;
247 return widgetid;
248}
This class contains context information for attribute editor widgets.
Editor widget factory for binary (BLOB) widgets.
This class should be subclassed for every configurable editor widget type.
Every attribute editor widget needs a factory, which inherits this class.
virtual QHash< const char *, int > supportedWidgetTypes()
Returns a list of widget types which this editor widget supports.
~QgsEditorWidgetRegistry() override
Destructor.
QString name(const QString &widgetId)
Gets the human readable name for a widget type.
QgsEditorConfigWidget * createConfigWidget(const QString &widgetId, QgsVectorLayer *vl, int fieldIdx, QWidget *parent)
Creates a configuration widget.
QMap< QString, QgsEditorWidgetFactory * > factories()
Gets access to all registered factories.
void initEditors(QgsMapCanvas *mapCanvas=nullptr, QgsMessageBar *messageBar=nullptr)
Registers all the default widgets.
QgsEditorWidgetSetup findBest(const QgsVectorLayer *vl, const QString &fieldName) const
Find the best editor widget and its configuration for a given field.
QgsEditorWidgetWrapper * create(const QString &widgetId, QgsVectorLayer *vl, int fieldIdx, const QVariantMap &config, QWidget *editor, QWidget *parent, const QgsAttributeEditorContext &context=QgsAttributeEditorContext())
Create an attribute editor widget wrapper of a given type for a given field.
QgsEditorWidgetFactory * factory(const QString &widgetId)
Gets a factory for the given widget type id.
QgsSearchWidgetWrapper * createSearchWidget(const QString &widgetId, QgsVectorLayer *vl, int fieldIdx, const QVariantMap &config, QWidget *parent, const QgsAttributeEditorContext &context=QgsAttributeEditorContext())
QgsEditorWidgetRegistry()
Constructor for QgsEditorWidgetRegistry.
bool registerWidget(const QString &widgetId, QgsEditorWidgetFactory *widgetFactory)
Register a new widget factory with the given id.
Holder for the widget type and its configuration for a field.
QVariantMap config() const
Manages an editor widget Widget and wrapper share the same parent.
QString name
Definition: qgsfield.h:62
QgsEditorWidgetSetup editorWidgetSetup() const
Gets the editor widget setup for the field.
Definition: qgsfield.cpp:714
Container of fields for a vector layer.
Definition: qgsfields.h:45
int indexOf(const QString &fieldName) const
Gets the field index from the field name.
Definition: qgsfields.cpp:207
QgsField field(int fieldIdx) const
Returns the field at particular index (must be in range 0..N-1).
Definition: qgsfields.cpp:168
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Definition: qgsfields.cpp:163
Editor widget factory for geometry widgets.
Editor widget factory for JSON edit widgets.
Factory for widgets for editing a QVariantMap.
Factory for widgets for editing a QVariantList or a QStringList.
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:93
A bar for displaying non-blocking messages to the user.
Definition: qgsmessagebar.h:61
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Shows a search widget on a filter form.
virtual void clearWidget()
Clears the widget's current value and resets it back to the default state.
Represents a vector layer which manages a vector based data sets.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
virtual bool valid() const =0
Returns true if the widget has been properly initialized.
QWidget * widget()
Access the widget managed by this wrapper.
void setConfig(const QVariantMap &config)
Will set the config of this wrapper to the specified config.
void setContext(const QgsAttributeEditorContext &context)
Set the context in which this widget is shown.