29#include <QRegularExpression>
36 tableWidget->insertRow( 0 );
38 tableWidget->horizontalHeader()->setSectionsClickable(
true );
39 tableWidget->setSortingEnabled(
true );
41 connect( addNullButton, &QAbstractButton::clicked,
this, &QgsValueMapConfigDlg::addNullButtonPushed );
42 connect( removeSelectedButton, &QAbstractButton::clicked,
this, &QgsValueMapConfigDlg::removeSelectedButtonPushed );
43 connect( loadFromLayerButton, &QAbstractButton::clicked,
this, &QgsValueMapConfigDlg::loadFromLayerButtonPushed );
44 connect( loadFromCSVButton, &QAbstractButton::clicked,
this, &QgsValueMapConfigDlg::loadFromCSVButtonPushed );
45 connect( tableWidget, &QTableWidget::cellChanged,
this, &QgsValueMapConfigDlg::vCellChanged );
46 tableWidget->installEventFilter(
this );
51 QList<QVariant> valueList;
54 for (
int i = 0; i < tableWidget->rowCount() - 1; i++ )
56 QTableWidgetItem *ki = tableWidget->item( i, 0 );
57 QTableWidgetItem *vi = tableWidget->item( i, 1 );
62 QString ks = ki->text();
68 if ( !vi || vi->text().isNull() )
70 value.insert( ks, ks );
74 value.insert( vi->text(), ks );
76 valueList.append( value );
80 cfg.insert( QStringLiteral(
"map" ), valueList );
86 tableWidget->clearContents();
87 for (
int i = tableWidget->rowCount() - 1; i > 0; i-- )
89 tableWidget->removeRow( i );
92 QList<QVariant> valueList =
config.value( QStringLiteral(
"map" ) ).toList();
94 if ( valueList.count() > 0 )
96 for (
int i = 0, row = 0; i < valueList.count(); i++, row++ )
98 setRow( row, valueList[i].toMap().constBegin().value().toString(), valueList[i].toMap().constBegin().key() );
104 const QVariantMap values =
config.value( QStringLiteral(
"map" ) ).toMap();
105 for ( QVariantMap::ConstIterator mit = values.constBegin(); mit != values.constEnd(); mit++, row++ )
108 setRow( row, mit.key(), QString() );
110 setRow( row, mit.value().toString(), mit.key() );
115void QgsValueMapConfigDlg::vCellChanged(
int row,
int column )
118 if ( row == tableWidget->rowCount() - 1 )
120 tableWidget->insertRow( row + 1 );
126void QgsValueMapConfigDlg::removeSelectedButtonPushed()
128 QList<QTableWidgetItem *> list = tableWidget->selectedItems();
129 QSet<int> rowsToRemove;
132 for ( i = 0; i < list.size(); i++ )
134 if ( list[i]->column() == 0 )
136 const int row = list[i]->row();
137 if ( !rowsToRemove.contains( row ) )
139 rowsToRemove.insert( row );
143 for (
const int rowToRemoved : rowsToRemove )
145 tableWidget->removeRow( rowToRemoved - removed );
153 QList<QPair<QString, QVariant>> orderedMap;
154 const auto end = map.constEnd();
155 for (
auto it = map.constBegin(); it != end; ++it )
157 orderedMap.append( qMakePair( it.key(), it.value() ) );
165 tableWidget->clearContents();
166 for (
int i = tableWidget->rowCount() - 1; i > 0; i-- )
168 tableWidget->removeRow( i );
178 for (
const auto &pair : list )
181 setRow( row, pair.first, QString() );
183 setRow( row, pair.first, pair.second.toString() );
190 const QList<QVariant> valueList =
config.value( QStringLiteral(
"map" ) ).toList();
192 if ( !valueList.empty() )
194 for (
const QVariant &value : valueList )
196 const QVariantMap valueMap = value.toMap();
201 comboBox->addItem( valueMap.constBegin().key(), valueMap.constBegin().value() );
206 const QVariantMap map =
config.value( QStringLiteral(
"map" ) ).toMap();
207 for (
auto it = map.constBegin(); it != map.constEnd(); ++it )
212 comboBox->addItem( it.key(), it.value() );
220 if ( event->type() == QEvent::KeyPress )
222 QKeyEvent *keyEvent =
static_cast<QKeyEvent *
>( event );
223 if ( keyEvent->matches( QKeySequence::Copy ) )
225 copySelectionToClipboard();
233void QgsValueMapConfigDlg::setRow(
int row,
const QString &value,
const QString &description )
236 QTableWidgetItem *valueCell =
nullptr;
237 QTableWidgetItem *descriptionCell =
new QTableWidgetItem( description );
238 tableWidget->insertRow( row );
242 cellFont.setItalic(
true );
244 valueCell->setFont( cellFont );
245 valueCell->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled );
246 descriptionCell->setFont( cellFont );
250 valueCell =
new QTableWidgetItem( value );
252 tableWidget->setItem( row, 0, valueCell );
253 tableWidget->setItem( row, 1, descriptionCell );
256void QgsValueMapConfigDlg::copySelectionToClipboard()
258 QAbstractItemModel *model = tableWidget->model();
259 QItemSelectionModel *selection = tableWidget->selectionModel();
260 const QModelIndexList indexes = selection->selectedIndexes();
262 QString clipboardText;
263 QModelIndex previous = indexes.first();
264 std::unique_ptr<QMimeData> mimeData = std::make_unique<QMimeData>();
265 for (
const QModelIndex ¤t : indexes )
267 const QString text = model->data( current ).toString();
268 if ( current.row() != previous.row() )
270 clipboardText.append(
'\n' );
272 else if ( current.column() != previous.column() )
274 clipboardText.append(
'\t' );
276 clipboardText.append( text );
279 mimeData->setData( QStringLiteral(
"text/plain" ), clipboardText.toUtf8() );
280 QApplication::clipboard()->setMimeData( mimeData.release() );
283void QgsValueMapConfigDlg::addNullButtonPushed()
288void QgsValueMapConfigDlg::loadFromLayerButtonPushed()
291 if ( !layerDialog.exec() )
294 updateMap( layerDialog.valueMap(), layerDialog.insertNull() );
297void QgsValueMapConfigDlg::loadFromCSVButtonPushed()
301 const QString fileName = QFileDialog::getOpenFileName(
nullptr, tr(
"Load Value Map from File" ), QDir::homePath() );
302 if ( fileName.isNull() )
311 if ( !f.open( QIODevice::ReadOnly ) )
313 QMessageBox::information(
nullptr,
314 tr(
"Load Value Map from File" ),
315 tr(
"Could not open file %1\nError was: %2" ).arg( filePath, f.errorString() ),
316 QMessageBox::Cancel );
321 s.setAutoDetectUnicode(
true );
323 const thread_local QRegularExpression re(
"(?:^\"|[;,]\")(\"\"|[\\w\\W]*?)(?=\"[;,]|\"$)|(?:^(?!\")|[;,](?!\"))([^;,]*?)(?=$|[;,])|(\\r\\n|\\n)" );
324 QList<QPair<QString, QVariant>> map;
327 const QString l = s.readLine().trimmed();
328 QRegularExpressionMatchIterator matches = re.globalMatch( l );
330 while ( matches.hasNext() && ceils.size() < 2 )
332 const QRegularExpressionMatch match = matches.next();
333 ceils << match.capturedTexts().last().trimmed().replace( QLatin1String(
"\"\"" ), QLatin1String(
"\"" ) );
336 if ( ceils.size() != 2 )
339 QString key = ceils[0];
340 QString val = ceils[1];
343 map.append( qMakePair( key, val ) );
static QString nullRepresentation()
This string is used to represent the value NULL throughout QGIS.
This class is a composition of two QSettings instances:
void loadMapFromCSV(const QString &filePath)
Updates the displayed table with the values from a CSV file.
void setConfig(const QVariantMap &config) override
Update the configuration widget to represent the given configuration.
bool eventFilter(QObject *watched, QEvent *event) override
QgsValueMapConfigDlg(QgsVectorLayer *vl, int fieldIdx, QWidget *parent)
void updateMap(const QMap< QString, QVariant > &map, bool insertNull)
Updates the displayed table with the values from map.
static void populateComboBox(QComboBox *comboBox, const QVariantMap &configuration, bool skipNull)
Populates a comboBox with the appropriate entries based on a value map configuration.
QVariantMap config() override
Create a configuration from the current GUI state.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
Represents a vector layer which manages a vector based data sets.