GroupingWidget.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/se/GroupingWidget.cpp
22 
23  \brief A widget used to build a grouping.
24 */
25 
26 // TerraLib
27 #include "../../../color/ColorBar.h"
28 #include "../../../common/Globals.h"
29 #include "../../../common/STLUtils.h"
30 #include "../../../dataaccess/datasource/DataSource.h"
31 #include "../../../dataaccess/query/SQLVisitor.h"
32 #include "../../../dataaccess/dataset/DataSet.h"
33 #include "../../../dataaccess/dataset/DataSetType.h"
34 #include "../../../dataaccess/query/OrderByItem.h"
35 #include "../../../dataaccess/utils/Utils.h"
36 #include "../../../fe/Filter.h"
37 #include "../../../fe/Utils.h"
38 #include "../../../geometry/GeometryProperty.h"
39 #include "../../../maptools/Enums.h"
40 #include "../../../maptools/GroupingAlgorithms.h"
41 #include "../../../maptools/Grouping.h"
42 #include "../../../maptools/Utils.h"
43 #include "../../../maptools/QueryEncoder.h"
44 #include "../../../maptools/QueryLayer.h"
45 #include "../../../se.h"
46 #include "../../../se/Symbolizer.h"
47 #include "../../../se/SymbolizerColorFinder.h"
48 #include "../../../se/Style.h"
49 #include "../../../se/Utils.h"
50 #include "../colorbar/ColorBar.h"
51 #include "../colorbar/ColorCatalogWidget.h"
52 #include "../se/LineSymbolizerWidget.h"
53 #include "../se/PointSymbolizerWidget.h"
54 #include "../se/PolygonSymbolizerWidget.h"
55 #include "../se/SymbologyPreview.h"
56 #include "GroupingWidget.h"
57 #include "ui_GroupingWidgetForm.h"
58 
59 // STL
60 #include <cassert>
61 
62 // QT
63 #include <QDialogButtonBox>
64 #include <QMessageBox>
65 #include <QFileDialog>
66 #include <QPainter>
67 
68 // Boost
69 #include <boost/algorithm/string.hpp>
70 #include <boost/filesystem.hpp>
71 #include <boost/lexical_cast.hpp>
72 #include <boost/property_tree/json_parser.hpp>
73 
74 #define MAX_SLICES 200
75 #define PRECISION 15
76 #define NO_TITLE "No Value"
77 
79 
80 std::string GetRuleDescription(te::se::Rule* rule, te::da::DataSourcePtr ds)
81 {
82  std::string sql;
83 
84  te::map::QueryEncoder filter2Query;
85 
86  te::da::Expression* exp = filter2Query.getExpression(rule->getFilter());
87 
88  te::da::SQLVisitor visitor(*ds->getDialect(), sql);
89 
90  try
91  {
92  exp->accept(visitor);
93  }
94  catch (...)
95  {
96  return "";
97  }
98 
99  return sql;
100 }
101 
103  : QWidget(parent, f),
104  m_ui(new Ui::GroupingWidgetForm),
105  m_cb(nullptr)
106 {
107  m_ui->setupUi(this);
108 
109  QGridLayout* l = new QGridLayout(m_ui->m_colorBarWidget);
110  l->setContentsMargins(0,0,0,0);
111  m_colorBar = new te::qt::widgets::ColorCatalogWidget(m_ui->m_colorBarWidget);
112  l->addWidget(m_colorBar);
113 
114 //connects
115  connect(m_colorBar, SIGNAL(colorBarChanged()), this, SLOT(onColorBarChanged()));
116  connect(m_ui->m_typeComboBox, SIGNAL(activated(int)), this, SLOT(onTypeComboBoxActivated(int)));
117  connect(m_ui->m_attrComboBox, SIGNAL(activated(int)), this, SLOT(onAttrComboBoxActivated(int)));
118  connect(m_ui->m_applyPushButton, SIGNAL(clicked()), this, SLOT(onApplyPushButtonClicked()));
119  connect(m_ui->m_tableWidget, SIGNAL(itemDoubleClicked(QTableWidgetItem*)), this, SLOT(onTableWidgetItemDoubleClicked(QTableWidgetItem*)));
120  connect(m_ui->m_importPushButton, SIGNAL(clicked()), this, SLOT(onImportPushButtonClicked()));
121  connect(m_ui->m_loadLegendPushButton, SIGNAL(clicked()), this, SLOT(onLoadPushButtonClicked()));
122  connect(m_ui->m_saveLegendPushButton, SIGNAL(clicked()), this, SLOT(onSavePushButtonClicked()));
123 
124  //m_importGroupingGroupBox
125  initialize();
126 }
127 
129 {
130  delete m_cb;
131 
133  m_rules.clear();
134 }
135 
136 std::unique_ptr<te::map::Grouping> te::qt::widgets::GroupingWidget::getGrouping()
137 {
138  if (m_ui->m_importGroupBox->isChecked())
139  {
140  QVariant varLayer = m_ui->m_layersComboBox->itemData(m_ui->m_layersComboBox->currentIndex(), Qt::UserRole);
141  te::map::AbstractLayerPtr layer = varLayer.value<te::map::AbstractLayerPtr>();
142 
143  te::map::Grouping* ref = layer->getGrouping();
144 
145  std::unique_ptr<te::map::Grouping> group(new te::map::Grouping(*ref));
146 
147  return group;
148  }
149 
150  std::string attr = m_ui->m_attrComboBox->currentText().toUtf8().data();
151  int attrIdx = m_ui->m_attrComboBox->currentIndex();
152  int attrType = m_ui->m_attrComboBox->itemData(attrIdx).toInt();
153 
154  int index = m_ui->m_typeComboBox->currentIndex();
155  int type = m_ui->m_typeComboBox->itemData(index).toInt();
156 
157  std::unique_ptr<te::map::Grouping> group(new te::map::Grouping(attr, (te::map::GroupingType)type));
158 
159  group->setPropertyType(attrType);
160 
161  group->setNumSlices(m_ui->m_slicesSpinBox->value());
162 
163  group->setPrecision(m_ui->m_precSpinBox->value());
164 
165  group->setStdDeviation(m_ui->m_stdDevDoubleSpinBox->value());
166 
167  group->setSummary(m_ui->m_summaryComboBox->currentText().toUtf8().data());
168 
169  return group;
170 }
171 
173 {
174  if (m_layer)
175  {
177 
178  te::se::Style* style = m_layer->getStyle();
179 
180  //set style name
181  std::string prefixName = tr("Grouping Style: ").toUtf8().data();
182  std::string* styleName = new std::string(prefixName + m_ui->m_typeComboBox->currentText().toUtf8().data());
183  style->setName(styleName);
184 
185  //set style description
186  QString descInfo = QObject::tr("Grouping Information") + ":\n";
187 
188  descInfo += QObject::tr("\tProperty: ") + m_ui->m_attrComboBox->currentText() + "\n";
189  descInfo += QObject::tr("\tNum Slices: ") + QString::number(m_ui->m_slicesSpinBox->value()) + "\n";
190  descInfo += QObject::tr("\tPrecision: ") + QString::number(m_ui->m_precSpinBox->value()) + "\n";
191  descInfo += QObject::tr("\tStd Deviation: ") + QString::number(m_ui->m_stdDevDoubleSpinBox->value()) + "\n";
192  descInfo += QObject::tr("\tSumary: ") + m_ui->m_summaryComboBox->currentText();
193 
194  te::se::Description* descStyle = new te::se::Description;
195  descStyle->setTitle(descInfo.toUtf8().data());
196  style->setDescription(descStyle);
197 
198  style->removeRules();
199 
200  for (std::size_t t = 0; t < m_rules.size(); ++t)
201  {
202  te::se::Rule* rule = m_rules[t];
203 
204  //set rule description
205  std::string descStr = GetRuleDescription(rule, ds);
207  desc->setTitle(descStr);
208  rule->setDescription(desc);
209 
210  style->push_back(rule);
211  }
212 
213  m_rules.clear();
214  }
215 }
216 
218 {
219  // create color bar
222 
223  // fill grouping type combo box
224  m_ui->m_typeComboBox->addItem(tr("Equal Steps"), te::map::EQUAL_STEPS);
225  m_ui->m_typeComboBox->addItem(tr("Quantil"), te::map::QUANTIL);
226  m_ui->m_typeComboBox->addItem(tr("Standard Deviation"), te::map::STD_DEVIATION);
227  m_ui->m_typeComboBox->addItem(tr("Unique Value"), te::map::UNIQUE_VALUE);
228 
230 
231  //set number of slices
232  m_ui->m_slicesSpinBox->setMinimum(1);
233  m_ui->m_slicesSpinBox->setMaximum(MAX_SLICES);
234  m_ui->m_slicesSpinBox->setValue(5);
235  m_ui->m_slicesSpinBox->setSingleStep(1);
236 
237  //set standard deviation values
238  m_ui->m_stdDevDoubleSpinBox->setMinimum(0.25);
239  m_ui->m_stdDevDoubleSpinBox->setMaximum(1.0);
240  m_ui->m_stdDevDoubleSpinBox->setValue(0.5);
241  m_ui->m_stdDevDoubleSpinBox->setSingleStep(0.25);
242 
243  //set number of precision
244  m_ui->m_precSpinBox->setMinimum(1);
245  m_ui->m_precSpinBox->setMaximum(PRECISION);
246  m_ui->m_precSpinBox->setValue(6);
247  m_ui->m_precSpinBox->setSingleStep(1);
248 
249  //adjust table
250 #if (QT_VERSION >= 0x050000)
251  m_ui->m_tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
252 #else
253  m_ui->m_tableWidget->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
254 #endif
255 
256  m_manual = false;
257 }
258 
260 {
261  disconnect(m_ui->m_tableWidget, SIGNAL(itemChanged(QTableWidgetItem*)), this, SLOT(onTableWidgetItemChanged(QTableWidgetItem*)));
262 
263  m_ui->m_tableWidget->setRowCount(0);
264 
265  int index = m_ui->m_typeComboBox->currentIndex();
266  int type = m_ui->m_typeComboBox->itemData(index).toInt();
267 
268  if(type == te::map::EQUAL_STEPS || type == te::map::QUANTIL || type == te::map::STD_DEVIATION)
269  {
270  QStringList list;
271  list.append(tr("Symbol"));
272  list.append(tr("Title"));
273  list.append(tr("Min"));
274  list.append(tr("Max"));
275 
276  m_ui->m_tableWidget->setColumnCount(4);
277  m_ui->m_tableWidget->setHorizontalHeaderLabels(list);
278  }
279  else if(type == te::map::UNIQUE_VALUE)
280  {
281  QStringList list;
282  list.append(tr("Symbol"));
283  list.append(tr("Title"));
284  list.append(tr("Value"));
285 
286  m_ui->m_tableWidget->setColumnCount(3);
287  m_ui->m_tableWidget->setHorizontalHeaderLabels(list);
288  }
289 
290  te::color::ColorBar* cb = nullptr;
291 
292  if(loadColorBar)
293  {
294  if (!m_rules.empty() && !m_rules[0]->getSymbolizers().empty() && !m_rules[m_rules.size() - 1]->getSymbolizers().empty())
295  {
297 
298  scf.find(m_rules[0]->getSymbolizers()[0]);
299  te::color::RGBAColor initColor = scf.getColor();
300 
301  scf.find(m_rules[m_rules.size() - 1]->getSymbolizers()[0]);
302  te::color::RGBAColor endColor = scf.getColor();
303 
304  cb = new te::color::ColorBar(initColor, endColor, 256);
305  }
306  }
307 
308  int count = 0;
309 
310  for(std::size_t t = 0; t < m_rules.size(); ++t)
311  {
312  te::se::Rule* ruleItem = m_rules[t];
313  const te::fe::Filter* ruleFilter = ruleItem->getFilter();
314 
315  if (!ruleFilter)
316  continue;
317 
318  int newrow = m_ui->m_tableWidget->rowCount();
319  m_ui->m_tableWidget->insertRow(newrow);
320 
321  //symbol
322  {
323  const std::vector<te::se::Symbolizer*>& ss = ruleItem->getSymbolizers();
324  QPixmap pix = te::qt::widgets::SymbologyPreview::build(ss, QSize(24, 24));
325  QIcon icon(pix);
326  QTableWidgetItem* item = new QTableWidgetItem(icon, "");
327  item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
328  m_ui->m_tableWidget->setItem(newrow, 0, item);
329  }
330 
331  //title
332  {
333  QTableWidgetItem* item = new QTableWidgetItem(QString::fromUtf8((*ruleItem->getName()).c_str()));
334  item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable);
335  m_ui->m_tableWidget->setItem(newrow, 1, item);
336  }
337 
338  if(loadColorBar)
339  {
340  if (count != 0 && count != static_cast<int>(m_rules.size()) - 1)
341  {
342  double pos = (1. / (m_rules.size() - 1)) * count;
343 
344  if (!ruleItem->getSymbolizers().empty())
345  {
347 
348  scf.find(ruleItem->getSymbolizers()[0]);
349 
350  te::color::RGBAColor color = scf.getColor();
351 
352  if(cb)
353  cb->addColor(color, pos);
354  }
355  }
356  }
357 
358  ++count;
359 
360  std::string ruleName = *ruleItem->getName();
361 
362  if(type == te::map::EQUAL_STEPS || type == te::map::QUANTIL || type == te::map::STD_DEVIATION)
363  {
364  if (ruleName != NO_TITLE)
365  {
366  //Values
367  std::string valueMin;
368  std::string valueMax;
369  te::fe::GetFilterStepValues(ruleFilter, valueMin, valueMax);
370 
371  //Min
372  {
373  QTableWidgetItem* item = new QTableWidgetItem(QString::fromUtf8(valueMin.c_str()));
374  item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable);
375  m_ui->m_tableWidget->setItem(newrow, 2, item);
376  }
377 
378  //Max
379  {
380  QTableWidgetItem* item = new QTableWidgetItem(QString::fromUtf8(valueMax.c_str()));
381  item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable);
382  m_ui->m_tableWidget->setItem(newrow, 3, item);
383  }
384  }
385  }
386  else if(type == te::map::UNIQUE_VALUE)
387  {
388  if (ruleName != NO_TITLE)
389  {
390  //Value
391  std::string value;
392  te::fe::GetFilterUniqueValue(ruleFilter, value);
393 
394  QTableWidgetItem* item = new QTableWidgetItem(QString::fromUtf8(value.c_str()));
395  item->setFlags(Qt::ItemIsEnabled);
396  m_ui->m_tableWidget->setItem(newrow, 2, item);
397  }
398  }
399  }
400 
401  if(cb)
402  {
403  disconnect(m_colorBar, SIGNAL(colorBarChanged()), this, SLOT(onColorBarChanged()));
404 
406  cbW->setColorBar(cb);
407 
408  connect(m_colorBar, SIGNAL(colorBarChanged()), this, SLOT(onColorBarChanged()));
409  }
410 
411 #if (QT_VERSION >= 0x050000)
412  m_ui->m_tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
413 #else
414  m_ui->m_tableWidget->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
415 #endif
416 
417  connect(m_ui->m_tableWidget, SIGNAL(itemChanged(QTableWidgetItem*)), this, SLOT(onTableWidgetItemChanged(QTableWidgetItem*)));
418 }
419 
421 {
422  listAttributes();
423 }
424 
426 {
427  if (m_layer)
428  {
429  te::map::Grouping* grouping = m_layer->getGrouping();
430 
431  if (grouping)
432  {
433  setGrouping(grouping, m_layer->getStyle());
434 
435  emit applyPushButtonClicked();
436  }
437  }
438 }
439 
441 {
442  if (!grouping)
443  return;
444 
445  //type
446  te::map::GroupingType type = grouping->getType();
447 
448  for (int i = 0; i < m_ui->m_typeComboBox->count(); ++i)
449  {
450  if (type == m_ui->m_typeComboBox->itemData(i).toInt())
451  {
452  m_ui->m_typeComboBox->setCurrentIndex(i);
453 
455 
456  break;
457  }
458  }
459 
460  //attr name
461  std::string attrName = grouping->getPropertyName();
462 
463  for (int i = 0; i < m_ui->m_attrComboBox->count(); ++i)
464  {
465  if (attrName == m_ui->m_attrComboBox->itemText(i).toUtf8().data())
466  {
467  m_ui->m_attrComboBox->setCurrentIndex(i);
468  break;
469  }
470  }
471 
472  //precision
473  size_t prec = grouping->getPrecision();
474 
475  m_ui->m_precSpinBox->setValue((int)prec);
476 
477  //slices
478  size_t slices = grouping->getNumSlices();
479 
480  m_ui->m_slicesSpinBox->setValue((int)slices);
481 
482  //std dev
483  float stdDev = grouping->getStdDeviation();
484 
485  m_ui->m_stdDevDoubleSpinBox->setValue((double)stdDev);
486 
487  //grouping items
489  m_rules.clear();
490 
491  for (size_t t = 0; t < style->getRules().size(); ++t)
492  {
493  te::se::Rule* rule = style->getRule(t)->clone();
494 
495  m_rules.push_back(rule);
496  }
497 
498  updateUi(true);
499 }
500 
502 {
503  if(m_manual)
504  {
505  int reply = QMessageBox::question(this, tr("Edit Legend"), tr("Manual changes will be lost. Continue?"), QMessageBox::Yes | QMessageBox::Cancel);
506 
507  if(reply != QMessageBox::Yes)
508  return;
509  }
510 
511  int index = m_ui->m_typeComboBox->currentIndex();
512 
513  int type = m_ui->m_typeComboBox->itemData(index).toInt();
514  int slices = m_ui->m_slicesSpinBox->value();
515  int prec = m_ui->m_precSpinBox->value();
516  double stdDev = m_ui->m_stdDevDoubleSpinBox->value();
517 
518  std::string attr = m_ui->m_attrComboBox->currentText().toUtf8().data();
519  int attrIdx = m_ui->m_attrComboBox->currentIndex();
520  int attrType = m_ui->m_attrComboBox->itemData(attrIdx).toInt();
521 
523  m_rules.clear();
524 
525  std::string mean;
526 
527  int nullValues = 0;
528 
529  bool update = false;
530 
531  if(type == te::map::EQUAL_STEPS)
532  {
533  std::vector<double> vec;
534 
535  getDataAsDouble(vec, attr, attrType, nullValues);
536 
537  if (!vec.empty())
538  {
539  te::map::GroupingByEqualSteps(attr, vec.begin(), vec.end(), slices, m_rules, prec);
540 
541  buildSymbolizer(mean);
542 
543  createDoubleNullGroupingItem(nullValues);
544  }
545  }
546  else if(type == te::map::QUANTIL)
547  {
548  std::vector<double> vec;
549 
550  getDataAsDouble(vec, attr, attrType, nullValues);
551 
552  if (!vec.empty())
553  {
554  te::map::GroupingByQuantil(attr, vec.begin(), vec.end(), slices, m_rules, prec);
555 
556  buildSymbolizer(mean);
557 
558  createDoubleNullGroupingItem(nullValues);
559  }
560  }
561  else if(type == te::map::STD_DEVIATION)
562  {
563  std::vector<double> vec;
564 
565  getDataAsDouble(vec, attr, attrType, nullValues);
566 
567  if (!vec.empty())
568  {
569  te::map::GroupingByStdDeviation(attr, vec.begin(), vec.end(), stdDev, m_rules, mean, prec);
570 
571  buildSymbolizer(mean);
572 
573  createDoubleNullGroupingItem(nullValues);
574  }
575 
576  update = false;
577  }
578  else if(type == te::map::UNIQUE_VALUE)
579  {
580  std::vector<std::string> vec;
581 
582  getDataAsString(vec, attr, nullValues);
583 
584  if (!vec.empty())
585  {
586  te::map::GroupingByUniqueValues(attr, vec, attrType, m_rules, prec);
587 
588  buildSymbolizer(mean);
589 
590  createStringNullGroupingItem(nullValues);
591  }
592  }
593 
594  updateUi(update);
595 
596  m_manual = false;
597 
598  emit applyPushButtonClicked();
599 }
600 
602 {
603  int type = m_ui->m_typeComboBox->itemData(idx).toInt();
604 
605  if(type == te::map::EQUAL_STEPS)
606  {
607  m_ui->m_slicesSpinBox->setEnabled(true);
608  m_ui->m_precSpinBox->setEnabled(true);
609  m_ui->m_stdDevDoubleSpinBox->setEnabled(false);
610  }
611  else if(type == te::map::QUANTIL)
612  {
613  m_ui->m_slicesSpinBox->setEnabled(true);
614  m_ui->m_precSpinBox->setEnabled(true);
615  m_ui->m_stdDevDoubleSpinBox->setEnabled(false);
616  }
617  else if(type == te::map::STD_DEVIATION)
618  {
619  m_ui->m_slicesSpinBox->setEnabled(false);
620  m_ui->m_precSpinBox->setEnabled(true);
621  m_ui->m_stdDevDoubleSpinBox->setEnabled(true);
622  }
623  else if(type == te::map::UNIQUE_VALUE)
624  {
625  m_ui->m_slicesSpinBox->setEnabled(false);
626  m_ui->m_precSpinBox->setEnabled(true);
627  m_ui->m_stdDevDoubleSpinBox->setEnabled(false);
628  }
629 
630  if(m_layer.get())
631  listAttributes();
632 }
633 
635 {
636 
637 }
638 
640 {
641  if(m_layer.get())
642  {
643  buildSymbolizer();
644 
645  updateUi();
646  }
647 }
648 
650 {
651  int index = m_ui->m_typeComboBox->currentIndex();
652  int type = m_ui->m_typeComboBox->itemData(index).toInt();
653 
654  int curRow = m_ui->m_tableWidget->currentRow();
655  int curCol = m_ui->m_tableWidget->currentColumn();
656 
657  std::string attrName = m_ui->m_attrComboBox->currentText().toUtf8().data();
658 
659  QString str = item->text();
660 
661  if(curCol == 1) // title
662  {
663  std::string ruleName = str.toUtf8().data();
664  m_rules[curRow]->setName(&ruleName);
665 
666  m_manual = true;
667  }
668  else if(curCol == 2 || curCol == 3) // min and max
669  {
670  if(type == te::map::EQUAL_STEPS || type == te::map::QUANTIL || type == te::map::STD_DEVIATION)
671  {
672  bool ok = false;
673 
674  str.toDouble(&ok);
675 
676  if(!ok)
677  {
678  std::string valueMin;
679  std::string valueMax;
680  const te::fe::Filter* ruleFilter = m_rules[curRow]->getFilter();
681  te::fe::GetFilterStepValues(ruleFilter, valueMin, valueMax);
682 
683  if(curCol == 2)
684  item->setText(valueMin.c_str());
685  else if(curCol ==3)
686  item->setText(valueMax.c_str());
687  }
688  else
689  {
690  std::string valueMin;
691  std::string valueMax;
692  const te::fe::Filter* ruleFilter = m_rules[curRow]->getFilter();
693  te::fe::GetFilterStepValues(ruleFilter, valueMin, valueMax);
694 
695  if(curCol == 2)
696  valueMin = item->text().toUtf8().data();
697  else if(curCol ==3)
698  valueMax = item->text().toUtf8().data();
699 
700  m_rules[curRow]->setFilter(te::fe::CreateFilterByStep(attrName, valueMin, valueMax));
701 
702  m_manual = true;
703  }
704  }
705  }
706 }
707 
709  QTableWidgetItem* /*item*/)
710 {
711  int curRow = m_ui->m_tableWidget->currentRow();
712  int curCol = m_ui->m_tableWidget->currentColumn();
713 
714  if(curCol == 0)
715  {
716  te::se::Rule* ruleItem = m_rules[curRow];
717 
718  std::vector<te::se::Symbolizer*> symbVec = ruleItem->getSymbolizers();
719 
720  QDialog* dialog = new QDialog(this);
721  QBoxLayout* layout = new QBoxLayout(QBoxLayout::TopToBottom, dialog);
722 
723  QDialogButtonBox* bbox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, dialog);
724 
725  QWidget* symbWidget = nullptr;
726 
727  if(symbVec[0]->getType() == "PolygonSymbolizer")
728  {
729  symbWidget = new te::qt::widgets::PolygonSymbolizerWidget(dialog);
731  polygonSymbolizerWidget->setSymbolizer((te::se::PolygonSymbolizer*)symbVec[0]);
732  }
733  else if(symbVec[0]->getType() == "LineSymbolizer")
734  {
735  symbWidget = new te::qt::widgets::LineSymbolizerWidget(dialog);
737  lineSymbolizerWidget->setSymbolizer((te::se::LineSymbolizer*)symbVec[0]);
738  }
739  else if(symbVec[0]->getType() == "PointSymbolizer")
740  {
741  symbWidget = new te::qt::widgets::PointSymbolizerWidget(dialog);
743  pointSymbolizerWidget->setSymbolizer((te::se::PointSymbolizer*)symbVec[0]);
744  }
745 
746  layout->addWidget(symbWidget);
747  layout->addWidget(bbox);
748 
749  connect(bbox, SIGNAL(accepted()), dialog, SLOT(accept()));
750  connect(bbox, SIGNAL(rejected()), dialog, SLOT(reject()));
751 
752  if(dialog->exec() == QDialog::Rejected)
753  {
754  delete dialog;
755  return;
756  }
757 
758  if(symbVec[0]->getType() == "PolygonSymbolizer")
759  {
760  symbVec.clear();
762  symbVec.push_back(polygonSymbolizerWidget->getSymbolizer());
763  }
764  else if(symbVec[0]->getType() == "LineSymbolizer")
765  {
766  symbVec.clear();
768  symbVec.push_back(lineSymbolizerWidget->getSymbolizer());
769  }
770  else if(symbVec[0]->getType() == "PointSymbolizer")
771  {
772  symbVec.clear();
774  symbVec.push_back(pointSymbolizerWidget->getSymbolizer());
775  }
776 
777  ruleItem->setSymbolizers(symbVec);
778 
779  QPixmap pix = te::qt::widgets::SymbologyPreview::build(symbVec, QSize(24, 24));
780  QIcon icon(pix);
781 
782  QTableWidgetItem* newItem = new QTableWidgetItem(icon, "");
783  newItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled);
784 
785  m_ui->m_tableWidget->setItem(curRow, 0, newItem);
786 
787  delete dialog;
788 
789  updateUi(true);
790 
791  emit applyPushButtonClicked();
792  }
793 }
794 
795 
796 void te::qt::widgets::GroupingWidget::getDataAsDouble(std::vector<double>& vec, const std::string& attrName, const int& dataType, int& nullValues)
797 {
798  assert(m_layer.get());
799 
800  if (te::da::HasLinkedTable(m_layer->getSchema().get()) && (m_ui->m_summaryComboBox->currentText().toStdString() != "NONE"))
801  {
802  getLinkedDataAsDouble(vec, attrName, dataType, nullValues);
803  return;
804  }
805 
806  std::unique_ptr<te::map::LayerSchema> dsType(m_layer->getSchema());
807 
808  std::size_t idx=std::string::npos;
809 
810  for(std::size_t t = 0; t < dsType->getProperties().size(); ++t)
811  {
812  if(dsType->getProperty(t)->getName() == attrName)
813  {
814  idx = t;
815  break;
816  }
817  }
818 
819  std::unique_ptr<te::da::DataSet> ds(m_layer->getData());
820 
821  ds->moveBeforeFirst();
822 
823  while(ds->moveNext())
824  {
825  if(ds->isNull(idx))
826  {
827  ++nullValues;
828  continue;
829  }
830 
831  if(dataType == te::dt::INT16_TYPE)
832  vec.push_back((double)ds->getInt16(idx));
833  else if(dataType == te::dt::INT32_TYPE)
834  vec.push_back((double)ds->getInt32(idx));
835  else if(dataType == te::dt::INT64_TYPE)
836  vec.push_back((double)ds->getInt64(idx));
837  else if(dataType == te::dt::FLOAT_TYPE)
838  vec.push_back((double)ds->getFloat(idx));
839  else if(dataType == te::dt::DOUBLE_TYPE)
840  vec.push_back(ds->getDouble(idx));
841  else if(dataType == te::dt::NUMERIC_TYPE)
842  {
843  QString strNum = ds->getNumeric(idx).c_str();
844 
845  bool ok = false;
846 
847  double value = strNum.toDouble(&ok);
848 
849  if(ok)
850  vec.push_back(value);
851  }
852  }
853 }
854 
855 void te::qt::widgets::GroupingWidget::getLinkedDataAsDouble(std::vector<double>& vec, const std::string& attrName, const int& dataType, int& nullValues)
856 {
857  assert(m_layer.get());
858 
859  std::unique_ptr<te::map::LayerSchema> dsType(m_layer->getSchema());
860 
861  std::string function = m_ui->m_summaryComboBox->currentText().toUtf8().data();
862  std::vector<std::string> poid;
863  size_t pksize = 0;
864  te::map::QueryLayer* qlayer = nullptr;
865  te::da::Select* select = nullptr;
866 
867  // make sorting by object id
868  qlayer = dynamic_cast<te::map::QueryLayer*>(m_layer.get());
869  select = dynamic_cast<te::da::Select*>(qlayer->getQuery()->clone());
870  te::da::Select* selectaux = dynamic_cast<te::da::Select*>(select->clone());
871  te::da::OrderBy* orderBy = new te::da::OrderBy;
872 
873  std::vector<te::dt::Property*> props = dsType->getPrimaryKey()->getProperties();
874  while(++pksize < props.size())
875  {
876  poid.push_back(props[pksize-1]->getName());
877  if(props[pksize-1]->getDatasetName() != props[pksize]->getDatasetName())
878  break;
879  }
880 
881  for(size_t i = 0; i < pksize; ++i)
882  orderBy->push_back(new te::da::OrderByItem(poid[i]));
883 
884  selectaux->setOrderBy(orderBy);
885  qlayer->setQuery(selectaux);
886 
887  std::size_t idx=std::string::npos;
888 
889  for(std::size_t t = 0; t < dsType->getProperties().size(); ++t)
890  {
891  if(dsType->getProperty(t)->getName() == attrName)
892  {
893  idx = t;
894  break;
895  }
896  }
897 
898  std::vector<std::string> pkdata(pksize), pkdataaux(pksize);
899  std::unique_ptr<te::da::DataSet> ds(m_layer->getData());
900  qlayer->setQuery(select);
901 
902  bool nullValue = false;
903  std::vector<double> values;
904  bool isBegin = true;
905  ds->moveBeforeFirst();
906 
907  while(ds->moveNext())
908  {
909  if(pksize)
910  {
911  // it is linked. Remove redundancies.
912  size_t i;
913  for(i = 0; i < pksize; ++i)
914  {
915  pkdata[i] = ds->getAsString(poid[i]);
916  if(isBegin)
917  {
918  isBegin = false;
919  pkdataaux[i] = ds->getAsString(poid[i]);
920  }
921  }
922 
923  for(i = 0; i < pksize; ++i)
924  {
925  if(pkdata[i] != pkdataaux[i])
926  {
927  pkdataaux = pkdata;
928  break;
929  }
930  }
931  if(i == pksize) // it is the same object
932  {
933  if(nullValue == false)
934  {
935  if(ds->isNull(idx))
936  nullValue = true;
937  else
938  {
939  if(dataType == te::dt::INT16_TYPE)
940  values.push_back((double)ds->getInt16(idx));
941  else if(dataType == te::dt::INT32_TYPE)
942  values.push_back((double)ds->getInt32(idx));
943  else if(dataType == te::dt::INT64_TYPE)
944  values.push_back((double)ds->getInt64(idx));
945  else if(dataType == te::dt::FLOAT_TYPE)
946  values.push_back((double)ds->getFloat(idx));
947  else if(dataType == te::dt::DOUBLE_TYPE)
948  values.push_back(ds->getDouble(idx));
949  else if(dataType == te::dt::NUMERIC_TYPE)
950  {
951  QString strNum = ds->getNumeric(idx).c_str();
952 
953  bool ok = false;
954 
955  double value = strNum.toDouble(&ok);
956 
957  if(ok)
958  values.push_back(value);
959  }
960  }
961  }
962  continue;
963  // read other values
964  }
965  else // it is other object
966  {
967  // sumarize value according to the required summarization
968  if(nullValue)
969  ++nullValues;
970  else
971  vec.push_back(te::da::GetSummarizedValue(values, function));
972 
973  nullValue = false;
974  values.clear();
975 
976  // get new value
977  if(ds->isNull(idx))
978  nullValue = true;
979  else
980  {
981  if(dataType == te::dt::INT16_TYPE)
982  values.push_back((double)ds->getInt16(idx));
983  else if(dataType == te::dt::INT32_TYPE)
984  values.push_back((double)ds->getInt32(idx));
985  else if(dataType == te::dt::INT64_TYPE)
986  values.push_back((double)ds->getInt64(idx));
987  else if(dataType == te::dt::FLOAT_TYPE)
988  values.push_back((double)ds->getFloat(idx));
989  else if(dataType == te::dt::DOUBLE_TYPE)
990  values.push_back(ds->getDouble(idx));
991  else if(dataType == te::dt::NUMERIC_TYPE)
992  {
993  QString strNum = ds->getNumeric(idx).c_str();
994 
995  bool ok = false;
996 
997  double value = strNum.toDouble(&ok);
998 
999  if(ok)
1000  values.push_back(value);
1001  }
1002  }
1003  }
1004  }
1005  }
1006  // sumarize value according to the required summarization
1007  if(nullValue)
1008  ++nullValues;
1009  else
1010  vec.push_back(te::da::GetSummarizedValue(values, function));
1011  values.clear();
1012 }
1013 
1014 void te::qt::widgets::GroupingWidget::getDataAsString(std::vector<std::string>& vec, const std::string& attrName, int& nullValues)
1015 {
1016  assert(m_layer.get());
1017 
1018  if (te::da::HasLinkedTable(m_layer->getSchema().get()) && (m_ui->m_summaryComboBox->currentText().toStdString() != "NONE"))
1019  {
1020  getLinkedDataAsString(vec, attrName, nullValues);
1021  return;
1022  }
1023 
1024  std::unique_ptr<te::map::LayerSchema> dsType(m_layer->getSchema());
1025 
1026  std::size_t idx=std::string::npos;
1027 
1028  for(std::size_t t = 0; t < dsType->getProperties().size(); ++t)
1029  {
1030  if(dsType->getProperty(t)->getName() == attrName)
1031  {
1032  idx = t;
1033  break;
1034  }
1035  }
1036 
1037  std::unique_ptr<te::da::DataSet> ds(m_layer->getData());
1038 
1039  ds->moveBeforeFirst();
1040 
1041  while(ds->moveNext())
1042  {
1043  if(!ds->isNull(idx))
1044  vec.push_back(ds->getAsString(idx));
1045  else
1046  ++nullValues;
1047  }
1048 }
1049 
1050 void te::qt::widgets::GroupingWidget::getLinkedDataAsString(std::vector<std::string>& vec, const std::string& attrName, int& nullValues)
1051 {
1052  assert(m_layer.get());
1053 
1054  std::unique_ptr<te::map::LayerSchema> dsType(m_layer->getSchema());
1055 
1056  std::string function = m_ui->m_summaryComboBox->currentText().toUtf8().data();
1057  std::vector<std::string> poid;
1058  size_t pksize = 0;
1059  te::map::QueryLayer* qlayer = nullptr;
1060  te::da::Select* select = nullptr;
1061 
1062  // make sorting by object id
1063  qlayer = dynamic_cast<te::map::QueryLayer*>(m_layer.get());
1064  select = dynamic_cast<te::da::Select*>(qlayer->getQuery()->clone());
1065  te::da::Select* selectaux = dynamic_cast<te::da::Select*>(select->clone());
1066  te::da::OrderBy* orderBy = new te::da::OrderBy;
1067 
1068  std::vector<te::dt::Property*> props = dsType->getPrimaryKey()->getProperties();
1069  while(++pksize < props.size())
1070  {
1071  poid.push_back(props[pksize-1]->getName());
1072  if(props[pksize-1]->getDatasetName() != props[pksize]->getDatasetName())
1073  break;
1074  }
1075 
1076  for(size_t i = 0; i < pksize; ++i)
1077  orderBy->push_back(new te::da::OrderByItem(poid[i]));
1078 
1079  selectaux->setOrderBy(orderBy);
1080  qlayer->setQuery(selectaux);
1081 
1082  std::size_t idx=std::string::npos;
1083 
1084  for(std::size_t t = 0; t < dsType->getProperties().size(); ++t)
1085  {
1086  if(dsType->getProperty(t)->getName() == attrName)
1087  {
1088  idx = t;
1089  break;
1090  }
1091  }
1092 
1093  std::vector<std::string> pkdata(pksize), pkdataaux(pksize);
1094  std::unique_ptr<te::da::DataSet> ds(m_layer->getData());
1095  qlayer->setQuery(select);
1096 
1097  bool nullValue = false;
1098  std::vector<std::string> values;
1099  bool isBegin = true;
1100  ds->moveBeforeFirst();
1101 
1102  while(ds->moveNext())
1103  {
1104  if(pksize)
1105  {
1106  // it is linked. Remove redundancies.
1107  size_t i;
1108  for(i = 0; i < pksize; ++i)
1109  {
1110  pkdata[i] = ds->getAsString(poid[i]);
1111  if(isBegin)
1112  {
1113  isBegin = false;
1114  pkdataaux[i] = ds->getAsString(poid[i]);
1115  }
1116  }
1117 
1118  for(i = 0; i < pksize; ++i)
1119  {
1120  if(pkdata[i] != pkdataaux[i])
1121  {
1122  pkdataaux = pkdata;
1123  break;
1124  }
1125  }
1126  if(i == pksize) // it is the same object
1127  {
1128  if(nullValue == false)
1129  {
1130  if(ds->isNull(idx))
1131  nullValue = true;
1132  else
1133  values.push_back(ds->getAsString(idx));
1134  }
1135  continue;
1136  // read other values
1137  }
1138  else // it is other object
1139  {
1140  // sumarize value according to the required summarization
1141  if(nullValue)
1142  ++nullValues;
1143  else
1144  vec.push_back(te::da::GetSummarizedValue(values, function));
1145 
1146  nullValue = false;
1147  values.clear();
1148 
1149  // get new value
1150  if(ds->isNull(idx))
1151  nullValue = true;
1152  else
1153  values.push_back(ds->getAsString(idx));
1154  }
1155  }
1156  }
1157  // sumarize value according to the required summarization
1158  if(nullValue)
1159  ++nullValues;
1160  else
1161  vec.push_back(te::da::GetSummarizedValue(values, function));
1162  values.clear();
1163 }
1164 
1166 {
1167  if(count == 0)
1168  return;
1169 
1170  std::string attrName = m_ui->m_attrComboBox->currentText().toUtf8().data();
1171 
1172  std::string* ruleName = new std::string(NO_TITLE);
1173 
1174  te::se::Rule* rule = new te::se::Rule;
1175  rule->setName(ruleName);
1177 
1178  int geomType = getGeometryType();
1179  std::vector<te::se::Symbolizer*> symbVec;
1181  symbVec.push_back(s);
1182  rule->setSymbolizers(symbVec);
1183 
1184  m_rules.push_back(rule);
1185 }
1186 
1188 {
1189  if(count == 0)
1190  return;
1191 
1192  std::string attrName = m_ui->m_attrComboBox->currentText().toUtf8().data();
1193 
1194  std::string* ruleName = new std::string(NO_TITLE);
1195 
1196  te::se::Rule* rule = new te::se::Rule;
1197  rule->setName(ruleName);
1199 
1200  int geomType = getGeometryType();
1201  std::vector<te::se::Symbolizer*> symbVec;
1203  symbVec.push_back(s);
1204  rule->setSymbolizers(symbVec);
1205 
1206  m_rules.push_back(rule);
1207 }
1208 
1210 {
1211  assert(m_layer.get());
1212 
1213  return te::map::GetGeomType(m_layer);
1214 }
1215 
1217 {
1218  delete m_cb;
1219 
1221 
1222  int legendSize = static_cast<int>(m_rules.size());
1223 
1224  std::vector<te::color::RGBAColor> colorVec;
1225 
1226  if(meanTitle.empty())
1227  {
1228  colorVec = m_cb->getSlices(legendSize);
1229  }
1230  else
1231  {
1232  int beforeMean = 0;
1233  int afterMean = 0;
1234 
1235  for(size_t t = 0; t < m_rules.size(); ++t)
1236  {
1237  std::string ruleName = *m_rules[t]->getName();
1238  if (ruleName != meanTitle)
1239  {
1240  beforeMean++;
1241  }
1242  else
1243  {
1244  afterMean = static_cast<int>(m_rules.size() - t - 1);
1245  break;
1246  }
1247  }
1248 
1249  std::vector<te::color::RGBAColor> lowerColorVec = m_cb->getLowerMeanSlices(beforeMean);
1250  te::color::RGBAColor meanColor = m_cb->getMeanSlice();
1251  std::vector<te::color::RGBAColor> upperColorVec = m_cb->getUpperMeanSlices(afterMean);
1252 
1253  for(size_t t = 0; t < lowerColorVec.size(); ++t)
1254  colorVec.push_back(lowerColorVec[t]);
1255 
1256  colorVec.push_back(meanColor);
1257 
1258  for(size_t t = 0; t < upperColorVec.size(); ++t)
1259  colorVec.push_back(upperColorVec[t]);
1260  }
1261 
1262  if (colorVec.size() != m_rules.size())
1263  return;
1264 
1265  int geomType = getGeometryType();
1266 
1267  for(size_t t = 0; t < colorVec.size(); ++t)
1268  {
1269  std::vector<te::se::Symbolizer*> symbVec;
1270 
1271  te::se::Symbolizer* s = te::se::CreateSymbolizer((te::gm::GeomType)geomType, colorVec[t].getColor());
1272 
1273  symbVec.push_back(s);
1274 
1275  m_rules[t]->setSymbolizers(symbVec);
1276  }
1277 }
1278 
1280 {
1281  QString curValue = m_ui->m_attrComboBox->currentText();
1282 
1283  m_ui->m_attrComboBox->clear();
1284 
1285  std::unique_ptr<te::map::LayerSchema> dsType(m_layer->getSchema());
1286 
1287  //grouping type
1288  int index = m_ui->m_typeComboBox->currentIndex();
1289  int type = m_ui->m_typeComboBox->itemData(index).toInt();
1290 
1291  if(type == te::map::EQUAL_STEPS ||type == te::map::QUANTIL || type == te::map::STD_DEVIATION)
1292  {
1293  for(size_t t = 0; t < dsType->getProperties().size(); ++t)
1294  {
1295  te::dt::Property* p = dsType->getProperty(t);
1296 
1297  int dataType = p->getType();
1298 
1299  switch(dataType)
1300  {
1301  case te::dt::INT16_TYPE:
1302  case te::dt::INT32_TYPE:
1303  case te::dt::INT64_TYPE:
1304  case te::dt::FLOAT_TYPE:
1305  case te::dt::DOUBLE_TYPE:
1306  case te::dt::NUMERIC_TYPE:
1307  m_ui->m_attrComboBox->addItem(p->getName().c_str(), p->getType());
1308 
1309  default:
1310  continue;
1311  }
1312  }
1313  }
1314  else if(type == te::map::UNIQUE_VALUE)
1315  {
1316  for(size_t t = 0; t < dsType->getProperties().size(); ++t)
1317  {
1318  te::dt::Property* p = dsType->getProperty(t);
1319 
1320  int dataType = p->getType();
1321 
1322  switch(dataType)
1323  {
1324  case te::dt::INT16_TYPE:
1325  case te::dt::INT32_TYPE:
1326  case te::dt::INT64_TYPE:
1327  case te::dt::FLOAT_TYPE:
1328  case te::dt::DOUBLE_TYPE:
1329  case te::dt::NUMERIC_TYPE:
1330  case te::dt::STRING_TYPE:
1331  m_ui->m_attrComboBox->addItem(p->getName().c_str(), p->getType());
1332 
1333  default:
1334  continue;
1335  }
1336  }
1337  }
1338 
1339  if(curValue.isEmpty() == false)
1340  {
1341  int idx = m_ui->m_attrComboBox->findText(curValue);
1342 
1343  if(idx != -1)
1344  m_ui->m_attrComboBox->setCurrentIndex(idx);
1345  }
1346 }
1347 
1348 void te::qt::widgets::GroupingWidget::setLayers(te::map::AbstractLayerPtr selectedLayer, std::vector<te::map::AbstractLayerPtr> allLayers)
1349 {
1350  m_layer = selectedLayer;
1351 
1352  //set data type
1353  setDataSetType();
1354 
1355  //set grouping
1356  setGrouping();
1357 
1358  //Adjusting summary options
1359  m_ui->m_summaryComboBox->clear();
1360  if(te::da::HasLinkedTable(m_layer->getSchema().get()))
1361  {
1362  m_ui->m_summaryComboBox->addItem("MIN");
1363  m_ui->m_summaryComboBox->addItem("MAX");
1364  m_ui->m_summaryComboBox->addItem("SUM");
1365  m_ui->m_summaryComboBox->addItem("AVERAGE");
1366  m_ui->m_summaryComboBox->addItem("MEDIAN");
1367  m_ui->m_summaryComboBox->addItem("STDDEV");
1368  m_ui->m_summaryComboBox->addItem("VARIANCE");
1369  m_ui->m_summaryComboBox->addItem("NONE");
1370 
1371  if (m_layer->getGrouping())
1372  {
1373  int index = m_ui->m_summaryComboBox->findText(QString::fromUtf8(m_layer->getGrouping()->getSummary().c_str()));
1374  m_ui->m_summaryComboBox->setCurrentIndex(index);
1375  }
1376 
1377  m_ui->m_summaryComboBox->setEnabled(true);
1378  m_ui->m_summaryComboBox->show();
1379  m_ui->m_summaryLabel->show();
1380  }
1381  else
1382  {
1383  m_ui->m_summaryComboBox->addItem("NONE");
1384  m_ui->m_summaryComboBox->setEnabled(false);
1385  m_ui->m_summaryComboBox->hide();
1386  m_ui->m_summaryLabel->hide();
1387  }
1388 
1389  for(std::size_t i = 0; i < allLayers.size(); ++i)
1390  {
1391  if(!allLayers[i]->isValid())
1392  continue;
1393 
1394  std::unique_ptr<te::da::DataSetType> dt(allLayers[i]->getSchema());
1395 
1396  if(dt->hasGeom() && allLayers[i]->getGrouping() && allLayers[i]->getId() != selectedLayer->getId())
1397  {
1398  m_ui->m_layersComboBox->addItem(allLayers[i]->getTitle().c_str(), QVariant::fromValue(allLayers[i]));
1399  }
1400  }
1401 }
1402 
1404 {
1405  if(m_ui->m_layersComboBox->currentText() == "")
1406  {
1407  QMessageBox::warning(this, tr("Grouping"), tr("There are no other layers with Grouping!"));
1408  return;
1409  }
1410 
1411  if(m_manual)
1412  {
1413  int reply = QMessageBox::question(this, tr("Grouping"), tr("Manual changes will be lost. Continue?"), QMessageBox::Yes | QMessageBox::Cancel);
1414 
1415  if(reply != QMessageBox::Yes)
1416  return;
1417  }
1418 
1419  QVariant varLayer = m_ui->m_layersComboBox->itemData(m_ui->m_layersComboBox->currentIndex(), Qt::UserRole);
1420  te::map::AbstractLayerPtr layer = varLayer.value<te::map::AbstractLayerPtr>();
1421 
1422  te::map::Grouping* ref = layer->getGrouping();
1423 
1424  std::unique_ptr<te::da::DataSetType> dt = m_layer->getSchema();
1425 
1426  std::vector<te::dt::Property*> props = dt->getProperties();
1427 
1428  bool isValid = false;
1429  for(std::size_t i = 0; i < props.size(); ++i)
1430  {
1431  te::dt::Property* prop = props[i];
1432  if((te::common::Convert2UCase(prop->getName()) == te::common::Convert2UCase(ref->getPropertyName())) && (prop->getType() == ref->getPropertyType()))
1433  {
1434  isValid = true;
1435  break;
1436  }
1437  }
1438 
1439  if(!isValid)
1440  {
1441  QString err = tr("There is no grouping that can be imported!\nThe layer must have an attribute with the same name of the attribute used to make the reference layer grouping: ");
1442  err.append(ref->getPropertyName().c_str());
1443  QMessageBox::warning(this, tr("Grouping"), err);
1444  return;
1445  }
1446 
1447  te::map::Grouping* newGrouping = new te::map::Grouping(*ref);
1448 
1449  setGrouping(newGrouping, layer->getStyle());
1450 
1451  updateUi(true);
1452 
1453  m_manual = false;
1454 
1455  emit applyPushButtonClicked();
1456 }
1457 
1459 {
1460  QString fileName = QFileDialog::getOpenFileName(this, tr("Open..."),
1461  QString(), tr("LEG (*.leg *.LEG);;"), nullptr, QFileDialog::DontConfirmOverwrite);
1462 
1463  if (fileName.isEmpty())
1464  return;
1465 
1466  m_ui->m_tableWidget->setRowCount(0);
1467 
1468  boost::property_tree::ptree pt;
1469 
1470  try
1471  {
1472  boost::property_tree::json_parser::read_json(fileName.toUtf8().data(), pt);
1473 
1474  try
1475  {
1476  boost::property_tree::ptree legend = pt.get_child("Legend");
1477 
1478  std::string attrName = legend.get<std::string>("Attribute");
1479  std::string precision = legend.get<std::string>("Precision");
1480  std::string catalog = legend.get<std::string>("Catalog");
1481  std::string group = legend.get<std::string>("Group");
1482  std::string schema = legend.get<std::string>("Schema");
1483 
1484  if(!m_ui->m_attrComboBox->findText(attrName.c_str()))
1485  {
1486  QMessageBox::warning(this, tr("Grouping"), tr("Attribute not found."));
1487  return;
1488  }
1489 
1490  m_ui->m_attrComboBox->setCurrentIndex(m_ui->m_attrComboBox->findText(attrName.c_str()));
1491  m_ui->m_precSpinBox->setValue(boost::lexical_cast<double>(precision));
1492 
1494 
1495  m_colorBar->setCatalog(catalog);
1496  m_colorBar->setGroup(group);
1497  m_colorBar->setSchema(schema);
1498 
1499  std::vector<std::vector<std::string> > items;
1500 
1501  for(boost::property_tree::ptree::value_type &v: legend.get_child("Items"))
1502  {
1503  std::vector<std::string> item;
1504  item.push_back(v.second.get<std::string>("Title"));
1505  item.push_back(v.second.get<std::string>("Min"));
1506  item.push_back(v.second.get<std::string>("Max"));
1507  item.push_back(v.second.get<std::string>("R"));
1508  item.push_back(v.second.get<std::string>("G"));
1509  item.push_back(v.second.get<std::string>("B"));
1510 
1511  items.push_back(item);
1512  }
1513 
1514  m_ui->m_tableWidget->setRowCount(items.size());
1515 
1516  for (std::size_t i = 0; i < items.size(); ++i)
1517  {
1518  m_ui->m_tableWidget->setItem(i, 1, new QTableWidgetItem(items[i][0].c_str()));
1519  m_ui->m_tableWidget->setItem(i, 2, new QTableWidgetItem(items[i][1].c_str()));
1520  m_ui->m_tableWidget->setItem(i, 3, new QTableWidgetItem(items[i][2].c_str()));
1521 
1522  QColor color;
1523  color.setRgb(boost::lexical_cast<int>(items[i][3]), boost::lexical_cast<int>(items[i][4]), boost::lexical_cast<int>(items[i][5]));
1524 
1525  QPixmap pix(24, 24);
1526  QPainter p(&pix);
1527 
1528  p.fillRect(0, 0, 12, 24, color);
1529  p.fillRect(12, 0, 12, 24, color);
1530  p.setBrush(Qt::transparent);
1531  p.setPen(Qt::black);
1532  p.drawRect(0, 0, 23, 23);
1533 
1534  QIcon icon(pix);
1535 
1536  QTableWidgetItem* item = new QTableWidgetItem(icon, "");
1537  item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
1538  m_ui->m_tableWidget->setItem(i, 0, item);
1539 
1540  }
1541  }
1542  catch(boost::property_tree::ptree_error& e)
1543  {
1544  QMessageBox::warning(this, tr("Grouping"), tr("Attribute not found."));
1545  return;
1546  }
1547  }
1548  catch(boost::property_tree::json_parser::json_parser_error& e)
1549  {
1550  QMessageBox::warning(this, tr("Grouping"), tr("Invalid file"));
1551  return;
1552  }
1553 }
1554 
1556 {
1557  QString fileName = QFileDialog::getSaveFileName(this, tr("Save as..."),
1558  QString(), tr("LEG (*.leg *.LEG);;"), nullptr, QFileDialog::DontConfirmOverwrite);
1559 
1560  saveLegend(fileName.toUtf8().data());
1561 }
1562 
1563 void te::qt::widgets::GroupingWidget::saveLegend(const std::string& path)
1564 {
1565  int rowCount = m_ui->m_tableWidget->rowCount();
1566 
1567  if (rowCount < 1)
1568  return;
1569 
1570  if (path.empty())
1571  return;
1572 
1573  boost::property_tree::ptree pt;
1574  boost::property_tree::ptree legend;
1575 
1576  std::string attrName = m_ui->m_attrComboBox->currentText().toUtf8().data();
1577  std::string precision = m_ui->m_precSpinBox->text().toUtf8().data();
1578  std::string catalog = m_colorBar->getCatalog();
1579  std::string group = m_colorBar->getGroup();
1580  std::string schema = m_colorBar->getSchema();
1581 
1582  legend.add("Attribute", attrName);
1583  legend.add("Precision", precision);
1584  legend.add("Catalog", catalog);
1585  legend.add("Group", group);
1586  legend.add("Schema", schema);
1587 
1588  boost::property_tree::ptree items;
1589 
1590  for (int i = 0; i < m_ui->m_tableWidget->rowCount(); ++i)
1591  {
1592  std::string title = m_ui->m_tableWidget->item(i, 1)->text().toUtf8().data();
1593  std::string min = m_ui->m_tableWidget->item(i, 2)->text().toUtf8().data();
1594  std::string max = m_ui->m_tableWidget->item(i, 3)->text().toUtf8().data();
1595 
1596  te::se::Rule* rule = m_rules[i];
1597 
1598  const std::vector<te::se::Symbolizer*>& ss = rule->getSymbolizers();
1600  const te::se::Fill* fill = ps->getFill();
1602 
1603  boost::property_tree::ptree item;
1604  item.add("Title", title);
1605  item.add("Min", min);
1606  item.add("Max", max);
1607  item.add("R", color.getRed());
1608  item.add("G", color.getGreen());
1609  item.add("B", color.getBlue());
1610 
1611  items.add_child("Item", item);
1612  }
1613 
1614  legend.add_child("Items", items);
1615 
1616  pt.add_child("Legend", legend);
1617 
1618  boost::property_tree::write_json(path, pt);
1619 }
TEDATAACCESSEXPORT DataSourcePtr GetDataSource(const std::string &datasourceId, const bool opened=true)
Search for a data source with the informed id in the DataSourceManager.
std::vector< te::se::Rule * > m_rules
Grouping items.
void createStringNullGroupingItem(int count)
const Fill * getFill() const
Gets the Fill associates with the PolygonSymbolizer.
void setScaleVisible(bool flag)
Sets scale of color bar visibility.
void onTableWidgetItemChanged(QTableWidgetItem *item)
TESEEXPORT void GetColor(const te::se::Stroke *stroke, te::color::RGBAColor &color)
It gets the RGBA color from the Stroke element.
const double getStdDeviation() const
It gets the standard deviation used in the Standard Deviation grouping.
Definition: Grouping.cpp:119
GeomType
Each enumerated type is compatible with a Well-known Binary (WKB) type code.
A Description gives human-readable descriptive information for the object it is included within...
Definition: Description.h:56
The Style defines the styling that is to be applied to a geographic dataset (vector geometries or cov...
Definition: Style.h:65
A widget used to build a point symbolizer element.
int getRed() const
It returns the red component color value (a value from 0 to 255).
Definition: RGBAColor.h:307
A PolygonSymbolizer is used to draw a polygon (or other area-type geometries), including filling its ...
TESEEXPORT Symbolizer * CreateSymbolizer(const te::gm::GeomType &geomType)
Try creates an appropriate symbolizer based on given geometry type.
boost::shared_ptr< DataSource > DataSourcePtr
TEDATAACCESSEXPORT bool HasLinkedTable(te::da::DataSetType *type)
It checks if the datasettype has a linked table.
const size_t getPrecision() const
It gets the precision used for the property values.
Definition: Grouping.cpp:99
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.
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.
void setDescription(Description *d)
Definition: Rule.cpp:69
Rule * clone() const
It creates a new copy of this object.
Definition: Rule.cpp:184
#define PRECISION
std::string getPropertyName() const
It gets the property name whose values will be grouped.
Definition: Grouping.cpp:67
void setName(std::string *name)
Definition: Rule.cpp:58
void setSymbolizer(const te::se::PointSymbolizer *symb)
Sets a point symbolizer element to this widget.
TEMAPEXPORT te::gm::GeomType GetGeomType(const te::map::AbstractLayerPtr &layer)
It gets the geometry type of the given layer.
int getBlue() const
It returns the blue component color value (a value from 0 to 255).
Definition: RGBAColor.h:317
int getGreen() const
It returns the green component color value (a value from 0 to 255).
Definition: RGBAColor.h:312
const std::vector< te::color::RGBAColor > & getUpperMeanSlices(const int &n)
A widget used to build a line symbolizer element.
boost::ptr_vector< OrderByItem > OrderBy
A class that can be used to model an ORDER BY clause.
Definition: OrderBy.h:37
void GroupingByQuantil(std::string attrName, iterator begin, iterator end, int nSteps, std::vector< te::se::Rule * > &rules, int precision=0)
It groups the values defined by a range of iterators using the quantil algorithm. ...
std::string Convert2UCase(const std::string &value)
It converts a string to upper case.
Definition: StringUtils.h:168
A PointSymbolizer specifies the rendering of a graphic Symbolizer at a point.
te::da::Expression * getExpression(const te::fe::Filter *f)
It converts the OGC Filter Expression to a TerraLib Expression.
virtual ReturnType accept(VisitorType &guest) const =0
It call the visit method from the guest object.
A layer resulting from a query.
Definition: QueryLayer.h:50
static te::dt::Date ds(2010, 01, 01)
void GroupingByEqualSteps(std::string attrName, iterator begin, iterator end, int nSteps, std::vector< te::se::Rule * > &rules, int precision=0)
It groups the values defined by a range of iterators using the equal steps algorithm.
void setFilter(te::fe::Filter *f)
Definition: Rule.cpp:91
Q_DECLARE_METATYPE(te::map::AbstractLayerPtr) std
const te::fe::Filter * getFilter() const
Definition: Rule.cpp:97
It models a property definition.
Definition: Property.h:59
void setCatalog(const std::string &catalog)
This is an abstract class that models a query expression.
#define MAX_SLICES
Rule * getRule(std::size_t i) const
Definition: Style.cpp:105
const std::vector< Rule * > & getRules() const
Definition: Style.cpp:94
const std::vector< te::color::RGBAColor > & getLowerMeanSlices(const int &n)
te::se::Symbolizer * getSymbolizer() const
Gets the configured point symbolizer element.
This class contains the parameters needed for grouping the values of a Property.
Definition: Grouping.h:57
TEFEEXPORT void GetFilterStepValues(const te::fe::Filter *filter, std::string &valueMin, std::string &valueMax)
TEFEEXPORT te::fe::Filter * CreateFilterByStep(const std::string &attrName, const std::string &minValue, const std::string &maxValue)
TEFEEXPORT te::fe::Filter * CreateFilterByUniqueValue(const std::string &attrName, const std::string &value)
URI C++ Library.
Definition: Attributes.h:37
static te::dt::TimeDuration dt(20, 30, 50, 11)
void setTitle(const std::string &title)
Definition: Description.cpp:33
A visitor that converts a OGC Filter Expression to TerraLib Expression.
Definition: QueryEncoder.h:53
GroupingWidget(QWidget *parent=0, Qt::WindowFlags f=0)
Constructs a basic fill widget which is a child of parent, with widget flags set to f...
TEDATAACCESSEXPORT double GetSummarizedValue(std::vector< double > &values, const std::string &summary)
It gets the summarized value.
te::gm::Polygon * p
te::se::Symbolizer * getSymbolizer() const
Gets the configured line symbolizer element.
A Fill specifies the pattern for filling an area geometry.
Definition: Fill.h:59
te::da::Select * getQuery() const
Definition: QueryLayer.cpp:363
A filter is any valid predicate expression.
Definition: fe/Filter.h:55
Query * clone() const
It creates a new copy of this query.
Definition: Select.cpp:276
const te::color::RGBAColor & getMeanSlice()
void setSymbolizers(const std::vector< Symbolizer * > &symbs)
Definition: Rule.cpp:152
void setOrderBy(OrderBy *o)
It sets the list of expressions used to sort the output result.
Definition: Select.cpp:829
void buildSymbolizer(std::string meanTitle="")
te::map::AbstractLayerPtr m_layer
TerraLib layer auto ptr.
A Select models a query to be used when retrieving data from a DataSource.
Definition: Select.h:65
void saveLegend(const std::string &path)
A Symbology Enconding visitor that finds a color given a symbolizer element. If you want to use this ...
void initialize()
Internal method to initialize the widget (e.g.: color, combos, icons, etc.)
A widget used to build a polygon symbolizer element.
void onTableWidgetItemDoubleClicked(QTableWidgetItem *item)
const std::vector< te::color::RGBAColor > & getSlices(const int &n)
It generates color bar.
const std::vector< Symbolizer * > & getSymbolizers() const
Definition: Rule.cpp:158
void createDoubleNullGroupingItem(int count)
int getType() const
It returns the property data type.
Definition: Property.h:161
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.
GroupingType
The grouping type associated to the layer.
void setSchema(const std::string &schema)
void getLinkedDataAsString(std::vector< std::string > &vec, const std::string &attrName, int &nullValues)
void updateUi(bool loadColorBar=false)
Updates the widget form based on internal fill element.
A Rule is used to attach property/scale conditions to and group the individual symbols used for rende...
Definition: Rule.h:76
#define NO_TITLE
void setQuery(te::da::Select *s)
Definition: QueryLayer.cpp:390
void getLinkedDataAsDouble(std::vector< double > &vec, const std::string &attrName, const int &dataType, int &nullValues)
void getDataAsString(std::vector< std::string > &vec, const std::string &attrName, int &nullValues)
void setLayers(te::map::AbstractLayerPtr selectedLayer, std::vector< te::map::AbstractLayerPtr > allLayers)
A helper class for 32-bit RGBA (Red-Green-Blue-Alpha channel) color.
Definition: RGBAColor.h:57
const GroupingType getType() const
It gets the grouping type.
Definition: Grouping.cpp:89
void setSymbolizer(const te::se::PolygonSymbolizer *symb)
Sets a polygon symbolizer element to this widget.
te::color::ColorBar * getColorBar()
It returns the colorbar.
It models the concept of color bar.
void getDataAsDouble(std::vector< double > &vec, const std::string &attrName, const int &dataType, int &nullValues)
A widget used to build a grouping.
A LineSymbolizer is used to style a stroke along a linear geometry type, such as a string of line seg...
std::unique_ptr< te::map::Grouping > getGrouping()
A visitor for building an SQL statement from a given Query hierarchy.
const SvgParameter * getColor() const
Definition: Fill.cpp:76
te::qt::widgets::colorbar::ColorBar * getColorBar()
const size_t getNumSlices() const
It gets the number of slices used in the Equal Steps and Quantil groupings.
Definition: Grouping.cpp:109
void setColorBar(te::color::ColorBar *cb)
It sets the color bar.
void setGroup(const std::string &group)
std::unique_ptr< Ui::GroupingWidgetForm > m_ui
Widget form.
A class that can be used in an ORDER BY clause to sort the items of a resulting query.
Definition: OrderByItem.h:53
te::qt::widgets::ColorCatalogWidget * m_colorBar
Widget used to pick a color.
te::color::RGBAColor getColor()
Get the color.
te::color::ColorBar * m_cb
Terralib color bar objetc.
boost::intrusive_ptr< AbstractLayer > AbstractLayerPtr
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.
te::se::Symbolizer * getSymbolizer() const
Gets the configured polygon symbolizer element.
void setSymbolizer(const te::se::LineSymbolizer *symb)
Sets a line symbolizer element to this widget.
void GroupingByStdDeviation(std::string attrName, iterator begin, iterator end, double nDevs, std::vector< te::se::Rule * > &rules, std::string &meanTitle, int precision=0)
It groups the values defined by a range of iterators using the standard deviation algorithm...
static const std::string sm_nanStr
Not a number string value.
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