From 39520b1af68803ce9ebe72a6a02a6988a73282b9 Mon Sep 17 00:00:00 2001 From: wonder Date: Wed, 22 Jul 2009 20:56:14 +0000 Subject: [PATCH] [FEATURE] GUI for setting edit widgets for layer attributes. Additionally added a dialog for loading value map from a layer (could be aspatial table too!) Contributed by Richard Kostecky. git-svn-id: http://svn.osgeo.org/qgis/trunk@11149 c8812cc2-4d05-0410-92ff-de0c093fc19c --- src/app/CMakeLists.txt | 4 + src/app/qgsattributetypedialog.cpp | 488 ++++++++++++++++++++++++ src/app/qgsattributetypedialog.h | 136 +++++++ src/app/qgsattributetypeloaddialog.cpp | 210 +++++++++++ src/app/qgsattributetypeloaddialog.h | 98 +++++ src/app/qgsvectorlayerproperties.cpp | 291 +++++++++----- src/app/qgsvectorlayerproperties.h | 11 +- src/ui/qgsattributeloadfrommap.ui | 138 +++++++ src/ui/qgsattributetypeedit.ui | 499 +++++++++++++++++++++++++ 9 files changed, 1777 insertions(+), 98 deletions(-) create mode 100644 src/app/qgsattributetypedialog.cpp create mode 100644 src/app/qgsattributetypedialog.h create mode 100644 src/app/qgsattributetypeloaddialog.cpp create mode 100644 src/app/qgsattributetypeloaddialog.h create mode 100644 src/ui/qgsattributeloadfrommap.ui create mode 100644 src/ui/qgsattributetypeedit.ui diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index 356a66b13666..c0d84fcf5bd0 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -6,6 +6,8 @@ SET(QGIS_APP_SRCS qgsaddattrdialog.cpp qgsattributeactiondialog.cpp qgsattributedialog.cpp + qgsattributetypedialog.cpp + qgsattributetypeloaddialog.cpp qgsbookmarkitem.cpp qgsbookmarks.cpp qgsclipboard.cpp @@ -108,6 +110,8 @@ SET (QGIS_APP_MOC_HDRS qgsaddattrdialog.h qgsattributeactiondialog.h qgsattributedialog.h + qgsattributetypedialog.h + qgsattributetypeloaddialog.h qgsbookmarks.h qgscontinuouscolordialog.h qgsconfigureshortcutsdialog.h diff --git a/src/app/qgsattributetypedialog.cpp b/src/app/qgsattributetypedialog.cpp new file mode 100644 index 000000000000..1eedaef4931d --- /dev/null +++ b/src/app/qgsattributetypedialog.cpp @@ -0,0 +1,488 @@ +/*************************************************************************** + qgsattributetypedialog.cpp - description + ------------------- + begin : June 2009 + copyright : (C) 2000 by Richard Kostecky + email : cSf.Kostej@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* $Id$ */ + +#include "qgsattributetypedialog.h" + +#include "qgsattributetypeloaddialog.h" + +#include "qgsvectordataprovider.h" +#include "qgslogger.h" + +#include + + +QgsAttributeTypeDialog::QgsAttributeTypeDialog( QgsVectorLayer *vl ) + : QDialog(), + mLayer( vl ) +{ + setupUi( this ); + tableWidget->insertRow(0); + connect( selectionComboBox, SIGNAL( currentIndexChanged( int ) ), this, SLOT( setStackPage( int ) ) ); + connect( removeSelectedButton, SIGNAL( pressed( ) ), this, SLOT( removeSelectedButtonPushed( ) ) ); + connect( loadFromLayerButton, SIGNAL( pressed( ) ), this, SLOT( loadFromLayerButtonPushed( ) ) ); + connect( tableWidget, SIGNAL( cellChanged( int, int ) ), this, SLOT( vCellChanged( int, int ) ) ); +} + + +QgsAttributeTypeDialog::~QgsAttributeTypeDialog() +{ + +} + +QgsVectorLayer::EditType QgsAttributeTypeDialog::editType() +{ + return mEditType; +} + +QgsVectorLayer::RangeData QgsAttributeTypeDialog::rangeData() +{ + return mRangeData; +} + +QMap &QgsAttributeTypeDialog::valueMap() +{ + return mValueMap; +} + + +void QgsAttributeTypeDialog::vCellChanged(int row, int column) +{ + if (row == tableWidget->rowCount() -1) + { + tableWidget->insertRow(row + 1); + } //else check type +} + +void QgsAttributeTypeDialog::removeSelectedButtonPushed() +{ + QList list = tableWidget->selectedItems(); + QList::iterator it = list.begin(); + QSet rowsToRemove; + int removed = 0; + int i = 0; + for (; i < list.size(); i++) + { + if (list[i]->column() == 0) + { + int row = list[i]->row(); + if (!rowsToRemove.contains( row )) + { + rowsToRemove.insert( row ); + } + } + } + for (i = 0; i< rowsToRemove.values().size(); i++) + { + tableWidget->removeRow( rowsToRemove.values()[i] - removed ); + removed++; + } +} + +void QgsAttributeTypeDialog::loadFromLayerButtonPushed() +{ + QgsAttributeTypeLoadDialog layerDialog( mLayer ); + if ( !layerDialog.exec() ) + return; + + tableWidget->clearContents(); + for (int i = tableWidget->rowCount() -1; i > 0; i--) + { + tableWidget->removeRow(i); + } + int row = 0; + QMap &map = layerDialog.valueMap(); + for ( QMap::iterator mit = map.begin(); mit != map.end(); mit++, row++ ) + { + tableWidget->insertRow( row ); + if ( mit.value().isNull() ) + { + tableWidget->setItem( row, 0, new QTableWidgetItem( mit.key() ) ); + } + else + { + tableWidget->setItem( row, 0, new QTableWidgetItem( mit.key() ) ); + tableWidget->setItem( row, 1, new QTableWidgetItem( mit.value().toString() ) ); + } + } + +} + + +void QgsAttributeTypeDialog::setPageForIndex( int index ) +{ + if ( mLayer->editType( index ) == QgsVectorLayer::LineEdit ) + { + setPage( 0 ); + } + else if ( mLayer->editType( index ) == QgsVectorLayer::Classification) + { + setPage( 1 ); + } + else if ( mLayer->editType( index ) == QgsVectorLayer::EditRange || + mLayer->editType( index ) == QgsVectorLayer::SliderRange ) + { + setPage( 2 ); + } + else if ( mLayer->editType( index ) == QgsVectorLayer::UniqueValues || + mLayer->editType( index ) == QgsVectorLayer::UniqueValuesEditable ) + { + setPage( 3 ); + } + else if ( mLayer->editType( index ) == QgsVectorLayer::FileName) + { + setPage( 4 ); + } + else if ( mLayer->editType( index ) == QgsVectorLayer::ValueMap) + { + setPage( 5 ); + } + else if ( mLayer->editType( index ) == QgsVectorLayer::Enumeration) + { + setPage( 6 ); + } + else if ( mLayer->editType( index ) == QgsVectorLayer::Immutable) + { + setPage( 7 ); + } +} + +void QgsAttributeTypeDialog::setPageForEditType( QgsVectorLayer::EditType editType ) +{ + if ( editType == QgsVectorLayer::LineEdit ) + { + setPage( 0 ); + } + else if ( editType == QgsVectorLayer::Classification) + { + setPage( 1 ); + } + else if ( editType == QgsVectorLayer::EditRange || + editType == QgsVectorLayer::SliderRange ) + { + setPage( 2 ); + } + else if ( editType == QgsVectorLayer::UniqueValues || + editType == QgsVectorLayer::UniqueValuesEditable ) + { + setPage( 3 ); + } + else if ( editType == QgsVectorLayer::FileName) + { + setPage( 4 ); + } + else if ( editType == QgsVectorLayer::ValueMap) + { + setPage( 5 ); + } + else if ( editType == QgsVectorLayer::Enumeration) + { + setPage( 6 ); + } + else if ( editType == QgsVectorLayer::Immutable) + { + setPage( 7 ); + } +} + +void QgsAttributeTypeDialog::setValueMap(QMap valueMap) +{ + mValueMap = valueMap; +} + +void QgsAttributeTypeDialog::setRange(QgsVectorLayer::RangeData range) +{ + mRangeData = range; +} + +void QgsAttributeTypeDialog::setIndex( int index, int editTypeInt ) +{ + mIndex = index; + //need to set index for combobox + QgsVectorLayer::EditType editType; + if (editTypeInt > -1) + { + editType = QgsVectorLayer::EditType( editTypeInt ); + } + else + { + editType = mLayer->editType( index ); + } + + setWindowTitle( defaultWindowTitle() + " \"" + mLayer->pendingFields()[index].name() + "\""); + QgsAttributeList attributeList = QgsAttributeList(); + attributeList.append( index ); + mLayer->select( attributeList, QgsRectangle(), false ); + + QgsFeature f; + QString text; + //calculate min and max for range for this field + if (mLayer->pendingFields()[index].type() == QVariant::Int) + { + sliderRadioButton->setDisabled( false ); + int min; + int max; + //filling initial values + if (mLayer->nextFeature( f )) + { + min = f.attributeMap()[index].toInt(); + max = f.attributeMap()[index].toInt(); + } + for ( ; mLayer->nextFeature( f ); ) + { + QVariant val = f.attributeMap()[index]; + if ( val.isValid() && !val.isNull() ) + { + int valInt = val.toInt(); + if (min > valInt) + min = valInt; + if (max < valInt) + max = valInt; + } + text = tr( "Current minimum for this value is %1 and current maximum is %2." ).arg( min ).arg( max ); + } + } + else if (mLayer->pendingFields()[index].type() == QVariant::Double) + { + double dMin; + double dMax; + + if (mLayer->nextFeature( f )) + { + dMin = f.attributeMap()[index].toDouble(); + dMax = f.attributeMap()[index].toDouble(); + } + + sliderRadioButton->setDisabled( true ); + editableRadioButton->setChecked( true ); + for ( ; mLayer->nextFeature( f ); ) + { + QVariant val = f.attributeMap()[index]; + if ( val.isValid() && !val.isNull() ) + { + double dVal = val.toDouble(); + if (dMin > dVal) + dMin = dVal; + if (dMax < dVal) + dMax = dVal; + } + text = tr( "Current minimum for this value is %1 and current maximum is %2." ).arg( dMin ).arg( dMax ); + } + } + else + { + text = tr( "Attribute has no integer or real type, threfore range is not usable."); + } + valuesLabel->setText(text); + + //setPageForIndex( index ); + setPageForEditType( editType ); + + if ( editType == QgsVectorLayer::ValueMap) + { + + tableWidget->clearContents(); + for (int i = tableWidget->rowCount() -1; i > 0; i--) + { + tableWidget->removeRow(i); + } + + // if some value map already present use it + QMap map; + if (!mValueMap.empty()) + { + map = mValueMap; + } + else + { + map = mLayer->valueMap( index ); + } + + int row = 0; + for ( QMap::iterator mit = map.begin(); mit != map.end(); mit++, row++ ) + { + tableWidget->insertRow( row ); + if ( mit.value().isNull() ) + { + tableWidget->setItem( row, 0, new QTableWidgetItem( mit.key() ) ); + } + else + { + tableWidget->setItem( row, 0, new QTableWidgetItem( mit.value().toString() ) ); + tableWidget->setItem( row, 1, new QTableWidgetItem( mit.key() ) ); + } + } + + } + else if ( editType == QgsVectorLayer::EditRange || + editType == QgsVectorLayer::SliderRange ) + { + if (mLayer->pendingFields()[mIndex].type() != QVariant::Int) + { + minimumSpinBox->setValue( mLayer->range( index ).mMin.toInt() ); + maximumSpinBox->setValue( mLayer->range( index ).mMax.toInt() ); + stepSpinBox->setValue( mLayer->range( index ).mStep.toInt() ); + } + else if ( mLayer->pendingFields()[mIndex].type() == QVariant::Double ) + { + minimumDoubleSpinBox->setValue( mLayer->range( index ).mMin.toDouble() ); + maximumDoubleSpinBox->setValue( mLayer->range( index ).mMax.toDouble() ); + stepDoubleSpinBox->setValue( mLayer->range( index ).mStep.toDouble() ); + } + if ( editType == QgsVectorLayer::EditRange ) + editableRadioButton->setChecked( true ); + else //slider range + sliderRadioButton->setChecked( true ); + } +} + + +void QgsAttributeTypeDialog::setPage( int index ) +{ + this->selectionComboBox->setCurrentIndex( index ); + setStackPage( index ); +} + +void QgsAttributeTypeDialog::setStackPage( int index ) +{ + this->stackedWidget->setCurrentIndex( index ); + + bool okDisabled = false; + if ( index == 2 ) + { + if (mLayer->pendingFields()[mIndex].type() != QVariant::Double && + mLayer->pendingFields()[mIndex].type() != QVariant::Int) + { + okDisabled = true; + } + else if (mLayer->pendingFields()[mIndex].type() != QVariant::Double) + { + this->rangeStackedWidget->setCurrentIndex( 0 ); + //load data + minimumSpinBox->setValue( mRangeData.mMin.toInt() ); + maximumSpinBox->setValue( mRangeData.mMax.toInt() ); + stepSpinBox->setValue( mRangeData.mStep.toInt() ); + } + else + { + this->rangeStackedWidget->setCurrentIndex( 1 ); + //load data + minimumDoubleSpinBox->setValue( mRangeData.mMin.toDouble() ); + maximumDoubleSpinBox->setValue( mRangeData.mMax.toDouble() ); + stepDoubleSpinBox->setValue( mRangeData.mStep.toDouble() ); + } + } + else if ( index == 6 ) + { + QStringList list; + mLayer->dataProvider()->enumValues( mIndex, list ); + if ( list.size() == 0 ) + { + okDisabled = true; + enumerationWarningLabel->setText( tr( "Enumeration is not available for this attribute" ) ); + } + else + { + enumerationWarningLabel->setText( "" ); + } + + } + stackedWidget->currentWidget()->setDisabled( okDisabled ); + buttonBox->button( QDialogButtonBox::Ok )->setDisabled( okDisabled ); +} + +void QgsAttributeTypeDialog::accept() +{ + //store data to output variables + switch (selectionComboBox->currentIndex()) + { + case 0: + mEditType = QgsVectorLayer::LineEdit; + break; + case 1: + mEditType = QgsVectorLayer::Classification; + break; + case 2: + //store range data + if ( mLayer->pendingFields()[mIndex].type() == QVariant::Int ) + { + mRangeData = QgsVectorLayer::RangeData( minimumSpinBox->value(), + maximumSpinBox->value(), + stepSpinBox->value() ); + } + else + { + mRangeData = QgsVectorLayer::RangeData( minimumDoubleSpinBox->value(), + maximumDoubleSpinBox->value(), + stepDoubleSpinBox->value() ); + } + //select correct one + if (editableRadioButton->isChecked()) + { + mEditType = QgsVectorLayer::EditRange; + } + else + { + mEditType = QgsVectorLayer::SliderRange; + } + break; + case 3: + if (editableUniqueValues->isChecked()) + { + mEditType = QgsVectorLayer::UniqueValuesEditable; + } + else + { + mEditType = QgsVectorLayer::UniqueValues; + } + break; + case 4: + mEditType = QgsVectorLayer::FileName; + break; + case 5: + //store data to map + mValueMap.clear(); + for (int i = 0; i < tableWidget->rowCount() - 1; i++) + { + if ( tableWidget->item(i, 1)->text().isNull() ) + { + mValueMap.insert(tableWidget->item(i, 0)->text(), tableWidget->item(i, 0)->text()); + } + else + { + mValueMap.insert(tableWidget->item(i, 1)->text(), tableWidget->item(i, 0)->text()); + } + } + mEditType = QgsVectorLayer::ValueMap; + break; + case 6: + mEditType = QgsVectorLayer::Enumeration; + break; + case 7: + mEditType = QgsVectorLayer::Immutable; + break; + default: + mEditType = QgsVectorLayer::LineEdit; + } + + QDialog::accept(); +} + +QString QgsAttributeTypeDialog::defaultWindowTitle() +{ + return tr( "Attribute Edit Dialog" ); +} diff --git a/src/app/qgsattributetypedialog.h b/src/app/qgsattributetypedialog.h new file mode 100644 index 000000000000..71ba2c0e8c4a --- /dev/null +++ b/src/app/qgsattributetypedialog.h @@ -0,0 +1,136 @@ +/*************************************************************************** + qgsattributetypedialog.h - description + ------------------- + begin : June 2009 + copyright : (C) 2009 by Richard Kostecky + email : csf.kostej@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* $Id$ */ +#ifndef QGSATTRIBUTETYPEDIALOG_H +#define QGSATTRIBUTETYPEDIALOG_H + +#include "ui_qgsattributetypeedit.h" + +#include "qgsvectorlayer.h" + +class QDialog; +class QLayout; +class QgsField; + +class QgsAttributeTypeDialog: public QDialog, private Ui::QgsAttributeTypeDialog +{ + Q_OBJECT + + public: + QgsAttributeTypeDialog( QgsVectorLayer *vl ); + ~QgsAttributeTypeDialog(); + + /** + * Overloaded accept method which will write the feature field + * values, then delegate to QDialog::accept() + */ + void accept(); + + /** + * Setting index, which page should be selected + * @param index of page to be selected + * @param editTypeInt type of edit type which was selected before save + */ + void setIndex( int index, int editTypeInt = -1 ); + + /** + * Setting page which is to be selected + * @param index index of page which was selected + */ + void setPage( int index ); + + /** + * Getter to get selected edit type + * @return selected edit type + */ + QgsVectorLayer::EditType editType(); + + /** + * Setter to value map variable to display actual value + * @param valueMap map which is to be dispayed in this dialog + */ + void setValueMap( QMap valueMap); + + /** + * Setter to range for to be displayed and edited in this dialog + * @param rangeData rande data which is to be displayed + */ + void setRange( QgsVectorLayer::RangeData rangeData ); + + /** + * Getter for value map after editing + * @return map which is to be returned + */ + QMap &valueMap(); + + /** + * Getter for range data + * @return range data after editing + */ + QgsVectorLayer::RangeData rangeData(); + + private slots: + /** + * Slot to handle change of index in combobox to select correct page + * @param index index of value in combobox + */ + void setStackPage( int index ); + + /** + * Slot to handle button push to delete selected rows + */ + void removeSelectedButtonPushed( ); + + /** + * Slot to handle load from button pushed to display dialo to load data + */ + void loadFromLayerButtonPushed( ); + + /** + * Slot to handle change of cell to have always empty row at end + * @param row index of row which was changed + * @param column index of column which was changed + */ + void vCellChanged( int row, int column ); + + private: + + QString defaultWindowTitle(); + + /** + * Function to set page index + * @param index index of page to be changed + */ + void setPageForIndex( int index ); + + /** + * Function to set page according to edit type + * @param editType edit type to set page + */ + void setPageForEditType( QgsVectorLayer::EditType editType ); + + + QMap mValueMap; + + QgsVectorLayer *mLayer; + int mIndex; + + QgsVectorLayer::RangeData mRangeData; + QgsVectorLayer::EditType mEditType; +}; + +#endif diff --git a/src/app/qgsattributetypeloaddialog.cpp b/src/app/qgsattributetypeloaddialog.cpp new file mode 100644 index 000000000000..c2db1cae99e3 --- /dev/null +++ b/src/app/qgsattributetypeloaddialog.cpp @@ -0,0 +1,210 @@ +/*************************************************************************** + qgsattributetypeloaddialog.cpp + ------------------- + begin : June 2009 + copyright : (C) 2000 by Richard Kostecky + email : cSf.Kostej@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* $Id$ */ + +#include "qgsattributetypeloaddialog.h" + +#include "qgsmaplayer.h" +#include "qgsvectordataprovider.h" +#include "qgslogger.h" +#include "qgsmaplayerregistry.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QgsAttributeTypeLoadDialog::QgsAttributeTypeLoadDialog( QgsVectorLayer *vl ) + : QDialog(), + mLayer( vl ) +{ + setupUi( this ); + + connect( layerComboBox, SIGNAL( currentIndexChanged( int ) ), this, SLOT( fillComboBoxes( int ) ) ); + connect( keyComboBox, SIGNAL( currentIndexChanged( int ) ), this, SLOT( createPreview( int ) ) ); + connect( valueComboBox, SIGNAL( currentIndexChanged( int ) ), this, SLOT( createPreview( int ) ) ); + connect( previewButton, SIGNAL( pressed( ) ), this, SLOT( previewButtonPushed( ) ) ); + + fillLayerList(); +} + + +QgsAttributeTypeLoadDialog::~QgsAttributeTypeLoadDialog() +{ + +} + + +void QgsAttributeTypeLoadDialog::setVectorLayer( QgsVectorLayer *layer ) +{ + mLayer = layer; +} + + + +void QgsAttributeTypeLoadDialog::previewButtonPushed() +{ + createPreview( valueComboBox->currentIndex(), true); +} + +void QgsAttributeTypeLoadDialog::fillLayerList() +{ + layerComboBox->clear(); + int i = 0; + QgsMapLayer* dataLayer; + QMap::iterator layer_it = QgsMapLayerRegistry::instance()->mapLayers().begin(); + for ( ; layer_it != QgsMapLayerRegistry::instance()->mapLayers().end(); layer_it++ ) + { + layerComboBox->addItem( layer_it.key() ); + } +} + +void QgsAttributeTypeLoadDialog::fillComboBoxes( int layerIndex ) +{ + //clear comboboxes first + keyComboBox->clear(); + valueComboBox->clear(); + + if (layerIndex < 0) + { + return; + } + + QgsMapLayer* dataLayer = QgsMapLayerRegistry::instance()->mapLayer( layerComboBox->currentText() ); + QgsVectorLayer* vLayer = dynamic_cast( dataLayer ); + if (vLayer == NULL) + { + return; + } + QMap fieldMap = vLayer->dataProvider()->fieldNameMap(); + QMap::iterator it = fieldMap.begin(); + for (; it != fieldMap.end(); it++) + { + keyComboBox->addItem(it.key(), it.value()); + valueComboBox->addItem(it.key(), it.value()); + } + +} + +void QgsAttributeTypeLoadDialog::createPreview( int fieldIndex, bool full) +{ + previewTableWidget->clearContents(); + + for (int i = previewTableWidget->rowCount() -1; i > 0; i--) + { + previewTableWidget->removeRow(i); + } + if (layerComboBox->currentIndex() < 0 || fieldIndex < 0 ) + { + //when nothing is selected there is no reason for preview + return; + } + int idx = keyComboBox->itemData(keyComboBox->currentIndex()).toInt(); + int idx2 = valueComboBox->itemData(valueComboBox->currentIndex()).toInt(); + QgsMapLayer* dataLayer = QgsMapLayerRegistry::instance()->mapLayer( layerComboBox->currentText() ); + QgsVectorLayer* vLayer = dynamic_cast( dataLayer ); + if (vLayer == NULL) + { + return; + } + + QgsVectorDataProvider* dataProvider = vLayer->dataProvider(); + dataProvider->enableGeometrylessFeatures( true ); + + QgsAttributeList attributeList = QgsAttributeList(); + attributeList.append( idx ); + attributeList.append( idx2 ); + vLayer->select( attributeList, QgsRectangle(), false ); + + QgsFeature f; + QMap valueMap; + while ( vLayer->nextFeature( f ) ) + { + QVariant val1 = f.attributeMap()[idx]; + QVariant val2 = f.attributeMap()[idx2]; + if ( val1.isValid() && !val1.isNull() && !val1.toString().isEmpty() + && val2.isValid() && !val2.isNull() && !val2.toString().isEmpty() ) + { + valueMap.insert(val1.toString(), val2.toString() ); + } + if (!full && valueMap.size() > 8) + break; //just first entries all on button + } + int row = 0; + for ( QMap::iterator mit = valueMap.begin(); mit != valueMap.end(); mit++, row++ ) + { + previewTableWidget->insertRow( row ); + previewTableWidget->setItem( row, 0, new QTableWidgetItem( mit.value().toString() ) ); + previewTableWidget->setItem( row, 1, new QTableWidgetItem( mit.key() ) ); + } + + dataProvider->enableGeometrylessFeatures( false ); +} + +QMap &QgsAttributeTypeLoadDialog::valueMap() +{ + return mValueMap; +} + +void QgsAttributeTypeLoadDialog::loadDataToValueMap() +{ + mValueMap.clear(); + int idx = keyComboBox->itemData(keyComboBox->currentIndex()).toInt(); + int idx2 = valueComboBox->itemData(valueComboBox->currentIndex()).toInt(); + QgsMapLayer* dataLayer = QgsMapLayerRegistry::instance()->mapLayer( layerComboBox->currentText() ); + QgsVectorLayer* vLayer = dynamic_cast( dataLayer ); + if (vLayer == NULL) + { + return; + } + + QgsVectorDataProvider* dataProvider = vLayer->dataProvider(); + dataProvider->enableGeometrylessFeatures( true ); + + QgsAttributeList attributeList = QgsAttributeList(); + attributeList.append( idx ); + attributeList.append( idx2 ); + vLayer->select( attributeList, QgsRectangle(), false ); + + QgsFeature f; + while ( vLayer->nextFeature( f ) ) + { + QVariant val = f.attributeMap()[idx]; + if ( val.isValid() && !val.isNull() && !val.toString().isEmpty() ) + { + mValueMap.insert(f.attributeMap()[idx2].toString(), val ); + } + } + dataProvider->enableGeometrylessFeatures( false ); +} + + + +void QgsAttributeTypeLoadDialog::accept() +{ + //store data to output variable + loadDataToValueMap(); + QDialog::accept(); +} + diff --git a/src/app/qgsattributetypeloaddialog.h b/src/app/qgsattributetypeloaddialog.h new file mode 100644 index 000000000000..9229cb67bb33 --- /dev/null +++ b/src/app/qgsattributetypeloaddialog.h @@ -0,0 +1,98 @@ +/*************************************************************************** + qgsattributetypeloaddialog.h + ------------------- + begin : June 2009 + copyright : (C) 2009 by Richard Kostecky + email : csf.kostej@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* $Id$ */ +#ifndef QGSATTRIBUTETYPELOADDIALOG_H +#define QGSATTRIBUTETYPELOADDIALOG_H + +#include "ui_qgsattributeloadfrommap.h" + +#include "qgsfeature.h" +#include "qgsvectorlayer.h" +#include + +class QDialog; +class QLayout; +class QgsField; +class QgsMapCanvas; + +class QgsAttributeTypeLoadDialog: public QDialog, private Ui::QgsAttributeLoadValues +{ + Q_OBJECT + + public: + QgsAttributeTypeLoadDialog( QgsVectorLayer *vl ); + ~QgsAttributeTypeLoadDialog(); + + /** + * Overloaded accept method which will write the feature field + * values, then delegate to QDialog::accept() + */ + void accept(); + + /** + * Sets predefined vector layer for selection of data + * @param layer Vector layer which is to be set as predefined one + */ + void setVectorLayer( QgsVectorLayer *layer ); + + /** + * Getter to value map which is currently active + * @return value map of vlues selected from layer + */ + QMap &valueMap(); + + private slots: + /** + * Slot which reacts to change of selected layer to fill other two comboboxes with correct data + * @param layerIndex index of layer which was selected + */ + void fillComboBoxes( int layerIndex ); + + /** + * Slot to react to button push or change of selected column for display of preview + * @param fieldIndex indexOfChangedField + * @param full flag if all values should be displayed or just preview of first 10 + */ + void createPreview( int fieldIndex, bool full = false); + + + /** + * Slot to react to value Preview button pushed + */ + void previewButtonPushed( ); + + private: + + /** + * Internal function to fill the list of layers + */ + void fillLayerList(); + + /** + * Function to transfer data from layer to value map used in editing + */ + void loadDataToValueMap(); + + QgsVectorLayer *mLayer; + int mIndex; + + + QMap mValueMap; + QgsVectorLayer::EditType mEditType; +}; + +#endif diff --git a/src/app/qgsvectorlayerproperties.cpp b/src/app/qgsvectorlayerproperties.cpp index 13d02b2b1dc5..e7a9803623a1 100644 --- a/src/app/qgsvectorlayerproperties.cpp +++ b/src/app/qgsvectorlayerproperties.cpp @@ -64,7 +64,8 @@ QgsVectorLayerProperties::QgsVectorLayerProperties( QgsVectorLayer *lyr, QWidget * parent, - Qt::WFlags fl ) + Qt::WFlags fl + ) : QDialog( parent, fl ), layer( lyr ), mRendererDialog( 0 ) @@ -90,6 +91,7 @@ QgsVectorLayerProperties::QgsVectorLayerProperties( mDeleteAttributeButton->setIcon( QgisApp::getThemeIcon( "/mActionDeleteAttribute.png" ) ); mToggleEditingButton->setIcon( QgisApp::getThemeIcon( "/mActionToggleEditing.png" ) ); + // Create the Label dialog tab QVBoxLayout *layout = new QVBoxLayout( labelOptionsFrame ); layout->setMargin( 0 ); @@ -146,7 +148,7 @@ void QgsVectorLayerProperties::loadRows() tblAttributes->clear(); - tblAttributes->setColumnCount( 9 ); + tblAttributes->setColumnCount( 8 ); tblAttributes->setRowCount( fields.size() ); tblAttributes->setHorizontalHeaderItem( 0, new QTableWidgetItem( tr( "id" ) ) ); tblAttributes->setHorizontalHeaderItem( 1, new QTableWidgetItem( tr( "name" ) ) ); @@ -155,8 +157,7 @@ void QgsVectorLayerProperties::loadRows() tblAttributes->setHorizontalHeaderItem( 4, new QTableWidgetItem( tr( "precision" ) ) ); tblAttributes->setHorizontalHeaderItem( 5, new QTableWidgetItem( tr( "comment" ) ) ); tblAttributes->setHorizontalHeaderItem( 6, new QTableWidgetItem( tr( "edit widget" ) ) ); - tblAttributes->setHorizontalHeaderItem( 7, new QTableWidgetItem( tr( "values" ) ) ); - tblAttributes->setHorizontalHeaderItem( 8, new QTableWidgetItem( tr( "alias" ) ) ); + tblAttributes->setHorizontalHeaderItem( 7, new QTableWidgetItem( tr( "alias" ) ) ); tblAttributes->setSelectionBehavior( QAbstractItemView::SelectRows ); tblAttributes->setSelectionMode( QAbstractItemView::MultiSelection ); @@ -180,61 +181,144 @@ void QgsVectorLayerProperties::setRow( int row, int idx, const QgsField &field ) for ( int i = 0; i < 6; i++ ) tblAttributes->item( row, i )->setFlags( tblAttributes->item( row, i )->flags() & ~Qt::ItemIsEditable ); - QComboBox *cb = new QComboBox(); - cb->addItem( tr( "line edit" ), QgsVectorLayer::LineEdit ); - cb->addItem( tr( "unique values" ), QgsVectorLayer::UniqueValues ); - cb->addItem( tr( "unique values (editable)" ), QgsVectorLayer::UniqueValuesEditable ); - cb->addItem( tr( "value map" ), QgsVectorLayer::ValueMap ); - cb->addItem( tr( "classification" ), QgsVectorLayer::Classification ); - cb->addItem( tr( "range (editable)" ), QgsVectorLayer::EditRange ); - cb->addItem( tr( "range (slider)" ), QgsVectorLayer::SliderRange ); - cb->addItem( tr( "file name" ), QgsVectorLayer::FileName ); - cb->addItem( tr( "enumeration" ), QgsVectorLayer::Enumeration ); - cb->addItem( tr( "immutable" ), QgsVectorLayer::Immutable ); - cb->setSizeAdjustPolicy( QComboBox::AdjustToContentsOnFirstShow ); - cb->setCurrentIndex( layer->editType( idx ) ); - - tblAttributes->setCellWidget( row, 6, cb ); - - if ( layer->editType( idx ) == QgsVectorLayer::ValueMap ) - { - // TODO: create a gui for value maps - QStringList mapList; - QMap &map = layer->valueMap( idx ); - for ( QMap::iterator mit = map.begin(); mit != map.end(); mit++ ) - { - QgsDebugMsg( QString( "idx:%1 key:%2 value:%3" ).arg( idx ).arg( mit.key() ).arg( mit.value().toString() ) ); - if ( mit.value().isNull() ) - mapList << mit.key(); - else - mapList << QString( "%1=%2" ).arg( mit.key() ).arg( mit.value().toString() ); - } - - tblAttributes->setItem( row, 7, new QTableWidgetItem( mapList.join( ";" ) ) ); - } - else if ( layer->editType( idx ) == QgsVectorLayer::EditRange || - layer->editType( idx ) == QgsVectorLayer::SliderRange ) + QString buttonText; + switch (layer->editType( idx )) { - tblAttributes->setItem( - row, 7, - new QTableWidgetItem( QString( "%1;%2;%3" ) - .arg( layer->range( idx ).mMin.toString() ) - .arg( layer->range( idx ).mMax.toString() ) - .arg( layer->range( idx ).mStep.toString() ) - ) - ); + case QgsVectorLayer::LineEdit: + buttonText = "Line Edit"; + break; + case QgsVectorLayer::UniqueValues: + buttonText = "Unique Values"; + break; + case QgsVectorLayer::UniqueValuesEditable: + buttonText = "Unique Values Editable"; + break; + case QgsVectorLayer::Classification: + buttonText = "Classification"; + break; + case QgsVectorLayer::ValueMap: + buttonText = "Value Map"; + break; + case QgsVectorLayer::EditRange: + buttonText = "Edit Range"; + break; + case QgsVectorLayer::SliderRange: + buttonText = "Slider Range"; + break; + case QgsVectorLayer::FileName: + buttonText = "File Name"; + break; + case QgsVectorLayer::Enumeration: + buttonText = tr( "Enumeration" ); + break; + case QgsVectorLayer::Immutable: + buttonText = tr( "Immutable" ); + break; } + QPushButton * pb = new QPushButton(buttonText); + tblAttributes->setCellWidget( row, 6, pb ); + connect( pb, SIGNAL( pressed() ), this, SLOT( attributeTypeDialog( ) ) ); + mButtonMap.insert( idx, pb ); //set the alias for the attribute - tblAttributes->setItem( row, 8, new QTableWidgetItem( layer->attributeAlias( idx ) ) ); -} + tblAttributes->setItem( row, 7, new QTableWidgetItem(layer->attributeAlias(idx))); +} QgsVectorLayerProperties::~QgsVectorLayerProperties() { disconnect( labelDialog, SIGNAL( labelSourceSet() ), this, SLOT( setLabelCheckBox() ) ); } +void QgsVectorLayerProperties::attributeTypeDialog( ) +{ + int index = -1; + QMap::iterator it = mButtonMap.begin(); + for (; it != mButtonMap.end() ;it++) + { + if (it.value()->isDown()) + { + index = it.key(); + } + } + + QgsAttributeTypeDialog attributeTypeDialog( layer ); + + if (mValueMaps.contains(index)) + { + attributeTypeDialog.setValueMap(mValueMaps[index]); + } + else + { + attributeTypeDialog.setValueMap( QMap() ); + } + + if (mRanges.contains(index)) + { + attributeTypeDialog.setRange( mRanges[index] ); + } + else + { + attributeTypeDialog.setRange( QgsVectorLayer::RangeData(0, 5, 1)); + } + + if (mEditTypeMap.contains(index)) + { + attributeTypeDialog.setIndex( index, mEditTypeMap[index] ); + } + else + { + attributeTypeDialog.setIndex( index ); + } + + if (!attributeTypeDialog.exec()) + return; + + QgsVectorLayer::EditType editType = attributeTypeDialog.editType(); + mEditTypeMap.insert(index, editType); + QString buttonText; + switch ( editType ) + { + case QgsVectorLayer::LineEdit: + buttonText = "Line Edit"; + break; + case QgsVectorLayer::UniqueValues: + buttonText = "Unique Values"; + break; + case QgsVectorLayer::UniqueValuesEditable: + buttonText = "Unique Values Editable"; + break; + case QgsVectorLayer::Classification: + buttonText = "Classification"; + break; + case QgsVectorLayer::ValueMap: + buttonText = "Value Map"; + mValueMaps.insert(index, attributeTypeDialog.valueMap() ); + break; + case QgsVectorLayer::EditRange: + buttonText = "Edit Range"; + mRanges.insert(index, attributeTypeDialog.rangeData()); + break; + case QgsVectorLayer::SliderRange: + buttonText = "Slider Range"; + mRanges.insert(index, attributeTypeDialog.rangeData()); + break; + case QgsVectorLayer::FileName: + buttonText = "File Name"; + break; + case QgsVectorLayer::Enumeration: + buttonText = "Enumeration"; + break; + case QgsVectorLayer::Immutable: + buttonText = "Immutable"; + break; + } + QPushButton *pb = dynamic_cast( tblAttributes->cellWidget( index, 6 ) ); + pb->setText( buttonText ); + +} + + void QgsVectorLayerProperties::toggleEditing() { emit toggleEditing( layer ); @@ -267,10 +351,16 @@ void QgsVectorLayerProperties::addAttribute() QgsAddAttrDialog dialog( layer->dataProvider(), this ); if ( dialog.exec() == QDialog::Accepted ) { + layer->beginEditCommand("Attribute added"); if ( !addAttribute( dialog.field() ) ) { + layer->destroyEditCommand(); QMessageBox::information( this, tr( "Name conflict" ), tr( "The attribute could not be inserted. The name already exists in the table." ) ); } + else + { + layer->endEditCommand(); + } } } @@ -300,7 +390,6 @@ void QgsVectorLayerProperties::deleteAttribute() if (( *it )->column() == 0 ) idxs << ( *it )->text().toInt(); } - for ( QList::const_iterator it = idxs.begin(); it != idxs.end(); it++ ) { layer->beginEditCommand( tr( "Deleted attribute" ) ); @@ -506,6 +595,53 @@ void QgsVectorLayerProperties::on_buttonBox_helpRequested() QgsContextHelp::run( context_id ); } + +QgsVectorLayer::EditType QgsVectorLayerProperties::getEditType(QString text) +{ + if (text == "Line Edit") + { + return QgsVectorLayer::LineEdit; + } + else if (text == "Unique Values") + { + return QgsVectorLayer::UniqueValues; + } + else if (text == "Unique Values Editable") + { + return QgsVectorLayer::UniqueValuesEditable; + } + else if (text == "Classification") + { + return QgsVectorLayer::Classification; + } + else if (text == "Value Map") + { + return QgsVectorLayer::ValueMap; + } + else if (text == "Edit Range") + { + return QgsVectorLayer::EditRange; + } + else if (text == "Slider Range") + { + return QgsVectorLayer::SliderRange; + } + else if (text == "File Name") + { + return QgsVectorLayer::FileName; + } + else if (text == "Enumeration") + { + return QgsVectorLayer::Enumeration; + } + else if (text == "Immutable") + { + return QgsVectorLayer::Immutable; + } + return QgsVectorLayer::LineEdit; +} + + void QgsVectorLayerProperties::apply() { // @@ -546,67 +682,28 @@ void QgsVectorLayerProperties::apply() int idx = tblAttributes->item( i, 0 )->text().toInt(); const QgsField &field = layer->pendingFields()[idx]; - QComboBox *cb = dynamic_cast( tblAttributes->cellWidget( i, 6 ) ); - if ( !cb ) + QPushButton *pb = dynamic_cast( tblAttributes->cellWidget( i, 6 ) ); + if ( !pb ) continue; - QgsVectorLayer::EditType editType = ( QgsVectorLayer::EditType ) cb->itemData( cb->currentIndex() ).toInt(); + QgsVectorLayer::EditType editType = getEditType( pb->text()); layer->setEditType( idx, editType ); - QString value = tblAttributes->item( i, 7 ) ? tblAttributes->item( i, 7 )->text() : QString::null; - if ( editType == QgsVectorLayer::ValueMap ) { - QMap &map = layer->valueMap( idx ); - map.clear(); - - if ( !value.isEmpty() ) + if (mValueMaps.contains( idx )) { - QStringList values = value.split( ";" ); - for ( int j = 0; j < values.size(); j++ ) - { - QStringList args = values[j].split( "=" ); - QVariant value; - - if ( args.size() == 1 || ( args.size() == 2 && args[0] == args[1] ) ) - { - QgsDebugMsg( QString( "idx:%1 key:%2 value:%2" ).arg( idx ).arg( args[0] ) ); - value = args[0]; - } - else if ( args.size() == 2 ) - { - QgsDebugMsg( QString( "idx:%1 key:%2 value:%3" ).arg( idx ).arg( args[0] ).arg( args[1] ) ); - value = args[1]; - - } - - if ( value.canConvert( field.type() ) ) - { - map.insert( args[0], value ); - } - } + QMap &map = layer->valueMap( idx ); + map.clear(); + map = mValueMaps[idx]; } } else if ( editType == QgsVectorLayer::EditRange || editType == QgsVectorLayer::SliderRange ) { - QStringList values = value.split( ";" ); - - if ( values.size() == 3 ) + if (mRanges.contains( idx ) ) { - QVariant min = values[0]; - QVariant max = values[1]; - QVariant step = values[2]; - - if ( min.canConvert( field.type() ) && - max.canConvert( field.type() ) && - step.canConvert( field.type() ) ) - { - min.convert( field.type() ); - max.convert( field.type() ); - step.convert( field.type() ); - layer->range( idx ) = QgsVectorLayer::RangeData( min, max, step ); - } + layer->range( idx ) = mRanges[idx]; } } } diff --git a/src/app/qgsvectorlayerproperties.h b/src/app/qgsvectorlayerproperties.h index ff5c9ef3599d..f96c0d54033a 100644 --- a/src/app/qgsvectorlayerproperties.h +++ b/src/app/qgsvectorlayerproperties.h @@ -25,7 +25,9 @@ #include "qgsrenderer.h" #include "qgsaddattrdialog.h" #include "qgsdelattrdialog.h" +#include "qgsattributetypedialog.h" #include "qgsfield.h" +#include "qgsmapcanvas.h" class QgsMapLayer; @@ -39,7 +41,7 @@ class QgsVectorLayerProperties : public QDialog, private Ui::QgsVectorLayerPrope { Q_OBJECT public: - QgsVectorLayerProperties( QgsVectorLayer *lyr = 0, QWidget *parent = 0, Qt::WFlags fl = QgisGui::ModalDialogFlags ); + QgsVectorLayerProperties( QgsVectorLayer *lyr = 0, QWidget *parent = 0, Qt::WFlags fl = QgisGui::ModalDialogFlags); ~QgsVectorLayerProperties(); /**Sets the legend type to "single symbol", "graduated symbol" or "continuous color"*/ void setLegendType( QString type ); @@ -61,6 +63,8 @@ class QgsVectorLayerProperties : public QDialog, private Ui::QgsVectorLayerPrope public slots: + void attributeTypeDialog(); + void alterLayerDialog( const QString& string ); /** Reset to original (vector layer) values */ @@ -123,6 +127,10 @@ class QgsVectorLayerProperties : public QDialog, private Ui::QgsVectorLayerPrope QgsAttributeActionDialog* actionDialog; QList mOverlayDialogs; + QMap mButtonMap; + QMap mEditTypeMap; + QMap > mValueMaps; + QMap mRanges; void updateButtons(); void loadRows(); @@ -135,6 +143,7 @@ class QgsVectorLayerProperties : public QDialog, private Ui::QgsVectorLayerPrope //QPixmap bufferPixmap; static const int context_id = 94000531; + QgsVectorLayer::EditType getEditType(QString text); }; inline QString QgsVectorLayerProperties::displayName() diff --git a/src/ui/qgsattributeloadfrommap.ui b/src/ui/qgsattributeloadfrommap.ui new file mode 100644 index 000000000000..24d253c36be8 --- /dev/null +++ b/src/ui/qgsattributeloadfrommap.ui @@ -0,0 +1,138 @@ + + + QgsAttributeLoadValues + + + + 0 + 0 + 362 + 374 + + + + Load values from layer + + + + + 10 + 340 + 341 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + 10 + 10 + 341 + 331 + + + + + + + Layer + + + + + + + Description + + + + + + + + + + + Value + + + + + Description + + + + + + + + Select data from attributes in selected layer. + + + + + + + Value + + + + + + + + + + View All + + + + + + + + + + + + + buttonBox + accepted() + QgsAttributeLoadValues + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + QgsAttributeLoadValues + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/ui/qgsattributetypeedit.ui b/src/ui/qgsattributetypeedit.ui new file mode 100644 index 000000000000..420b9455fe9c --- /dev/null +++ b/src/ui/qgsattributetypeedit.ui @@ -0,0 +1,499 @@ + + + QgsAttributeTypeDialog + + + + 0 + 0 + 401 + 428 + + + + Attribute Edit Dialog + + + + + + + Line edit + + + + + Classification + + + + + Range + + + + + Unique values + + + + + File name + + + + + Value map + + + + + Enumeration + + + + + Immutable + + + + + + + + 0 + + + + + + + Simple edit box. This is the default editation widget. + + + + + + + Qt::Vertical + + + + 20 + 321 + + + + + + + + + + + + Displays combo box containing values of attribute used for classification. + + + true + + + + + + + Qt::Vertical + + + + 20 + 304 + + + + + + + + + + + + + + Allows to set numeric values from a specified range. The edit widget can be either a slider or a spin box. + + + true + + + + + + + + + Minimum + + + + + + + Maximum + + + + + + + Step + + + + + + + 1 + + + + + + + 999999999 + + + + + + + 999999999 + + + 5 + + + + + + + 999999999 + + + 1 + + + + + + + + + + + 999999999.990000009536743 + + + + + + + 999999999.990000009536743 + + + 5.000000000000000 + + + + + + + 999999999.990000009536743 + + + 1.000000000000000 + + + + + + + + + + + + + Slider + + + true + + + + + + + Editable + + + + + + + Local minimum/maximum = 0/0 + + + true + + + + + + + + + + + + + + + The user can select one of the values already used in the attribute. If editable, a line edit is shown with autocompletion support, otherwise a combo box is used. + + + true + + + + + + + Editable + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + Simplifies file selection by adding a file chooser dialog. + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + Combo box with predefined items. Value is stored in the attribute, description is shown in the combo box. + + + true + + + + + + + Load Data from layer + + + + + + + Qt::Horizontal + + + + 227 + 20 + + + + + + + + + Value + + + + + Description + + + + + + + + Remove Selected + + + + + + + Qt::Horizontal + + + + 227 + 20 + + + + + + + + + + + + Combo box with values that can be used within the column's type. Must be supported by the provider. + + + true + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 304 + + + + + + + + + + + + Immutable attribute is read-only - user is not able to modify the contents. + + + true + + + + + + + Qt::Vertical + + + + 20 + 304 + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + QgsAttributeTypeDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + QgsAttributeTypeDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + +