QGIS API Documentation  2.99.0-Master (9f5e33a)
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 
19 #include "qgsmessagelog.h"
20 #include "qgsproject.h"
21 #include "qgsvectorlayer.h"
22 #include "qgseditorwidgetwrapper.h"
23 #include "qgssearchwidgetwrapper.h"
24 
25 // Editors
28 #include "qgscolorwidgetfactory.h"
29 #include "qgsdatetimeeditfactory.h"
32 #include "qgshiddenwidgetfactory.h"
34 #include "qgslistwidgetfactory.h"
35 #include "qgsrangewidgetfactory.h"
39 #include "qgsuuidwidgetfactory.h"
42 
44 {
45  registerWidget( QStringLiteral( "TextEdit" ), new QgsTextEditWidgetFactory( tr( "Text Edit" ) ) );
46  registerWidget( QStringLiteral( "Classification" ), new QgsClassificationWidgetWrapperFactory( tr( "Classification" ) ) );
47  registerWidget( QStringLiteral( "Range" ), new QgsRangeWidgetFactory( tr( "Range" ) ) );
48  registerWidget( QStringLiteral( "UniqueValues" ), new QgsUniqueValueWidgetFactory( tr( "Unique Values" ) ) );
49  registerWidget( QStringLiteral( "ValueMap" ), new QgsValueMapWidgetFactory( tr( "Value Map" ) ) );
50  registerWidget( QStringLiteral( "Enumeration" ), new QgsEnumerationWidgetFactory( tr( "Enumeration" ) ) );
51  registerWidget( QStringLiteral( "Hidden" ), new QgsHiddenWidgetFactory( tr( "Hidden" ) ) );
52  registerWidget( QStringLiteral( "CheckBox" ), new QgsCheckboxWidgetFactory( tr( "Check Box" ) ) );
53  registerWidget( QStringLiteral( "ValueRelation" ), new QgsValueRelationWidgetFactory( tr( "Value Relation" ) ) );
54  registerWidget( QStringLiteral( "UuidGenerator" ), new QgsUuidWidgetFactory( tr( "Uuid Generator" ) ) );
55  registerWidget( QStringLiteral( "Color" ), new QgsColorWidgetFactory( tr( "Color" ) ) );
56  registerWidget( QStringLiteral( "RelationReference" ), new QgsRelationReferenceFactory( tr( "Relation Reference" ), mapCanvas, messageBar ) );
57  registerWidget( QStringLiteral( "DateTime" ), new QgsDateTimeEditFactory( tr( "Date/Time" ) ) );
58  registerWidget( QStringLiteral( "ExternalResource" ), new QgsExternalResourceWidgetFactory( tr( "Attachment" ) ) );
59  registerWidget( QStringLiteral( "KeyValue" ), new QgsKeyValueWidgetFactory( tr( "Key/Value" ) ) );
60  registerWidget( QStringLiteral( "List" ), new QgsListWidgetFactory( tr( "List" ) ) );
61 }
62 
64 {
65 }
66 
68 {
69  qDeleteAll( mWidgetFactories );
70 }
71 
72 QgsEditorWidgetSetup QgsEditorWidgetRegistry::findBest( const QgsVectorLayer *vl, const QString &fieldName ) const
73 {
74  QgsFields fields = vl->fields();
75  int index = fields.indexOf( fieldName );
76 
77  if ( index > -1 )
78  {
79  QgsEditorWidgetSetup setup = vl->fields().at( index ).editorWidgetSetup();
80  if ( !setup.isNull() )
81  return setup;
82  }
83  return mAutoConf.editorWidgetSetup( vl, fieldName );
84 }
85 
86 QgsEditorWidgetWrapper *QgsEditorWidgetRegistry::create( QgsVectorLayer *vl, int fieldIdx, QWidget *editor, QWidget *parent, const QgsAttributeEditorContext &context )
87 {
88  const QString fieldName = vl->fields().field( fieldIdx ).name();
89  const QgsEditorWidgetSetup setup = findBest( vl, fieldName );
90  return create( setup.type(), vl, fieldIdx, setup.config(), editor, parent, context );
91 }
92 
93 QgsEditorWidgetWrapper *QgsEditorWidgetRegistry::create( const QString &widgetId, QgsVectorLayer *vl, int fieldIdx, const QVariantMap &config, QWidget *editor, QWidget *parent, const QgsAttributeEditorContext &context )
94 {
95  if ( mWidgetFactories.contains( widgetId ) )
96  {
97  QgsEditorWidgetWrapper *ww = mWidgetFactories[widgetId]->create( vl, fieldIdx, editor, parent );
98 
99  if ( ww )
100  {
101  ww->setConfig( config );
102  ww->setContext( context );
103  // Make sure that there is a widget created at this point
104  // so setValue() et al won't crash
105  ww->widget();
106 
107  // If we tried to set a widget which is not supported by this wrapper
108  if ( !ww->valid() )
109  {
110  delete ww;
111  QString wid = findSuitableWrapper( editor, QStringLiteral( "TextEdit" ) );
112  ww = mWidgetFactories[wid]->create( vl, fieldIdx, editor, parent );
113  ww->setConfig( config );
114  ww->setContext( context );
115  }
116 
117  return ww;
118  }
119  }
120 
121  return nullptr;
122 }
123 
124 QgsSearchWidgetWrapper *QgsEditorWidgetRegistry::createSearchWidget( const QString &widgetId, QgsVectorLayer *vl, int fieldIdx, const QVariantMap &config, QWidget *parent, const QgsAttributeEditorContext &context )
125 {
126  if ( mWidgetFactories.contains( widgetId ) )
127  {
128  QgsSearchWidgetWrapper *ww = mWidgetFactories[widgetId]->createSearchWidget( vl, fieldIdx, parent );
129 
130  if ( ww )
131  {
132  ww->setConfig( config );
133  ww->setContext( context );
134  // Make sure that there is a widget created at this point
135  // so setValue() et al won't crash
136  ww->widget();
137  ww->clearWidget();
138  return ww;
139  }
140  }
141  return nullptr;
142 }
143 
144 QgsEditorConfigWidget *QgsEditorWidgetRegistry::createConfigWidget( const QString &widgetId, QgsVectorLayer *vl, int fieldIdx, QWidget *parent )
145 {
146  if ( mWidgetFactories.contains( widgetId ) )
147  {
148  return mWidgetFactories[widgetId]->configWidget( vl, fieldIdx, parent );
149  }
150  return nullptr;
151 }
152 
153 QString QgsEditorWidgetRegistry::name( const QString &widgetId )
154 {
155  if ( mWidgetFactories.contains( widgetId ) )
156  {
157  return mWidgetFactories[widgetId]->name();
158  }
159 
160  return QString();
161 }
162 
163 QMap<QString, QgsEditorWidgetFactory *> QgsEditorWidgetRegistry::factories()
164 {
165  return mWidgetFactories;
166 }
167 
169 {
170  return mWidgetFactories.value( widgetId );
171 }
172 
173 bool QgsEditorWidgetRegistry::registerWidget( const QString &widgetId, QgsEditorWidgetFactory *widgetFactory )
174 {
175  if ( !widgetFactory )
176  {
177  QgsApplication::messageLog()->logMessage( QStringLiteral( "QgsEditorWidgetRegistry: Factory not valid." ) );
178  return false;
179  }
180  else if ( mWidgetFactories.contains( widgetId ) )
181  {
182  QgsApplication::messageLog()->logMessage( QStringLiteral( "QgsEditorWidgetRegistry: Factory with id %1 already registered." ).arg( widgetId ) );
183  return false;
184  }
185  else
186  {
187  mWidgetFactories.insert( widgetId, widgetFactory );
188 
189  // Use this factory as default where it provides the heighest priority
190  QHash<const char *, int> types = widgetFactory->supportedWidgetTypes();
191  QHash<const char *, int>::ConstIterator it;
192  it = types.constBegin();
193 
194  for ( ; it != types.constEnd(); ++it )
195  {
196  if ( it.value() > mFactoriesByType[it.key()].first )
197  {
198  mFactoriesByType[it.key()] = qMakePair( it.value(), widgetId );
199  }
200  }
201 
202  return true;
203  }
204 }
205 
206 QString QgsEditorWidgetRegistry::findSuitableWrapper( QWidget *editor, const QString &defaultWidget )
207 {
208  QMap<const char *, QPair<int, QString> >::ConstIterator it;
209 
210  QString widgetid;
211 
212  // Editor can be null
213  if ( editor )
214  {
215  int weight = 0;
216 
217  it = mFactoriesByType.constBegin();
218  for ( ; it != mFactoriesByType.constEnd(); ++it )
219  {
220  if ( editor->staticMetaObject.className() == it.key() )
221  {
222  // if it's a perfect match: return it directly
223  return it.value().second;
224  }
225  else if ( editor->inherits( it.key() ) )
226  {
227  // if it's a subclass, continue evaluating, maybe we find a more-specific or one with more weight
228  if ( it.value().first > weight )
229  {
230  weight = it.value().first;
231  widgetid = it.value().second;
232  }
233  }
234  }
235  }
236 
237  if ( widgetid.isNull() )
238  widgetid = defaultWidget;
239  return widgetid;
240 }
Manages an editor widget Widget and wrapper share the same parent.
QVariantMap config() const
This class should be subclassed for every configurable editor widget type.
QString name
Definition: qgsfield.h:54
QgsEditorWidgetFactory * factory(const QString &widgetId)
Get a factory for the given widget type id.
This class contains context information for attribute editor widgets.
Manages an editor widget Widget and wrapper share the same parent.
Factory for widgets for editing a QVariantList or a QStringList.
A bar for displaying non-blocking messages to the user.
Definition: qgsmessagebar.h:44
Container of fields for a vector layer.
Definition: qgsfields.h:41
QgsEditorWidgetSetup editorWidgetSetup() const
Get the editor widget setup for the field.
Definition: qgsfield.cpp:291
virtual QHash< const char *, int > supportedWidgetTypes()
Returns a list of widget types which this editor widget supports.
QgsEditorConfigWidget * createConfigWidget(const QString &widgetId, QgsVectorLayer *vl, int fieldIdx, QWidget *parent)
Creates a configuration widget.
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:73
QgsField at(int i) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:135
QMap< QString, QgsEditorWidgetFactory * > factories()
Get access to all registered factories.
static QgsMessageLog * messageLog()
Returns the application&#39;s message log.
virtual void clearWidget()
Clears the widget&#39;s current value and resets it back to the default state.
void setContext(const QgsAttributeEditorContext &context)
Set the context in which this widget is shown.
QgsFields fields() const override
Returns the list of fields of this layer.
virtual bool valid() const =0
Return true if the widget has been properly initialized.
Every attribute editor widget needs a factory, which inherits this class.
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.
static void logMessage(const QString &message, const QString &tag=QString(), MessageLevel level=QgsMessageLog::WARNING)
add a message to the instance (and create it if necessary)
QgsEditorWidgetRegistry()
Constructor for QgsEditorWidgetRegistry.
int indexOf(const QString &fieldName) const
Get the field index from the field name.
Definition: qgsfields.cpp:179
QgsEditorWidgetSetup findBest(const QgsVectorLayer *vl, const QString &fieldName) const
Find the best editor widget and its configuration for a given field.
Holder for the widget type and its configuration for a field.
Factory for widgets for editing a QVariantMap.
QString name(const QString &widgetId)
Get the human readable name for a widget type.
QgsSearchWidgetWrapper * createSearchWidget(const QString &widgetId, QgsVectorLayer *vl, int fieldIdx, const QVariantMap &config, QWidget *parent, const QgsAttributeEditorContext &context=QgsAttributeEditorContext())
QWidget * widget()
Access the widget managed by this wrapper.
bool registerWidget(const QString &widgetId, QgsEditorWidgetFactory *widgetFactory)
Register a new widget factory with the given id.
void setConfig(const QVariantMap &config)
Will set the config of this wrapper to the specified config.
Represents a vector layer which manages a vector based data sets.
QgsField field(int fieldIdx) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:140
void initEditors(QgsMapCanvas *mapCanvas=nullptr, QgsMessageBar *messageBar=nullptr)
Registers all the default widgets.