QGIS API Documentation 3.99.0-Master (d270888f95f)
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
18#include <memory>
19
20#include "qgsapplication.h"
23#include "qgsmessagelog.h"
24#include "qgsproject.h"
26#include "qgsvectorlayer.h"
27
28#include <QString>
29
30#include "moc_qgseditorwidgetregistry.cpp"
31
32using namespace Qt::StringLiterals;
33
34// Editors
54
56{
57 mFallbackWidgetFactory = std::make_unique<QgsTextEditWidgetFactory>( tr( "Text Edit" ) );
58}
59
61{
62 registerWidget( u"TextEdit"_s, new QgsTextEditWidgetFactory( tr( "Text Edit" ), QgsApplication::getThemeIcon( u"/mEditorWidgetTextEdit.svg"_s ) ) );
63 registerWidget( u"Classification"_s, new QgsClassificationWidgetWrapperFactory( tr( "Classification" ), QgsApplication::getThemeIcon( u"/mEditorWidgetClassification.svg"_s ) ) );
64 registerWidget( u"Range"_s, new QgsRangeWidgetFactory( tr( "Range" ), QgsApplication::getThemeIcon( u"/mEditorWidgetRange.svg"_s ) ) );
65 registerWidget( u"UniqueValues"_s, new QgsUniqueValueWidgetFactory( tr( "Unique Values" ), QgsApplication::getThemeIcon( u"/mEditorWidgetList.svg"_s ) ) );
66 registerWidget( u"ValueMap"_s, new QgsValueMapWidgetFactory( tr( "Value Map" ), QgsApplication::getThemeIcon( u"/mEditorWidgetValueMap.svg"_s ) ) );
67 registerWidget( u"Enumeration"_s, new QgsEnumerationWidgetFactory( tr( "Enumeration" ), QgsApplication::getThemeIcon( u"/mEditorWidgetList.svg"_s ) ) );
68 registerWidget( u"Hidden"_s, new QgsHiddenWidgetFactory( tr( "Hidden" ), QgsApplication::getThemeIcon( u"/mEditorWidgetHidden.svg"_s ) ) );
69 registerWidget( u"CheckBox"_s, new QgsCheckboxWidgetFactory( tr( "Checkbox" ), QgsApplication::getThemeIcon( u"/mEditorWidgetCheckbox.svg"_s ) ) );
70 registerWidget( u"ValueRelation"_s, new QgsValueRelationWidgetFactory( tr( "Value Relation" ), QgsApplication::getThemeIcon( u"/mEditorWidgetValueRelation.svg"_s ) ) );
71 registerWidget( u"UuidGenerator"_s, new QgsUuidWidgetFactory( tr( "Uuid Generator" ), QgsApplication::getThemeIcon( u"/mEditorWidgetUuid.svg"_s ) ) );
72 registerWidget( u"Color"_s, new QgsColorWidgetFactory( tr( "Color" ), QgsApplication::getThemeIcon( u"/mEditorWidgetColor.svg"_s ) ) );
73 registerWidget( u"RelationReference"_s, new QgsRelationReferenceFactory( tr( "Relation Reference" ), mapCanvas, messageBar, QgsApplication::getThemeIcon( u"/mEditorWidgetRelationReference.svg"_s ) ) );
74 registerWidget( u"DateTime"_s, new QgsDateTimeEditFactory( tr( "Date/Time" ), QgsApplication::getThemeIcon( u"/mEditorWidgetDateTime.svg"_s ) ) );
75 registerWidget( u"ExternalResource"_s, new QgsExternalResourceWidgetFactory( tr( "Attachment" ), messageBar, QgsApplication::getThemeIcon( u"/mEditorWidgetAttachment.svg"_s ) ) );
76 registerWidget( u"KeyValue"_s, new QgsKeyValueWidgetFactory( tr( "Key/Value" ), QgsApplication::getThemeIcon( u"/mEditorWidgetValueMap.svg"_s ) ) );
77 registerWidget( u"List"_s, new QgsListWidgetFactory( tr( "List" ), QgsApplication::getThemeIcon( u"/mEditorWidgetList.svg"_s ) ) );
78 registerWidget( u"Binary"_s, new QgsBinaryWidgetFactory( tr( "Binary (BLOB)" ), messageBar, QgsApplication::getThemeIcon( u"/mEditorWidgetBinary.svg"_s ) ) );
79 registerWidget( u"JsonEdit"_s, new QgsJsonEditWidgetFactory( tr( "Json View" ), QgsApplication::getThemeIcon( u"/mEditorWidgetJsonView.svg"_s ) ) );
80 registerWidget( u"Geometry"_s, new QgsGeometryWidgetFactory( tr( "Geometry" ), messageBar, QgsApplication::getThemeIcon( u"/mEditorWidgetGeometry.svg"_s ) ) );
81}
82
84{
85 qDeleteAll( mWidgetFactories );
86}
87
88QgsEditorWidgetSetup QgsEditorWidgetRegistry::findBest( const QgsVectorLayer *vl, const QString &fieldName ) const
89{
90 const QgsFields fields = vl->fields();
91 const int index = fields.indexOf( fieldName );
92
93 if ( index > -1 )
94 {
95 QgsEditorWidgetSetup setup = fields.at( index ).editorWidgetSetup();
96 if ( !setup.isNull() )
97 return setup;
98 }
99 return mAutoConf.editorWidgetSetup( vl, fieldName );
100}
101
102QgsEditorWidgetWrapper *QgsEditorWidgetRegistry::create( QgsVectorLayer *vl, int fieldIdx, QWidget *editor, QWidget *parent, const QgsAttributeEditorContext &context )
103{
104 const QString fieldName = vl->fields().field( fieldIdx ).name();
105 const QgsEditorWidgetSetup setup = findBest( vl, fieldName );
106 return create( setup.type(), vl, fieldIdx, setup.config(), editor, parent, context );
107}
108
109QgsEditorWidgetWrapper *QgsEditorWidgetRegistry::create( const QString &widgetId, QgsVectorLayer *vl, int fieldIdx, const QVariantMap &config, QWidget *editor, QWidget *parent, const QgsAttributeEditorContext &context )
110{
111 if ( mWidgetFactories.contains( widgetId ) )
112 {
113 QgsEditorWidgetWrapper *ww = mWidgetFactories[widgetId]->create( vl, fieldIdx, editor, parent );
114
115 if ( ww )
116 {
117 ww->setConfig( config );
118 ww->setContext( context );
119 // Make sure that there is a widget created at this point
120 // so setValue() et al won't crash
121 ww->widget();
122
123 // If we tried to set a widget which is not supported by this wrapper
124 if ( !ww->valid() )
125 {
126 delete ww;
127 const QString wid = findSuitableWrapper( editor, u"TextEdit"_s );
128 ww = mWidgetFactories[wid]->create( vl, fieldIdx, editor, parent );
129 ww->setConfig( config );
130 ww->setContext( context );
131 }
132
133 return ww;
134 }
135 }
136
137 return nullptr;
138}
139
140QgsSearchWidgetWrapper *QgsEditorWidgetRegistry::createSearchWidget( const QString &widgetId, QgsVectorLayer *vl, int fieldIdx, const QVariantMap &config, QWidget *parent, const QgsAttributeEditorContext &context )
141{
142 if ( mWidgetFactories.contains( widgetId ) )
143 {
144 QgsSearchWidgetWrapper *ww = mWidgetFactories[widgetId]->createSearchWidget( vl, fieldIdx, parent );
145
146 if ( ww )
147 {
148 ww->setConfig( config );
149 ww->setContext( context );
150 // Make sure that there is a widget created at this point
151 // so setValue() et al won't crash
152 ww->widget();
153 ww->clearWidget();
154 return ww;
155 }
156 }
157 return nullptr;
158}
159
160QgsEditorConfigWidget *QgsEditorWidgetRegistry::createConfigWidget( const QString &widgetId, QgsVectorLayer *vl, int fieldIdx, QWidget *parent )
161{
162 if ( mWidgetFactories.contains( widgetId ) )
163 {
164 return mWidgetFactories[widgetId]->configWidget( vl, fieldIdx, parent );
165 }
166 return nullptr;
167}
168
169QString QgsEditorWidgetRegistry::name( const QString &widgetId )
170{
171 if ( mWidgetFactories.contains( widgetId ) )
172 {
173 return mWidgetFactories[widgetId]->name();
174 }
175
176 return QString();
177}
178
179QIcon QgsEditorWidgetRegistry::icon( const QString &widgetId )
180{
181 if ( mWidgetFactories.contains( widgetId ) )
182 {
183 return mWidgetFactories[widgetId]->icon();
184 }
185
186 return QIcon();
187}
188
189bool QgsEditorWidgetRegistry::isReadOnly( const QString &widgetId )
190{
191 if ( mWidgetFactories.contains( widgetId ) )
192 {
193 return mWidgetFactories[widgetId]->isReadOnly();
194 }
195
196 return false;
197}
198
199QMap<QString, QgsEditorWidgetFactory *> QgsEditorWidgetRegistry::factories()
200{
201 return mWidgetFactories;
202}
203
205{
206 return mWidgetFactories.value( widgetId, mFallbackWidgetFactory.get() );
207}
208
209bool QgsEditorWidgetRegistry::registerWidget( const QString &widgetId, QgsEditorWidgetFactory *widgetFactory )
210{
211 if ( !widgetFactory )
212 {
213 QgsMessageLog::logMessage( tr( "QgsEditorWidgetRegistry: Factory not valid." ) );
214 return false;
215 }
216 else if ( mWidgetFactories.contains( widgetId ) )
217 {
218 QgsMessageLog::logMessage( tr( "QgsEditorWidgetRegistry: Factory with id %1 already registered." ).arg( widgetId ) );
219 return false;
220 }
221 else
222 {
223 mWidgetFactories.insert( widgetId, widgetFactory );
224
225 // Use this factory as default where it provides the highest priority
226 const QHash<const char *, int> types = widgetFactory->supportedWidgetTypes();
227 QHash<const char *, int>::ConstIterator it;
228 it = types.constBegin();
229
230 for ( ; it != types.constEnd(); ++it )
231 {
232 if ( it.value() > mFactoriesByType[it.key()].first )
233 {
234 mFactoriesByType[it.key()] = qMakePair( it.value(), widgetId );
235 }
236 }
237
238 return true;
239 }
240}
241
242QString QgsEditorWidgetRegistry::findSuitableWrapper( QWidget *editor, const QString &defaultWidget )
243{
244 QMap<const char *, QPair<int, QString>>::ConstIterator it;
245
246 QString widgetid;
247
248 // Editor can be null
249 if ( editor )
250 {
251 int weight = 0;
252
253 it = mFactoriesByType.constBegin();
254 for ( ; it != mFactoriesByType.constEnd(); ++it )
255 {
256 if ( QWidget::staticMetaObject.className() == it.key() )
257 {
258 // if it's a perfect match: return it directly
259 return it.value().second;
260 }
261 else if ( editor->inherits( it.key() ) )
262 {
263 // if it's a subclass, continue evaluating, maybe we find a more-specific or one with more weight
264 if ( it.value().first > weight )
265 {
266 weight = it.value().first;
267 widgetid = it.value().second;
268 }
269 }
270 }
271 }
272
273 if ( widgetid.isNull() )
274 widgetid = defaultWidget;
275 return widgetid;
276}
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
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)
Returns 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.
QIcon icon(const QString &widgetId)
Returns the icon for a widget type.
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:65
QgsEditorWidgetSetup editorWidgetSetup() const
Gets the editor widget setup for the field.
Definition qgsfield.cpp:751
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.