~ubuntu-branches/ubuntu/quantal/qgis/quantal

« back to all changes in this revision

Viewing changes to src/qgsgramadialog.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
                          qgsgramadialog.cpp  -  description
 
3
                             -------------------
 
4
    begin                : April 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 */
 
18
 
 
19
#include "qgsgramadialog.h"
 
20
#include "qgsgramaextensionwidget.h"
 
21
#include "qgsmarkersymbol.h"
 
22
#include "qgsvectorlayer.h"
 
23
#include "qgsvectordataprovider.h"
 
24
#include "qgsgraduatedmarenderer.h"
 
25
#include "qgsdlgvectorlayerproperties.h"
 
26
#include "qgslegenditem.h"
 
27
#include "qgssvgcache.h"
 
28
#include <qcombobox.h>
 
29
#include <qlayout.h>
 
30
#include <qpainter.h>
 
31
#include <qpushbutton.h>
 
32
#include <qspinbox.h>
 
33
 
 
34
QgsGraMaDialog::QgsGraMaDialog(QgsVectorLayer* layer): QgsGraMaDialogBase(), ext(0), mVectorLayer(layer)
 
35
{
 
36
#ifdef QGISDEBUG
 
37
    qWarning("constructor QgsGraSyDialog");
 
38
#endif
 
39
 
 
40
    setOrientation(Qt::Vertical);
 
41
    setSizeGripEnabled(true);
 
42
 
 
43
    //find out the numerical fields of mVectorLayer
 
44
    QgsVectorDataProvider *provider;
 
45
    if (provider = dynamic_cast<QgsVectorDataProvider *>(mVectorLayer->getDataProvider()))
 
46
    {
 
47
        std::vector < QgsField > &fields = provider->fields();
 
48
        int fieldnumber = 0;
 
49
        QString str;
 
50
        
 
51
        for (std::vector < QgsField >::iterator it = fields.begin(); it != fields.end(); ++it)
 
52
        {
 
53
            QString type = (*it).type();
 
54
            if (type != "String" && type != "varchar" && type != "geometry")
 
55
            {
 
56
                str = (*it).name();
 
57
                str = str.left(1).upper() + str.right(str.length() - 1);  //make the first letter uppercase
 
58
                mClassificationComboBox->insertItem(str);
 
59
                mFieldMap.insert(std::make_pair(str, fieldnumber));
 
60
            }
 
61
            fieldnumber++;
 
62
        }
 
63
    } 
 
64
    else
 
65
    {
 
66
        qWarning("Warning, data provider is null in QgsGraSyDialog::QgsGraSyDialog(...)");
 
67
        return;
 
68
    }
 
69
 
 
70
    mModeComboBox->insertItem("Empty");
 
71
    mModeComboBox->insertItem("Equal Interval");
 
72
 
 
73
    //restore the correct settings
 
74
    QgsGraduatedMaRenderer *renderer;
 
75
    
 
76
    //initial settings, use the buffer of the propertiesDialog if possible. If this is not possible, use the renderer of the vectorlayer directly
 
77
    if (mVectorLayer->propertiesDialog())
 
78
    {
 
79
        renderer = dynamic_cast < QgsGraduatedMaRenderer * >(layer->propertiesDialog()->getBufferRenderer());
 
80
    } 
 
81
    else
 
82
    {
 
83
        renderer = dynamic_cast < QgsGraduatedMaRenderer * >(layer->renderer());
 
84
    }
 
85
 
 
86
    std::list < QgsRangeRenderItem * >list;
 
87
    
 
88
    if (renderer)
 
89
    {
 
90
        list = renderer->items();
 
91
        ext = new QgsGraMaExtensionWidget(this, renderer->classificationField(), QgsGraSyDialog::EMPTY, list.size(), mVectorLayer);
 
92
    }
 
93
 
 
94
    mClassificationComboBox->setCurrentItem(renderer->classificationField());
 
95
    
 
96
    //set the right colors and texts to the widgets
 
97
    int number = 0;
 
98
    for (std::list < QgsRangeRenderItem * >::iterator it = list.begin(); it != list.end(); ++it)
 
99
    {
 
100
        ((QLineEdit *) (ext->getWidget(0, number)))->setText((*it)->value());
 
101
        ((QLineEdit *) ext->getWidget(1, number))->setText((*it)->upper_value());
 
102
        ((QLineEdit *) ext->getWidget(2, number))->setText((*it)->label());
 
103
        ((QPushButton *) ext->getWidget(3, number))->setName(((QgsMarkerSymbol*)((*it)->getSymbol()))->picture());
 
104
        ((QLineEdit *) ext->getWidget(4, number))->setText(QString::number(((QgsMarkerSymbol*)((*it)->getSymbol()))->scaleFactor(),'f',2));
 
105
        number++;
 
106
    }
 
107
    
 
108
 
 
109
    mNumberOfClassesSpinbox->setValue(list.size());
 
110
    QgsGraMaDialogBaseLayout->addMultiCellWidget(ext, 5, 5, 0, 3);
 
111
    ext->show();
 
112
 
 
113
    //do the necessary signal/slot connections
 
114
    QObject::connect(mNumberOfClassesSpinbox, SIGNAL(valueChanged(int)), this, SLOT(adjustNumberOfClasses()));
 
115
    QObject::connect(mClassificationComboBox, SIGNAL(activated(int)), this, SLOT(adjustClassification()));
 
116
    QObject::connect(mModeComboBox, SIGNAL(activated(int)), this, SLOT(adjustClassification()));
 
117
}
 
118
 
 
119
QgsGraMaDialog::QgsGraMaDialog()
 
120
{
 
121
#ifdef QGISDEBUG
 
122
    qWarning("constructor QgsGraSyDialog");
 
123
#endif
 
124
}
 
125
    
 
126
QgsGraMaDialog::~QgsGraMaDialog()
 
127
{
 
128
    if (ext)
 
129
    {
 
130
        ext->hide();
 
131
        delete ext;
 
132
    }
 
133
#ifdef QGISDEBUG
 
134
    qWarning("destructor QgsGraSyDialog");
 
135
#endif
 
136
}
 
137
 
 
138
void QgsGraMaDialog::apply()
 
139
{
 
140
    if (ext)
 
141
    {
 
142
        ext->adjustMarkers();
 
143
 
 
144
        if (mClassificationComboBox->currentText().isEmpty())  //don't do anything, it there is no classification field
 
145
        {
 
146
            return;
 
147
        }
 
148
 
 
149
        //font tor the legend text
 
150
        QFont f("arial", 10, QFont::Normal);
 
151
        QFontMetrics fm(f);
 
152
        
 
153
        //spaces
 
154
        int topspace = 5;
 
155
        int bottomspace = 5;
 
156
        int leftspace = 10;       //space between left side of the pixmap and the text/graphics
 
157
        int rightspace = 5;       //space between text/graphics and right side of the pixmap
 
158
        int wordspace = 5;        //space between graphics/word
 
159
        int markerheight;    //height of a marker (is different for every row)
 
160
        int markerwidth;     //width of the broadest marker
 
161
        int lowerupperwidth; // widht of the broadest lower-upper pair
 
162
        int rowspace = 5;         //spaces between rows of symbols
 
163
        int rowheight = fm.height();  //height of a text row
 
164
        int classesheight; //height of the classes section
 
165
        
 
166
        //find out the width of the widest label and the widest lower - upper pair
 
167
        int labelwidth=0;
 
168
        lowerupperwidth=0;
 
169
 
 
170
        for (int i = 0; i < mNumberOfClassesSpinbox->value(); i++)
 
171
        {
 
172
            int currentlabelwidth=fm.width(((QLineEdit *) (ext->getWidget(2, i)))->text());
 
173
            if(currentlabelwidth>labelwidth)
 
174
            {
 
175
                labelwidth=currentlabelwidth;
 
176
            }
 
177
            
 
178
            int currentluwidth=fm.width(((QLineEdit *) (ext->getWidget(0, i)))->text() + " - " + ((QLineEdit *) (ext->getWidget(1, i)))->text());
 
179
            if(currentluwidth>lowerupperwidth)
 
180
            {
 
181
                lowerupperwidth=currentluwidth;
 
182
            }
 
183
        }
 
184
 
 
185
        //find out the width of the broadest marker and the total height of the class section
 
186
        markerwidth=0;
 
187
        classesheight=rowspace*(mNumberOfClassesSpinbox->value()-1);
 
188
        for (int i = 0; i < mNumberOfClassesSpinbox->value(); i++)
 
189
        {
 
190
          QPixmap p = QgsSVGCache::instance().
 
191
            getPixmap(((QPushButton*)(ext->getWidget(3,i)))->name(), 
 
192
                      ((QLineEdit*)(ext->getWidget(4,i)))->text().toDouble());
 
193
          int width = p.width();
 
194
          if(width>markerwidth) {
 
195
            markerwidth=width;
 
196
            qWarning("markerwidth: "+QString::number(markerwidth));
 
197
          }
 
198
          int height = p.height();
 
199
          height = (height>rowheight) ? height : rowheight;
 
200
          qWarning("height: " + QString::number(height));
 
201
          classesheight+=height;
 
202
        }
 
203
 
 
204
        //create the pixmap for the render item
 
205
        QPixmap *pix = mVectorLayer->legendPixmap();
 
206
        QString name;
 
207
        if (mVectorLayer->propertiesDialog())
 
208
        {
 
209
            name = mVectorLayer->propertiesDialog()->displayName();
 
210
        } 
 
211
        else
 
212
        {
 
213
            name = "";
 
214
        }
 
215
 
 
216
        //query the name and the maximum upper value to estimate the necessary width of the pixmap
 
217
        int pixwidth = leftspace + rightspace + markerwidth + 2 * wordspace + labelwidth + lowerupperwidth; //width of the pixmap with symbol and values
 
218
        //consider 240 pixel for labels
 
219
        int namewidth = leftspace + fm.width(name) + rightspace;
 
220
        int width = (pixwidth > namewidth) ? pixwidth : namewidth;
 
221
        pix->resize(width, topspace + 2 * fm.height() + bottomspace + classesheight);
 
222
        pix->fill();
 
223
 
 
224
        QPainter p(pix);
 
225
        p.setFont(f);
 
226
        //draw the layer name and the name of the classification field into the pixmap
 
227
        p.drawText(leftspace, topspace + fm.height(), name);
 
228
        p.drawText(leftspace, topspace + 2 * fm.height(), mClassificationComboBox->currentText());
 
229
        
 
230
        QgsGraduatedMaRenderer *renderer = dynamic_cast < QgsGraduatedMaRenderer * >(mVectorLayer->renderer());
 
231
        
 
232
        if (!renderer)
 
233
        {
 
234
            qWarning("Warning, typecast failed in QgsGraSyDialog::apply()");
 
235
            return;
 
236
        }
 
237
 
 
238
        renderer->removeItems();
 
239
      
 
240
        int offset = topspace + 2 * fm.height();
 
241
        for (int i = 0; i < mNumberOfClassesSpinbox->value(); i++)
 
242
        {
 
243
            QgsMarkerSymbol* sy = new QgsMarkerSymbol();
 
244
            sy->setPicture(((QPushButton*)(ext->getWidget(3,i)))->name());
 
245
            qWarning("SVG file: " + QString::fromAscii(((QPushButton*)(ext->getWidget(3,i)))->name()));
 
246
            sy->setScaleFactor(((QLineEdit*)(ext->getWidget(4,i)))->text().toDouble());
 
247
            
 
248
            QString lower_bound = ((QLineEdit *) (ext->getWidget(0, i)))->text();
 
249
            QString upper_bound = ((QLineEdit *) (ext->getWidget(1, i)))->text();
 
250
            QString label = ((QLineEdit *) (ext->getWidget(2, i)))->text();
 
251
            
 
252
            //test, if lower_bound is numeric or not (making a subclass of QString would be the proper solution)
 
253
            bool lbcontainsletter = false;
 
254
            for (uint j = 0; j < lower_bound.length(); j++)
 
255
            {
 
256
                if (lower_bound.ref(j).isLetter())
 
257
                {
 
258
                    lbcontainsletter = true;
 
259
                }
 
260
            }
 
261
            
 
262
            //test, if upper_bound is numeric or not (making a subclass of QString would be the proper solution)
 
263
            bool ubcontainsletter = false;
 
264
            for (uint j = 0; j < upper_bound.length(); j++)
 
265
            {
 
266
                if (upper_bound.ref(j).isLetter())
 
267
                {
 
268
                    ubcontainsletter = true;
 
269
                }
 
270
            }
 
271
            
 
272
            if (lbcontainsletter == false && ubcontainsletter == false && lower_bound.length() > 0 && upper_bound.length() > 0) //only add the item if the value bounds do not contain letters and are not null strings
 
273
            {
 
274
                QgsRangeRenderItem *item = new QgsRangeRenderItem(sy, lower_bound, upper_bound, label);
 
275
                qWarning("lower_bound: " +lower_bound);
 
276
                qWarning("upper_bound: " +upper_bound);
 
277
                qWarning("label: " +label);
 
278
                renderer->addItem(item);
 
279
                
 
280
                //add the symbol to the picture
 
281
                QString legendstring = lower_bound + " - " + upper_bound;
 
282
                //todo: paint the picture
 
283
                double scalefactor=((QLineEdit*)(ext->getWidget(4,i)))->text().
 
284
                  toDouble();
 
285
                QPixmap pix = QgsSVGCache::instance().
 
286
                  getPixmap(((QPushButton*)(ext->getWidget(3,i)))->name(),
 
287
                            scalefactor);
 
288
                int actrowheight=(int)(pix.height() * scalefactor);
 
289
                actrowheight = (actrowheight > rowheight ? 
 
290
                                actrowheight : rowheight);
 
291
                p.drawPixmap(leftspace, offset, pix);
 
292
                p.setPen(Qt::black);
 
293
                p.drawText(leftspace+markerwidth + wordspace, offset + actrowheight, legendstring);
 
294
                p.drawText(leftspace+markerwidth+2*wordspace+lowerupperwidth, offset + actrowheight, label);
 
295
                offset+=(rowspace+actrowheight);
 
296
            }
 
297
        }
 
298
        
 
299
        renderer->setClassificationField(ext->classfield());
 
300
 
 
301
        mVectorLayer->updateItemPixmap();
 
302
        
 
303
        if (mVectorLayer->propertiesDialog())
 
304
        {
 
305
            mVectorLayer->propertiesDialog()->setRendererDirty(false);
 
306
        }
 
307
        mVectorLayer->triggerRepaint();
 
308
 
 
309
    } 
 
310
    else                          //number of classes is 0
 
311
    {
 
312
        std::cout << "warning, number of classes is zero" << std::endl << std::flush;
 
313
    }
 
314
}
 
315
 
 
316
void QgsGraMaDialog::adjustNumberOfClasses()
 
317
{
 
318
    //find out the number of the classification field
 
319
    QString fieldstring = mClassificationComboBox->currentText();
 
320
    if (fieldstring.isEmpty())    //don't do anything, it there is no classification field
 
321
    {
 
322
        show();
 
323
        return;
 
324
    }
 
325
    
 
326
    std::map < QString, int >::iterator iter = mFieldMap.find(fieldstring);
 
327
    int field = iter->second;
 
328
    
 
329
    if(ext)
 
330
    {
 
331
        QgsGraMaDialogBaseLayout->remove(ext);
 
332
        delete ext;
 
333
    }
 
334
 
 
335
    //create a new extension dialog
 
336
    if (mModeComboBox->currentText() == "Empty")
 
337
    {
 
338
        ext = new QgsGraMaExtensionWidget(this, field, QgsGraSyDialog::EMPTY, mNumberOfClassesSpinbox->value(), mVectorLayer);
 
339
    } 
 
340
    else if (mModeComboBox->currentText() == "Equal Interval")
 
341
    {
 
342
        ext = new QgsGraMaExtensionWidget(this, field, QgsGraSyDialog::EQUAL_INTERVAL, mNumberOfClassesSpinbox->value(), mVectorLayer);
 
343
    }
 
344
    
 
345
    if (mNumberOfClassesSpinbox->value() == 0)
 
346
    {
 
347
        ext = 0;
 
348
        return;
 
349
    }
 
350
    
 
351
    QgsGraMaDialogBaseLayout->addMultiCellWidget(ext, 5, 5, 0, 3);
 
352
    ext->show();
 
353
}
 
354
 
 
355
void QgsGraMaDialog::adjustClassification()
 
356
{
 
357
   //find out the number of the classification field
 
358
    QString fieldstring = mClassificationComboBox->currentText();
 
359
    if (fieldstring.isEmpty())    //don't do anything, it there is no classification field
 
360
    {
 
361
        show();
 
362
        return;
 
363
    }
 
364
    
 
365
    std::map < QString, int >::iterator iter = mFieldMap.find(fieldstring);
 
366
    int field = iter->second; 
 
367
    
 
368
    if(ext)
 
369
    {
 
370
        if (mModeComboBox->currentText() == "Empty")
 
371
        {
 
372
            ext->setClassification(QgsGraSyDialog::EMPTY,field);
 
373
        }
 
374
        else if(mModeComboBox->currentText() == "Equal Interval")
 
375
        {
 
376
            ext->setClassification(QgsGraSyDialog::EQUAL_INTERVAL,field);
 
377
        }
 
378
    }
 
379
}