TimeViewerEditLegendDialog.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
4  applications.
5 
6  TerraLib is free software: you can redistribute it and/or modify
7  it under the terms of the GNU Lesser General Public License as published by
8  the Free Software Foundation, either version 3 of the License,
9  or (at your option) any later version.
10 
11  TerraLib is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public License
17  along with TerraLib. See COPYING. If not, write to
18  TerraLib Team at <terralib-team@terralib.org>.
19  */
20 
21 /*!
22  \file terralib/timeviewer/TimeViewEditLegendDialog.cpp
23 
24  \brief A dialog used to edit legend.
25 */
26 
27 // TerraLib
29 #include "../../../color/ColorBar.h"
30 #include "../../../common/Globals.h"
31 #include "../../../common/STLUtils.h"
32 #include "../../../core/translator/Translator.h"
33 #include "../../../dataaccess/dataset/DataSet.h"
34 #include "../../../dataaccess/datasource/DataSourceManager.h"
35 #include "../../../dataaccess/query_h.h"
36 #include "../../../dataaccess/utils/Utils.h"
37 #include "../../../maptools/GroupingAlgorithms.h"
38 #include "../../../maptools/Utils.h"
39 #include "../../../se.h"
40 #include "../../../se/SymbolizerColorFinder.h"
41 #include "../../../se/Utils.h"
42 #include "../../widgets/colorbar/ColorBar.h"
43 #include "../../widgets/colorbar/ColorCatalogWidget.h"
44 #include "../../widgets/se/LineSymbolizerWidget.h"
45 #include "../../widgets/se/PointSymbolizerWidget.h"
46 #include "../../widgets/se/PolygonSymbolizerWidget.h"
47 #include "../../widgets/se/SymbologyPreview.h"
48 #include "ui_TimeViewerEditLegendDialog.h"
49 
50 // Qt
51 #include <QDialogButtonBox>
52 #include <QFileDialog>
53 #include <QMessageBox>
54 #include <QPainter>
55 
56 // Boost
57 #include <boost/algorithm/string.hpp>
58 #include <boost/filesystem.hpp>
59 #include <boost/lexical_cast.hpp>
60 #include <boost/property_tree/json_parser.hpp>
61 
62 #define NO_TITLE "No Value"
63 #define PRECISION 15
64 
66  : QDialog(parent, f),
67  m_ui(new Ui::TimeViewerEditLegendDialog),
68  m_cb(0),
69  m_colorBar(0)
70 {
71  m_ui->setupUi(this);
72 
73  m_ui->m_okPushButton->setEnabled(false);
74 
75  m_ui->m_tableWidget->resizeColumnsToContents();
76 
77  QGridLayout* layout = new QGridLayout(m_ui->m_colorBarWidget);
78  layout->setContentsMargins(0, 0, 0, 0);
79  m_colorBar = new te::qt::widgets::ColorCatalogWidget(m_ui->m_colorBarWidget);
80  layout->addWidget(m_colorBar);
81 
82  // connects
83  connect(m_colorBar, SIGNAL(colorBarChanged()), this, SLOT(onColorBarChanged()));
84  connect(m_ui->m_applyPushButton, SIGNAL(clicked()), this, SLOT(onApplyPushButtonClicked()));
85  connect(m_ui->m_okPushButton, SIGNAL(clicked()), this, SLOT(onOkPushButtonClicked()));
86  connect(m_ui->m_cancelPushButton, SIGNAL(clicked()), this, SLOT(onCancelPushButtonClicked()));
87 
88  connect(m_ui->m_loadPushButton, SIGNAL(clicked()), this, SLOT(onLoadPushButtonClicked()));
89  connect(m_ui->m_savePushButton, SIGNAL(clicked()), this, SLOT(onSavePushButtonClicked()));
90  connect(m_ui->m_selectAllPushButton, SIGNAL(clicked()), this, SLOT(onSelectAllPushButtonClicked()));
91  connect(m_ui->m_unselectAllPushButton, SIGNAL(clicked()), this, SLOT(onUnselectAllPushButtonClicked()));
92 
93  initialize();
94 
95  // m_ui->m_helpPushButton->setPageReference(".html");
96 }
97 
99 
101 {
102  m_layer = selectedLayer;
103 
104  m_ui->m_layerNameLineEdit->setText(m_layer->getTitle().c_str());
105 
106  listAtrributes();
107 }
108 
110 {
111  std::unique_ptr<te::map::LayerSchema> dsType(m_layer->getSchema());
112 
113  m_ui->m_attributeComboBox->clear();
114 
115  for(size_t t = 0; t < dsType->getProperties().size(); ++t)
116  {
117  te::dt::Property* p = dsType->getProperty(t);
118 
119  int dataType = p->getType();
120 
121  switch(dataType)
122  {
123  case te::dt::INT16_TYPE:
124  case te::dt::INT32_TYPE:
125  case te::dt::INT64_TYPE:
126  case te::dt::FLOAT_TYPE:
127  case te::dt::DOUBLE_TYPE:
129  case te::dt::STRING_TYPE:
130  m_ui->m_attributeComboBox->addItem(p->getName().c_str(), p->getType());
131  break;
132 
133  default:
134  continue;
135  }
136  }
137 }
138 
139 void te::qt::plugins::tv::TimeViewerEditLegendDialog::getDataAsString(std::vector<std::string>& vec, const std::string& attrName, int& nullValues)
140 {
141  assert(m_layer.get());
142 
143  std::unique_ptr<te::map::LayerSchema> dsType(m_layer->getSchema());
144 
145  std::size_t idx;
146 
147  for(std::size_t t = 0; t < dsType->getProperties().size(); ++t)
148  {
149  if(dsType->getProperty(t)->getName() == attrName)
150  {
151  idx = t;
152  break;
153  }
154  }
155 
156  std::unique_ptr<te::da::DataSet> ds(m_layer->getData());
157 
158  ds->moveBeforeFirst();
159 
160  while(ds->moveNext())
161  {
162  if(!ds->isNull(idx))
163  vec.push_back(ds->getAsString(idx));
164  else
165  ++nullValues;
166  }
167 }
168 
170 {
171  int prec = m_ui->m_precisionSpinBox->value();
172 
173  std::string attr = m_ui->m_attributeComboBox->currentText().toUtf8().data();
174  int attrIdx = m_ui->m_attributeComboBox->currentIndex();
175  int attrType = m_ui->m_attributeComboBox->itemData(attrIdx).toInt();
176 
178  m_legend.clear();
179 
180  std::string mean;
181 
182  int nullValues = 0;
183 
184  bool update = false;
185 
186  std::vector<std::string> vec;
187 
188  getDataAsString(vec, attr, nullValues);
189 
190  if(!vec.empty())
191  {
192  te::map::GroupingByUniqueValues(attr, vec, attrType, m_legend, prec);
193 
194  buildSymbolizer(mean);
195  }
196 
197  updateUi(update);
198 
199  m_ui->m_okPushButton->setEnabled(true);
200 
201  m_manual = false;
202 }
203 
205 {
206  // create color bar
209 
210  // set number of precision
211  m_ui->m_precisionSpinBox->setMinimum(1);
212  m_ui->m_precisionSpinBox->setMaximum(PRECISION);
213  m_ui->m_precisionSpinBox->setValue(6);
214  m_ui->m_precisionSpinBox->setSingleStep(1);
215 
216 // adjust table
217 #if(QT_VERSION >= 0x050000)
218  m_ui->m_tableWidget->horizontalHeader()->setSectionResizeMode(
219  QHeaderView::Stretch);
220 #else
221  m_ui->m_tableWidget->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
222 #endif
223 
224  m_manual = false;
225 }
226 
228 {
229  delete m_cb;
230 
232 
233  int legendSize = m_legend.size();
234 
235  std::vector<te::color::RGBAColor> colorVec;
236 
237  if(meanTitle.empty())
238  {
239  colorVec = m_cb->getSlices(legendSize);
240  }
241  else
242  {
243  int beforeMean = 0;
244  int afterMean = 0;
245 
246  for(size_t t = 0; t < m_legend.size(); ++t)
247  {
248  std::string ruleName = *m_legend[t]->getName();
249 
250  if(ruleName != meanTitle)
251  {
252  beforeMean++;
253  }
254  else
255  {
256  afterMean = (int)(m_legend.size() - t - 1);
257  break;
258  }
259  }
260 
261  std::vector<te::color::RGBAColor> lowerColorVec = m_cb->getLowerMeanSlices(beforeMean);
262  te::color::RGBAColor meanColor = m_cb->getMeanSlice();
263  std::vector<te::color::RGBAColor> upperColorVec = m_cb->getUpperMeanSlices(afterMean);
264 
265  for(size_t t = 0; t < lowerColorVec.size(); ++t)
266  colorVec.push_back(lowerColorVec[t]);
267 
268  colorVec.push_back(meanColor);
269 
270  for(size_t t = 0; t < upperColorVec.size(); ++t)
271  colorVec.push_back(upperColorVec[t]);
272  }
273 
274  if(colorVec.size() != m_legend.size())
275  return;
276 
277  int geomType = getGeometryType();
278 
279  for(size_t t = 0; t < colorVec.size(); ++t)
280  {
281  std::vector<te::se::Symbolizer*> symbVec;
282 
283  te::se::Symbolizer* s = te::se::CreateSymbolizer((te::gm::GeomType)geomType, colorVec[t].getColor());
284 
285  symbVec.push_back(s);
286 
287  m_legend[t]->setSymbolizers(symbVec);
288  }
289 }
290 
292 {
293  assert(m_layer.get());
294 
296 }
297 
299  bool loadColorBar)
300 {
301  disconnect(m_ui->m_tableWidget, SIGNAL(itemChanged(QTableWidgetItem*)), this, SLOT(onTableWidgetItemChanged(QTableWidgetItem*)));
302 
303  m_ui->m_tableWidget->setRowCount(0);
304 
305  QStringList list;
306  list.append(tr("Symbol"));
307  list.append(tr("Title"));
308  list.append(tr("Value"));
309 
310  m_ui->m_tableWidget->setColumnCount(3);
311  m_ui->m_tableWidget->setHorizontalHeaderLabels(list);
312 
313  te::color::ColorBar* cb = 0;
314 
315  if(loadColorBar)
316  {
317  if(!m_legend.empty() && !m_legend[0]->getSymbolizers().empty() && !m_legend[m_legend.size() - 1]->getSymbolizers().empty())
318  {
320 
321  scf.find(m_legend[0]->getSymbolizers()[0]);
322  te::color::RGBAColor initColor = scf.getColor();
323 
324  scf.find(m_legend[m_legend.size() - 1]->getSymbolizers()[0]);
325  te::color::RGBAColor endColor = scf.getColor();
326 
327  cb = new te::color::ColorBar(initColor, endColor, 256);
328  }
329  }
330 
331  std::size_t count = 0;
332 
333  for(std::size_t t = 0; t < m_legend.size(); ++t)
334  {
335  te::se::Rule* ruleItem = m_legend[t];
336 
337  const te::fe::Filter* ruleFilter = ruleItem->getFilter();
338 
339  if(!ruleFilter)
340  continue;
341 
342  int newrow = m_ui->m_tableWidget->rowCount();
343  m_ui->m_tableWidget->insertRow(newrow);
344 
345  // symbol
346  {
347  const std::vector<te::se::Symbolizer*>& ss = ruleItem->getSymbolizers();
348  QPixmap pix = te::qt::widgets::SymbologyPreview::build(ss, QSize(24, 24));
349  QIcon icon(pix);
350  QTableWidgetItem* item = new QTableWidgetItem(icon, "");
351  item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
352  m_ui->m_tableWidget->setItem(newrow, 0, item);
353  }
354 
355  // title
356  {
357  QTableWidgetItem* item = new QTableWidgetItem( QString::fromUtf8((*ruleItem->getName()).c_str()));
358  item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable);
359  m_ui->m_tableWidget->setItem(newrow, 1, item);
360  }
361 
362  if(loadColorBar)
363  {
364  if(count != 0 && count != m_legend.size() - 1)
365  {
366  double pos = (1. / (m_legend.size() - 1)) * count;
367 
368  if(!ruleItem->getSymbolizers().empty())
369  {
371 
372  scf.find(ruleItem->getSymbolizers()[0]);
373 
374  te::color::RGBAColor color = scf.getColor();
375 
376  if(cb)
377  cb->addColor(color, pos);
378  }
379  }
380  }
381 
382  ++count;
383 
384  std::string ruleName = *ruleItem->getName();
385 
386  if(ruleName != NO_TITLE)
387  {
388  // Value
389  std::string value;
390  te::fe::GetFilterUniqueValue(ruleFilter, value);
391 
392  QTableWidgetItem* item = new QTableWidgetItem(QString::fromUtf8(value.c_str()));
393  item->setFlags(Qt::ItemIsEnabled);
394  m_ui->m_tableWidget->setItem(newrow, 2, item);
395  }
396  }
397 
398  if(cb)
399  {
400  disconnect(m_colorBar, SIGNAL(colorBarChanged()), this, SLOT(onColorBarChanged()));
401 
403  cbW->setColorBar(cb);
404 
405  connect(m_colorBar, SIGNAL(colorBarChanged()), this, SLOT(onColorBarChanged()));
406  }
407 
408 #if(QT_VERSION >= 0x050000)
409  m_ui->m_tableWidget->horizontalHeader()->setSectionResizeMode(
410  QHeaderView::Stretch);
411 #else
412  m_ui->m_tableWidget->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
413 #endif
414 
415  connect(m_ui->m_tableWidget, SIGNAL(itemChanged(QTableWidgetItem*)), this, SLOT(onTableWidgetItemChanged(QTableWidgetItem*)));
416 }
417 
419 {
420  if(m_layer.get())
421  {
422  buildSymbolizer();
423 
424  updateUi();
425  }
426 }
427 
429 {
430  reject();
431 }
432 
434 {
435  accept();
436 
437  emit okPushButtonClicked();
438 }
439 
440 const std::vector<te::se::Rule*>&te::qt::plugins::tv::TimeViewerEditLegendDialog::getRules() const
441 {
442  return m_legend;
443 }
444 
446 {
447  QString fileName = QFileDialog::getSaveFileName(this, tr("Save as..."), QString(), tr("LEG (*.leg *.LEG);;"), 0,QFileDialog::DontConfirmOverwrite);
448 
449  saveLegend(fileName.toUtf8().data());
450 }
451 
453 {
454  int rowCount = m_ui->m_tableWidget->rowCount();
455 
456  if(rowCount < 1)
457  return;
458 
459  if(path.empty())
460  return;
461 
462  boost::property_tree::ptree pt;
463  boost::property_tree::ptree legend;
464 
465  std::string attrName = m_ui->m_attributeComboBox->currentText().toUtf8().data();
466  std::string precision = m_ui->m_precisionSpinBox->text().toUtf8().data();
467 
468  legend.add("Attribute", attrName);
469  legend.add("Precision", precision);
470 
471  boost::property_tree::ptree items;
472 
473  for(int i = 0; i < m_ui->m_tableWidget->rowCount(); ++i)
474  {
475  std::string className = m_ui->m_tableWidget->item(i, 0)->text().toUtf8().data();
476  std::string r = m_ui->m_tableWidget->item(i, 1)->text().toUtf8().data();
477  std::string g = m_ui->m_tableWidget->item(i, 2)->text().toUtf8().data();
478  std::string b = m_ui->m_tableWidget->item(i, 3)->text().toUtf8().data();
479 
480  boost::property_tree::ptree item;
481  item.add("ClassName", className);
482  item.add("Red", r);
483  item.add("Green", g);
484  item.add("Blue", b);
485 
486  items.add_child("Item", item);
487  }
488 
489  legend.add_child("Items", items);
490 
491  pt.add_child("Legend", legend);
492 
493  boost::property_tree::write_json(path, pt);
494 }
495 
497 {
498  int size = m_ui->m_tableWidget->rowCount();
499 
500  for(int i = 0; i < size; ++i)
501  {
502  QTableWidgetItem* item = m_ui->m_tableWidget->item(i, 5);
503  item->setCheckState(Qt::Checked);
504  }
505 }
506 
508 {
509  int size = m_ui->m_tableWidget->rowCount();
510 
511  for(int i = 0; i < size; ++i)
512  {
513  QTableWidgetItem* item = m_ui->m_tableWidget->item(i, 5);
514  item->setCheckState(Qt::Unchecked);
515  }
516 }
517 
519 {
520  QString fileName = QFileDialog::getOpenFileName( this, tr("Open..."), QString(), tr("LEG (*.leg *.LEG);;"), 0,
521  QFileDialog::DontConfirmOverwrite);
522 
523  if(fileName.isEmpty())
524  return;
525 
526  m_ui->m_tableWidget->setRowCount(0);
527 
528  boost::property_tree::ptree pt;
529  boost::property_tree::json_parser::read_json(fileName.toUtf8().data(), pt);
530 
531  boost::property_tree::ptree legend = pt.get_child("Legend");
532 
533  std::string attrName = legend.get<std::string>("Attribute");
534  std::string precision = legend.get<std::string>("Precision");
535 
536  m_ui->m_attributeComboBox->setCurrentIndex( m_ui->m_attributeComboBox->findText(attrName.c_str()));
537  m_ui->m_precisionSpinBox->setValue(boost::lexical_cast<double>(precision));
538 
539  std::vector<std::vector<std::string> > items;
540 
541  for(boost::property_tree::ptree::value_type& v : legend.get_child("Items"))
542  {
543  std::vector<std::string> item;
544  item.push_back(v.second.get<std::string>("ClassName"));
545  item.push_back(v.second.get<std::string>("Red"));
546  item.push_back(v.second.get<std::string>("Green"));
547  item.push_back(v.second.get<std::string>("Blue"));
548 
549  items.push_back(item);
550  }
551 
552  m_ui->m_tableWidget->setRowCount(items.size());
553 
554  for(std::size_t i = 0; i < items.size(); ++i)
555  {
556  m_ui->m_tableWidget->setItem(i, 0,new QTableWidgetItem(items[i][0].c_str()));
557  m_ui->m_tableWidget->setItem(i, 1,new QTableWidgetItem(items[i][1].c_str()));
558  m_ui->m_tableWidget->setItem(i, 2,new QTableWidgetItem(items[i][2].c_str()));
559  m_ui->m_tableWidget->setItem(i, 3,new QTableWidgetItem(items[i][3].c_str()));
560 
561  QColor color;
562 
563  color.setRgb(boost::lexical_cast<int>(items[i][1]),
564  boost::lexical_cast<int>(items[i][2]),
565  boost::lexical_cast<int>(items[i][3]));
566 
567  QPixmap pix(24, 24);
568  QPainter p(&pix);
569 
570  p.fillRect(0, 0, 12, 24, color);
571  p.fillRect(12, 0, 12, 24, color);
572  p.setBrush(Qt::transparent);
573  p.setPen(Qt::black);
574  p.drawRect(0, 0, 23, 23);
575 
576  QIcon icon(pix);
577 
578  QTableWidgetItem* item = new QTableWidgetItem(icon, "");
579  // item->setBackgroundColor(color);
580  item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
581  m_ui->m_tableWidget->setItem(i, 4, item);
582 
583  {
584  QTableWidgetItem* item = new QTableWidgetItem();
585  item->setCheckState(Qt::Checked);
586  m_ui->m_tableWidget->setItem(i, 5, item);
587  }
588  }
589 }
te::qt::widgets::ColorCatalogWidget * m_colorBar
Widget used to pick a color.
void setScaleVisible(bool flag)
Sets scale of color bar visibility.
GeomType
Each enumerated type is compatible with a Well-known Binary (WKB) type code.
te::color::ColorBar * m_cb
Terralib color bar objetc.
TESEEXPORT Symbolizer * CreateSymbolizer(const te::gm::GeomType &geomType)
Try creates an appropriate symbolizer based on given geometry type.
A Symbolizer describes how a feature is to appear on a map.
Definition: Symbolizer.h:80
void setHeight(int value)
Sets the height of colobar.
void getDataAsString(std::vector< std::string > &vec, const std::string &attrName, int &nullValues)
TEMAPEXPORT void GroupingByUniqueValues(std::string attrName, std::vector< std::string > &inputValues, int dataType, std::vector< te::se::Rule * > &rules, int precision)
It groups the values using the unique value algorithm.
TEMAPEXPORT te::gm::GeomType GetGeomType(const te::map::AbstractLayerPtr &layer)
It gets the geometry type of the given layer.
const std::vector< te::color::RGBAColor > & getUpperMeanSlices(const int &n)
static te::dt::Date ds(2010, 01, 01)
const te::fe::Filter * getFilter() const
Definition: Rule.cpp:97
It models a property definition.
Definition: Property.h:59
const std::vector< te::color::RGBAColor > & getLowerMeanSlices(const int &n)
const std::vector< se::Rule * > & getRules() const
int b
Definition: TsRtree.cpp:32
te::gm::Polygon * p
A filter is any valid predicate expression.
Definition: fe/Filter.h:55
const te::color::RGBAColor & getMeanSlice()
A dialog used to edit legend.
A Symbology Enconding visitor that finds a color given a symbolizer element. If you want to use this ...
const std::vector< te::color::RGBAColor > & getSlices(const int &n)
It generates color bar.
const std::vector< Symbolizer * > & getSymbolizers() const
Definition: Rule.cpp:158
int getType() const
It returns the property data type.
Definition: Property.h:161
#define NO_TITLE
void find(const te::se::Symbolizer *symbolizer)
It find the color based on given symbolizer.
void addColor(const RGBAColor &color, const double &pos)
It adds a color in the color bar.
A Rule is used to attach property/scale conditions to and group the individual symbols used for rende...
Definition: Rule.h:76
A helper class for 32-bit RGBA (Red-Green-Blue-Alpha channel) color.
Definition: RGBAColor.h:57
te::color::ColorBar * getColorBar()
It returns the colorbar.
It models the concept of color bar.
te::qt::widgets::colorbar::ColorBar * getColorBar()
std::unique_ptr< Ui::TimeViewerEditLegendDialog > m_ui
Dialog form.
TimeViewerEditLegendDialog(QWidget *parent=0, Qt::WindowFlags f=0)
Constructs a basic fill dialog which is a child of parent, with widget flags set to f...
te::map::AbstractLayerPtr m_layer
TerraLib layer auto ptr.
void setColorBar(te::color::ColorBar *cb)
It sets the color bar.
te::color::RGBAColor getColor()
Get the color.
std::vector< te::se::Rule * > m_legend
Rule items.
boost::intrusive_ptr< AbstractLayer > AbstractLayerPtr
#define PRECISION
void FreeContents(boost::unordered_map< K, V * > &m)
This function can be applied to a map of pointers. It will delete each pointer in the map...
Definition: BoostUtils.h:55
static QPixmap build(const te::se::Symbolizer *symb, const QSize &size)
Generates the preview of given symbolizer element.
const std::string & getName() const
It returns the property name.
Definition: Property.h:127
TEFEEXPORT void GetFilterUniqueValue(const te::fe::Filter *filter, std::string &value)
const std::string * getName() const
Definition: Rule.cpp:64