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