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 
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 
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::fromUtf8(m_layer->getChart()->getSummary().c_str()));
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(static_cast<te::map::ChartType>(chartType), attrs, colors);
143  chart->setHeight(static_cast<std::size_t>(m_ui->m_sizeSpinBox->value()));
144  chart->setContourWidth(static_cast<std::size_t>(m_ui->m_contourWidthSpinBox->value()));
146  chart->setAvoidConflicts(m_ui->m_avoidConflictsCheckBox->isChecked());
147  chart->setSummary(m_ui->m_summaryComboBox->currentText().toUtf8().data());
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 = static_cast<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(static_cast<int>(chart->getHeight()));
179  m_ui->m_contourWidthSpinBox->setValue(static_cast<int>(chart->getContourWidth()));
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().toUtf8().data();
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[static_cast<size_t>(row)].second;
275 
276  QColor c = QColorDialog::getColor(curColor, this);
277 
278  if(c.isValid())
279  {
280  curColor = c;
281  }
282 
283  m_chartVec[static_cast<size_t>(row)].second = curColor;
284 
285  updateUi();
286 }
287 
289 {
290  m_ui->m_attrComboBox->clear();
291 
292  std::unique_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  break;
310 
311  default:
312  continue;
313  }
314  }
315 }
316 
318 {
319  double maxValue = std::numeric_limits<double>::min();
320 
321  // Gets the chart properties
322  const std::vector<std::string>& properties = chart->getProperties();
323 
324  std::unique_ptr<te::da::DataSetType> schema = m_layer->getSchema();
325  if(te::da::HasLinkedTable(schema.get()) == false)
326  {
327  // Gets the dataset
328  std::unique_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  double value = te::da::GetValueAsDouble(dataset.get(), chart->getPropertiesPos()[i]);
340  maxValue = std::max(maxValue, value);
341  }
342  }
343  return maxValue;
344  }
345 
346  te::da::PrimaryKey* pk = schema->getPrimaryKey();
347  std::vector<te::dt::Property*> props = pk->getProperties();
348  std::vector<std::string> boid;
349  size_t pksize = 0;
350  while(++pksize < props.size())
351  {
352  boid.push_back(props[pksize-1]->getName());
353  if(props[pksize-1]->getDatasetName() != props[pksize]->getDatasetName())
354  break;
355  }
356 
357  // make sorting by object id
358  te::map::QueryLayer* qlayer = dynamic_cast<te::map::QueryLayer*>(m_layer.get());
359  te::da::Select* select = dynamic_cast<te::da::Select*>(qlayer->getQuery()->clone());
360  te::da::Select* selectaux = dynamic_cast<te::da::Select*>(select->clone());
361  te::da::OrderBy* orderBy = new te::da::OrderBy;
362 
363  for(size_t i = 0; i < pksize; ++i)
364  orderBy->push_back(new te::da::OrderByItem(boid[i]));
365 
366  selectaux->setOrderBy(orderBy);
367  qlayer->setQuery(selectaux);
368  std::unique_ptr<te::da::DataSet> dataset(qlayer->getData());
369  qlayer->setQuery(select);
370 
371  std::vector<std::string> pkdata(pksize), pkdataaux(pksize);
372  std::string cfunction = chart->getSummary();
373  std::map<std::string, std::vector<double> > chartValues;
374  std::map<std::string, double> chartValue;
375  std::vector<size_t> chartPropPos;
376  size_t csize = properties.size();
377  for(std::size_t i = 0; i < csize; ++i)
378  {
379  std::vector<double> v;
380  chartValues[properties[i]] = v;
381  chartPropPos.push_back(te::da::GetPropertyPos(dataset.get(), properties[i]));
382  }
383  chart->setPropertiesPos(chartPropPos);
384 
385  dataset->moveFirst();
386  do
387  {
388  // calculate summarized value
389  size_t i;
390  for(i = 0; i < pksize; ++i)
391  pkdata[i] = dataset->getAsString(boid[i]);
392 
393  for(i = 0; i < pksize; ++i)
394  {
395  if(dataset->isAtBegin())
396  pkdataaux[i] = dataset->getAsString(boid[i]);
397  else
398  {
399  if(pkdata[i] != pkdataaux[i])
400  {
401  pkdataaux = pkdata;
402  break;
403  }
404  }
405  }
406  if(i == pksize) // it is the same object
407  {
408  // read value chart value
409  for(std::size_t i = 0; i < csize; ++i)
410  {
411  if(dataset->isNull(chart->getProperties()[i]) == false)
412  chartValues[properties[i]].push_back(te::da::GetValueAsDouble(dataset.get(), chart->getPropertiesPos()[i]));
413  }
414  // read other values
415  continue;
416  }
417  else // it is other object
418  {
419  // sumarize chart value according to the required summarization
420  for(std::size_t i = 0; i < csize; ++i)
421  chartValue[properties[i]] = te::da::GetSummarizedValue(chartValues[properties[i]], cfunction);
422 
423  // prepare the next loop
424  for(std::size_t i = 0; i < csize; ++i)
425  chartValues[properties[i]].clear();
426 
427  for(std::size_t i = 0; i < csize; ++i)
428  chartValues[properties[i]].push_back(boost::lexical_cast<double>(dataset->getAsString(properties[i])));
429  }
430 
431  // get max value
432  std::map<std::string, double>::iterator it = chartValue.begin();
433  while(it != chartValue.end())
434  {
435  maxValue = std::max(maxValue, it->second);
436  ++it;
437  }
438 
439  } while(dataset->moveNext());
440 
441  for(std::size_t i = 0; i < csize; ++i)
442  chartValue[properties[i]] = te::da::GetSummarizedValue(chartValues[properties[i]], cfunction);
443 
444  // get max value
445  std::map<std::string, double>::iterator it = chartValue.begin();
446  while(it != chartValue.end())
447  {
448  maxValue = std::max(maxValue, it->second);
449  ++it;
450  }
451 
452  return maxValue;
453 }
void setLayer(te::map::AbstractLayerPtr layer)
Set a layer.
void setChart(te::map::Chart *chart)
Update the interface with the chart properties.
ChartType getType() const
Definition: Chart.cpp:92
TEQTWIDGETSEXPORT te::color::RGBAColor Convert2TerraLib(const QColor &color)
It converts a Qt Color to TerraLib Color.
const std::vector< std::string > & getProperties() const
Definition: Chart.cpp:97
void setContourColor(const te::color::RGBAColor &color)
Definition: Chart.cpp:131
std::string getSummary() const
It gets the grouping summary. It is used only in case 1 to n.
Definition: Chart.cpp:211
TEDATAACCESSEXPORT bool HasLinkedTable(te::da::DataSetType *type)
It checks if the datasettype has a linked table.
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)
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:151
TEDATAACCESSEXPORT double GetValueAsDouble(const te::da::DataSet *ds, const size_t pos)
It gets the value as double.
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...
std::unique_ptr< Ui::ChartLayerWidgetForm > m_ui
Widget form.
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:216
std::vector< std::pair< std::string, QColor > > m_chartVec
Chart Vec.
void setAvoidConflicts(bool on)
Definition: Chart.cpp:201
const te::color::RGBAColor & getColor(std::size_t i) const
Definition: Chart.cpp:112
Custom tool button used to pick a color.
te::map::AbstractLayerPtr m_layer
TerraLib layer auto ptr.
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
std::unique_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:184
void listAttributes()
List the layer attributes (from layer schema)
std::size_t getHeight() const
Definition: Chart.cpp:146
TEDATAACCESSEXPORT double GetSummarizedValue(std::vector< double > &values, const std::string &summary)
It gets the summarized value.
te::gm::Polygon * p
te::da::Select * getQuery() const
Definition: QueryLayer.cpp:363
Query * clone() const
It creates a new copy of this query.
Definition: Select.cpp:276
void setOrderBy(OrderBy *o)
It sets the list of expressions used to sort the output result.
Definition: Select.cpp:829
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:107
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:136
const te::color::RGBAColor & getContourColor() const
Definition: Chart.cpp:126
const std::vector< size_t > & getPropertiesPos() const
Definition: Chart.cpp:102
void setQuery(te::da::Select *s)
Definition: QueryLayer.cpp:390
It describes a primary key (pk) constraint.
Definition: PrimaryKey.h:52
A helper class for 32-bit RGBA (Red-Green-Blue-Alpha channel) color.
Definition: RGBAColor.h:57
bool getAvoidConflicts() const
Definition: Chart.cpp:206
TEQTWIDGETSEXPORT QColor Convert2Qt(const te::color::RGBAColor &color)
It converts a TerraLib Color to Qt Color.
void setMaxValue(double value)
Definition: Chart.cpp:181
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).
boost::intrusive_ptr< AbstractLayer > AbstractLayerPtr
void setContourWidth(std::size_t width)
Definition: Chart.cpp:141
const std::string & getName() const
It returns the property name.
Definition: Property.h:127