QGIS API Documentation  3.2.0-Bonn (bc43194)
qgsvaluemapconfigdlg.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsvaluemapconfigdlg.cpp
3  --------------------------------------
4  Date : 5.1.2014
5  Copyright : (C) 2014 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 
16 #include "qgsvaluemapconfigdlg.h"
17 
20 #include "qgsapplication.h"
21 #include "qgssettings.h"
22 
23 #include <QFileDialog>
24 #include <QMessageBox>
25 #include <QTextStream>
26 
27 QgsValueMapConfigDlg::QgsValueMapConfigDlg( QgsVectorLayer *vl, int fieldIdx, QWidget *parent )
28  : QgsEditorConfigWidget( vl, fieldIdx, parent )
29 {
30  setupUi( this );
31 
32  tableWidget->insertRow( 0 );
33 
34  tableWidget->horizontalHeader()->setClickable( true );
35  tableWidget->setSortingEnabled( true );
36 
37  connect( addNullButton, &QAbstractButton::clicked, this, &QgsValueMapConfigDlg::addNullButtonPushed );
38  connect( removeSelectedButton, &QAbstractButton::clicked, this, &QgsValueMapConfigDlg::removeSelectedButtonPushed );
39  connect( loadFromLayerButton, &QAbstractButton::clicked, this, &QgsValueMapConfigDlg::loadFromLayerButtonPushed );
40  connect( loadFromCSVButton, &QAbstractButton::clicked, this, &QgsValueMapConfigDlg::loadFromCSVButtonPushed );
41  connect( tableWidget, &QTableWidget::cellChanged, this, &QgsValueMapConfigDlg::vCellChanged );
42 }
43 
45 {
46  QList<QVariant> valueList;
47 
48  //store data to map
49  for ( int i = 0; i < tableWidget->rowCount() - 1; i++ )
50  {
51  QTableWidgetItem *ki = tableWidget->item( i, 0 );
52  QTableWidgetItem *vi = tableWidget->item( i, 1 );
53 
54  if ( !ki )
55  continue;
56 
57  QString ks = ki->text();
58  if ( ( ks == QgsApplication::nullRepresentation() ) && !( ki->flags() & Qt::ItemIsEditable ) )
60 
61  QVariantMap value;
62 
63  if ( !vi || vi->text().isNull() )
64  {
65  value.insert( ks, ks );
66  }
67  else
68  {
69  value.insert( vi->text(), ks );
70  }
71  valueList.append( value );
72  }
73 
74  QVariantMap cfg;
75  cfg.insert( QStringLiteral( "map" ), valueList );
76  return cfg;
77 }
78 
79 void QgsValueMapConfigDlg::setConfig( const QVariantMap &config )
80 {
81  tableWidget->clearContents();
82  for ( int i = tableWidget->rowCount() - 1; i > 0; i-- )
83  {
84  tableWidget->removeRow( i );
85  }
86 
87  QList<QVariant> valueList = config.value( QStringLiteral( "map" ) ).toList();
88 
89  if ( valueList.count() > 0 )
90  {
91  for ( int i = 0, row = 0; i < valueList.count(); i++, row++ )
92  {
93  setRow( row, valueList[i].toMap().constBegin().value().toString(), valueList[i].toMap().constBegin().key() );
94  }
95  }
96  else
97  {
98  int row = 0;
99  QVariantMap values = config.value( QStringLiteral( "map" ) ).toMap();
100  for ( QVariantMap::ConstIterator mit = values.constBegin(); mit != values.constEnd(); mit++, row++ )
101  {
102  if ( mit.value().isNull() )
103  setRow( row, mit.key(), QString() );
104  else
105  setRow( row, mit.value().toString(), mit.key() );
106  }
107  }
108 }
109 
110 void QgsValueMapConfigDlg::vCellChanged( int row, int column )
111 {
112  Q_UNUSED( column );
113  if ( row == tableWidget->rowCount() - 1 )
114  {
115  tableWidget->insertRow( row + 1 );
116  } //else check type
117 
118  emit changed();
119 }
120 
121 void QgsValueMapConfigDlg::removeSelectedButtonPushed()
122 {
123  QList<QTableWidgetItem *> list = tableWidget->selectedItems();
124  QSet<int> rowsToRemove;
125  int removed = 0;
126  int i;
127  for ( i = 0; i < list.size(); i++ )
128  {
129  if ( list[i]->column() == 0 )
130  {
131  int row = list[i]->row();
132  if ( !rowsToRemove.contains( row ) )
133  {
134  rowsToRemove.insert( row );
135  }
136  }
137  }
138  for ( i = 0; i < rowsToRemove.size(); i++ )
139  {
140  tableWidget->removeRow( rowsToRemove.values().at( i ) - removed );
141  removed++;
142  }
143  emit changed();
144 }
145 
146 void QgsValueMapConfigDlg::updateMap( const QMap<QString, QVariant> &map, bool insertNull )
147 {
148  tableWidget->clearContents();
149  for ( int i = tableWidget->rowCount() - 1; i > 0; i-- )
150  {
151  tableWidget->removeRow( i );
152  }
153  int row = 0;
154 
155  if ( insertNull )
156  {
157  setRow( row, QgsValueMapFieldFormatter::NULL_VALUE, QStringLiteral( "<NULL>" ) );
158  ++row;
159  }
160 
161  for ( QMap<QString, QVariant>::const_iterator mit = map.begin(); mit != map.end(); ++mit, ++row )
162  {
163  if ( mit.value().isNull() )
164  setRow( row, mit.key(), QString() );
165  else
166  setRow( row, mit.key(), mit.value().toString() );
167  }
168 }
169 
170 void QgsValueMapConfigDlg::populateComboBox( QComboBox *comboBox, const QVariantMap &config, bool skipNull )
171 {
172  const QList<QVariant> valueList = config.value( QStringLiteral( "map" ) ).toList();
173 
174  if ( !valueList.empty() )
175  {
176  for ( const QVariant &value : valueList )
177  {
178  const QVariantMap valueMap = value.toMap();
179 
180  if ( skipNull && valueMap.constBegin().value() == QgsValueMapFieldFormatter::NULL_VALUE )
181  continue;
182 
183  comboBox->addItem( valueMap.constBegin().key(), valueMap.constBegin().value() );
184  }
185  }
186  else
187  {
188  const QVariantMap map = config.value( QStringLiteral( "map" ) ).toMap();
189  for ( auto it = map.constBegin(); it != map.constEnd(); ++it )
190  {
191  if ( skipNull && it.value() == QgsValueMapFieldFormatter::NULL_VALUE )
192  continue;
193 
194  comboBox->addItem( it.key(), it.value() );
195  }
196  }
197 }
198 
199 void QgsValueMapConfigDlg::setRow( int row, const QString &value, const QString &description )
200 {
201  QgsSettings settings;
202  QTableWidgetItem *valueCell = nullptr;
203  QTableWidgetItem *descriptionCell = new QTableWidgetItem( description );
204  tableWidget->insertRow( row );
206  {
207  QFont cellFont;
208  cellFont.setItalic( true );
209  valueCell = new QTableWidgetItem( QgsApplication::nullRepresentation() );
210  valueCell->setFont( cellFont );
211  valueCell->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled );
212  descriptionCell->setFont( cellFont );
213  }
214  else
215  {
216  valueCell = new QTableWidgetItem( value );
217  }
218  tableWidget->setItem( row, 0, valueCell );
219  tableWidget->setItem( row, 1, descriptionCell );
220 }
221 
222 void QgsValueMapConfigDlg::addNullButtonPushed()
223 {
224  setRow( tableWidget->rowCount() - 1, QgsValueMapFieldFormatter::NULL_VALUE, QStringLiteral( "<NULL>" ) );
225 }
226 
227 void QgsValueMapConfigDlg::loadFromLayerButtonPushed()
228 {
229  QgsAttributeTypeLoadDialog layerDialog( layer() );
230  if ( !layerDialog.exec() )
231  return;
232 
233  updateMap( layerDialog.valueMap(), layerDialog.insertNull() );
234 }
235 
236 void QgsValueMapConfigDlg::loadFromCSVButtonPushed()
237 {
238  QgsSettings settings;
239 
240  QString fileName = QFileDialog::getOpenFileName( nullptr, tr( "Select a File" ), QDir::homePath() );
241  if ( fileName.isNull() )
242  return;
243 
244  QFile f( fileName );
245 
246  if ( !f.open( QIODevice::ReadOnly ) )
247  {
248  QMessageBox::information( nullptr,
249  tr( "Load Value Map from File" ),
250  tr( "Could not open file %1\nError was: %2" ).arg( fileName, f.errorString() ),
251  QMessageBox::Cancel );
252  return;
253  }
254 
255  QTextStream s( &f );
256  s.setAutoDetectUnicode( true );
257 
258  QRegExp re0( "^([^;]*);(.*)$" );
259  re0.setMinimal( true );
260  QRegExp re1( "^([^,]*),(.*)$" );
261  re1.setMinimal( true );
262  QMap<QString, QVariant> map;
263 
264  s.readLine();
265 
266  while ( !s.atEnd() )
267  {
268  QString l = s.readLine().trimmed();
269 
270  QString key, val;
271  if ( re0.indexIn( l ) >= 0 && re0.captureCount() == 2 )
272  {
273  key = re0.cap( 1 ).trimmed();
274  val = re0.cap( 2 ).trimmed();
275  }
276  else if ( re1.indexIn( l ) >= 0 && re1.captureCount() == 2 )
277  {
278  key = re1.cap( 1 ).trimmed();
279  val = re1.cap( 2 ).trimmed();
280  }
281  else
282  continue;
283 
284  if ( ( key.startsWith( '\"' ) && key.endsWith( '\"' ) ) ||
285  ( key.startsWith( '\'' ) && key.endsWith( '\'' ) ) )
286  {
287  key = key.mid( 1, key.length() - 2 );
288  }
289 
290  if ( ( val.startsWith( '\"' ) && val.endsWith( '\"' ) ) ||
291  ( val.startsWith( '\'' ) && val.endsWith( '\'' ) ) )
292  {
293  val = val.mid( 1, val.length() - 2 );
294  }
295 
296  if ( key == QgsApplication::nullRepresentation() )
298 
299  map[ key ] = val;
300  }
301 
302  updateMap( map, false );
303 }
void updateMap(const QMap< QString, QVariant > &map, bool insertNull)
QgsVectorLayer * layer()
Returns the layer for which this configuration widget applies.
This class should be subclassed for every configurable editor widget type.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:58
QgsValueMapConfigDlg(QgsVectorLayer *vl, int fieldIdx, QWidget *parent)
void setConfig(const QVariantMap &config) override
Update the configuration widget to represent the given configuration.
QMap< QString, QVariant > & valueMap()
Returns the value map which is currently active.
QVariantMap config() override
Create a configuration from the current GUI state.
bool insertNull()
Returns true if the "Add NULL value" checkbox has been checked.
static QString nullRepresentation()
This string is used to represent the value NULL throughout QGIS.
void changed()
Emitted when the configuration of the widget is changed.
Represents a vector layer which manages a vector based data sets.
static const QString NULL_VALUE
Will be saved in the configuration when a value is NULL.
static void populateComboBox(QComboBox *comboBox, const QVariantMap &configuration, bool skipNull)
Populates a comboBox with the appropriate entries based on a value map configuration.