QGIS API Documentation  2.8.2-Wien
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 dot kuhn at gmx 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 "qgseditorwidgetfactory.h"
20 #include "qgslegacyhelpers.h"
21 #include "qgsmessagelog.h"
22 #include "qgsproject.h"
23 #include "qgsvectorlayer.h"
24 #include "qgsmaplayerregistry.h"
25 
26 // Editors
28 #include "qgsrangewidgetfactory.h"
33 #include "qgshiddenwidgetfactory.h"
37 #include "qgsuuidwidgetfactory.h"
38 #include "qgsphotowidgetfactory.h"
40 #include "qgscolorwidgetfactory.h"
42 #include "qgsdatetimeeditfactory.h"
43 
45 {
46  static QgsEditorWidgetRegistry sInstance;
47  return &sInstance;
48 }
49 
51 {
53  reg->registerWidget( "Classification", new QgsClassificationWidgetWrapperFactory( tr( "Classification" ) ) );
54  reg->registerWidget( "Range", new QgsRangeWidgetFactory( tr( "Range" ) ) );
55  reg->registerWidget( "UniqueValues", new QgsUniqueValueWidgetFactory( tr( "Unique Values" ) ) );
56  reg->registerWidget( "FileName", new QgsFileNameWidgetFactory( tr( "File Name" ) ) );
57  reg->registerWidget( "ValueMap", new QgsValueMapWidgetFactory( tr( "Value Map" ) ) );
58  reg->registerWidget( "Enumeration", new QgsEnumerationWidgetFactory( tr( "Enumeration" ) ) );
59  reg->registerWidget( "Hidden", new QgsHiddenWidgetFactory( tr( "Hidden" ) ) );
60  reg->registerWidget( "CheckBox", new QgsCheckboxWidgetFactory( tr( "Check Box" ) ) );
61  reg->registerWidget( "TextEdit", new QgsTextEditWidgetFactory( tr( "Text Edit" ) ) );
62  reg->registerWidget( "ValueRelation", new QgsValueRelationWidgetFactory( tr( "Value Relation" ) ) );
63  reg->registerWidget( "UuidGenerator", new QgsUuidWidgetFactory( tr( "Uuid Generator" ) ) );
64  reg->registerWidget( "Photo", new QgsPhotoWidgetFactory( tr( "Photo" ) ) );
65  reg->registerWidget( "WebView", new QgsWebViewWidgetFactory( tr( "Web View" ) ) );
66  reg->registerWidget( "Color", new QgsColorWidgetFactory( tr( "Color" ) ) );
67  reg->registerWidget( "RelationReference", new QgsRelationReferenceFactory( tr( "Relation Reference" ), mapCanvas, messageBar ) );
68  reg->registerWidget( "DateTime", new QgsDateTimeEditFactory( tr( "Date/Time" ) ) );
69 }
70 
72 {
73  connect( QgsProject::instance(), SIGNAL( readMapLayer( QgsMapLayer*, const QDomElement& ) ), this, SLOT( readMapLayer( QgsMapLayer*, const QDomElement& ) ) );
74  connect( QgsProject::instance(), SIGNAL( writeMapLayer( QgsMapLayer*, QDomElement&, QDomDocument& ) ), this, SLOT( writeMapLayer( QgsMapLayer*, QDomElement&, QDomDocument& ) ) );
75 
76  connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWasAdded( QgsMapLayer* ) ), this, SLOT( mapLayerAdded( QgsMapLayer* ) ) );
77 }
78 
80 {
81  qDeleteAll( mWidgetFactories.values() );
82 }
83 
84 QgsEditorWidgetWrapper* QgsEditorWidgetRegistry::create( const QString& widgetId, QgsVectorLayer* vl, int fieldIdx, const QgsEditorWidgetConfig& config, QWidget* editor, QWidget* parent, const QgsAttributeEditorContext &context )
85 {
86  if ( mWidgetFactories.contains( widgetId ) )
87  {
88  QgsEditorWidgetWrapper* ww = mWidgetFactories[widgetId]->create( vl, fieldIdx, editor, parent );
89 
90  if ( ww )
91  {
92  ww->setConfig( config );
93  ww->setContext( context );
94  // Make sure that there is a widget created at this point
95  // so setValue() et al won't crash
96  ww->widget();
97  return ww;
98  }
99  }
100  return 0;
101 }
102 
103 QgsEditorConfigWidget* QgsEditorWidgetRegistry::createConfigWidget( const QString& widgetId, QgsVectorLayer* vl, int fieldIdx, QWidget* parent )
104 {
105  if ( mWidgetFactories.contains( widgetId ) )
106  {
107  return mWidgetFactories[widgetId]->configWidget( vl, fieldIdx, parent );
108  }
109  return 0;
110 }
111 
112 QString QgsEditorWidgetRegistry::name( const QString& widgetId )
113 {
114  if ( mWidgetFactories.contains( widgetId ) )
115  {
116  return mWidgetFactories[widgetId]->name();
117  }
118 
119  return QString();
120 }
121 
122 const QMap<QString, QgsEditorWidgetFactory*>& QgsEditorWidgetRegistry::factories()
123 {
124  return mWidgetFactories;
125 }
126 
128 {
129  return mWidgetFactories.value( widgetId );
130 }
131 
132 bool QgsEditorWidgetRegistry::registerWidget( const QString& widgetId, QgsEditorWidgetFactory* widgetFactory )
133 {
134  if ( !widgetFactory )
135  {
136  QgsMessageLog::instance()->logMessage( "QgsEditorWidgetRegistry: Factory not valid." );
137  return false;
138  }
139  else if ( mWidgetFactories.contains( widgetId ) )
140  {
141  QgsMessageLog::instance()->logMessage( QString( "QgsEditorWidgetRegistry: Factory with id %1 already registered." ).arg( widgetId ) );
142  return false;
143  }
144  else
145  {
146  mWidgetFactories.insert( widgetId, widgetFactory );
147  return true;
148  }
149 }
150 
151 void QgsEditorWidgetRegistry::readMapLayer( QgsMapLayer* mapLayer, const QDomElement& layerElem )
152 {
153  if ( mapLayer->type() != QgsMapLayer::VectorLayer )
154  {
155  return;
156  }
157 
158  QgsVectorLayer* vectorLayer = qobject_cast<QgsVectorLayer*>( mapLayer );
159  Q_ASSERT( vectorLayer );
160 
161  QDomNodeList editTypeNodes = layerElem.namedItem( "edittypes" ).childNodes();
162 
163  for ( int i = 0; i < editTypeNodes.size(); i++ )
164  {
165  QDomNode editTypeNode = editTypeNodes.at( i );
166  QDomElement editTypeElement = editTypeNode.toElement();
167 
168  QString name = editTypeElement.attribute( "name" );
169 
170  int idx = vectorLayer->fieldNameIndex( name );
171  if ( idx == -1 )
172  continue;
173 
174  bool hasLegacyType;
175  QgsVectorLayer::EditType editType =
176  ( QgsVectorLayer::EditType ) editTypeElement.attribute( "type" ).toInt( &hasLegacyType );
177 
178  QString ewv2Type;
180 
181  if ( hasLegacyType && editType != QgsVectorLayer::EditorWidgetV2 )
182  {
184  ewv2Type = readLegacyConfig( vectorLayer, editTypeElement, cfg );
186  }
187  else
188  ewv2Type = editTypeElement.attribute( "widgetv2type" );
189 
190  if ( mWidgetFactories.contains( ewv2Type ) )
191  {
192  vectorLayer->setEditorWidgetV2( idx, ewv2Type );
193  QDomElement ewv2CfgElem = editTypeElement.namedItem( "widgetv2config" ).toElement();
194 
195  if ( !ewv2CfgElem.isNull() )
196  {
197  cfg = mWidgetFactories[ewv2Type]->readEditorConfig( ewv2CfgElem, vectorLayer, idx );
198  }
199 
200  vectorLayer->setFieldEditable( idx, ewv2CfgElem.attribute( "fieldEditable", "1" ) == "1" );
201  vectorLayer->setLabelOnTop( idx, ewv2CfgElem.attribute( "labelOnTop", "0" ) == "1" );
202  vectorLayer->setEditorWidgetV2Config( idx, cfg );
203  }
204  else
205  {
206  QgsMessageLog::logMessage( tr( "Unknown attribute editor widget '%1'" ).arg( ewv2Type ) );
207  }
208  }
209 }
210 
211 const QString QgsEditorWidgetRegistry::readLegacyConfig( QgsVectorLayer* vl, const QDomElement& editTypeElement, QgsEditorWidgetConfig& cfg )
212 {
213  QString name = editTypeElement.attribute( "name" );
214 
215  QgsVectorLayer::EditType editType = ( QgsVectorLayer::EditType ) editTypeElement.attribute( "type" ).toInt();
216 
218  return QgsLegacyHelpers::convertEditType( editType, cfg, vl, name, editTypeElement );
220 }
221 
222 void QgsEditorWidgetRegistry::writeMapLayer( QgsMapLayer* mapLayer, QDomElement& layerElem, QDomDocument& doc ) const
223 {
224  if ( mapLayer->type() != QgsMapLayer::VectorLayer )
225  {
226  return;
227  }
228 
229  QgsVectorLayer* vectorLayer = qobject_cast<QgsVectorLayer*>( mapLayer );
230  if ( !vectorLayer )
231  {
232  return;
233  }
234 
235  QDomNode editTypesNode = doc.createElement( "edittypes" );
236 
237  for ( int idx = 0; idx < vectorLayer->pendingFields().count(); ++idx )
238  {
239  const QgsField &field = vectorLayer->pendingFields()[ idx ];
240  const QString& widgetType = vectorLayer->editorWidgetV2( idx );
241  if ( !mWidgetFactories.contains( widgetType ) )
242  {
243  QgsMessageLog::logMessage( tr( "Could not save unknown editor widget type '%1'." ).arg( widgetType ) );
244  continue;
245  }
246 
247 
248  QDomElement editTypeElement = doc.createElement( "edittype" );
249  editTypeElement.setAttribute( "name", field.name() );
250  editTypeElement.setAttribute( "widgetv2type", widgetType );
251 
252  if ( mWidgetFactories.contains( widgetType ) )
253  {
254  QDomElement ewv2CfgElem = doc.createElement( "widgetv2config" );
255  ewv2CfgElem.setAttribute( "fieldEditable", vectorLayer->fieldEditable( idx ) );
256  ewv2CfgElem.setAttribute( "labelOnTop", vectorLayer->labelOnTop( idx ) );
257 
258  mWidgetFactories[widgetType]->writeConfig( vectorLayer->editorWidgetV2Config( idx ), ewv2CfgElem, doc, vectorLayer, idx );
259 
260  editTypeElement.appendChild( ewv2CfgElem );
261  }
262 
263  editTypesNode.appendChild( editTypeElement );
264  }
265 
266  layerElem.appendChild( editTypesNode );
267 }
268 
269 void QgsEditorWidgetRegistry::mapLayerAdded( QgsMapLayer* mapLayer )
270 {
271  QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( mapLayer );
272 
273  if ( vl )
274  {
275  connect( vl, SIGNAL( readCustomSymbology( const QDomElement&, QString& ) ), this, SLOT( readSymbology( const QDomElement&, QString& ) ) );
276  connect( vl, SIGNAL( writeCustomSymbology( QDomElement&, QDomDocument&, QString& ) ), this, SLOT( writeSymbology( QDomElement&, QDomDocument&, QString& ) ) );
277  }
278 }
279 
280 void QgsEditorWidgetRegistry::readSymbology( const QDomElement& element, QString& errorMessage )
281 {
282  Q_UNUSED( errorMessage )
283  QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( sender() );
284 
285  Q_ASSERT( vl );
286 
287  readMapLayer( vl, element );
288 }
289 
290 void QgsEditorWidgetRegistry::writeSymbology( QDomElement& element, QDomDocument& doc, QString& errorMessage )
291 {
292  Q_UNUSED( errorMessage )
293  QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( sender() );
294 
295  Q_ASSERT( vl );
296 
297  writeMapLayer( vl, element, doc );
298 }