mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-16 00:03:12 -04:00
QgsVectorLayer: - move attribute part of editing to vector layer class and unify with geometry handling: * remove commitAttributeChanges(), addedFeatures(), deletedFeatureIds(), changedAttributes() and replace with changeAttributeValue(), deleteFeature(), addAttribute() and deleteAttribute() * add pendingFields(), pendingAttributeList(), pendingFeatureCount() * emit signals on start editing and commit, change of attribute values, adding/deleting of attributes and layer or feature removal (currently used in the attribute table) - new commitErrors() method to query errors from commitChanges() - replaced featuresInRectangle with select/getNextFeature combo - edit types added to support more input widgets and input constraints QgsFeature: - remove update aware ctor - unify geometry handling in ctors QgsVectorDataProvider: - add QVariant::Type to supportNativeTypes() QgisApp: - add instance() method to query QgisApp object - replace code at various place to use it instead of passing the pointer arround or searching it in the widget tree. - move toggleEditing() code from the legend here QgsAttributeTable/QgsAttributeTableDisplay: - move attribute table creation legend here - make attribute table dockable (from Tim) - most editing logic moved to QgsVectorLayer - adding/deleting attributes moved to QgsVectorLayerProperties QgsIdentifyResults: - add support for attribute editing when it edit mode QgsVectorLayerProperties: add a new tab to show attribute list: * start/stop editing * add/delete attributes * assign edit type to attributes (unique values, value map, ranges) QgsAttributeDialog: add support for attribute edit types: * selection from unique value render classes (combobox) * selection from unique values of existing features (combobox or line edits with completion) * spinboxes for ranges QgsPostgresProvider: - use read-only connection for cursors and read-write connection for updates - updated native types QgsOgrProvider: - remove unused references to GEOS geometry factory - updated native types git-svn-id: http://svn.osgeo.org/qgis/trunk@9092 c8812cc2-4d05-0410-92ff-de0c093fc19c
275 lines
7.8 KiB
C++
275 lines
7.8 KiB
C++
/***************************************************************************
|
|
qgsuniquevaluerenderer.cpp - description
|
|
-------------------
|
|
begin : July 2004
|
|
copyright : (C) 2004 by Marco Hugentobler
|
|
email : marco.hugentobler@autoform.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. *
|
|
* *
|
|
***************************************************************************/
|
|
/* $Id: qgsuniquevaluerenderer.cpp 5371 2006-04-25 01:52:13Z wonder $ */
|
|
|
|
#include "qgsuniquevaluerenderer.h"
|
|
#include "qgsfeature.h"
|
|
#include "qgsvectorlayer.h"
|
|
#include "qgssymbol.h"
|
|
#include "qgssymbologyutils.h"
|
|
#include "qgslogger.h"
|
|
#include <math.h>
|
|
#include <QDomNode>
|
|
#include <QPainter>
|
|
#include <QImage>
|
|
#include <vector>
|
|
|
|
QgsUniqueValueRenderer::QgsUniqueValueRenderer(QGis::VectorType type): mClassificationField(0)
|
|
{
|
|
mVectorType = type;
|
|
mSymbolAttributesDirty = false;
|
|
}
|
|
|
|
QgsUniqueValueRenderer::QgsUniqueValueRenderer(const QgsUniqueValueRenderer& other)
|
|
{
|
|
mVectorType = other.mVectorType;
|
|
mClassificationField = other.mClassificationField;
|
|
QMap<QString, QgsSymbol*> s = other.mSymbols;
|
|
for(QMap<QString, QgsSymbol*>::iterator it=s.begin(); it!=s.end(); ++it)
|
|
{
|
|
QgsSymbol* s = new QgsSymbol(* it.value());
|
|
insertValue(it.key(), s);
|
|
}
|
|
updateSymbolAttributes();
|
|
}
|
|
|
|
QgsUniqueValueRenderer& QgsUniqueValueRenderer::operator=(const QgsUniqueValueRenderer& other)
|
|
{
|
|
if(this != &other)
|
|
{
|
|
mVectorType = other.mVectorType;
|
|
mClassificationField = other.mClassificationField;
|
|
clearValues();
|
|
for(QMap<QString, QgsSymbol*>::iterator it=mSymbols.begin(); it!=mSymbols.end(); ++it)
|
|
{
|
|
QgsSymbol* s = new QgsSymbol(*it.value());
|
|
insertValue(it.key(), s);
|
|
}
|
|
updateSymbolAttributes();
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
QgsUniqueValueRenderer::~QgsUniqueValueRenderer()
|
|
{
|
|
for(QMap<QString,QgsSymbol*>::iterator it=mSymbols.begin();it!=mSymbols.end();++it)
|
|
{
|
|
delete it.value();
|
|
}
|
|
}
|
|
|
|
const QList<QgsSymbol*> QgsUniqueValueRenderer::symbols() const
|
|
{
|
|
QList <QgsSymbol*> symbollist;
|
|
for(QMap<QString, QgsSymbol*>::const_iterator it = mSymbols.begin(); it!=mSymbols.end(); ++it)
|
|
{
|
|
symbollist.append(it.value());
|
|
}
|
|
return symbollist;
|
|
}
|
|
|
|
void QgsUniqueValueRenderer::insertValue(QString name, QgsSymbol* symbol)
|
|
{
|
|
mSymbols.insert(name, symbol);
|
|
mSymbolAttributesDirty=true;
|
|
}
|
|
|
|
void QgsUniqueValueRenderer::setClassificationField(int field)
|
|
{
|
|
mClassificationField=field;
|
|
}
|
|
|
|
int QgsUniqueValueRenderer::classificationField() const
|
|
{
|
|
return mClassificationField;
|
|
}
|
|
|
|
bool QgsUniqueValueRenderer::willRenderFeature(QgsFeature *f)
|
|
{
|
|
return (symbolForFeature(f) != 0);
|
|
}
|
|
|
|
void QgsUniqueValueRenderer::renderFeature(QPainter* p, QgsFeature& f,QImage* img, bool selected, double widthScale, double rasterScaleFactor)
|
|
{
|
|
QgsSymbol* symbol = symbolForFeature(&f);
|
|
if(!symbol) //no matching symbol
|
|
{
|
|
if ( img && mVectorType == QGis::Point )
|
|
{
|
|
img->fill(0);
|
|
}
|
|
else if ( mVectorType != QGis::Point )
|
|
{
|
|
p->setPen(Qt::NoPen);
|
|
p->setBrush(Qt::NoBrush);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Point
|
|
if ( img && mVectorType == QGis::Point )
|
|
{
|
|
double fieldScale = 1.0;
|
|
double rotation = 0.0;
|
|
|
|
if ( symbol->scaleClassificationField() >= 0)
|
|
{
|
|
//first find out the value for the scale classification attribute
|
|
const QgsAttributeMap& attrs = f.attributeMap();
|
|
fieldScale = sqrt(fabs(attrs[symbol->scaleClassificationField()].toDouble()));
|
|
QgsDebugMsg(QString("Feature has field scale factor %1").arg(fieldScale));
|
|
}
|
|
if ( symbol->rotationClassificationField() >= 0 )
|
|
{
|
|
const QgsAttributeMap& attrs = f.attributeMap();
|
|
rotation = attrs[symbol->rotationClassificationField()].toDouble();
|
|
QgsDebugMsg(QString("Feature has rotation factor %1").arg(rotation));
|
|
}
|
|
*img = symbol->getPointSymbolAsImage( widthScale, selected, mSelectionColor,
|
|
fieldScale, rotation, rasterScaleFactor);
|
|
}
|
|
// Line, polygon
|
|
else if ( mVectorType != QGis::Point )
|
|
{
|
|
if( !selected )
|
|
{
|
|
QPen pen=symbol->pen();
|
|
pen.setWidthF ( widthScale * pen.widthF() );
|
|
p->setPen(pen);
|
|
p->setBrush(symbol->brush());
|
|
}
|
|
else
|
|
{
|
|
QPen pen=symbol->pen();
|
|
pen.setWidthF ( widthScale * pen.widthF() );
|
|
pen.setColor(mSelectionColor);
|
|
QBrush brush=symbol->brush();
|
|
brush.setColor(mSelectionColor);
|
|
p->setPen(pen);
|
|
p->setBrush(brush);
|
|
}
|
|
}
|
|
}
|
|
|
|
QgsSymbol *QgsUniqueValueRenderer::symbolForFeature(const QgsFeature *f)
|
|
{
|
|
//first find out the value
|
|
const QgsAttributeMap& attrs = f->attributeMap();
|
|
QString value = attrs[mClassificationField].toString();
|
|
|
|
QMap<QString,QgsSymbol*>::iterator it=mSymbols.find(value);
|
|
if(it == mSymbols.end())
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return it.value();
|
|
}
|
|
}
|
|
|
|
void QgsUniqueValueRenderer::readXML(const QDomNode& rnode, QgsVectorLayer& vl)
|
|
{
|
|
mVectorType = vl.vectorType();
|
|
QDomNode classnode = rnode.namedItem("classificationfield");
|
|
int classificationfield = classnode.toElement().text().toInt();
|
|
this->setClassificationField(classificationfield);
|
|
|
|
QDomNode symbolnode = rnode.namedItem("symbol");
|
|
while (!symbolnode.isNull())
|
|
{
|
|
QgsSymbol* msy = new QgsSymbol(mVectorType);
|
|
msy->readXML ( symbolnode );
|
|
insertValue(msy->lowerValue(),msy);
|
|
symbolnode = symbolnode.nextSibling();
|
|
}
|
|
updateSymbolAttributes();
|
|
vl.setRenderer(this);
|
|
}
|
|
|
|
void QgsUniqueValueRenderer::clearValues()
|
|
{
|
|
for(QMap<QString,QgsSymbol*>::iterator it=mSymbols.begin();it!=mSymbols.end();++it)
|
|
{
|
|
delete it.value();
|
|
}
|
|
mSymbols.clear();
|
|
updateSymbolAttributes();
|
|
}
|
|
|
|
void QgsUniqueValueRenderer::updateSymbolAttributes()
|
|
{
|
|
mSymbolAttributesDirty = false;
|
|
|
|
mSymbolAttributes.clear();
|
|
|
|
QMap<QString, QgsSymbol*>::iterator it;
|
|
for (it = mSymbols.begin(); it != mSymbols.end(); ++it)
|
|
{
|
|
int rotationField = (*it)->rotationClassificationField();
|
|
if ( rotationField >= 0 && !(mSymbolAttributes.contains(rotationField)) )
|
|
{
|
|
mSymbolAttributes.append(rotationField);
|
|
}
|
|
int scaleField = (*it)->scaleClassificationField();
|
|
if ( scaleField >= 0 && !(mSymbolAttributes.contains(scaleField)) )
|
|
{
|
|
mSymbolAttributes.append(scaleField);
|
|
}
|
|
}
|
|
}
|
|
|
|
QString QgsUniqueValueRenderer::name() const
|
|
{
|
|
return "Unique Value";
|
|
}
|
|
|
|
QgsAttributeList QgsUniqueValueRenderer::classificationAttributes() const
|
|
{
|
|
QgsAttributeList list(mSymbolAttributes);
|
|
if ( ! list.contains(mClassificationField) )
|
|
{
|
|
list.append(mClassificationField);
|
|
}
|
|
return list;
|
|
}
|
|
|
|
bool QgsUniqueValueRenderer::writeXML( QDomNode & layer_node, QDomDocument & document ) const
|
|
{
|
|
bool returnval=true;
|
|
QDomElement uniquevalue=document.createElement("uniquevalue");
|
|
layer_node.appendChild(uniquevalue);
|
|
QDomElement classificationfield=document.createElement("classificationfield");
|
|
QDomText classificationfieldtxt=document.createTextNode(QString::number(mClassificationField));
|
|
classificationfield.appendChild(classificationfieldtxt);
|
|
uniquevalue.appendChild(classificationfield);
|
|
for(QMap<QString,QgsSymbol*>::const_iterator it=mSymbols.begin();it!=mSymbols.end();++it)
|
|
{
|
|
if(!(it.value()->writeXML(uniquevalue,document)))
|
|
{
|
|
returnval=false;
|
|
}
|
|
}
|
|
return returnval;
|
|
}
|
|
|
|
QgsRenderer* QgsUniqueValueRenderer::clone() const
|
|
{
|
|
QgsUniqueValueRenderer* r = new QgsUniqueValueRenderer(*this);
|
|
return r;
|
|
}
|