~ubuntu-branches/ubuntu/utopic/qgis/utopic

« back to all changes in this revision

Viewing changes to src/qgsuvaldialog.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Steve Halasz
  • Date: 2004-12-21 09:46:27 UTC
  • Revision ID: james.westby@ubuntu.com-20041221094627-r9lb6mlz2o3yp8gn
Tags: upstream-0.6.0
ImportĀ upstreamĀ versionĀ 0.6.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
                         qgsuvaldialog.cpp  -  description
 
3
                             -------------------
 
4
    begin                : July 2004
 
5
    copyright            : (C) 2004 by Marco Hugentobler
 
6
    email                : marco.hugentobler@autoform.ch
 
7
 ***************************************************************************/
 
8
 
 
9
/***************************************************************************
 
10
 *                                                                         *
 
11
 *   This program is free software; you can redistribute it and/or modify  *
 
12
 *   it under the terms of the GNU General Public License as published by  *
 
13
 *   the Free Software Foundation; either version 2 of the License, or     *
 
14
 *   (at your option) any later version.                                   *
 
15
 *                                                                         *
 
16
 ***************************************************************************/
 
17
/* $Id: qgsuvaldialog.cpp,v 1.16.2.3 2004/12/12 23:28:23 mhugent Exp $ */
 
18
#include "qgsuvaldialog.h"
 
19
#include "qgsvectordataprovider.h"
 
20
#include "qgsvectorlayer.h"
 
21
#include "qgsdlgvectorlayerproperties.h"
 
22
#include "qgsfeature.h"
 
23
#include "qgsfeatureattribute.h"
 
24
#include "qgsuniquevalrenderer.h"
 
25
#include "qgssisydialog.h"
 
26
#include "qgssymbol.h"
 
27
#include "qgsrenderitem.h"
 
28
#include "qgsuniquevalrenderer.h"
 
29
#include <qwidgetstack.h>
 
30
#include <qlistbox.h>
 
31
#include <qcombobox.h>
 
32
#include <qpainter.h>
 
33
#include <list>
 
34
 
 
35
QgsUValDialog::QgsUValDialog(QgsVectorLayer* vl): QgsUValDialogBase(), mVectorLayer(vl), sydialog(vl)
 
36
{
 
37
    setSizeGripEnabled(true); 
 
38
 
 
39
    //find out the fields of mVectorLayer
 
40
    QgsVectorDataProvider *provider;
 
41
    if (provider = dynamic_cast<QgsVectorDataProvider *>(mVectorLayer->getDataProvider()))
 
42
    {
 
43
        std::vector < QgsField > &fields = provider->fields();
 
44
        QString str;
 
45
        
 
46
        for (std::vector < QgsField >::iterator it = fields.begin(); it != fields.end(); ++it)
 
47
        {
 
48
            str = (*it).name();
 
49
            str = str.left(1).upper() + str.right(str.length() - 1);  //make the first letter uppercase
 
50
            mClassificationComboBox->insertItem(str);
 
51
        }
 
52
    } 
 
53
    else
 
54
    {
 
55
        qWarning("Warning, data provider is null in QgsUValDialog::QgsUValDialog");
 
56
        return;
 
57
    }
 
58
 
 
59
    QObject::connect(mClassificationComboBox, SIGNAL(activated(int)), this, SLOT(changeClassificationAttribute(int)));
 
60
    QObject::connect(mClassBreakBox, SIGNAL(selectionChanged()), this, SLOT(changeCurrentValue()));
 
61
    QObject::connect(&sydialog, SIGNAL(settingsChanged()), this, SLOT(applySymbologyChanges()));
 
62
    mSymbolWidgetStack->addWidget(&sydialog);
 
63
    mSymbolWidgetStack->raiseWidget(&sydialog);
 
64
 
 
65
    //restore settings if unique value renderer was read from a project file
 
66
    QgsUniqueValRenderer *renderer;
 
67
    //initial settings, use the buffer of the propertiesDialog if possible. If this is not possible, use the renderer of the vectorlayer directly
 
68
    if (mVectorLayer->propertiesDialog())
 
69
    {
 
70
        renderer = dynamic_cast < QgsUniqueValRenderer * >(mVectorLayer->propertiesDialog()->getBufferRenderer());
 
71
    } 
 
72
    else
 
73
    {
 
74
        renderer = dynamic_cast < QgsUniqueValRenderer * >(mVectorLayer->renderer());
 
75
    }
 
76
 
 
77
 
 
78
    if (renderer)
 
79
    {
 
80
        mClassBreakBox->clear();
 
81
        std::list<int>::iterator iter=renderer->classificationAttributes().begin();
 
82
        int classattr=*iter;
 
83
        mClassificationComboBox->setCurrentItem(classattr);
 
84
        
 
85
        if(renderer->items().size()==0)
 
86
        {
 
87
            changeClassificationAttribute(classattr);
 
88
        }
 
89
        
 
90
        //fill the items of the renderer into mValues
 
91
        for(std::map<QString,QgsRenderItem*>::iterator iter=renderer->items().begin();iter!=renderer->items().end();++iter)
 
92
        {
 
93
            QgsRenderItem* item=(*iter).second;
 
94
            QString itemvalue=item->value();
 
95
            QgsSymbol* sym=new QgsSymbol();
 
96
            sym->setPen(item->getSymbol()->pen());
 
97
            sym->setBrush(item->getSymbol()->brush());
 
98
            QgsRenderItem* ritem=new QgsRenderItem(sym,item->value(),item->label());
 
99
            mValues.insert(std::make_pair(itemvalue,ritem));
 
100
            mClassBreakBox->insertItem(itemvalue);
 
101
        }
 
102
    }
 
103
    mClassBreakBox->setCurrentItem(0);
 
104
}
 
105
 
 
106
QgsUValDialog::~QgsUValDialog()
 
107
{
 
108
    std::map<QString, QgsRenderItem *>::iterator myValueIterator = mValues.begin();
 
109
    while ( myValueIterator != mValues.end() )
 
110
    {
 
111
        delete myValueIterator->second;
 
112
        
 
113
        mValues.erase( myValueIterator );
 
114
        
 
115
        myValueIterator = mValues.begin(); // since iterator invalidated due to
 
116
                                        // erase(), reset to new first element
 
117
    }
 
118
    mClassBreakBox->setCurrentItem(0);
 
119
}
 
120
 
 
121
void QgsUValDialog::apply()
 
122
{
 
123
    //font tor the legend text
 
124
    QFont f("arial", 10, QFont::Normal);
 
125
    QFontMetrics fm(f);
 
126
 
 
127
    int symbolheight = 15;    //height of an area where a symbol is painted
 
128
    int symbolwidth = 15;     //width of an area where a symbol is painted
 
129
    int rowheight = (fm.height() > symbolheight) ? fm.height() : symbolheight;  //height of a row in the symbology part
 
130
    int topspace = 5;
 
131
    int bottomspace = 5;
 
132
    int leftspace = 5;
 
133
    int rightspace = 5;
 
134
    int rowspace = 5;
 
135
    int wordspace = 5;        //space between graphics/word
 
136
    int widestvalue = 0;
 
137
    int valuewidth;
 
138
 
 
139
    //find out the width of the widest label and of the broadest value string
 
140
    int maxlabelwidth=0;
 
141
    int maxvaluewidth=0;
 
142
 
 
143
    for(std::map<QString,QgsRenderItem*>::iterator it=mValues.begin();it!=mValues.end();++it)
 
144
    {
 
145
        int currentlabelwidth=fm.width(it->second->label());
 
146
        if(currentlabelwidth>maxlabelwidth)
 
147
        {
 
148
            maxlabelwidth=currentlabelwidth;
 
149
        }
 
150
        int currentvwidth=fm.width(it->second->value());
 
151
        if(currentvwidth>maxvaluewidth)
 
152
        {
 
153
            //widestlu = string2;
 
154
            maxvaluewidth=currentvwidth;
 
155
        }
 
156
    }
 
157
 
 
158
    QgsUniqueValRenderer *renderer = dynamic_cast < QgsUniqueValRenderer * >(mVectorLayer->renderer());
 
159
 
 
160
    //go through mValues and add the entries to the renderer
 
161
    if(renderer)
 
162
    {
 
163
        renderer->clearValues();
 
164
        for(std::map<QString,QgsRenderItem*>::iterator it=mValues.begin();it!=mValues.end();++it)
 
165
        {
 
166
            QgsSymbol* symbol=it->second->getSymbol();
 
167
            QgsSymbol* newsymbol=new QgsSymbol();
 
168
            newsymbol->setPen(symbol->pen());
 
169
            newsymbol->setBrush(symbol->brush());
 
170
            QgsRenderItem* ritem=new QgsRenderItem(newsymbol,it->first,it->second->label());
 
171
            renderer->insertValue(it->first,ritem);
 
172
            //find out the width of the string
 
173
            valuewidth=fm.width(it->first);
 
174
            if(valuewidth>widestvalue)
 
175
            {
 
176
                widestvalue=valuewidth;
 
177
            }
 
178
        }
 
179
        renderer->setClassificationField(mClassificationComboBox->currentItem());
 
180
    }
 
181
    else
 
182
    {
 
183
#ifdef QGISDEBUG
 
184
        qWarning("Warning, typecast failed in qgsuvaldialog.cpp, l. 61"); 
 
185
#endif
 
186
    }
 
187
 
 
188
    //render the legend item
 
189
    QPixmap *pix = mVectorLayer->legendPixmap();
 
190
    QString name;
 
191
    QString field=mClassificationComboBox->currentText();
 
192
    int fieldwidth=fm.width(field);
 
193
    if(fieldwidth>widestvalue)
 
194
    {
 
195
        widestvalue=fieldwidth;
 
196
    }
 
197
    if (mVectorLayer->propertiesDialog())
 
198
    {
 
199
        name = mVectorLayer->propertiesDialog()->displayName();
 
200
    } 
 
201
    else
 
202
    {
 
203
        name = "";
 
204
    }
 
205
    int namewidth=fm.width(name);
 
206
    int pixwidth;
 
207
    if(namewidth>widestvalue)
 
208
    {
 
209
        if(namewidth>(symbolwidth+wordspace+widestvalue+maxlabelwidth))
 
210
        {
 
211
            pixwidth = leftspace+wordspace+namewidth+rightspace;
 
212
        }
 
213
        else
 
214
        {
 
215
            pixwidth = leftspace+2*wordspace+symbolwidth+maxlabelwidth+widestvalue+rightspace; 
 
216
        }
 
217
    }
 
218
    else
 
219
    {
 
220
        pixwidth = leftspace+2*wordspace+symbolwidth+widestvalue+maxlabelwidth+rightspace;
 
221
    }
 
222
   
 
223
    int pixheight = topspace+2*fm.height()+rowspace+(rowheight+rowspace)*mValues.size()+bottomspace;
 
224
    
 
225
    pix->resize(pixwidth,pixheight);
 
226
    pix->fill();
 
227
    QPainter p(pix);
 
228
    p.setFont(f);
 
229
    
 
230
    //draw the layer name and the name of the classification field into the pixmap
 
231
    p.drawText(leftspace, topspace + fm.height(), name);
 
232
    p.drawText(leftspace, topspace + 2 * fm.height(), field);
 
233
    int intermheight=topspace+2*fm.height()+rowspace;
 
234
    int row=0;
 
235
 
 
236
    for(std::map<QString,QgsRenderItem*>::iterator it=mValues.begin();it!=mValues.end();++it)
 
237
    {
 
238
        QgsSymbol* sym=it->second->getSymbol();
 
239
        p.setPen(sym->pen());
 
240
        p.setBrush(sym->brush());
 
241
 
 
242
        if (mVectorLayer->vectorType() == QGis::Polygon)
 
243
        {
 
244
            p.drawRect(leftspace,intermheight+row*(rowheight+rowspace)+rowheight-symbolheight,symbolwidth,symbolheight); 
 
245
        }
 
246
        else if (mVectorLayer->vectorType() == QGis::Line)
 
247
        {
 
248
            p.drawLine(leftspace,intermheight+row*(rowheight+rowspace)+rowheight-symbolheight,leftspace+symbolwidth,intermheight+row*(rowheight+rowspace)+rowheight);
 
249
        }
 
250
        else if (mVectorLayer->vectorType() == QGis::Point)
 
251
        {
 
252
            p.drawRect(leftspace + symbolwidth / 2, intermheight + (int) ((rowheight+rowspace) * (row + 0.5)),5,5);
 
253
        }
 
254
        p.setPen(Qt::black);
 
255
        p.drawText(leftspace+symbolwidth+wordspace, intermheight+row*(rowheight+rowspace)+rowheight, it->first);
 
256
        p.drawText(leftspace+symbolwidth+2*wordspace+widestvalue, intermheight+row*(rowheight+rowspace)+rowheight, it->second->label());
 
257
        ++row;
 
258
    }
 
259
 
 
260
    
 
261
    
 
262
    mVectorLayer->updateItemPixmap();
 
263
    mVectorLayer->triggerRepaint();
 
264
}
 
265
 
 
266
void QgsUValDialog::changeClassificationAttribute(int nr)
 
267
{
 
268
    //delete old entries
 
269
    for(std::map<QString,QgsRenderItem*>::iterator it=mValues.begin();it!=mValues.end();++it)
 
270
    {
 
271
        delete it->second;
 
272
    }
 
273
    mValues.clear();
 
274
    
 
275
    QgsVectorDataProvider *provider = dynamic_cast<QgsVectorDataProvider *>(mVectorLayer->getDataProvider());
 
276
    if (provider)
 
277
    {
 
278
        QString value;
 
279
        std::list<int> attlist;
 
280
        attlist.push_back(nr);
 
281
        std::vector < QgsFeatureAttribute > vec;
 
282
        QgsSymbol* symbol;
 
283
        QgsRenderItem* ritemptr;
 
284
 
 
285
        provider->reset();
 
286
        QgsFeature* f;
 
287
 
 
288
        //go through all the features and insert their value into the map and into mClassBreakBox
 
289
        mClassBreakBox->clear();
 
290
        while((f=provider->getNextFeature(attlist)))
 
291
        {
 
292
            vec = f->attributeMap();
 
293
            value=vec[0].fieldValue();
 
294
           
 
295
            if(mValues.find(value)==mValues.end())
 
296
            {
 
297
                symbol=new QgsSymbol();
 
298
                ritemptr=new QgsRenderItem(symbol,"","");
 
299
                mValues.insert(std::make_pair(value,ritemptr));
 
300
            }
 
301
            delete f;
 
302
        }
 
303
 
 
304
        //set symbology for all QgsSiSyDialogs
 
305
        QColor thecolor;
 
306
        double number=0;
 
307
        double frac;
 
308
 
 
309
        for(std::map<QString,QgsRenderItem*>::iterator it=mValues.begin();it!=mValues.end();++it)
 
310
        {
 
311
            ++number;
 
312
            //color range from blue to red
 
313
            frac=number/mValues.size();
 
314
            thecolor.setRgb(int(255*frac),0,int(255-(255*frac)));
 
315
            mClassBreakBox->insertItem(it->first);
 
316
            QgsSymbol* sym=it->second->getSymbol();
 
317
            QPen pen;
 
318
            QBrush brush;
 
319
            if(mVectorLayer->vectorType() == QGis::Line)
 
320
            {
 
321
                pen.setColor(thecolor);
 
322
                pen.setStyle(Qt::SolidLine);
 
323
                pen.setWidth(1);
 
324
            }
 
325
            else
 
326
            {
 
327
                brush.setColor(thecolor);
 
328
                brush.setStyle(Qt::SolidPattern);
 
329
                pen.setColor(Qt::black);
 
330
                pen.setStyle(Qt::SolidLine);
 
331
                pen.setWidth(1);
 
332
            }
 
333
            sym->setPen(pen);
 
334
            sym->setBrush(brush);
 
335
        }
 
336
    }
 
337
    mClassBreakBox->setCurrentItem(0);
 
338
}
 
339
 
 
340
void QgsUValDialog::changeCurrentValue()
 
341
{
 
342
    sydialog.blockSignals(true);//block signal to prevent sydialog from changing the current QgsRenderItem
 
343
    QListBoxItem* item=mClassBreakBox->selectedItem();
 
344
    QString value=item->text();
 
345
    std::map<QString,QgsRenderItem*>::iterator it=mValues.find(value);
 
346
    if(it!=mValues.end())
 
347
    {
 
348
        QPen& pen=it->second->getSymbol()->pen();
 
349
        QBrush& brush=it->second->getSymbol()->brush();
 
350
        QColor fcolor(brush.color().red(),brush.color().green(),brush.color().blue());
 
351
        QColor ocolor(pen.color().red(),pen.color().green(),pen.color().blue());
 
352
        sydialog.setFillColor(fcolor);
 
353
        sydialog.setFillStyle(brush.style());
 
354
        sydialog.setOutlineColor(ocolor);
 
355
        sydialog.setOutlineStyle(pen.style());
 
356
        sydialog.setOutlineWidth(pen.width());
 
357
        sydialog.setLabel(it->second->label());
 
358
    }
 
359
    else
 
360
    {
 
361
        //no entry found
 
362
    }
 
363
    sydialog.blockSignals(false);
 
364
}
 
365
 
 
366
void QgsUValDialog::applySymbologyChanges()
 
367
{
 
368
  QListBoxItem* item=mClassBreakBox->selectedItem();
 
369
  QString value=item->text();
 
370
  std::map<QString,QgsRenderItem*>::iterator it=mValues.find(value);
 
371
  if(it!=mValues.end())
 
372
  {
 
373
      QPen& pen=it->second->getSymbol()->pen();
 
374
      QBrush& brush=it->second->getSymbol()->brush(); 
 
375
      pen.setWidth(sydialog.getOutlineWidth());
 
376
      pen.setColor(sydialog.getOutlineColor());
 
377
      pen.setStyle(sydialog.getOutlineStyle());
 
378
      brush.setColor(sydialog.getFillColor());
 
379
      brush.setStyle(sydialog.getFillStyle());
 
380
      it->second->setLabel(sydialog.label());
 
381
  }
 
382
}