All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
ChartLayerWidget.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2008 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 /*!
21  \file terralib/qt/widgets/charts/ChartLayerWidget.cpp
22 
23  \brief A widget used to build a grouping.
24 */
25 
26 // TerraLib
27 #include "../../../color/RGBAColor.h"
28 #include "../../../common/STLUtils.h"
29 #include "../../../dataaccess/utils/Utils.h"
30 #include "../../../dataaccess/query/OrderByItem.h"
31 #include "../../../maptools/Chart.h"
32 #include "../../../maptools/Enums.h"
33 #include "../../../maptools/QueryLayer.h"
34 #include "../utils/ColorPickerToolButton.h"
35 #include "../Utils.h"
36 #include "ChartLayerWidget.h"
37 #include "ui_ChartLayerWidgetForm.h"
38 
39 // Qt
40 #include <QString>
41 #include <QColor>
42 #include <QMessageBox>
43 #include <QPainterPath>
44 
45 // STL
46 #include <memory>
47 
48 //Boost
49 #include <boost/lexical_cast.hpp>
50 
51 
52 te::qt::widgets::ChartLayerWidget::ChartLayerWidget(QWidget* parent, Qt::WindowFlags f)
53  : QWidget(parent, f),
54  m_ui(new Ui::ChartLayerWidgetForm)
55 {
56  m_ui->setupUi(this);
57 
58 // Adjusting the color picker
59  QGridLayout* layout = new QGridLayout(m_ui->m_contourColorWidget);
60  layout->setContentsMargins(0, 0, 0, 0);
61 
62 //Color Picker
63  m_colorPicker = new te::qt::widgets::ColorPickerToolButton(m_ui->m_contourColorWidget);
64  m_colorPicker->setFixedSize(107, 24);
65  layout->addWidget(m_colorPicker);
66 
67  //connects
68  connect(m_ui->m_addToolButton, SIGNAL(clicked()), this, SLOT(onAddToolButtonClicked()));
69  connect(m_ui->m_removeToolButton, SIGNAL(clicked()), this, SLOT(onRemoveToolButtonClicked()));
70  connect(m_ui->m_contourWidthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateUi()));
71  connect(m_ui->m_tableWidget, SIGNAL(cellClicked(int, int)), this, SLOT(onItemClicked(int, int)));
72  connect(m_colorPicker, SIGNAL(colorChanged(const QColor&)), this, SLOT(updateUi()));
73 
74  initialize();
75 }
76 
78 {
79  m_chartVec.clear();
80 }
81 
83 {
84  m_layer = layer;
85 
86  listAttributes();
87 
88  m_ui->m_summaryComboBox->clear();
89  if(te::da::HasLinkedTable(layer->getSchema().get()))
90  {
91 
92  m_ui->m_summaryComboBox->addItem("MIN");
93  m_ui->m_summaryComboBox->addItem("MAX");
94  m_ui->m_summaryComboBox->addItem("SUM");
95  m_ui->m_summaryComboBox->addItem("AVERAGE");
96  m_ui->m_summaryComboBox->addItem("MEDIAN");
97  m_ui->m_summaryComboBox->addItem("STDDEV");
98  m_ui->m_summaryComboBox->addItem("VARIANCE");
99 
100  if(m_layer->getChart())
101  {
102  int index = m_ui->m_summaryComboBox->findText(QString::fromStdString(m_layer->getChart()->getSummary()));
103  m_ui->m_summaryComboBox->setCurrentIndex(index);
104  }
105 
106  m_ui->m_summaryComboBox->setEnabled(true);
107  m_ui->m_summaryComboBox->show();
108  m_ui->m_summaryLabel->show();
109  }
110  else
111  {
112  m_ui->m_summaryComboBox->addItem("NONE");
113  m_ui->m_summaryComboBox->setEnabled(false);
114  m_ui->m_summaryComboBox->hide();
115  m_ui->m_summaryLabel->hide();
116  }
117 }
118 
120 {
121  if(m_chartVec.empty())
122  {
123  QMessageBox::warning(this, tr("Warning"), tr("No attribute selected."));
124  return false;
125  }
126 
127  //chart type
128  int index = m_ui->m_typeComboBox->currentIndex();
129  int chartType = m_ui->m_typeComboBox->itemData(index).toInt();
130 
131  //get attributes
132  std::vector<std::string> attrs;
133  std::vector<te::color::RGBAColor> colors;
134 
135  for(std::size_t t = 0; t < m_chartVec.size(); ++t)
136  {
137  attrs.push_back(m_chartVec[t].first);
139  colors.push_back(c);
140  }
141 
142  te::map::Chart* chart = new te::map::Chart((te::map::ChartType)chartType, attrs, colors);
143  chart->setHeight((std::size_t)m_ui->m_sizeSpinBox->value());
144  chart->setContourWidth((std::size_t)m_ui->m_contourWidthSpinBox->value());
145  chart->setContourColor(te::qt::widgets::Convert2TerraLib(m_colorPicker->getColor()));
146  chart->setAvoidConflicts(m_ui->m_avoidConflictsCheckBox->isChecked());
147  chart->setSummary(m_ui->m_summaryComboBox->currentText().toStdString());
148 
149  // Is necessary compute the max value?
150  if(chart->getType() == te::map::Bar)
151  {
152  double maxValue = getMaxValue(chart);
153  chart->setMaxValue(maxValue);
154  }
155 
156  m_layer->setChart(chart);
157 
158  return true;
159 }
160 
162 {
163  m_chartVec.clear();
164 
165  int type = (int)chart->getType();
166 
167  for(int i = 0; i < m_ui->m_typeComboBox->count(); ++i)
168  {
169  int t = m_ui->m_typeComboBox->itemData(i).toInt();
170 
171  if(t == type)
172  {
173  m_ui->m_typeComboBox->setCurrentIndex(i);
174  break;
175  }
176  }
177 
178  m_ui->m_sizeSpinBox->setValue((int)chart->getHeight());
179  m_ui->m_contourWidthSpinBox->setValue((int)chart->getContourWidth());
180  m_colorPicker->setColor(te::qt::widgets::Convert2Qt(chart->getContourColor()));
181  m_ui->m_avoidConflictsCheckBox->setChecked(chart->getAvoidConflicts());
182 
183  for(std::size_t t = 0; t < chart->getProperties().size(); ++t)
184  {
185  std::string value = chart->getProperties()[t];
186  QColor c = te::qt::widgets::Convert2Qt(chart->getColor(t));
187  std::pair<std::string, QColor> pair(value, c);
188  m_chartVec.push_back(pair);
189  }
190 
191  updateUi();
192 }
193 
195 {
196  //add chart types
197  m_ui->m_typeComboBox->clear();
198  m_ui->m_typeComboBox->addItem(tr("Pie Chart"), QVariant(te::map::Pie));
199  m_ui->m_typeComboBox->addItem(tr("Bar Chart"), QVariant(te::map::Bar));
200 
201 
202  //set icons
203  m_ui->m_addToolButton->setIcon(QIcon::fromTheme("list-add"));
204  m_ui->m_removeToolButton->setIcon(QIcon::fromTheme("list-remove"));
205 }
206 
208 {
209  m_ui->m_tableWidget->setRowCount(0);
210 
211  for(std::size_t t = 0; t < m_chartVec.size(); ++t)
212  {
213  int newrow = m_ui->m_tableWidget->rowCount();
214  m_ui->m_tableWidget->insertRow(newrow);
215 
216  QIcon icon(te::qt::widgets::CreatePixmapIcon(28, m_colorPicker->getColor(), m_chartVec[t].second, m_ui->m_contourWidthSpinBox->value()));
217 
218  QTableWidgetItem* item = new QTableWidgetItem(icon, "");
219  item->setFlags(Qt::ItemIsEnabled);
220  m_ui->m_tableWidget->setItem(newrow, 0, item);
221 
222  //attr name
223  QTableWidgetItem* itemAttr = new QTableWidgetItem(m_chartVec[t].first.c_str());
224  itemAttr->setFlags(Qt::ItemIsEnabled);
225  m_ui->m_tableWidget->setItem(newrow, 1, itemAttr);
226  }
227 }
228 
230 {
231  std::string value = m_ui->m_attrComboBox->currentText().toStdString();
232 
233  bool found = false;
234 
235  for(std::size_t t = 0; t < m_chartVec.size(); ++t)
236  {
237  if(m_chartVec[t].first == value)
238  {
239  found = true;
240  break;
241  }
242  }
243 
244  if(found)
245  {
246  QMessageBox::warning(this, tr("Warning"), tr("Attribute already selected."));
247  return;
248  }
249 
250  QColor c(rand() % 255,rand() % 255,rand() % 255);
251 
252  std::pair<std::string, QColor> pair(value, c);
253 
254  m_chartVec.push_back(pair);
255 
256  updateUi();
257 }
258 
260 {
261  if(m_ui->m_tableWidget->currentRow() == -1)
262  return;
263 
264  m_chartVec.erase(m_chartVec.begin() + m_ui->m_tableWidget->currentRow());
265 
266  updateUi();
267 }
268 
270 {
271  if(column != 0)
272  return;
273 
274  QColor curColor = m_chartVec[row].second;
275 
276  QColor c = QColorDialog::getColor(curColor, this);
277 
278  if(c.isValid())
279  {
280  curColor = c;
281  }
282 
283  m_chartVec[row].second = curColor;
284 
285  updateUi();
286 }
287 
289 {
290  m_ui->m_attrComboBox->clear();
291 
292  std::auto_ptr<te::map::LayerSchema> dsType(m_layer->getSchema());
293 
294  for(size_t t = 0; t < dsType->getProperties().size(); ++t)
295  {
296  te::dt::Property* p = dsType->getProperty(t);
297 
298  int dataType = p->getType();
299 
300  switch(dataType)
301  {
302  case te::dt::INT16_TYPE:
303  case te::dt::INT32_TYPE:
304  case te::dt::INT64_TYPE:
305  case te::dt::FLOAT_TYPE:
306  case te::dt::DOUBLE_TYPE:
308  m_ui->m_attrComboBox->addItem(p->getName().c_str(), p->getType());
309 
310  default:
311  continue;
312  }
313  }
314 }
315 
317 {
318  double maxValue = std::numeric_limits<double>::min();
319 
320  // Gets the chart properties
321  const std::vector<std::string>& properties = chart->getProperties();
322  bool hasChartNullValue = false;
323 
324  std::auto_ptr<te::da::DataSetType> schema = m_layer->getSchema();
325  if(te::da::HasLinkedTable(schema.get()) == false)
326  {
327  // Gets the dataset
328  std::auto_ptr<te::da::DataSet> dataset(m_layer->getData());
329  std::vector<size_t> chartPropPos;
330  size_t csize = properties.size();
331  for(std::size_t i = 0; i < csize; ++i)
332  chartPropPos.push_back(te::da::GetPropertyPos(dataset.get(), properties[i]));
333  chart->setPropertiesPos(chartPropPos);
334 
335  while(dataset->moveNext())
336  {
337  for(std::size_t i = 0; i < csize; ++i)
338  {
339  if(dataset->isNull(chart->getPropertiesPos()[i]))
340  {
341  hasChartNullValue = true;
342  break;
343  }
344  }
345 
346  if(hasChartNullValue == false)
347  {
348  for(std::size_t i = 0; i < csize; ++i)
349  {
350  double value = te::da::GetValueAsDouble(dataset.get(), chart->getPropertiesPos()[i]);
351  maxValue = std::max(maxValue, value);
352  }
353  }
354  }
355  return maxValue;
356  }
357 
358  te::da::PrimaryKey* pk = schema->getPrimaryKey();
359  std::vector<te::dt::Property*> props = pk->getProperties();
360  std::vector<std::string> boid;
361  size_t pksize = 0;
362  while(++pksize < props.size())
363  {
364  boid.push_back(props[pksize-1]->getName());
365  if(props[pksize-1]->getDatasetName() != props[pksize]->getDatasetName())
366  break;
367  }
368 
369  // make sorting by object id
370  te::map::QueryLayer* qlayer = dynamic_cast<te::map::QueryLayer*>(m_layer.get());
371  te::da::Select* select = dynamic_cast<te::da::Select*>(qlayer->getQuery()->clone());
372  te::da::Select* selectaux = dynamic_cast<te::da::Select*>(select->clone());
373  te::da::OrderBy* orderBy = new te::da::OrderBy;
374 
375  for(size_t i = 0; i < pksize; ++i)
376  orderBy->push_back(new te::da::OrderByItem(boid[i]));
377 
378  selectaux->setOrderBy(orderBy);
379  qlayer->setQuery(selectaux);
380  std::auto_ptr<te::da::DataSet> dataset(qlayer->getData());
381  qlayer->setQuery(select);
382 
383  std::vector<std::string> pkdata(pksize), pkdataaux(pksize);
384  std::string cfunction = chart->getSummary();
385  std::map<std::string, std::vector<double> > chartValues;
386  std::map<std::string, double> chartValue;
387  std::vector<size_t> chartPropPos;
388  bool hasChartNullValueAux = false;
389  size_t csize = properties.size();
390  for(std::size_t i = 0; i < csize; ++i)
391  {
392  std::vector<double> v;
393  chartValues[properties[i]] = v;
394  chartPropPos.push_back(te::da::GetPropertyPos(dataset.get(), properties[i]));
395  }
396  chart->setPropertiesPos(chartPropPos);
397 
398  dataset->moveFirst();
399  do
400  {
401  // calculate summarized value
402  size_t i;
403  for(i = 0; i < pksize; ++i)
404  pkdata[i] = dataset->getAsString(boid[i]);
405 
406  for(i = 0; i < pksize; ++i)
407  {
408  if(dataset->isAtBegin())
409  pkdataaux[i] = dataset->getAsString(boid[i]);
410  else
411  {
412  if(pkdata[i] != pkdataaux[i])
413  {
414  pkdataaux = pkdata;
415  break;
416  }
417  }
418  }
419  if(i == pksize) // it is the same object
420  {
421  if(hasChartNullValue == false)
422  {
423  // read value chart value
424  for(std::size_t i = 0; i < csize; ++i)
425  {
426  if(dataset->isNull(chart->getProperties()[i]) == false)
427  chartValues[properties[i]].push_back(te::da::GetValueAsDouble(dataset.get(), chart->getPropertiesPos()[i]));
428  //chartValues[properties[i]].push_back(boost::lexical_cast<double>(dataset->getAsString(properties[i])));
429  else
430  {
431  hasChartNullValue = true;
432  break;
433  }
434  }
435  }
436  // read other values
437  continue;
438  }
439  else // it is other object
440  {
441  // sumarize chart value according to the required summarization
442  if(hasChartNullValue == false)
443  {
444  for(std::size_t i = 0; i < csize; ++i)
445  chartValue[properties[i]] = te::da::GetSummarizedValue(chartValues[properties[i]], cfunction);
446  }
447 
448  // prepare the next loop
449  for(std::size_t i = 0; i < csize; ++i)
450  chartValues[properties[i]].clear();
451 
452  hasChartNullValueAux = false;
453  for(std::size_t i = 0; i < csize; ++i)
454  {
455  if(dataset->isNull(properties[i]))
456  {
457  hasChartNullValueAux = true;
458  break;
459  }
460  }
461  if(hasChartNullValueAux == false)
462  {
463  for(std::size_t i = 0; i < csize; ++i)
464  chartValues[properties[i]].push_back(boost::lexical_cast<double>(dataset->getAsString(properties[i])));
465  }
466  }
467 
468  if(hasChartNullValue == false)
469  {
470  // get max value
471  std::map<std::string, double>::iterator it = chartValue.begin();
472  while(it != chartValue.end())
473  {
474  maxValue = std::max(maxValue, it->second);
475  ++it;
476  }
477  }
478 
479  hasChartNullValue = hasChartNullValueAux;
480  hasChartNullValueAux = false;
481  } while(dataset->moveNext());
482 
483  if(hasChartNullValue == false)
484  {
485  for(std::size_t i = 0; i < csize; ++i)
486  chartValue[properties[i]] = te::da::GetSummarizedValue(chartValues[properties[i]], cfunction);
487 
488  // get max value
489  std::map<std::string, double>::iterator it = chartValue.begin();
490  while(it != chartValue.end())
491  {
492  maxValue = std::max(maxValue, it->second);
493  ++it;
494  }
495  }
496  return maxValue;
497 }
void setLayer(te::map::AbstractLayerPtr layer)
Set a layer.
void setChart(te::map::Chart *chart)
Update the interface with the chart properties.
ChartType
The chart types.
Definition: Enums.h:163
ChartType getType() const
Definition: Chart.cpp:78
TEQTWIDGETSEXPORT te::color::RGBAColor Convert2TerraLib(const QColor &color)
It converts a Qt Color to TerraLib Color.
Definition: Utils.cpp:227
const std::vector< std::string > & getProperties() const
Definition: Chart.cpp:83
void setContourColor(const te::color::RGBAColor &color)
Definition: Chart.cpp:117
std::string getSummary() const
It gets the grouping summary. It is used only in case 1 to n.
Definition: Chart.cpp:197
TEDATAACCESSEXPORT bool HasLinkedTable(te::da::DataSetType *type)
It checks if the datasettype has a linked table.
Definition: Utils.cpp:1175
double getMaxValue(te::map::Chart *chart)
void updateUi()
Updates the widget form based on internal fill element.
A widget used to build a chart.
TEDATAACCESSEXPORT std::size_t GetPropertyPos(const DataSet *dataset, const std::string &name)
Definition: Utils.cpp:500
boost::ptr_vector< OrderByItem > OrderBy
A class that can be used to model an ORDER BY clause.
Definition: OrderBy.h:37
void onAddToolButtonClicked()
Function used when the user clicked over the add tool button.
A layer resulting from a query.
Definition: QueryLayer.h:50
void setHeight(std::size_t height)
Definition: Chart.cpp:137
TEDATAACCESSEXPORT double GetValueAsDouble(const te::da::DataSet *ds, const size_t pos)
It gets the value as double.
Definition: Utils.cpp:1337
ChartLayerWidget(QWidget *parent=0, Qt::WindowFlags f=0)
Constructs a basic fill widget which is a child of parent, with widget flags set to f...
It models a property definition.
Definition: Property.h:59
ColorPickerToolButton * m_colorPicker
The color picker used to customise the color of several chart parameters.
const std::vector< te::dt::Property * > & getProperties() const
It returns the properties that take part of the primary key.
Definition: PrimaryKey.h:109
void onRemoveToolButtonClicked()
Function used when the user clicked over the remove tool button.
void initialize()
Internal method to initialize the widget (e.g.: color, combos, icons, etc.)
void setSummary(const std::string &summary)
It gets the grouping summary. It is used only in case 1 to n.
Definition: Chart.cpp:202
void setAvoidConflicts(bool on)
Definition: Chart.cpp:187
const te::color::RGBAColor & getColor(std::size_t i) const
Definition: Chart.cpp:98
Custom tool button used to pick a color.
void onItemClicked(int row, int column)
Function used when the user clicked over the table (color column).
This class represents the informations needed to build map charts.
Definition: Chart.h:51
void listAttributes()
List the layer attributes (from layer schema)
std::size_t getHeight() const
Definition: Chart.cpp:132
TEDATAACCESSEXPORT double GetSummarizedValue(std::vector< double > &values, const std::string &summary)
It gets the summarized value.
Definition: Utils.cpp:1196
te::da::Select * getQuery() const
Definition: QueryLayer.cpp:340
Query * clone() const
It creates a new copy of this query.
Definition: Select.cpp:424
void setOrderBy(OrderBy *o)
It sets the list of expressions used to sort the output result.
Definition: Select.cpp:977
A Select models a query to be used when retrieving data from a DataSource.
Definition: Select.h:65
void setPropertiesPos(const std::vector< size_t > &propPos)
Definition: Chart.cpp:93
int getType() const
It returns the property data type.
Definition: Property.h:161
bool buildChart()
Creates the te::map::Chart object using the interface parameters.
std::size_t getContourWidth() const
Definition: Chart.cpp:122
const te::color::RGBAColor & getContourColor() const
Definition: Chart.cpp:112
const std::vector< size_t > & getPropertiesPos() const
Definition: Chart.cpp:88
void setQuery(te::da::Select *s)
Definition: QueryLayer.cpp:345
It describes a primary key (pk) constraint.
Definition: PrimaryKey.h:52
std::auto_ptr< Ui::ChartLayerWidgetForm > m_ui
Widget form.
A helper class for 32-bit RGBA (Red-Green-Blue-Alpha channel) color.
Definition: RGBAColor.h:57
bool getAvoidConflicts() const
Definition: Chart.cpp:192
TEQTWIDGETSEXPORT QColor Convert2Qt(const te::color::RGBAColor &color)
It converts a TerraLib Color to Qt Color.
Definition: Utils.cpp:232
std::auto_ptr< te::da::DataSet > getData(te::common::TraverseType travType=te::common::FORWARDONLY, const te::common::AccessPolicy accessPolicy=te::common::RAccess) const
It gets the dataset identified by the layer name.
Definition: QueryLayer.cpp:159
void setMaxValue(double value)
Definition: Chart.cpp:167
A class that can be used in an ORDER BY clause to sort the items of a resulting query.
Definition: OrderByItem.h:53
TEQTWIDGETSEXPORT QPixmap CreatePixmapIcon(const int &size, const QColor &penColor, const QColor &brushColor, const int &contourSize)
It creates a pixmap to use as icon (to be used as legend icon).
Definition: Utils.cpp:340
boost::intrusive_ptr< AbstractLayer > AbstractLayerPtr
void setContourWidth(std::size_t width)
Definition: Chart.cpp:127
const std::string & getName() const
It returns the property name.
Definition: Property.h:127