QGIS API Documentation 3.43.0-Master (0cdc48caa8d)
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
172bool QgsEditorWidgetRegistry::isReadOnly( const QString &widgetId )
173{
174 if ( mWidgetFactories.contains( widgetId ) )
175 {
176 return mWidgetFactories[widgetId]->isReadOnly();
177 }
178
179 return false;
180}
181
182QMap<QString, QgsEditorWidgetFactory *> QgsEditorWidgetRegistry::factories()
183{
184 return mWidgetFactories;
185}
186
188{
189 return mWidgetFactories.value( widgetId, mFallbackWidgetFactory.get() );
190}
191
192bool QgsEditorWidgetRegistry::registerWidget( const QString &widgetId, QgsEditorWidgetFactory *widgetFactory )
193{
194 if ( !widgetFactory )
195 {
196 QgsMessageLog::logMessage( tr( "QgsEditorWidgetRegistry: Factory not valid." ) );
197 return false;
198 }
199 else if ( mWidgetFactories.contains( widgetId ) )
200 {
201 QgsMessageLog::logMessage( tr( "QgsEditorWidgetRegistry: Factory with id %1 already registered." ).arg( widgetId ) );
202 return false;
203 }
204 else
205 {
206 mWidgetFactories.insert( widgetId, widgetFactory );
207
208 // Use this factory as default where it provides the highest priority
209 const QHash<const char *, int> types = widgetFactory->supportedWidgetTypes();
210 QHash<const char *, int>::ConstIterator it;
211 it = types.constBegin();
212
213 for ( ; it != types.constEnd(); ++it )
214 {
215 if ( it.value() > mFactoriesByType[it.key()].first )
216 {
217 mFactoriesByType[it.key()] = qMakePair( it.value(), widgetId );
218 }
219 }
220
221 return true;
222 }
223}
224
225QString QgsEditorWidgetRegistry::findSuitableWrapper( QWidget *editor, const QString &defaultWidget )
226{
227 QMap<const char *, QPair<int, QString>>::ConstIterator it;
228
229 QString widgetid;
230
231 // Editor can be null
232 if ( editor )
233 {
234 int weight = 0;
235
236 it = mFactoriesByType.constBegin();
237 for ( ; it != mFactoriesByType.constEnd(); ++it )
238 {
239 if ( QWidget::staticMetaObject.className() == it.key() )
240 {
241 // if it's a perfect match: return it directly
242 return it.value().second;
243 }
244 else if ( editor->inherits( it.key() ) )
245 {
246 // if it's a subclass, continue evaluating, maybe we find a more-specific or one with more weight
247 if ( it.value().first > weight )
248 {
249 weight = it.value().first;
250 widgetid = it.value().second;
251 }
252 }
253 }
254 }
255
256 if ( widgetid.isNull() )
257 widgetid = defaultWidget;
258 return widgetid;
259}
Contains context information for attribute editor widgets.
Editor widget factory for binary (BLOB) widgets.
Editor widget factory for checkbox widgets.
Editor widget factory for classification widgets.
Factory for creation of color widgets.
Editor widget factory for datetime widgets.
Base class for widgets which configure editor widget types.
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.
bool isReadOnly(const QString &widgetId)
Gets the widget's read-only flag.
~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.
QString type() const
Returns the widget type to use.
QVariantMap config() const
Returns the widget configuration.
bool isNull() const
Returns true if there is no widget configured.
Manages an editor widget.
Editor widget factory for enum widgets.
Editor widget factory for external resource widgets.
QString name
Definition qgsfield.h:62
QgsEditorWidgetSetup editorWidgetSetup() const
Gets the editor widget setup for the field.
Definition qgsfield.cpp:746
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 hidden 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, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
Adds a message to the log instance (and creates it if necessary).
Editor widget factory for range widgets.
Editor widget factory for relation reference widgets.
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.
Editor widget factory for text editor widgets.
Editor widget factory for unique value widgets.
Editor widget factory for UUID widgets.
Editor widget factory for value map widgets.
Editor widget factory for value relation widgets.
Represents a vector layer which manages a vector based dataset.
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.