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