mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-16 00:03:12 -04:00
New functionality for merging features
git-svn-id: http://svn.osgeo.org/qgis/trunk@10879 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
parent
aa18385d53
commit
dbaf7bd454
BIN
images/themes/default/mActionFromSelectedFeature.png
Normal file
BIN
images/themes/default/mActionFromSelectedFeature.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
BIN
images/themes/default/mActionMergeFeatures.png
Normal file
BIN
images/themes/default/mActionMergeFeatures.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
BIN
images/themes/default/mActionRemoveSelectedFeature.png
Normal file
BIN
images/themes/default/mActionRemoveSelectedFeature.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
@ -41,6 +41,7 @@ SET(QGIS_APP_SRCS
|
|||||||
qgsmaptoolvertexedit.cpp
|
qgsmaptoolvertexedit.cpp
|
||||||
qgsmeasuredialog.cpp
|
qgsmeasuredialog.cpp
|
||||||
qgsmeasuretool.cpp
|
qgsmeasuretool.cpp
|
||||||
|
qgsmergeattributesdialog.cpp
|
||||||
qgsnewhttpconnection.cpp
|
qgsnewhttpconnection.cpp
|
||||||
qgsnumericsortlistviewitem.cpp
|
qgsnumericsortlistviewitem.cpp
|
||||||
qgsogrsublayersdialog.cpp
|
qgsogrsublayersdialog.cpp
|
||||||
@ -129,6 +130,7 @@ SET (QGIS_APP_MOC_HDRS
|
|||||||
|
|
||||||
qgsmeasuretool.h
|
qgsmeasuretool.h
|
||||||
qgsmeasuredialog.h
|
qgsmeasuredialog.h
|
||||||
|
qgsmergeattributesdialog.h
|
||||||
qgsnewhttpconnection.h
|
qgsnewhttpconnection.h
|
||||||
qgsoptions.h
|
qgsoptions.h
|
||||||
qgsogrsublayersdialog.h
|
qgsogrsublayersdialog.h
|
||||||
|
@ -114,6 +114,7 @@
|
|||||||
#include "qgsmapoverviewcanvas.h"
|
#include "qgsmapoverviewcanvas.h"
|
||||||
#include "qgsmaprenderer.h"
|
#include "qgsmaprenderer.h"
|
||||||
#include "qgsmaptip.h"
|
#include "qgsmaptip.h"
|
||||||
|
#include "qgsmergeattributesdialog.h"
|
||||||
#include "qgsmessageviewer.h"
|
#include "qgsmessageviewer.h"
|
||||||
#include "qgsoptions.h"
|
#include "qgsoptions.h"
|
||||||
#include "qgspastetransformations.h"
|
#include "qgspastetransformations.h"
|
||||||
@ -703,6 +704,12 @@ void QgisApp::createActions()
|
|||||||
connect( mActionDeletePart, SIGNAL( triggered() ), this, SLOT( deletePart() ) );
|
connect( mActionDeletePart, SIGNAL( triggered() ), this, SLOT( deletePart() ) );
|
||||||
mActionDeletePart->setEnabled( false );
|
mActionDeletePart->setEnabled( false );
|
||||||
|
|
||||||
|
mActionMergeFeatures = new QAction( getThemeIcon("mActionMergeFeatures.png"), tr("Merge selected features"), this);
|
||||||
|
shortcuts->registerAction(mActionMergeFeatures);
|
||||||
|
mActionMergeFeatures->setStatusTip( tr("Merge selected features"));
|
||||||
|
connect( mActionMergeFeatures, SIGNAL(triggered()), this, SLOT(mergeSelectedFeatures()));
|
||||||
|
mActionMergeFeatures->setEnabled(false);
|
||||||
|
|
||||||
|
|
||||||
// View Menu Items
|
// View Menu Items
|
||||||
|
|
||||||
@ -1053,6 +1060,7 @@ void QgisApp::createActionGroups()
|
|||||||
mMapToolGroup->addAction( mActionDeleteRing );
|
mMapToolGroup->addAction( mActionDeleteRing );
|
||||||
mActionDeletePart->setCheckable( true );
|
mActionDeletePart->setCheckable( true );
|
||||||
mMapToolGroup->addAction( mActionDeletePart );
|
mMapToolGroup->addAction( mActionDeletePart );
|
||||||
|
mMapToolGroup->addAction( mActionMergeFeatures);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgisApp::createMenus()
|
void QgisApp::createMenus()
|
||||||
@ -1141,6 +1149,7 @@ void QgisApp::createMenus()
|
|||||||
mEditMenu->addAction( mActionAddIsland );
|
mEditMenu->addAction( mActionAddIsland );
|
||||||
mEditMenu->addAction( mActionDeleteRing );
|
mEditMenu->addAction( mActionDeleteRing );
|
||||||
mEditMenu->addAction( mActionDeletePart );
|
mEditMenu->addAction( mActionDeletePart );
|
||||||
|
mEditMenu->addAction( mActionMergeFeatures );
|
||||||
|
|
||||||
if ( layout == QDialogButtonBox::GnomeLayout || layout == QDialogButtonBox::MacLayout )
|
if ( layout == QDialogButtonBox::GnomeLayout || layout == QDialogButtonBox::MacLayout )
|
||||||
{
|
{
|
||||||
@ -1345,6 +1354,7 @@ void QgisApp::createToolBars()
|
|||||||
mAdvancedDigitizeToolBar->addAction( mActionAddIsland );
|
mAdvancedDigitizeToolBar->addAction( mActionAddIsland );
|
||||||
mAdvancedDigitizeToolBar->addAction( mActionDeleteRing );
|
mAdvancedDigitizeToolBar->addAction( mActionDeleteRing );
|
||||||
mAdvancedDigitizeToolBar->addAction( mActionDeletePart );
|
mAdvancedDigitizeToolBar->addAction( mActionDeletePart );
|
||||||
|
mAdvancedDigitizeToolBar->addAction( mActionMergeFeatures );
|
||||||
mToolbarMenu->addAction( mAdvancedDigitizeToolBar->toggleViewAction() );
|
mToolbarMenu->addAction( mAdvancedDigitizeToolBar->toggleViewAction() );
|
||||||
|
|
||||||
|
|
||||||
@ -4085,6 +4095,139 @@ void QgisApp::deletePart()
|
|||||||
mMapCanvas->setMapTool( mMapTools.mDeletePart );
|
mMapCanvas->setMapTool( mMapTools.mDeletePart );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsGeometry* QgisApp::unionGeometries(const QgsVectorLayer* vl, QgsFeatureList& featureList) const
|
||||||
|
{
|
||||||
|
if(!vl || featureList.size() < 2)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsGeometry* unionGeom = featureList[0].geometry();
|
||||||
|
QgsGeometry* backupPtr = 0; //pointer to delete intermediate results
|
||||||
|
if(!unionGeom)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 1; i < featureList.size(); ++i)
|
||||||
|
{
|
||||||
|
QgsGeometry* currentGeom = featureList[i].geometry();
|
||||||
|
if(currentGeom)
|
||||||
|
{
|
||||||
|
backupPtr = unionGeom;
|
||||||
|
unionGeom = unionGeom->combine(currentGeom);
|
||||||
|
if(i > 1) //delete previous intermediate results
|
||||||
|
{
|
||||||
|
delete backupPtr;
|
||||||
|
backupPtr = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return unionGeom;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgisApp::mergeSelectedFeatures()
|
||||||
|
{
|
||||||
|
//get active layer (hopefully vector)
|
||||||
|
QgsMapLayer* activeMapLayer = activeLayer();
|
||||||
|
if(!activeMapLayer)
|
||||||
|
{
|
||||||
|
QMessageBox::information(0, tr("No active layer"), tr("No active layer found. Please select a layer in the layer list"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>(activeMapLayer);
|
||||||
|
if(!vl)
|
||||||
|
{
|
||||||
|
QMessageBox::information(0, tr("Active layer is not vector"), tr("The merge features tool only works on vector layers. Please select a vector layer from the layer list"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(!vl->isEditable())
|
||||||
|
{
|
||||||
|
QMessageBox::information(0, tr("Layer not editable"), tr("Merging features can only be done for layers in editing mode. To use the merge tool, go to Layer->Toggle editing"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get selected feature ids (as a QSet<int> )
|
||||||
|
const QgsFeatureIds& featureIdSet = vl->selectedFeaturesIds();
|
||||||
|
if(featureIdSet.size() < 2)
|
||||||
|
{
|
||||||
|
QMessageBox::information(0, "Not enough features selected", tr("The merge tool requires at least two selected features"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get initial selection (may be altered by attribute merge dialog later)
|
||||||
|
QgsFeatureList featureList = vl->selectedFeatures(); //get QList<QgsFeature>
|
||||||
|
QgsGeometry* unionGeom = unionGeometries(vl, featureList);
|
||||||
|
if(!unionGeom)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//make a first geometry union and notify the user straight away if the union geometry type does not match the layer one
|
||||||
|
QGis::WkbType originalType = vl->wkbType();
|
||||||
|
QGis::WkbType newType = unionGeom->wkbType();
|
||||||
|
if(unionGeom->wkbType() != vl->wkbType())
|
||||||
|
{
|
||||||
|
QMessageBox::critical(0, "Union operation canceled", tr("The union operation would result in a geometry type that is not compatible with the current layer and therefore is canceled"));
|
||||||
|
delete unionGeom;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//merge the attributes together
|
||||||
|
QgsMergeAttributesDialog d(featureList, vl, mapCanvas());
|
||||||
|
if(d.exec() == QDialog::Rejected)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsFeatureList featureListAfter = vl->selectedFeatures();
|
||||||
|
|
||||||
|
if(featureListAfter.size() < 2)
|
||||||
|
{
|
||||||
|
QMessageBox::information(0, "Not enough features selected", tr("The merge tool requires at least two selected features"));
|
||||||
|
delete unionGeom;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//if the user changed the feature selection in the merge dialog, we need to repead the union and check the type
|
||||||
|
if(featureList.size() != featureListAfter.size())
|
||||||
|
{
|
||||||
|
delete unionGeom;
|
||||||
|
unionGeom = unionGeometries(vl, featureListAfter);
|
||||||
|
if(!unionGeom)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
originalType = vl->wkbType();
|
||||||
|
newType = unionGeom->wkbType();
|
||||||
|
if(unionGeom->wkbType() != vl->wkbType())
|
||||||
|
{
|
||||||
|
QMessageBox::critical(0, "Union operation canceled", tr("The union operation would result in a geometry type that is not compatible with the current layer and therefore is canceled"));
|
||||||
|
delete unionGeom;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//create new feature
|
||||||
|
QgsFeature newFeature;
|
||||||
|
newFeature.setGeometry(unionGeom);
|
||||||
|
newFeature.setAttributeMap(d.mergedAttributesMap());
|
||||||
|
|
||||||
|
QgsFeatureList::const_iterator feature_it = featureListAfter.constBegin();
|
||||||
|
for(; feature_it != featureListAfter.constEnd(); ++feature_it)
|
||||||
|
{
|
||||||
|
vl->deleteFeature(feature_it->id());
|
||||||
|
}
|
||||||
|
|
||||||
|
vl->addFeature(newFeature, false);
|
||||||
|
|
||||||
|
if(mapCanvas())
|
||||||
|
{
|
||||||
|
mapCanvas()->refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void QgisApp::splitFeatures()
|
void QgisApp::splitFeatures()
|
||||||
{
|
{
|
||||||
mMapCanvas->setMapTool( mMapTools.mSplitFeatures );
|
mMapCanvas->setMapTool( mMapTools.mSplitFeatures );
|
||||||
@ -5314,6 +5457,17 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
|
|||||||
mActionCutFeatures->setEnabled( false );
|
mActionCutFeatures->setEnabled( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//merge tool needs editable layer and provider with the capability of adding and deleting features
|
||||||
|
if ( vlayer->isEditable() && (dprovider->capabilities() & QgsVectorDataProvider::DeleteFeatures) \
|
||||||
|
&& QgsVectorDataProvider::AddFeatures)
|
||||||
|
{
|
||||||
|
mActionMergeFeatures->setEnabled(layerHasSelection);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mActionMergeFeatures->setEnabled( false );
|
||||||
|
}
|
||||||
|
|
||||||
// moving enabled if geometry changes are supported
|
// moving enabled if geometry changes are supported
|
||||||
if ( vlayer->isEditable() && dprovider->capabilities() & QgsVectorDataProvider::ChangeGeometries )
|
if ( vlayer->isEditable() && dprovider->capabilities() & QgsVectorDataProvider::ChangeGeometries )
|
||||||
{
|
{
|
||||||
@ -5366,6 +5520,7 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
|
|||||||
mActionSplitFeatures->setEnabled( true );
|
mActionSplitFeatures->setEnabled( true );
|
||||||
mActionSimplifyFeature->setEnabled( true );
|
mActionSimplifyFeature->setEnabled( true );
|
||||||
mActionDeletePart->setEnabled( true );
|
mActionDeletePart->setEnabled( true );
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -41,6 +41,7 @@ class QValidator;
|
|||||||
class QgisAppInterface;
|
class QgisAppInterface;
|
||||||
class QgsClipboard;
|
class QgsClipboard;
|
||||||
class QgsComposer;
|
class QgsComposer;
|
||||||
|
class QgsGeometry;
|
||||||
class QgsHelpViewer;
|
class QgsHelpViewer;
|
||||||
class QgsFeature;
|
class QgsFeature;
|
||||||
|
|
||||||
@ -63,6 +64,7 @@ class QgsVectorLayer;
|
|||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
|
|
||||||
#include "qgsconfig.h"
|
#include "qgsconfig.h"
|
||||||
|
#include "qgsfeature.h"
|
||||||
#include "qgspoint.h"
|
#include "qgspoint.h"
|
||||||
|
|
||||||
/*! \class QgisApp
|
/*! \class QgisApp
|
||||||
@ -509,6 +511,8 @@ class QgisApp : public QMainWindow
|
|||||||
void deleteRing();
|
void deleteRing();
|
||||||
//! deletes part of polygon
|
//! deletes part of polygon
|
||||||
void deletePart();
|
void deletePart();
|
||||||
|
//! merges the selected features together
|
||||||
|
void mergeSelectedFeatures();
|
||||||
|
|
||||||
//! activates the selection tool
|
//! activates the selection tool
|
||||||
void select();
|
void select();
|
||||||
@ -655,6 +659,9 @@ class QgisApp : public QMainWindow
|
|||||||
void pasteTransformations();
|
void pasteTransformations();
|
||||||
//! check to see if file is dirty and if so, prompt the user th save it
|
//! check to see if file is dirty and if so, prompt the user th save it
|
||||||
bool saveDirty();
|
bool saveDirty();
|
||||||
|
/** Helper function to union several geometries together (used in function mergeSelectedFeatures)
|
||||||
|
@return 0 in case of error*/
|
||||||
|
QgsGeometry* unionGeometries(const QgsVectorLayer* vl, QgsFeatureList& featureList) const;
|
||||||
|
|
||||||
/// QgisApp aren't copyable
|
/// QgisApp aren't copyable
|
||||||
QgisApp( QgisApp const & );
|
QgisApp( QgisApp const & );
|
||||||
@ -719,6 +726,7 @@ class QgisApp : public QMainWindow
|
|||||||
QAction *mActionSimplifyFeature;
|
QAction *mActionSimplifyFeature;
|
||||||
QAction *mActionDeleteRing;
|
QAction *mActionDeleteRing;
|
||||||
QAction *mActionDeletePart;
|
QAction *mActionDeletePart;
|
||||||
|
QAction *mActionMergeFeatures;
|
||||||
QAction *mActionEditSeparator3;
|
QAction *mActionEditSeparator3;
|
||||||
|
|
||||||
QAction *mActionPan;
|
QAction *mActionPan;
|
||||||
|
532
src/app/qgsmergeattributesdialog.cpp
Normal file
532
src/app/qgsmergeattributesdialog.cpp
Normal file
@ -0,0 +1,532 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgsmergeattributesdialog.cpp
|
||||||
|
----------------------------
|
||||||
|
begin : May 2009
|
||||||
|
copyright : (C) 2009 by Marco Hugentobler
|
||||||
|
email : marco dot hugentobler at karto dot baug dot ethz dot ch
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* 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. *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#include "qgsmergeattributesdialog.h"
|
||||||
|
#include "qgisapp.h"
|
||||||
|
#include "qgsfield.h"
|
||||||
|
#include "qgsmapcanvas.h"
|
||||||
|
#include "qgsrubberband.h"
|
||||||
|
#include "qgsvectorlayer.h"
|
||||||
|
#include <limits>
|
||||||
|
#include <QComboBox>
|
||||||
|
|
||||||
|
QgsMergeAttributesDialog::QgsMergeAttributesDialog(const QgsFeatureList& features, QgsVectorLayer* vl, QgsMapCanvas* canvas, QWidget * parent, Qt::WindowFlags f): QDialog(parent, f), mFeatureList(features), mVectorLayer(vl), mMapCanvas(canvas), mSelectionRubberBand(0)
|
||||||
|
{
|
||||||
|
setupUi(this);
|
||||||
|
createTableWidgetContents();
|
||||||
|
|
||||||
|
QHeaderView* verticalHeader = mTableWidget->verticalHeader();
|
||||||
|
if(verticalHeader)
|
||||||
|
{
|
||||||
|
QObject::connect(mTableWidget, SIGNAL(itemSelectionChanged ()), this, SLOT(selectedRowChanged()));
|
||||||
|
}
|
||||||
|
mTableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
|
mTableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||||
|
|
||||||
|
mFromSelectedPushButton->setIcon(QgisApp::getThemeIcon("mActionFromSelectedFeature.png"));
|
||||||
|
mRemoveFeatureFromSelectionButton->setIcon(QgisApp::getThemeIcon("mActionRemoveSelectedFeature.png"));
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsMergeAttributesDialog::QgsMergeAttributesDialog(): QDialog()
|
||||||
|
{
|
||||||
|
setupUi(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsMergeAttributesDialog::~QgsMergeAttributesDialog()
|
||||||
|
{
|
||||||
|
delete mSelectionRubberBand;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMergeAttributesDialog::createTableWidgetContents()
|
||||||
|
{
|
||||||
|
//get information about attributes from vector layer
|
||||||
|
if(!mVectorLayer)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const QgsFieldMap& fieldMap = mVectorLayer->pendingFields();
|
||||||
|
|
||||||
|
//combo box row, attributes titles, feature values and current merge results
|
||||||
|
mTableWidget->setRowCount(mFeatureList.size() + 2);
|
||||||
|
mTableWidget->setColumnCount(fieldMap.size());
|
||||||
|
|
||||||
|
//create combo boxes
|
||||||
|
for(int i = 0; i < fieldMap.size(); ++i)
|
||||||
|
{
|
||||||
|
mTableWidget->setCellWidget(0, i, createMergeComboBox(fieldMap[i].type()));
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsFieldMap::const_iterator fieldIt = fieldMap.constBegin();
|
||||||
|
|
||||||
|
//insert attribute names
|
||||||
|
QStringList horizontalHeaderLabels;
|
||||||
|
for(; fieldIt != fieldMap.constEnd(); ++fieldIt)
|
||||||
|
{
|
||||||
|
horizontalHeaderLabels << fieldIt.value().name();
|
||||||
|
}
|
||||||
|
mTableWidget->setHorizontalHeaderLabels(horizontalHeaderLabels);
|
||||||
|
|
||||||
|
//insert the attribute values
|
||||||
|
int currentRow = 1;
|
||||||
|
QStringList verticalHeaderLabels; //the id column is in the
|
||||||
|
verticalHeaderLabels << tr("Id");
|
||||||
|
|
||||||
|
for(int i = 0; i < mFeatureList.size(); ++i)
|
||||||
|
{
|
||||||
|
verticalHeaderLabels << QString::number(mFeatureList[i].id());
|
||||||
|
QgsAttributeMap currentAttributeMap = mFeatureList[i].attributeMap();
|
||||||
|
QgsAttributeMap::const_iterator currentMapIt = currentAttributeMap.constBegin();
|
||||||
|
int col = 0;
|
||||||
|
for(; currentMapIt != currentAttributeMap.constEnd(); ++currentMapIt)
|
||||||
|
{
|
||||||
|
QTableWidgetItem* attributeValItem = new QTableWidgetItem(currentMapIt.value().toString());
|
||||||
|
attributeValItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
|
||||||
|
mTableWidget->setItem(currentRow, col, attributeValItem);
|
||||||
|
++col;
|
||||||
|
}
|
||||||
|
++currentRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
//merge
|
||||||
|
verticalHeaderLabels << tr("Merge");
|
||||||
|
mTableWidget->setVerticalHeaderLabels(verticalHeaderLabels);
|
||||||
|
|
||||||
|
|
||||||
|
//insert currently merged values
|
||||||
|
for(int i = 0; i < fieldMap.size(); ++i)
|
||||||
|
{
|
||||||
|
refreshMergedValue(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QComboBox* QgsMergeAttributesDialog::createMergeComboBox(QVariant::Type columnType) const
|
||||||
|
{
|
||||||
|
QComboBox* newComboBox = new QComboBox();
|
||||||
|
//add items for feature
|
||||||
|
QgsFeatureList::const_iterator f_it = mFeatureList.constBegin();
|
||||||
|
for(; f_it != mFeatureList.constEnd(); ++f_it)
|
||||||
|
{
|
||||||
|
newComboBox->addItem(tr("feature %1").arg(f_it->id()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(columnType == QVariant::Double || columnType == QVariant::Int)
|
||||||
|
{
|
||||||
|
newComboBox->addItem(tr("Minimum"));
|
||||||
|
newComboBox->addItem(tr("Maximum"));
|
||||||
|
newComboBox->addItem(tr("Median"));
|
||||||
|
}
|
||||||
|
else if(columnType == QVariant::String)
|
||||||
|
{
|
||||||
|
newComboBox->addItem(tr("Concatenation"));
|
||||||
|
}
|
||||||
|
if(columnType == QVariant::Double)
|
||||||
|
{
|
||||||
|
newComboBox->addItem(tr("Mean"));
|
||||||
|
}
|
||||||
|
|
||||||
|
QObject::connect(newComboBox, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(comboValueChanged(const QString&)));
|
||||||
|
return newComboBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
int QgsMergeAttributesDialog::findComboColumn(QComboBox* c) const
|
||||||
|
{
|
||||||
|
for(int i = 0; i < mTableWidget->columnCount(); ++i)
|
||||||
|
{
|
||||||
|
if(mTableWidget->cellWidget(0, i) == c)
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMergeAttributesDialog::comboValueChanged(const QString & text)
|
||||||
|
{
|
||||||
|
QComboBox* senderComboBox = dynamic_cast<QComboBox*>(sender());
|
||||||
|
if(!senderComboBox)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int column = findComboColumn(senderComboBox);
|
||||||
|
refreshMergedValue(column);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMergeAttributesDialog::selectedRowChanged()
|
||||||
|
{
|
||||||
|
//find out selected row
|
||||||
|
QList<QTableWidgetItem *> selectionList = mTableWidget->selectedItems();
|
||||||
|
if(selectionList.size() < 1)
|
||||||
|
{
|
||||||
|
delete mSelectionRubberBand;
|
||||||
|
mSelectionRubberBand = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int row = selectionList[0]->row();
|
||||||
|
|
||||||
|
if(!mTableWidget || !mMapCanvas || !mVectorLayer || row < 1 || row >= (mTableWidget->rowCount()))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//read the feature id
|
||||||
|
QTableWidgetItem* idItem = mTableWidget->verticalHeaderItem(row);
|
||||||
|
if(!idItem)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool conversionSuccess = false;
|
||||||
|
int featureIdToSelect = idItem->text().toInt(&conversionSuccess);
|
||||||
|
if(!conversionSuccess)
|
||||||
|
{
|
||||||
|
//the merge result row was selected
|
||||||
|
delete mSelectionRubberBand;
|
||||||
|
mSelectionRubberBand = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
createRubberBandForFeature(featureIdToSelect);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMergeAttributesDialog::refreshMergedValue(int col)
|
||||||
|
{
|
||||||
|
//get QComboBox
|
||||||
|
QWidget* cellWidget = mTableWidget->cellWidget(0, col);
|
||||||
|
if(!cellWidget)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QComboBox* comboBox = dynamic_cast<QComboBox*>(cellWidget);
|
||||||
|
if(!comboBox)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//evaluate behaviour (feature value or min / max / mean )
|
||||||
|
QString mergeBehaviourString = comboBox->currentText();
|
||||||
|
QString evalText; //text that has to be inserted into merge result field
|
||||||
|
if(mergeBehaviourString == tr("Minimum"))
|
||||||
|
{
|
||||||
|
evalText = minimumAttributeString(col);
|
||||||
|
}
|
||||||
|
else if(mergeBehaviourString == tr("Maximum"))
|
||||||
|
{
|
||||||
|
evalText = maximumAttributeString(col);
|
||||||
|
}
|
||||||
|
else if(mergeBehaviourString == tr("Mean"))
|
||||||
|
{
|
||||||
|
evalText = meanAttributeString(col);
|
||||||
|
}
|
||||||
|
else if(mergeBehaviourString == tr("Median"))
|
||||||
|
{
|
||||||
|
evalText = medianAttributeString(col);
|
||||||
|
}
|
||||||
|
else if(mergeBehaviourString == tr("Concatenation"))
|
||||||
|
{
|
||||||
|
evalText = concatenationAttributeString(col);
|
||||||
|
}
|
||||||
|
else //an existing feature value
|
||||||
|
{
|
||||||
|
int featureId = mergeBehaviourString.split(" ").at(1).toInt(); //probably not very robust for translations...
|
||||||
|
evalText = featureAttributeString(featureId, col);
|
||||||
|
}
|
||||||
|
|
||||||
|
//insert string into table widget
|
||||||
|
QTableWidgetItem* newTotalItem = new QTableWidgetItem(evalText);
|
||||||
|
newTotalItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
|
||||||
|
mTableWidget->setItem(mTableWidget->rowCount() - 1, col, newTotalItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QgsMergeAttributesDialog::featureAttributeString(int featureId, int col)
|
||||||
|
{
|
||||||
|
QString resultText;
|
||||||
|
for(int i = 0; i < mFeatureList.size(); ++i)
|
||||||
|
{
|
||||||
|
int currentFid = mFeatureList[i].id();
|
||||||
|
if(currentFid == featureId)
|
||||||
|
{
|
||||||
|
QTableWidgetItem* currentItem = mTableWidget->item(i+1, col);
|
||||||
|
if(!currentItem)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
resultText = currentItem->text();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resultText;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QgsMergeAttributesDialog::minimumAttributeString(int col)
|
||||||
|
{
|
||||||
|
double minimumValue = std::numeric_limits<double>::max();
|
||||||
|
double currentValue;
|
||||||
|
bool conversion = false;
|
||||||
|
int numberOfConsideredFeatures = 0;
|
||||||
|
|
||||||
|
for(int i = 0; i < mFeatureList.size(); ++i)
|
||||||
|
{
|
||||||
|
currentValue = mTableWidget->item(i+1, col)->text().toDouble(&conversion);
|
||||||
|
if(conversion)
|
||||||
|
{
|
||||||
|
if(currentValue < minimumValue)
|
||||||
|
{
|
||||||
|
minimumValue = currentValue;
|
||||||
|
++numberOfConsideredFeatures;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(numberOfConsideredFeatures < 1)
|
||||||
|
{
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return QString::number(minimumValue, 'f');
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QgsMergeAttributesDialog::maximumAttributeString(int col)
|
||||||
|
{
|
||||||
|
double maximumValue = -std::numeric_limits<double>::max();
|
||||||
|
double currentValue;
|
||||||
|
bool conversion = false;
|
||||||
|
int numberOfConsideredFeatures = 0;
|
||||||
|
|
||||||
|
for(int i = 0; i < mFeatureList.size(); ++i)
|
||||||
|
{
|
||||||
|
currentValue = mTableWidget->item(i+1, col)->text().toDouble(&conversion);
|
||||||
|
if(conversion)
|
||||||
|
{
|
||||||
|
if(currentValue > maximumValue)
|
||||||
|
{
|
||||||
|
maximumValue = currentValue;
|
||||||
|
++numberOfConsideredFeatures;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(numberOfConsideredFeatures < 1)
|
||||||
|
{
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return QString::number(maximumValue, 'f');
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QgsMergeAttributesDialog::meanAttributeString(int col)
|
||||||
|
{
|
||||||
|
int numberOfConsideredFeatures = 0;
|
||||||
|
double currentValue;
|
||||||
|
double sum = 0;
|
||||||
|
bool conversion = false;
|
||||||
|
|
||||||
|
for(int i = 0; i < mFeatureList.size(); ++i)
|
||||||
|
{
|
||||||
|
currentValue = mTableWidget->item(i+1, col)->text().toDouble(&conversion);
|
||||||
|
if(conversion)
|
||||||
|
{
|
||||||
|
sum += currentValue;
|
||||||
|
++numberOfConsideredFeatures;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
double mean = sum / numberOfConsideredFeatures;
|
||||||
|
return QString::number(mean, 'f');
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QgsMergeAttributesDialog::medianAttributeString(int col)
|
||||||
|
{
|
||||||
|
//bring all values into a list and sort
|
||||||
|
QList<double> valueList;
|
||||||
|
double currentValue;
|
||||||
|
bool conversionSuccess;
|
||||||
|
|
||||||
|
for(int i = 0; i < mFeatureList.size(); ++i)
|
||||||
|
{
|
||||||
|
currentValue = mTableWidget->item(i+1, col)->text().toDouble(&conversionSuccess);
|
||||||
|
if(!conversionSuccess)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
valueList.push_back(currentValue);
|
||||||
|
}
|
||||||
|
qSort(valueList);
|
||||||
|
|
||||||
|
double medianValue;
|
||||||
|
int size = valueList.size();
|
||||||
|
bool even = (size % 2) < 1;
|
||||||
|
if(even)
|
||||||
|
{
|
||||||
|
medianValue = (valueList[size / 2 - 1] + valueList[size / 2]) / 2;
|
||||||
|
}
|
||||||
|
else //odd
|
||||||
|
{
|
||||||
|
medianValue = valueList[(size + 1) / 2 - 1];
|
||||||
|
}
|
||||||
|
return QString::number(medianValue, 'f');
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QgsMergeAttributesDialog::concatenationAttributeString(int col)
|
||||||
|
{
|
||||||
|
QStringList concatString;
|
||||||
|
for(int i = 0; i < mFeatureList.size(); ++i)
|
||||||
|
{
|
||||||
|
concatString << mTableWidget->item(i+1, col)->text();
|
||||||
|
}
|
||||||
|
return concatString.join(","); //todo: make separator user configurable
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMergeAttributesDialog::on_mFromSelectedPushButton_clicked()
|
||||||
|
{
|
||||||
|
//find the selected feature
|
||||||
|
if(!mVectorLayer)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//find out feature id of selected row
|
||||||
|
QList<QTableWidgetItem *> selectionList = mTableWidget->selectedItems();
|
||||||
|
if(selectionList.size() < 1)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//assume all selected items to be in the same row
|
||||||
|
QTableWidgetItem* selectedItem = selectionList[0];
|
||||||
|
int selectedRow = selectedItem->row();
|
||||||
|
QTableWidgetItem* selectedHeaderItem = mTableWidget->verticalHeaderItem(selectedRow);
|
||||||
|
if(!selectedHeaderItem)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool conversionSuccess;
|
||||||
|
int featureId = selectedHeaderItem->text().toInt(&conversionSuccess);
|
||||||
|
if(!conversionSuccess)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < mTableWidget->columnCount(); ++i)
|
||||||
|
{
|
||||||
|
QComboBox* currentComboBox = dynamic_cast<QComboBox*>(mTableWidget->cellWidget(0, i));
|
||||||
|
if(currentComboBox)
|
||||||
|
{
|
||||||
|
currentComboBox->setCurrentIndex(currentComboBox->findText(tr("feature %1").arg(featureId)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMergeAttributesDialog::on_mRemoveFeatureFromSelectionButton_clicked()
|
||||||
|
{
|
||||||
|
if(!mVectorLayer)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//find out feature id of selected row
|
||||||
|
QList<QTableWidgetItem *> selectionList = mTableWidget->selectedItems();
|
||||||
|
if(selectionList.size() < 1)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//assume all selected items to be in the same row
|
||||||
|
QTableWidgetItem* selectedItem = selectionList[0];
|
||||||
|
int selectedRow = selectedItem->row();
|
||||||
|
QTableWidgetItem* selectedHeaderItem = mTableWidget->verticalHeaderItem(selectedRow);
|
||||||
|
if(!selectedHeaderItem)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool conversionSuccess;
|
||||||
|
int featureId = selectedHeaderItem->text().toInt(&conversionSuccess);
|
||||||
|
if(!conversionSuccess)
|
||||||
|
{
|
||||||
|
selectedRowChanged();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mTableWidget->removeRow(selectedRow);
|
||||||
|
selectedRowChanged();
|
||||||
|
|
||||||
|
//remove feature from the vector layer selection
|
||||||
|
QgsFeatureIds selectedIds = mVectorLayer->selectedFeaturesIds();
|
||||||
|
selectedIds.remove(featureId);
|
||||||
|
mVectorLayer->setSelectedFeatures(selectedIds);
|
||||||
|
mMapCanvas->repaint();
|
||||||
|
|
||||||
|
//remove feature option from the combo box (without altering the current merge values)
|
||||||
|
for(int i = 0; i < mTableWidget->columnCount(); ++i)
|
||||||
|
{
|
||||||
|
QComboBox* currentComboBox = dynamic_cast<QComboBox*>(mTableWidget->cellWidget(0, i));
|
||||||
|
if(currentComboBox)
|
||||||
|
{
|
||||||
|
currentComboBox->blockSignals(true);
|
||||||
|
currentComboBox->removeItem(currentComboBox->findText(tr("feature %1").arg(featureId)));
|
||||||
|
currentComboBox->blockSignals(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//finally remove the feature from mFeatureList
|
||||||
|
QgsFeatureList::iterator f_it = mFeatureList.begin();
|
||||||
|
for(; f_it != mFeatureList.end(); ++f_it)
|
||||||
|
{
|
||||||
|
if(f_it->id() == featureId)
|
||||||
|
{
|
||||||
|
mFeatureList.erase(f_it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMergeAttributesDialog::createRubberBandForFeature(int featureId)
|
||||||
|
{
|
||||||
|
//create rubber band to highlight the feature
|
||||||
|
delete mSelectionRubberBand;
|
||||||
|
mSelectionRubberBand = new QgsRubberBand(mMapCanvas, mVectorLayer->geometryType() == QGis::Polygon);
|
||||||
|
mSelectionRubberBand->setColor(QColor(255, 0, 0));
|
||||||
|
QgsFeature featureToSelect;
|
||||||
|
mVectorLayer->featureAtId(featureId, featureToSelect, true, false);
|
||||||
|
mSelectionRubberBand->setToGeometry( featureToSelect.geometry(), mVectorLayer );
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsAttributeMap QgsMergeAttributesDialog::mergedAttributesMap() const
|
||||||
|
{
|
||||||
|
QgsAttributeMap resultMap;
|
||||||
|
if(mFeatureList.size() < 1)
|
||||||
|
{
|
||||||
|
return resultMap; //return empty map
|
||||||
|
}
|
||||||
|
|
||||||
|
resultMap = mFeatureList[0].attributeMap();
|
||||||
|
//go through all the items and replace the values in the attribute map
|
||||||
|
for(int i = 0; i < resultMap.size(); ++i)
|
||||||
|
{
|
||||||
|
QTableWidgetItem* currentItem = mTableWidget->item(mFeatureList.size() + 1, i);
|
||||||
|
if(!currentItem)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
QString mergedString = currentItem->text();
|
||||||
|
QVariant newValue(mergedString);
|
||||||
|
resultMap.insert(i, newValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultMap;
|
||||||
|
}
|
||||||
|
|
78
src/app/qgsmergeattributesdialog.h
Normal file
78
src/app/qgsmergeattributesdialog.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgsmergeattributesdialog.h
|
||||||
|
--------------------------
|
||||||
|
begin : May 2009
|
||||||
|
copyright : (C) 2009 by Marco Hugentobler
|
||||||
|
email : marco dot hugentobler at karto dot baug dot ethz dot ch
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* 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. *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef QGSMERGEATTRIBUTESDIALOG_H
|
||||||
|
#define QGSMERGEATTRIBUTESDIALOG_H
|
||||||
|
|
||||||
|
#include "ui_qgsmergeattributesdialogbase.h"
|
||||||
|
#include "qgsfeature.h"
|
||||||
|
|
||||||
|
class QgsMapCanvas;
|
||||||
|
class QgsRubberBand;
|
||||||
|
class QgsVectorLayer;
|
||||||
|
class QComboBox;
|
||||||
|
|
||||||
|
|
||||||
|
/**A dialog to insert the merge behaviour for attributes (e.g. for the union features editing tool)*/
|
||||||
|
class QgsMergeAttributesDialog: public QDialog, private Ui::QgsMergeAttributesDialogBase
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
QgsMergeAttributesDialog(const QgsFeatureList& features, QgsVectorLayer* vl, QgsMapCanvas* canvas, QWidget * parent = 0, Qt::WindowFlags f = 0);
|
||||||
|
~QgsMergeAttributesDialog();
|
||||||
|
QgsAttributeMap mergedAttributesMap() const;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void comboValueChanged(const QString & text);
|
||||||
|
void selectedRowChanged();
|
||||||
|
void on_mFromSelectedPushButton_clicked();
|
||||||
|
void on_mRemoveFeatureFromSelectionButton_clicked();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QgsMergeAttributesDialog(); //default constructor forbidden
|
||||||
|
void createTableWidgetContents();
|
||||||
|
/**Create new combo box with the options for featureXX / mean / min / max */
|
||||||
|
QComboBox* createMergeComboBox(QVariant::Type columnType) const;
|
||||||
|
/**Returns the table widget column index of a combo box
|
||||||
|
@return the column index or -1 in case of error*/
|
||||||
|
int findComboColumn(QComboBox* c) const;
|
||||||
|
/**Calculates the merged value of a column (depending on the selected merge behaviour) and inserts the value in the corresponding cell*/
|
||||||
|
void refreshMergedValue(int col);
|
||||||
|
/**Inserts the attribute value of a specific feature into the row of merged attributes*/
|
||||||
|
QString featureAttributeString(int featureId, int col);
|
||||||
|
/**Calculates and inserts the minimum attribute value of a column*/
|
||||||
|
QString minimumAttributeString(int col);
|
||||||
|
/**Calculates and inserts the maximum value of a column*/
|
||||||
|
QString maximumAttributeString(int col);
|
||||||
|
/**Calculates and inserts the mean value of a column*/
|
||||||
|
QString meanAttributeString(int col);
|
||||||
|
/**Calculates and inserts the median value of a column*/
|
||||||
|
QString medianAttributeString(int col);
|
||||||
|
/**Appends the values of the features for the final value*/
|
||||||
|
QString concatenationAttributeString(int col);
|
||||||
|
/**Sets mSelectionRubberBand to a new feature*/
|
||||||
|
void createRubberBandForFeature(int featureId);
|
||||||
|
|
||||||
|
QgsFeatureList mFeatureList;
|
||||||
|
QgsVectorLayer* mVectorLayer;
|
||||||
|
QgsMapCanvas* mMapCanvas;
|
||||||
|
/**Item that highlights the selected feature in the merge table*/
|
||||||
|
QgsRubberBand* mSelectionRubberBand;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QGSMERGEATTRIBUTESDIALOG_H
|
134
src/ui/qgsmergeattributesdialogbase.ui
Normal file
134
src/ui/qgsmergeattributesdialogbase.ui
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
<ui version="4.0" >
|
||||||
|
<class>QgsMergeAttributesDialogBase</class>
|
||||||
|
<widget class="QDialog" name="QgsMergeAttributesDialogBase" >
|
||||||
|
<property name="geometry" >
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>450</width>
|
||||||
|
<height>382</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle" >
|
||||||
|
<string>Merge feature attributes</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout" >
|
||||||
|
<item row="0" column="0" >
|
||||||
|
<widget class="QTableWidget" name="mTableWidget" />
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0" >
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout" >
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="mFromSelectedPushButton" >
|
||||||
|
<property name="sizePolicy" >
|
||||||
|
<sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text" >
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="mTakeSelectedAttributesLabel" >
|
||||||
|
<property name="text" >
|
||||||
|
<string>Take attributes from selected feature</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer" >
|
||||||
|
<property name="orientation" >
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0" >
|
||||||
|
<size>
|
||||||
|
<width>58</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0" >
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2" >
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="mRemoveFeatureFromSelectionButton" >
|
||||||
|
<property name="text" >
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="mRemoveFeatureFromSelectionLabel" >
|
||||||
|
<property name="text" >
|
||||||
|
<string>Remove feature from selection</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_2" >
|
||||||
|
<property name="orientation" >
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0" >
|
||||||
|
<size>
|
||||||
|
<width>98</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0" >
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox" >
|
||||||
|
<property name="orientation" >
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons" >
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>QgsMergeAttributesDialogBase</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel" >
|
||||||
|
<x>248</x>
|
||||||
|
<y>254</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel" >
|
||||||
|
<x>157</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>QgsMergeAttributesDialogBase</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel" >
|
||||||
|
<x>316</x>
|
||||||
|
<y>260</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel" >
|
||||||
|
<x>286</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
Loading…
x
Reference in New Issue
Block a user