mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-26 00:02:08 -05:00
git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@1961 c8812cc2-4d05-0410-92ff-de0c093fc19c
375 lines
12 KiB
C++
375 lines
12 KiB
C++
/***************************************************************************
|
|
qgsuvaldialog.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. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include "qgsuvaldialog.h"
|
|
#include "qgsdataprovider.h"
|
|
#include "qgsvectorlayer.h"
|
|
#include "qgsdlgvectorlayerproperties.h"
|
|
#include "qgsfeature.h"
|
|
#include "qgsfeatureattribute.h"
|
|
#include "qgsuniquevalrenderer.h"
|
|
#include "qgssisydialog.h"
|
|
#include "qgssymbol.h"
|
|
#include "qgsrenderitem.h"
|
|
#include "qgsuniquevalrenderer.h"
|
|
#include <qwidgetstack.h>
|
|
#include <qlistbox.h>
|
|
#include <qcombobox.h>
|
|
#include <qpainter.h>
|
|
#include <list>
|
|
|
|
QgsUValDialog::QgsUValDialog(QgsVectorLayer* vl): QgsUValDialogBase(), mVectorLayer(vl), sydialog(vl)
|
|
{
|
|
setSizeGripEnabled(true);
|
|
|
|
//find out the fields of mVectorLayer
|
|
QgsDataProvider *provider;
|
|
if (provider = mVectorLayer->getDataProvider())
|
|
{
|
|
std::vector < QgsField > &fields = provider->fields();
|
|
QString str;
|
|
|
|
for (std::vector < QgsField >::iterator it = fields.begin(); it != fields.end(); ++it)
|
|
{
|
|
str = (*it).name();
|
|
str = str.left(1).upper() + str.right(str.length() - 1); //make the first letter uppercase
|
|
mClassificationComboBox->insertItem(str);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
qWarning("Warning, data provider is null in QgsUValDialog::QgsUValDialog");
|
|
return;
|
|
}
|
|
|
|
QObject::connect(mClassificationComboBox, SIGNAL(activated(int)), this, SLOT(changeClassificationAttribute(int)));
|
|
QObject::connect(mClassBreakBox, SIGNAL(selectionChanged()), this, SLOT(changeCurrentValue()));
|
|
QObject::connect(&sydialog, SIGNAL(settingsChanged()), this, SLOT(applySymbologyChanges()));
|
|
mSymbolWidgetStack->addWidget(&sydialog);
|
|
mSymbolWidgetStack->raiseWidget(&sydialog);
|
|
|
|
//restore settings if unique value renderer was read from a project file
|
|
QgsUniqueValRenderer *renderer;
|
|
//initial settings, use the buffer of the propertiesDialog if possible. If this is not possible, use the renderer of the vectorlayer directly
|
|
if (mVectorLayer->propertiesDialog())
|
|
{
|
|
renderer = dynamic_cast < QgsUniqueValRenderer * >(mVectorLayer->propertiesDialog()->getBufferRenderer());
|
|
}
|
|
else
|
|
{
|
|
renderer = dynamic_cast < QgsUniqueValRenderer * >(mVectorLayer->renderer());
|
|
}
|
|
|
|
|
|
if (renderer)
|
|
{
|
|
mClassBreakBox->clear();
|
|
std::map<QString,QgsRenderItem*>& map=renderer->items();
|
|
for(std::map<QString,QgsRenderItem*>::iterator it=map.begin();it!=map.end();++it)
|
|
{
|
|
mClassBreakBox->insertItem(it->first);
|
|
QgsSymbol* symbol=new QgsSymbol();
|
|
QgsRenderItem* ritem=new QgsRenderItem(symbol,"","");
|
|
symbol->setPen(it->second->getSymbol()->pen());
|
|
symbol->setBrush(it->second->getSymbol()->brush());
|
|
mValues.insert(std::make_pair(it->first,ritem));
|
|
}
|
|
|
|
std::list<int>::iterator iter=renderer->classificationAttributes().begin();
|
|
int classattr=*iter;
|
|
mClassificationComboBox->setCurrentItem(classattr);
|
|
mClassBreakBox->setCurrentItem(0);
|
|
changeClassificationAttribute(0);
|
|
}
|
|
|
|
}
|
|
|
|
QgsUValDialog::~QgsUValDialog()
|
|
{
|
|
for(std::map<QString,QgsRenderItem*>::iterator it=mValues.begin();it!=mValues.end();++it)
|
|
{
|
|
delete it->second;
|
|
}
|
|
mClassBreakBox->setCurrentItem(0);
|
|
}
|
|
|
|
void QgsUValDialog::apply()
|
|
{
|
|
//font tor the legend text
|
|
QFont f("arial", 10, QFont::Normal);
|
|
QFontMetrics fm(f);
|
|
|
|
int symbolheight = 15; //height of an area where a symbol is painted
|
|
int symbolwidth = 15; //width of an area where a symbol is painted
|
|
int rowheight = (fm.height() > symbolheight) ? fm.height() : symbolheight; //height of a row in the symbology part
|
|
int topspace = 5;
|
|
int bottomspace = 5;
|
|
int leftspace = 5;
|
|
int rightspace = 5;
|
|
int rowspace = 5;
|
|
int wordspace = 5; //space between graphics/word
|
|
int widestvalue = 0;
|
|
int valuewidth;
|
|
|
|
//find out the width of the widest label and of the broadest value string
|
|
int maxlabelwidth=0;
|
|
int maxvaluewidth=0;
|
|
|
|
for(std::map<QString,QgsRenderItem*>::iterator it=mValues.begin();it!=mValues.end();++it)
|
|
{
|
|
int currentlabelwidth=fm.width(it->second->label());
|
|
if(currentlabelwidth>maxlabelwidth)
|
|
{
|
|
maxlabelwidth=currentlabelwidth;
|
|
}
|
|
int currentvwidth=fm.width(it->second->value());
|
|
if(currentvwidth>maxvaluewidth)
|
|
{
|
|
//widestlu = string2;
|
|
maxvaluewidth=currentvwidth;
|
|
}
|
|
}
|
|
|
|
QgsUniqueValRenderer *renderer = dynamic_cast < QgsUniqueValRenderer * >(mVectorLayer->renderer());
|
|
|
|
//go through mValues and add the entries to the renderer
|
|
if(renderer)
|
|
{
|
|
renderer->clearValues();
|
|
for(std::map<QString,QgsRenderItem*>::iterator it=mValues.begin();it!=mValues.end();++it)
|
|
{
|
|
QgsSymbol* symbol=it->second->getSymbol();
|
|
QgsSymbol* newsymbol=new QgsSymbol();
|
|
newsymbol->setPen(symbol->pen());
|
|
newsymbol->setBrush(symbol->brush());
|
|
QgsRenderItem* ritem=new QgsRenderItem(newsymbol,it->first,"");
|
|
renderer->insertValue(it->first,ritem);
|
|
//find out the width of the string
|
|
valuewidth=fm.width(it->first);
|
|
if(valuewidth>widestvalue)
|
|
{
|
|
widestvalue=valuewidth;
|
|
}
|
|
}
|
|
renderer->setClassificationField(mClassificationComboBox->currentItem());
|
|
}
|
|
else
|
|
{
|
|
#ifdef QGISDEBUG
|
|
qWarning("Warning, typecast failed in qgsuvaldialog.cpp, l. 61");
|
|
#endif
|
|
}
|
|
|
|
//render the legend item
|
|
QPixmap *pix = mVectorLayer->legendPixmap();
|
|
QString name;
|
|
QString field=mClassificationComboBox->currentText();
|
|
int fieldwidth=fm.width(field);
|
|
if(fieldwidth>widestvalue)
|
|
{
|
|
widestvalue=fieldwidth;
|
|
}
|
|
if (mVectorLayer->propertiesDialog())
|
|
{
|
|
name = mVectorLayer->propertiesDialog()->displayName();
|
|
}
|
|
else
|
|
{
|
|
name = "";
|
|
}
|
|
int namewidth=fm.width(name);
|
|
int pixwidth;
|
|
if(namewidth>widestvalue)
|
|
{
|
|
if(namewidth>(symbolwidth+wordspace+widestvalue+maxlabelwidth))
|
|
{
|
|
pixwidth = leftspace+wordspace+namewidth+rightspace;
|
|
}
|
|
else
|
|
{
|
|
pixwidth = leftspace+2*wordspace+symbolwidth+maxlabelwidth+widestvalue+rightspace;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pixwidth = leftspace+2*wordspace+symbolwidth+widestvalue+maxlabelwidth+rightspace;
|
|
}
|
|
|
|
int pixheight = topspace+2*fm.height()+rowspace+(rowheight+rowspace)*mValues.size()+bottomspace;
|
|
|
|
pix->resize(pixwidth,pixheight);
|
|
pix->fill();
|
|
QPainter p(pix);
|
|
p.setFont(f);
|
|
|
|
//draw the layer name and the name of the classification field into the pixmap
|
|
p.drawText(leftspace, topspace + fm.height(), name);
|
|
p.drawText(leftspace, topspace + 2 * fm.height(), field);
|
|
int intermheight=topspace+2*fm.height()+rowspace;
|
|
int row=0;
|
|
|
|
for(std::map<QString,QgsRenderItem*>::iterator it=mValues.begin();it!=mValues.end();++it)
|
|
{
|
|
QgsSymbol* sym=it->second->getSymbol();
|
|
p.setPen(sym->pen());
|
|
p.setBrush(sym->brush());
|
|
|
|
if (mVectorLayer->vectorType() == QGis::Polygon)
|
|
{
|
|
p.drawRect(leftspace,intermheight+row*(rowheight+rowspace)+rowheight-symbolheight,symbolwidth,symbolheight);
|
|
}
|
|
else if (mVectorLayer->vectorType() == QGis::Line)
|
|
{
|
|
p.drawLine(leftspace,intermheight+row*(rowheight+rowspace)+rowheight-symbolheight,leftspace+symbolwidth,intermheight+row*(rowheight+rowspace)+rowheight);
|
|
}
|
|
else if (mVectorLayer->vectorType() == QGis::Point)
|
|
{
|
|
p.drawRect(leftspace + symbolwidth / 2, intermheight + (int) ((rowheight+rowspace) * (row + 0.5)),5,5);
|
|
}
|
|
p.setPen(Qt::black);
|
|
p.drawText(leftspace+symbolwidth+wordspace, intermheight+row*(rowheight+rowspace)+rowheight, it->first);
|
|
p.drawText(leftspace+symbolwidth+2*wordspace+widestvalue, intermheight+row*(rowheight+rowspace)+rowheight, it->second->label());
|
|
++row;
|
|
}
|
|
|
|
|
|
|
|
mVectorLayer->updateItemPixmap();
|
|
mVectorLayer->triggerRepaint();
|
|
}
|
|
|
|
void QgsUValDialog::changeClassificationAttribute(int nr)
|
|
{
|
|
#ifdef QGISDEBUG
|
|
qWarning("in changeClassificationAttribute, nr is: "+QString::number(nr));
|
|
#endif
|
|
|
|
//todo: reset sdialog
|
|
|
|
//delete old entries
|
|
for(std::map<QString,QgsRenderItem*>::iterator it=mValues.begin();it!=mValues.end();++it)
|
|
{
|
|
delete it->second;
|
|
}
|
|
mValues.clear();
|
|
|
|
QgsDataProvider *provider = mVectorLayer->getDataProvider();
|
|
if (provider)
|
|
{
|
|
QString value;
|
|
std::list<int> attlist;
|
|
attlist.push_back(nr);
|
|
std::vector < QgsFeatureAttribute > vec;
|
|
QgsSymbol* symbol;
|
|
QgsRenderItem* ritemptr;
|
|
|
|
provider->reset();
|
|
QgsFeature* f;
|
|
|
|
//go through all the features and insert their value into the map and into mClassBreakBox
|
|
mClassBreakBox->clear();
|
|
while((f=provider->getNextFeature(attlist)))
|
|
{
|
|
vec = f->attributeMap();
|
|
value=vec[0].fieldValue();
|
|
|
|
if(mValues.find(value)==mValues.end())
|
|
{
|
|
symbol=new QgsSymbol();
|
|
ritemptr=new QgsRenderItem(symbol,"","");
|
|
mValues.insert(std::make_pair(value,ritemptr));
|
|
}
|
|
}
|
|
|
|
//set symbology for all QgsSiSyDialogs
|
|
QColor thecolor;
|
|
double number=0;
|
|
double frac;
|
|
|
|
for(std::map<QString,QgsRenderItem*>::iterator it=mValues.begin();it!=mValues.end();++it)
|
|
{
|
|
++number;
|
|
//color range from blue to red
|
|
frac=number/mValues.size();
|
|
thecolor.setRgb(int(255*frac),0,int(255-(255*frac)));
|
|
mClassBreakBox->insertItem(it->first);
|
|
QgsSymbol* sym=it->second->getSymbol();
|
|
QPen pen;
|
|
QBrush brush;
|
|
if(mVectorLayer->vectorType() == QGis::Line)
|
|
{
|
|
pen.setColor(thecolor);
|
|
pen.setStyle(Qt::SolidLine);
|
|
pen.setWidth(1);
|
|
}
|
|
else
|
|
{
|
|
brush.setColor(thecolor);
|
|
brush.setStyle(Qt::SolidPattern);
|
|
pen.setColor(Qt::black);
|
|
pen.setStyle(Qt::SolidLine);
|
|
pen.setWidth(1);
|
|
}
|
|
sym->setPen(pen);
|
|
sym->setBrush(brush);
|
|
}
|
|
}
|
|
mClassBreakBox->setCurrentItem(0);
|
|
}
|
|
|
|
void QgsUValDialog::changeCurrentValue()
|
|
{
|
|
QListBoxItem* item=mClassBreakBox->selectedItem();
|
|
QString value=item->text();
|
|
std::map<QString,QgsRenderItem*>::iterator it=mValues.find(value);
|
|
if(it!=mValues.end())
|
|
{
|
|
QPen& pen=it->second->getSymbol()->pen();
|
|
QBrush& brush=it->second->getSymbol()->brush();
|
|
QColor fcolor(brush.color().red(),brush.color().green(),brush.color().blue());
|
|
QColor ocolor(pen.color().red(),pen.color().green(),pen.color().blue());
|
|
sydialog.setFillColor(fcolor);
|
|
sydialog.setFillStyle(brush.style());
|
|
sydialog.setOutlineColor(ocolor);
|
|
sydialog.setOutlineStyle(pen.style());
|
|
sydialog.setOutlineWidth(pen.width());
|
|
sydialog.setLabel(it->second->label());
|
|
}
|
|
else
|
|
{
|
|
//no entry found
|
|
}
|
|
}
|
|
|
|
void QgsUValDialog::applySymbologyChanges()
|
|
{
|
|
QListBoxItem* item=mClassBreakBox->selectedItem();
|
|
QString value=item->text();
|
|
std::map<QString,QgsRenderItem*>::iterator it=mValues.find(value);
|
|
if(it!=mValues.end())
|
|
{
|
|
QPen& pen=it->second->getSymbol()->pen();
|
|
QBrush& brush=it->second->getSymbol()->brush();
|
|
pen.setWidth(sydialog.getOutlineWidth());
|
|
pen.setColor(sydialog.getOutlineColor());
|
|
pen.setStyle(sydialog.getOutlineStyle());
|
|
brush.setColor(sydialog.getFillColor());
|
|
brush.setStyle(sydialog.getFillStyle());
|
|
it->second->setLabel(sydialog.label());
|
|
}
|
|
}
|