QGIS API Documentation  2.99.0-Master (5753576)
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 #ifdef WITH_QTWEBKIT
44 #endif
45 
46 
48 {
49  static QgsEditorWidgetRegistry sInstance;
50  return &sInstance;
51 }
52 
54 {
56  reg->registerWidget( QStringLiteral( "TextEdit" ), new QgsTextEditWidgetFactory( tr( "Text Edit" ) ) );
57  reg->registerWidget( QStringLiteral( "Classification" ), new QgsClassificationWidgetWrapperFactory( tr( "Classification" ) ) );
58  reg->registerWidget( QStringLiteral( "Range" ), new QgsRangeWidgetFactory( tr( "Range" ) ) );
59  reg->registerWidget( QStringLiteral( "UniqueValues" ), new QgsUniqueValueWidgetFactory( tr( "Unique Values" ) ) );
60  reg->registerWidget( QStringLiteral( "ValueMap" ), new QgsValueMapWidgetFactory( tr( "Value Map" ) ) );
61  reg->registerWidget( QStringLiteral( "Enumeration" ), new QgsEnumerationWidgetFactory( tr( "Enumeration" ) ) );
62  reg->registerWidget( QStringLiteral( "Hidden" ), new QgsHiddenWidgetFactory( tr( "Hidden" ) ) );
63  reg->registerWidget( QStringLiteral( "CheckBox" ), new QgsCheckboxWidgetFactory( tr( "Check Box" ) ) );
64  reg->registerWidget( QStringLiteral( "ValueRelation" ), new QgsValueRelationWidgetFactory( tr( "Value Relation" ) ) );
65  reg->registerWidget( QStringLiteral( "UuidGenerator" ), new QgsUuidWidgetFactory( tr( "Uuid Generator" ) ) );
66 #ifdef WITH_QTWEBKIT
67  reg->registerWidget( QStringLiteral( "WebView" ), new QgsWebViewWidgetFactory( tr( "Web View" ) ) );
68 #endif
69  reg->registerWidget( QStringLiteral( "Color" ), new QgsColorWidgetFactory( tr( "Color" ) ) );
70  reg->registerWidget( QStringLiteral( "RelationReference" ), new QgsRelationReferenceFactory( tr( "Relation Reference" ), mapCanvas, messageBar ) );
71  reg->registerWidget( QStringLiteral( "DateTime" ), new QgsDateTimeEditFactory( tr( "Date/Time" ) ) );
72  reg->registerWidget( QStringLiteral( "ExternalResource" ), new QgsExternalResourceWidgetFactory( tr( "Attachment" ) ) );
73  reg->registerWidget( QStringLiteral( "KeyValue" ), new QgsKeyValueWidgetFactory( tr( "Key/Value" ) ) );
74  reg->registerWidget( QStringLiteral( "List" ), new QgsListWidgetFactory( tr( "List" ) ) );
75 }
76 
78 {
79 }
80 
82 {
83  qDeleteAll( mWidgetFactories );
84 }
85 
86 QgsEditorWidgetSetup QgsEditorWidgetRegistry::findBest( const QgsVectorLayer* vl, const QString& fieldName ) const
87 {
88  QgsFields fields = vl->fields();
89  int index = fields.indexOf( fieldName );
90 
91  if ( index > -1 )
92  {
93  QgsEditorWidgetSetup setup = vl->fields().at( index ).editorWidgetSetup();
94  if ( !setup.isNull() )
95  return setup;
96  }
97 
98  return mAutoConf.editorWidgetSetup( vl, fieldName );
99 }
100 
101 QgsEditorWidgetWrapper* QgsEditorWidgetRegistry::create( QgsVectorLayer* vl, int fieldIdx, QWidget* editor, QWidget* parent, const QgsAttributeEditorContext &context )
102 {
103  const QString fieldName = vl->fields().field( fieldIdx ).name();
104  const QgsEditorWidgetSetup setup = findBest( vl, fieldName );
105  return create( setup.type(), vl, fieldIdx, setup.config(), editor, parent, context );
106 }
107 
108 QgsEditorWidgetWrapper* QgsEditorWidgetRegistry::create( const QString& widgetId, QgsVectorLayer* vl, int fieldIdx, const QVariantMap& config, QWidget* editor, QWidget* parent, const QgsAttributeEditorContext &context )
109 {
110  if ( mWidgetFactories.contains( widgetId ) )
111  {
112  QgsEditorWidgetWrapper* ww = mWidgetFactories[widgetId]->create( vl, fieldIdx, editor, parent );
113 
114  if ( ww )
115  {
116  ww->setConfig( config );
117  ww->setContext( context );
118  // Make sure that there is a widget created at this point
119  // so setValue() et al won't crash
120  ww->widget();
121 
122  // If we tried to set a widget which is not supported by this wrapper
123  if ( !ww->valid() )
124  {
125  delete ww;
126  QString wid = findSuitableWrapper( editor, QStringLiteral( "TextEdit" ) );
127  ww = mWidgetFactories[wid]->create( vl, fieldIdx, editor, parent );
128  ww->setConfig( config );
129  ww->setContext( context );
130  }
131 
132  return ww;
133  }
134  }
135 
136  return nullptr;
137 }
138 
139 QgsSearchWidgetWrapper* QgsEditorWidgetRegistry::createSearchWidget( const QString& widgetId, QgsVectorLayer* vl, int fieldIdx, const QVariantMap& config, QWidget* parent, const QgsAttributeEditorContext &context )
140 {
141  if ( mWidgetFactories.contains( widgetId ) )
142  {
143  QgsSearchWidgetWrapper* ww = mWidgetFactories[widgetId]->createSearchWidget( vl, fieldIdx, parent );
144 
145  if ( ww )
146  {
147  ww->setConfig( config );
148  ww->setContext( context );
149  // Make sure that there is a widget created at this point
150  // so setValue() et al won't crash
151  ww->widget();
152  ww->clearWidget();
153  return ww;
154  }
155  }
156  return nullptr;
157 }
158 
159 QgsEditorConfigWidget* QgsEditorWidgetRegistry::createConfigWidget( const QString& widgetId, QgsVectorLayer* vl, int fieldIdx, QWidget* parent )
160 {
161  if ( mWidgetFactories.contains( widgetId ) )
162  {
163  return mWidgetFactories[widgetId]->configWidget( vl, fieldIdx, parent );
164  }
165  return nullptr;
166 }
167 
168 QString QgsEditorWidgetRegistry::name( const QString& widgetId )
169 {
170  if ( mWidgetFactories.contains( widgetId ) )
171  {
172  return mWidgetFactories[widgetId]->name();
173  }
174 
175  return QString();
176 }
177 
178 QMap<QString, QgsEditorWidgetFactory*> QgsEditorWidgetRegistry::factories()
179 {
180  return mWidgetFactories;
181 }
182 
184 {
185  return mWidgetFactories.value( widgetId );
186 }
187 
188 bool QgsEditorWidgetRegistry::registerWidget( const QString& widgetId, QgsEditorWidgetFactory* widgetFactory )
189 {
190  if ( !widgetFactory )
191  {
192  QgsApplication::messageLog()->logMessage( QStringLiteral( "QgsEditorWidgetRegistry: Factory not valid." ) );
193  return false;
194  }
195  else if ( mWidgetFactories.contains( widgetId ) )
196  {
197  QgsApplication::messageLog()->logMessage( QStringLiteral( "QgsEditorWidgetRegistry: Factory with id %1 already registered." ).arg( widgetId ) );
198  return false;
199  }
200  else
201  {
202  mWidgetFactories.insert( widgetId, widgetFactory );
203 
204  // Use this factory as default where it provides the heighest priority
205  QHash<const char*, int> types = widgetFactory->supportedWidgetTypes();
206  QHash<const char*, int>::ConstIterator it;
207  it = types.constBegin();
208 
209  for ( ; it != types.constEnd(); ++it )
210  {
211  if ( it.value() > mFactoriesByType[it.key()].first )
212  {
213  mFactoriesByType[it.key()] = qMakePair( it.value(), widgetId );
214  }
215  }
216 
217  return true;
218  }
219 }
220 
221 QString QgsEditorWidgetRegistry::findSuitableWrapper( QWidget* editor, const QString& defaultWidget )
222 {
223  QMap<const char*, QPair<int, QString> >::ConstIterator it;
224 
225  QString widgetid;
226 
227  // Editor can be null
228  if ( editor )
229  {
230  int weight = 0;
231 
232  it = mFactoriesByType.constBegin();
233  for ( ; it != mFactoriesByType.constEnd(); ++it )
234  {
235  if ( editor->staticMetaObject.className() == it.key() )
236  {
237  // if it's a perfect match: return it directly
238  return it.value().second;
239  }
240  else if ( editor->inherits( it.key() ) )
241  {
242  // if it's a subclass, continue evaluating, maybe we find a more-specific or one with more weight
243  if ( it.value().first > weight )
244  {
245  weight = it.value().first;
246  widgetid = it.value().second;
247  }
248  }
249  }
250  }
251 
252  if ( widgetid.isNull() )
253  widgetid = defaultWidget;
254  return widgetid;
255 }
Manages an editor widget Widget and wrapper share the same parent.
static unsigned index
QVariantMap config() const
This class should be subclassed for every configurable editor widget type.
QString name
Definition: qgsfield.h:53
QgsEditorWidgetFactory * factory(const QString &widgetId)
Get a factory for the given widget type id.
This class manages all known edit widget factories.
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:43
Container of fields for a vector layer.
Definition: qgsfields.h:39
QgsEditorWidgetSetup editorWidgetSetup() const
Get the editor widget setup for the field.
Definition: qgsfield.cpp:291
QgsEditorConfigWidget * createConfigWidget(const QString &widgetId, QgsVectorLayer *vl, int fieldIdx, QWidget *parent)
Creates a configuration widget.
static QgsEditorWidgetRegistry * instance()
This class is a singleton and has therefore to be accessed with this method instead of a constructor...
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:74
QgsFields fields() const
Returns the list of fields of this layer.
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.
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.
static void logMessage(const QString &message, const QString &tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
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.
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.
virtual QHash< const char *, int > supportedWidgetTypes()
Returns a list of widget types which this editor widget supports.
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
static void initEditors(QgsMapCanvas *mapCanvas=nullptr, QgsMessageBar *messageBar=nullptr)
Registers all the default widgets.