QGIS API Documentation 4.1.0-Master (5bf3c20f3c9)
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
110 const QString &widgetId, QgsVectorLayer *vl, int fieldIdx, const QVariantMap &config, QWidget *editor, QWidget *parent, const QgsAttributeEditorContext &context
111)
112{
113 if ( mWidgetFactories.contains( widgetId ) )
114 {
115 QgsEditorWidgetWrapper *ww = mWidgetFactories[widgetId]->create( vl, fieldIdx, editor, parent );
116
117 if ( ww )
118 {
119 ww->setConfig( config );
120 ww->setContext( context );
121 // Make sure that there is a widget created at this point
122 // so setValue() et al won't crash
123 ww->widget();
124
125 // If we tried to set a widget which is not supported by this wrapper
126 if ( !ww->valid() )
127 {
128 delete ww;
129 const QString wid = findSuitableWrapper( editor, u"TextEdit"_s );
130 ww = mWidgetFactories[wid]->create( vl, fieldIdx, editor, parent );
131 ww->setConfig( config );
132 ww->setContext( context );
133 }
134
135 return ww;
136 }
137 }
138
139 return nullptr;
140}
141
143 const QString &widgetId, QgsVectorLayer *vl, int fieldIdx, const QVariantMap &config, QWidget *parent, const QgsAttributeEditorContext &context
144)
145{
146 if ( mWidgetFactories.contains( widgetId ) )
147 {
148 QgsSearchWidgetWrapper *ww = mWidgetFactories[widgetId]->createSearchWidget( vl, fieldIdx, parent );
149
150 if ( ww )
151 {
152 ww->setConfig( config );
153 ww->setContext( context );
154 // Make sure that there is a widget created at this point
155 // so setValue() et al won't crash
156 ww->widget();
157 ww->clearWidget();
158 return ww;
159 }
160 }
161 return nullptr;
162}
163
164QgsEditorConfigWidget *QgsEditorWidgetRegistry::createConfigWidget( const QString &widgetId, QgsVectorLayer *vl, int fieldIdx, QWidget *parent )
165{
166 if ( mWidgetFactories.contains( widgetId ) )
167 {
168 return mWidgetFactories[widgetId]->configWidget( vl, fieldIdx, parent );
169 }
170 return nullptr;
171}
172
173QString QgsEditorWidgetRegistry::name( const QString &widgetId )
174{
175 if ( mWidgetFactories.contains( widgetId ) )
176 {
177 return mWidgetFactories[widgetId]->name();
178 }
179
180 return QString();
181}
182
183QIcon QgsEditorWidgetRegistry::icon( const QString &widgetId )
184{
185 if ( mWidgetFactories.contains( widgetId ) )
186 {
187 return mWidgetFactories[widgetId]->icon();
188 }
189
190 return QIcon();
191}
192
193bool QgsEditorWidgetRegistry::isReadOnly( const QString &widgetId )
194{
195 if ( mWidgetFactories.contains( widgetId ) )
196 {
197 return mWidgetFactories[widgetId]->isReadOnly();
198 }
199
200 return false;
201}
202
203QMap<QString, QgsEditorWidgetFactory *> QgsEditorWidgetRegistry::factories()
204{
205 return mWidgetFactories;
206}
207
209{
210 return mWidgetFactories.value( widgetId, mFallbackWidgetFactory.get() );
211}
212
213bool QgsEditorWidgetRegistry::registerWidget( const QString &widgetId, QgsEditorWidgetFactory *widgetFactory )
214{
215 if ( !widgetFactory )
216 {
217 QgsMessageLog::logMessage( tr( "QgsEditorWidgetRegistry: Factory not valid." ) );
218 return false;
219 }
220 else if ( mWidgetFactories.contains( widgetId ) )
221 {
222 QgsMessageLog::logMessage( tr( "QgsEditorWidgetRegistry: Factory with id %1 already registered." ).arg( widgetId ) );
223 return false;
224 }
225 else
226 {
227 mWidgetFactories.insert( widgetId, widgetFactory );
228
229 // Use this factory as default where it provides the highest priority
230 const QHash<const char *, int> types = widgetFactory->supportedWidgetTypes();
231 QHash<const char *, int>::ConstIterator it;
232 it = types.constBegin();
233
234 for ( ; it != types.constEnd(); ++it )
235 {
236 if ( it.value() > mFactoriesByType[it.key()].first )
237 {
238 mFactoriesByType[it.key()] = qMakePair( it.value(), widgetId );
239 }
240 }
241
242 return true;
243 }
244}
245
246QString QgsEditorWidgetRegistry::findSuitableWrapper( QWidget *editor, const QString &defaultWidget )
247{
248 QMap<const char *, QPair<int, QString>>::ConstIterator it;
249
250 QString widgetid;
251
252 // Editor can be null
253 if ( editor )
254 {
255 int weight = 0;
256
257 it = mFactoriesByType.constBegin();
258 for ( ; it != mFactoriesByType.constEnd(); ++it )
259 {
260 if ( QWidget::staticMetaObject.className() == it.key() )
261 {
262 // if it's a perfect match: return it directly
263 return it.value().second;
264 }
265 else if ( editor->inherits( it.key() ) )
266 {
267 // if it's a subclass, continue evaluating, maybe we find a more-specific or one with more weight
268 if ( it.value().first > weight )
269 {
270 weight = it.value().first;
271 widgetid = it.value().second;
272 }
273 }
274 }
275 }
276
277 if ( widgetid.isNull() )
278 widgetid = defaultWidget;
279 return widgetid;
280}
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:739
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(), Qgis::StringFormat format=Qgis::StringFormat::PlainText)
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.