QGIS API Documentation  2.5.0-Master
 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 
26 {
27  static QgsEditorWidgetRegistry sInstance;
28  return &sInstance;
29 }
30 
32 {
33  connect( QgsProject::instance(), SIGNAL( readMapLayer( QgsMapLayer*, const QDomElement& ) ), this, SLOT( readMapLayer( QgsMapLayer*, const QDomElement& ) ) );
34  connect( QgsProject::instance(), SIGNAL( writeMapLayer( QgsMapLayer*, QDomElement&, QDomDocument& ) ), this, SLOT( writeMapLayer( QgsMapLayer*, QDomElement&, QDomDocument& ) ) );
35 }
36 
38 {
39  qDeleteAll( mWidgetFactories.values() );
40 }
41 
42 QgsEditorWidgetWrapper* QgsEditorWidgetRegistry::create( const QString& widgetId, QgsVectorLayer* vl, int fieldIdx, const QgsEditorWidgetConfig& config, QWidget* editor, QWidget* parent, const QgsAttributeEditorContext context )
43 {
44  if ( mWidgetFactories.contains( widgetId ) )
45  {
46  QgsEditorWidgetWrapper* ww = mWidgetFactories[widgetId]->create( vl, fieldIdx, editor, parent );
47 
48  if ( ww )
49  {
50  ww->setConfig( config );
51  ww->setContext( context );
52  // Make sure that there is a widget created at this point
53  // so setValue() et al won't crash
54  ww->widget();
55  return ww;
56  }
57  }
58  return 0;
59 }
60 
61 QgsEditorConfigWidget* QgsEditorWidgetRegistry::createConfigWidget( const QString& widgetId, QgsVectorLayer* vl, int fieldIdx, QWidget* parent )
62 {
63  if ( mWidgetFactories.contains( widgetId ) )
64  {
65  return mWidgetFactories[widgetId]->configWidget( vl, fieldIdx, parent );
66  }
67  return 0;
68 }
69 
70 QString QgsEditorWidgetRegistry::name( const QString& widgetId )
71 {
72  if ( mWidgetFactories.contains( widgetId ) )
73  {
74  return mWidgetFactories[widgetId]->name();
75  }
76 
77  return QString();
78 }
79 
80 const QMap<QString, QgsEditorWidgetFactory*>& QgsEditorWidgetRegistry::factories()
81 {
82  return mWidgetFactories;
83 }
84 
86 {
87  return mWidgetFactories.value( widgetId );
88 }
89 
90 bool QgsEditorWidgetRegistry::registerWidget( const QString& widgetId, QgsEditorWidgetFactory* widgetFactory )
91 {
92  if ( !widgetFactory )
93  {
94  QgsMessageLog::instance()->logMessage( "QgsEditorWidgetRegistry: Factory not valid." );
95  return false;
96  }
97  else if ( mWidgetFactories.contains( widgetId ) )
98  {
99  QgsMessageLog::instance()->logMessage( QString( "QgsEditorWidgetRegistry: Factory with id %1 already registered." ).arg( widgetId ) );
100  return false;
101  }
102  else
103  {
104  mWidgetFactories.insert( widgetId, widgetFactory );
105  return true;
106  }
107 }
108 
109 void QgsEditorWidgetRegistry::readMapLayer( QgsMapLayer* mapLayer, const QDomElement& layerElem )
110 {
111  if ( mapLayer->type() != QgsMapLayer::VectorLayer )
112  {
113  return;
114  }
115 
116  QgsVectorLayer* vectorLayer = qobject_cast<QgsVectorLayer*>( mapLayer );
117  Q_ASSERT( vectorLayer );
118 
119  QDomNodeList editTypeNodes = layerElem.namedItem( "edittypes" ).childNodes();
120 
121  for ( int i = 0; i < editTypeNodes.size(); i++ )
122  {
123  QDomNode editTypeNode = editTypeNodes.at( i );
124  QDomElement editTypeElement = editTypeNode.toElement();
125 
126  QString name = editTypeElement.attribute( "name" );
127 
128  int idx = vectorLayer->fieldNameIndex( name );
129  if ( idx == -1 )
130  continue;
131 
132  bool hasLegacyType;
133  QgsVectorLayer::EditType editType =
134  ( QgsVectorLayer::EditType ) editTypeElement.attribute( "type" ).toInt( &hasLegacyType );
135 
136  QString ewv2Type;
138 
139  if ( hasLegacyType && editType != QgsVectorLayer::EditorWidgetV2 )
140  {
142  ewv2Type = readLegacyConfig( vectorLayer, editTypeElement, cfg );
144  }
145  else
146  ewv2Type = editTypeElement.attribute( "widgetv2type" );
147 
148  if ( mWidgetFactories.contains( ewv2Type ) )
149  {
150  vectorLayer->setEditorWidgetV2( idx, ewv2Type );
151  QDomElement ewv2CfgElem = editTypeElement.namedItem( "widgetv2config" ).toElement();
152 
153  if ( !ewv2CfgElem.isNull() )
154  {
155  cfg = mWidgetFactories[ewv2Type]->readEditorConfig( ewv2CfgElem, vectorLayer, idx );
156  }
157 
158  vectorLayer->setFieldEditable( idx, ewv2CfgElem.attribute( "fieldEditable", "1" ) == "1" );
159  vectorLayer->setLabelOnTop( idx, ewv2CfgElem.attribute( "labelOnTop", "0" ) == "1" );
160  vectorLayer->setEditorWidgetV2Config( idx, cfg );
161  }
162  else
163  {
164  QgsMessageLog::logMessage( tr( "Unknown attribute editor widget '%1'" ).arg( ewv2Type ) );
165  }
166  }
167 }
168 
169 const QString QgsEditorWidgetRegistry::readLegacyConfig( QgsVectorLayer* vl, const QDomElement& editTypeElement, QgsEditorWidgetConfig& cfg )
170 {
171  QString name = editTypeElement.attribute( "name" );
172 
173  QgsVectorLayer::EditType editType = ( QgsVectorLayer::EditType ) editTypeElement.attribute( "type" ).toInt();
174 
176  return QgsLegacyHelpers::convertEditType( editType, cfg, vl, name, editTypeElement );
178 }
179 
180 void QgsEditorWidgetRegistry::writeMapLayer( QgsMapLayer* mapLayer, QDomElement& layerElem, QDomDocument& doc )
181 {
182  if ( mapLayer->type() != QgsMapLayer::VectorLayer )
183  {
184  return;
185  }
186 
187  QgsVectorLayer* vectorLayer = qobject_cast<QgsVectorLayer*>( mapLayer );
188  if ( !vectorLayer )
189  {
190  return;
191  }
192 
193  QDomNode editTypesNode = doc.createElement( "edittypes" );
194 
195  for ( int idx = 0; idx < vectorLayer->pendingFields().count(); ++idx )
196  {
197  const QgsField &field = vectorLayer->pendingFields()[ idx ];
198  const QString& widgetType = vectorLayer->editorWidgetV2( idx );
199  if ( !mWidgetFactories.contains( widgetType ) )
200  {
201  QgsMessageLog::logMessage( tr( "Could not save unknown editor widget type '%1'." ).arg( widgetType ) );
202  continue;
203  }
204 
205 
206  QDomElement editTypeElement = doc.createElement( "edittype" );
207  editTypeElement.setAttribute( "name", field.name() );
208  editTypeElement.setAttribute( "widgetv2type", widgetType );
209 
210  if ( mWidgetFactories.contains( widgetType ) )
211  {
212  QDomElement ewv2CfgElem = doc.createElement( "widgetv2config" );
213  ewv2CfgElem.setAttribute( "fieldEditable", vectorLayer->fieldEditable( idx ) );
214  ewv2CfgElem.setAttribute( "labelOnTop", vectorLayer->labelOnTop( idx ) );
215 
216  mWidgetFactories[widgetType]->writeConfig( vectorLayer->editorWidgetV2Config( idx ), ewv2CfgElem, doc, vectorLayer, idx );
217 
218  editTypeElement.appendChild( ewv2CfgElem );
219  }
220 
221  editTypesNode.appendChild( editTypeElement );
222  }
223 
224  layerElem.appendChild( editTypesNode );
225 }
const QgsEditorWidgetConfig editorWidgetV2Config(int fieldIdx) const
Get the configuration for the editor widget used to represent the field at the given index...
const QString & name() const
Gets the name of the field.
Definition: qgsfield.cpp:58
void writeMapLayer(QgsMapLayer *mapLayer, QDomElement &layerElem, QDomDocument &doc)
Write all the widget config to a layer XML node.
bool fieldEditable(int idx)
is edit widget editable
Base class for all map layer types.
Definition: qgsmaplayer.h:48
QgsMapLayer::LayerType type() const
Get the type of the layer.
Definition: qgsmaplayer.cpp:89
This class should be subclassed for every configurable editor widget type.
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.
QMap< QString, QgsEditorWidgetFactory * > mWidgetFactories
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:439
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...
static void logMessage(QString message, QString tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
void setContext(const QgsAttributeEditorContext &context)
Set the context in which this widget is shown.
void setConfig(const QgsEditorWidgetConfig &config)
Will set the config of this wrapper to the specified config.
void readMapLayer(QgsMapLayer *mapLayer, const QDomElement &layerElem)
Read all the editor widget information from a map layer XML node.
QgsEditorWidgetWrapper * create(const QString &widgetId, QgsVectorLayer *vl, int fieldIdx, const QgsEditorWidgetConfig &config, QWidget *editor, QWidget *parent, const QgsAttributeEditorContext context=QgsAttributeEditorContext())
Create an attribute editor widget wrapper of a given type for a given field.
const QString editorWidgetV2(int fieldIdx) const
Get the id for the editor widget used to represent the field at the given index.
const QMap< QString, QgsEditorWidgetFactory * > & factories()
Get access to all registered factories.
Every attribute editor widget needs a factory, which inherits this class.
int count() const
Return number of items.
Definition: qgsfield.h:200
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:33
bool labelOnTop(int idx)
label widget on top
void setEditorWidgetV2Config(int attrIdx, const QgsEditorWidgetConfig &config)
Set the editor widget config for a field.
static Q_DECL_DEPRECATED const QString convertEditType(QgsVectorLayer::EditType editType, QgsEditorWidgetConfig &cfg, QgsVectorLayer *vl, const QString &name, const QDomElement editTypeElement=QDomElement())
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:440
void setEditorWidgetV2(int attrIdx, const QString &widgetType)
Set the editor widget type for a field.
static QgsMessageLog * instance()
QString name(const QString &widgetId)
Get the human readable name for a widget type.
static QgsProject * instance()
access to canonical QgsProject instance
Definition: qgsproject.cpp:362
void setFieldEditable(int idx, bool editable)
set edit widget editable
Q_DECL_DEPRECATED const QString readLegacyConfig(QgsVectorLayer *vl, const QDomElement &layerElem, QgsEditorWidgetConfig &cfg)
Read all old-style editor widget configuration from a map node.
QMap< QString, QVariant > QgsEditorWidgetConfig
Holds a set of configuration parameters for a editor widget wrapper.
QWidget * widget()
Access the widget managed by this wrapper.
const QgsFields & pendingFields() const
returns field list in the to-be-committed state
void setLabelOnTop(int idx, bool onTop)
label widget on top
bool registerWidget(const QString &widgetId, QgsEditorWidgetFactory *widgetFactory)
Register a new widget factory with the given id.
Represents a vector layer which manages a vector based data sets.
int fieldNameIndex(const QString &fieldName) const
Returns the index of a field name or -1 if the field does not exist.
modularized edit widgets
#define tr(sourceText)