QGIS API Documentation 3.41.0-Master (af5edcb665c)
Loading...
Searching...
No Matches
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#include "moc_qgseditorwidgetregistry.cpp"
18
20#include "qgsmessagelog.h"
21#include "qgsproject.h"
22#include "qgsvectorlayer.h"
25#include "qgsapplication.h"
26
27// Editors
47
49{
50 mFallbackWidgetFactory.reset( new QgsTextEditWidgetFactory( tr( "Text Edit" ) ) );
51}
52
54{
55 registerWidget( QStringLiteral( "TextEdit" ), new QgsTextEditWidgetFactory( tr( "Text Edit" ) ) );
56 registerWidget( QStringLiteral( "Classification" ), new QgsClassificationWidgetWrapperFactory( tr( "Classification" ) ) );
57 registerWidget( QStringLiteral( "Range" ), new QgsRangeWidgetFactory( tr( "Range" ) ) );
58 registerWidget( QStringLiteral( "UniqueValues" ), new QgsUniqueValueWidgetFactory( tr( "Unique Values" ) ) );
59 registerWidget( QStringLiteral( "ValueMap" ), new QgsValueMapWidgetFactory( tr( "Value Map" ) ) );
60 registerWidget( QStringLiteral( "Enumeration" ), new QgsEnumerationWidgetFactory( tr( "Enumeration" ) ) );
61 registerWidget( QStringLiteral( "Hidden" ), new QgsHiddenWidgetFactory( tr( "Hidden" ) ) );
62 registerWidget( QStringLiteral( "CheckBox" ), new QgsCheckboxWidgetFactory( tr( "Checkbox" ) ) );
63 registerWidget( QStringLiteral( "ValueRelation" ), new QgsValueRelationWidgetFactory( tr( "Value Relation" ) ) );
64 registerWidget( QStringLiteral( "UuidGenerator" ), new QgsUuidWidgetFactory( tr( "Uuid Generator" ) ) );
65 registerWidget( QStringLiteral( "Color" ), new QgsColorWidgetFactory( tr( "Color" ) ) );
66 registerWidget( QStringLiteral( "RelationReference" ), new QgsRelationReferenceFactory( tr( "Relation Reference" ), mapCanvas, messageBar ) );
67 registerWidget( QStringLiteral( "DateTime" ), new QgsDateTimeEditFactory( tr( "Date/Time" ) ) );
68 registerWidget( QStringLiteral( "ExternalResource" ), new QgsExternalResourceWidgetFactory( tr( "Attachment" ), messageBar ) );
69 registerWidget( QStringLiteral( "KeyValue" ), new QgsKeyValueWidgetFactory( tr( "Key/Value" ) ) );
70 registerWidget( QStringLiteral( "List" ), new QgsListWidgetFactory( tr( "List" ) ) );
71 registerWidget( QStringLiteral( "Binary" ), new QgsBinaryWidgetFactory( tr( "Binary (BLOB)" ), messageBar ) );
72 registerWidget( QStringLiteral( "JsonEdit" ), new QgsJsonEditWidgetFactory( tr( "Json View" ) ) );
73 registerWidget( QStringLiteral( "Geometry" ), new QgsGeometryWidgetFactory( tr( "Geometry" ), messageBar ) );
74}
75
77{
78 qDeleteAll( mWidgetFactories );
79}
80
81QgsEditorWidgetSetup QgsEditorWidgetRegistry::findBest( const QgsVectorLayer *vl, const QString &fieldName ) const
82{
83 const QgsFields fields = vl->fields();
84 const int index = fields.indexOf( fieldName );
85
86 if ( index > -1 )
87 {
88 QgsEditorWidgetSetup setup = fields.at( index ).editorWidgetSetup();
89 if ( !setup.isNull() )
90 return setup;
91 }
92 return mAutoConf.editorWidgetSetup( vl, fieldName );
93}
94
95QgsEditorWidgetWrapper *QgsEditorWidgetRegistry::create( QgsVectorLayer *vl, int fieldIdx, QWidget *editor, QWidget *parent, const QgsAttributeEditorContext &context )
96{
97 const QString fieldName = vl->fields().field( fieldIdx ).name();
98 const QgsEditorWidgetSetup setup = findBest( vl, fieldName );
99 return create( setup.type(), vl, fieldIdx, setup.config(), editor, parent, context );
100}
101
102QgsEditorWidgetWrapper *QgsEditorWidgetRegistry::create( const QString &widgetId, QgsVectorLayer *vl, int fieldIdx, const QVariantMap &config, QWidget *editor, QWidget *parent, const QgsAttributeEditorContext &context )
103{
104 if ( mWidgetFactories.contains( widgetId ) )
105 {
106 QgsEditorWidgetWrapper *ww = mWidgetFactories[widgetId]->create( vl, fieldIdx, editor, parent );
107
108 if ( ww )
109 {
110 ww->setConfig( config );
111 ww->setContext( context );
112 // Make sure that there is a widget created at this point
113 // so setValue() et al won't crash
114 ww->widget();
115
116 // If we tried to set a widget which is not supported by this wrapper
117 if ( !ww->valid() )
118 {
119 delete ww;
120 const QString wid = findSuitableWrapper( editor, QStringLiteral( "TextEdit" ) );
121 ww = mWidgetFactories[wid]->create( vl, fieldIdx, editor, parent );
122 ww->setConfig( config );
123 ww->setContext( context );
124 }
125
126 return ww;
127 }
128 }
129
130 return nullptr;
131}
132
133QgsSearchWidgetWrapper *QgsEditorWidgetRegistry::createSearchWidget( const QString &widgetId, QgsVectorLayer *vl, int fieldIdx, const QVariantMap &config, QWidget *parent, const QgsAttributeEditorContext &context )
134{
135 if ( mWidgetFactories.contains( widgetId ) )
136 {
137 QgsSearchWidgetWrapper *ww = mWidgetFactories[widgetId]->createSearchWidget( vl, fieldIdx, parent );
138
139 if ( ww )
140 {
141 ww->setConfig( config );
142 ww->setContext( context );
143 // Make sure that there is a widget created at this point
144 // so setValue() et al won't crash
145 ww->widget();
146 ww->clearWidget();
147 return ww;
148 }
149 }
150 return nullptr;
151}
152
153QgsEditorConfigWidget *QgsEditorWidgetRegistry::createConfigWidget( const QString &widgetId, QgsVectorLayer *vl, int fieldIdx, QWidget *parent )
154{
155 if ( mWidgetFactories.contains( widgetId ) )
156 {
157 return mWidgetFactories[widgetId]->configWidget( vl, fieldIdx, parent );
158 }
159 return nullptr;
160}
161
162QString QgsEditorWidgetRegistry::name( const QString &widgetId )
163{
164 if ( mWidgetFactories.contains( widgetId ) )
165 {
166 return mWidgetFactories[widgetId]->name();
167 }
168
169 return QString();
170}
171
172QMap<QString, QgsEditorWidgetFactory *> QgsEditorWidgetRegistry::factories()
173{
174 return mWidgetFactories;
175}
176
178{
179 return mWidgetFactories.value( widgetId, mFallbackWidgetFactory.get() );
180}
181
182bool QgsEditorWidgetRegistry::registerWidget( const QString &widgetId, QgsEditorWidgetFactory *widgetFactory )
183{
184 if ( !widgetFactory )
185 {
186 QgsMessageLog::logMessage( tr( "QgsEditorWidgetRegistry: Factory not valid." ) );
187 return false;
188 }
189 else if ( mWidgetFactories.contains( widgetId ) )
190 {
191 QgsMessageLog::logMessage( tr( "QgsEditorWidgetRegistry: Factory with id %1 already registered." ).arg( widgetId ) );
192 return false;
193 }
194 else
195 {
196 mWidgetFactories.insert( widgetId, widgetFactory );
197
198 // Use this factory as default where it provides the highest priority
199 const QHash<const char *, int> types = widgetFactory->supportedWidgetTypes();
200 QHash<const char *, int>::ConstIterator it;
201 it = types.constBegin();
202
203 for ( ; it != types.constEnd(); ++it )
204 {
205 if ( it.value() > mFactoriesByType[it.key()].first )
206 {
207 mFactoriesByType[it.key()] = qMakePair( it.value(), widgetId );
208 }
209 }
210
211 return true;
212 }
213}
214
215QString QgsEditorWidgetRegistry::findSuitableWrapper( QWidget *editor, const QString &defaultWidget )
216{
217 QMap<const char *, QPair<int, QString>>::ConstIterator it;
218
219 QString widgetid;
220
221 // Editor can be null
222 if ( editor )
223 {
224 int weight = 0;
225
226 it = mFactoriesByType.constBegin();
227 for ( ; it != mFactoriesByType.constEnd(); ++it )
228 {
229 if ( QWidget::staticMetaObject.className() == it.key() )
230 {
231 // if it's a perfect match: return it directly
232 return it.value().second;
233 }
234 else if ( editor->inherits( it.key() ) )
235 {
236 // if it's a subclass, continue evaluating, maybe we find a more-specific or one with more weight
237 if ( it.value().first > weight )
238 {
239 weight = it.value().first;
240 widgetid = it.value().second;
241 }
242 }
243 }
244 }
245
246 if ( widgetid.isNull() )
247 widgetid = defaultWidget;
248 return widgetid;
249}
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:740
Container of fields for a vector layer.
Definition qgsfields.h:46
Q_INVOKABLE int indexOf(const QString &fieldName) const
Gets the field index from the field name.
QgsField field(int fieldIdx) const
Returns the field at particular index (must be in range 0..N-1).
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
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.
A bar for displaying non-blocking messages to the user.
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.
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.