WtssDialog.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 National Institute For Space Research (INPE) - Brazil.
3 
4  This file is part of the TerraLib - a Framework for building GIS enabled
5  applications.
6 
7  TerraLib is free software: you can redistribute it and/or modify
8  it under the terms of the GNU Lesser General Public License as published by
9  the Free Software Foundation, either version 3 of the License,
10  or (at your option) any later version.
11 
12  TerraLib is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU Lesser General Public License for more details.
16 
17  You should have received a copy of the GNU Lesser General Public License
18  along with TerraLib. See COPYING. If not, write to
19  TerraLib Team at <terralib-team@terralib.org>.
20 */
21 
22 /*!
23  \file terralib/qt/plugins/wtss/WtssDialog.cpp
24 
25  \brief Configuration dialog for Web Time Series Services plugin.
26 
27  \author Matheus Cavassan Zaglia
28  */
29 
30 // TerraLib
31 #include "../../../maptools/MarkRendererManager.h"
32 #include "../../../se/Fill.h"
33 #include "../../../se/Mark.h"
34 #include "../../../se/Stroke.h"
35 #include "../../../se/Utils.h"
36 #include "../../widgets/tools/AbstractTool.h"
37 #include "../../widgets/tools/PointPicker.h"
38 #include "../../widgets/utils/ScopedCursor.h"
39 #include "../../widgets/Utils.h"
40 
41 // QT
42 #include <QFileDialog>
43 #include <QInputDialog>
44 #include <QMessageBox>
45 
46 //Qwt
47 #include <qwt_legend.h>
48 
49 // STL
50 #include <ctime>
51 #include <fstream>
52 
53 // Boost
54 #include <boost/format.hpp>
55 
56 // wtss.cxx
57 #include <wtss-cxx/wtss.hpp>
58 
59 #include "WtssDialog.h"
60 #include "Exception.h"
61 #include "ServerManager.h"
62 #include "ui_WtssDialogForm.h"
63 
64 namespace cxx = wtss::cxx;
65 
67  Qt::WindowFlags f)
68  : QDialog(parent, f),
69  m_ui(new Ui::WtssDialogForm),
70  dirty(false),
71  m_checkServer(0),
72  m_checkCoverage(0),
73  m_checkAttribute(0),
74  m_mapDisplay(nullptr),
75  m_chartDisplay(nullptr),
76  m_timeSeriesChartVec(0),
77  m_timeSeriesVec(0)
78 {
79  m_ui->setupUi(this);
80 
81  this->setWindowTitle(tr("Web Time Series Services"));
82 
83  m_ui->m_addToolButton->setIcon(QIcon::fromTheme("list-add"));
84  m_ui->m_removeToolButton->setIcon(QIcon::fromTheme("list-remove"));
85  m_ui->m_refreshToolButton->setIcon(QIcon::fromTheme("view-refresh"));
86  m_ui->m_hideToolButton->setIcon(QIcon::fromTheme("hide"));
87  m_ui->m_importToolButton->setIcon(QIcon::fromTheme("document-open"));
88  m_ui->m_exportToolButton->setIcon(QIcon::fromTheme("document-save-as"));
89  m_ui->m_queryToolButton->setIcon(QIcon::fromTheme("media-playback-start-green"));
90 
91  srand(time(nullptr));
92 
93  connect(m_ui->m_addToolButton, SIGNAL(clicked()), this,
94  SLOT(onServerAddButtonClicked()));
95  connect(m_ui->m_removeToolButton, SIGNAL(clicked()), this,
97  connect(m_ui->m_serverTreeWidget, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
98  this, SLOT(onItemChecked(QTreeWidgetItem *)));
99  connect(m_ui->m_helpPushButton, SIGNAL(clicked()), this, SLOT(onHelpButtonClicked()));
100  connect(m_ui->m_closePushButton, SIGNAL(clicked()), this, SLOT(close()));
101  connect(m_ui->m_hideToolButton, SIGNAL(clicked()), this,
102  SLOT(onHideButtonClicked()));
103  connect(m_ui->m_refreshToolButton, SIGNAL(clicked()), this,
105  connect(m_ui->m_importToolButton, SIGNAL(clicked()), this,
106  SLOT(onImportGraphClicked()));
107  connect(m_ui->m_exportToolButton, SIGNAL(clicked()), this,
108  SLOT(onExportGraphClicked()));
109  connect(m_ui->m_queryToolButton, SIGNAL(clicked()), this,
110  SLOT(onQueryButtonClicked()));
111  connect(m_ui->m_coordSListWidget, SIGNAL(itemClicked(QListWidgetItem *)),
112  this, SLOT(onAddCoordToList(QListWidgetItem *)));
113  connect(m_ui->m_pointToolButton, SIGNAL(toggled(bool)), this,
114  SLOT(onPointPickerToggled(bool)));
115 
116  loadSettings();
117 
118  dirty = true;
119 }
120 
122 
124  te::qt::widgets::MapDisplay *mapDisplay)
125 {
126  m_mapDisplay = mapDisplay;
127  m_pickerAction->setChecked(true);
128 }
129 
131 {
132  m_actionGroup = actionGroup;
134 }
135 
137 {
138  m_pickerAction = new QAction(this);
139  m_pickerAction->setIcon(QIcon::fromTheme("placemark"));
140  m_pickerAction->setToolTip(tr("Create by Point"));
141  m_pickerAction->setCheckable(true);
142  m_pickerAction->setEnabled(true);
143 
144  m_ui->m_pointToolButton->setDefaultAction(m_pickerAction);
145  m_ui->m_pointToolButton->setVisible(true);
146  m_actionGroup->addAction(m_ui->m_pointToolButton->defaultAction());
147 }
148 
150 {
151  dirty = false;
152 
153  QInputDialog *inputDialog = new QInputDialog();
154  inputDialog->setOptions(QInputDialog::NoButtons);
155 
156  bool accept;
157 
158  QString uri = inputDialog->getText(nullptr, "Add Server", "Server URI:",
159  QLineEdit::Normal, "", &accept);
160  if(!accept)
161  {
162  dirty = true;
163  return;
164  }
165 
166  if(!uri.isEmpty())
167  {
168  te::qt::widgets::ScopedCursor c(Qt::WaitCursor);
169 
170  try
171  {
173 
175  .loadSettings()
176  .object();
177 
178  addServer(uri);
179  }
180  catch(...)
181  {
182  QMessageBox::warning(this, tr("Web Time Series"),
183  tr("An error has occurred, "
184  "please retype the wtss "
185  "server address."));
186  }
187  }
188  else
189  {
190  QMessageBox::warning(this, tr("Web Time Series"),
191  tr("Please, input a server."));
192  }
193 
194  dirty = true;
195 }
196 
198 {
199  dirty = false;
200 
201  if(m_ui->m_serverTreeWidget->currentItem() &&
202  !m_ui->m_serverTreeWidget->currentItem()->parent())
203  {
204  QMessageBox::StandardButton reply = QMessageBox::question(
205  this, "Remove server",
206  "Remove '" + m_ui->m_serverTreeWidget->currentItem()->text(0) +
207  "' server?",
208  QMessageBox::Yes | QMessageBox::No);
209 
210  if(reply == QMessageBox::Yes)
211  {
212  try
213  {
215  m_ui->m_serverTreeWidget->currentItem()->text(0));
216 
218  .loadSettings()
219  .object();
220 
221  delete m_ui->m_serverTreeWidget->currentItem();
222 
224 
225  QMessageBox::information(this, tr("Web Time Series"),
226  tr("The server was removed with success."));
227  }
228  catch(...)
229  {
230  QMessageBox::warning(this, tr("Web Time Series"),
231  tr("An error has occurred, please try again."));
232  }
233  }
234  }
235  else
236  {
237  QMessageBox::warning(this, tr("Web Time Series"),
238  tr("Please, select a server."));
239  }
240 
241  dirty = true;
242 }
243 
245 {
246  dirty = false;
247  if(m_ui->m_serverTreeWidget->currentItem() &&
248  !m_ui->m_serverTreeWidget->currentItem()->parent())
249  {
250  try
251  {
252  QString uri = m_ui->m_serverTreeWidget->currentItem()->text(0);
253 
255 
256  delete m_ui->m_serverTreeWidget->currentItem();
257 
258  addServer(uri);
259  }
260  catch(...)
261  {
262  QMessageBox::warning(this, tr("Web Time Series"),
263  tr("An error has occurred, "
264  "please check server list."));
265  }
266  }
267  else
268  {
269  QMessageBox::warning(this, tr("Web Time Series"),
270  tr("Please, select a server."));
271  }
272 
273  dirty = true;
274 }
275 
277 {
278  if(dirty)
279  {
280  if(item->type() == treeItemType::attribute)
281  {
282  QString serverUri = item->parent()->parent()->text(0);
283  QString cvName = item->parent()->text(0);
284  QString attribute = item->text(0);
285 
287  .changeStatusAttribute(serverUri, cvName, attribute);
288 
289  if(!m_timeSeriesChartVec.empty())
290  {
291  bool attributeChecked = false;
292 
293  for(int i = 0; i < item->parent()->parent()->childCount(); ++i)
294  {
295  QTreeWidgetItem *attributeItem = item->parent()->child(i);
296  if(attributeItem->text(0) != attribute)
297  {
298  if(attributeItem->checkState(0))
299  {
300  attributeChecked = true;
301 
302  for(int j = 0; j < m_timeSeriesChartVec.size(); ++j)
303  {
304  if(attribute.toUtf8().data() ==
305  std::string(
306  m_timeSeriesChartVec.at(j)->getTimeSeries()->getId()))
307  {
308  m_timeSeriesChartVec.at(j)->detach();
309  m_timeSeriesChartVec.removeAt(j);
310  }
311  }
312  }
313  }
314  }
315 
316  if(!attributeChecked)
317  {
319  m_timeSeriesChartVec.clear();
320  }
321  }
322  }
323  else if(item->type() == treeItemType::coverage)
324  {
325  QString serverUri = item->parent()->text(0);
326  QString cvName = item->text(0);
328  serverUri, cvName);
329  dirty = false;
330  for(int i = 0; i < item->parent()->childCount(); ++i)
331  {
332  QTreeWidgetItem *cv = item->parent()->child(i);
333  if(cv->text(0) != cvName)
334  {
335  if(cv->checkState(0))
336  cv->setCheckState(0, Qt::Unchecked);
337  }
338  }
339  dirty = true;
340  }
341  else if(item->type() == treeItemType::server)
342  {
343  QString serverUri = item->text(0);
344 
346  serverUri);
347  dirty = false;
348  int size = m_ui->m_serverTreeWidget->topLevelItemCount();
349  for(int i = 0; i < size; ++i)
350  {
351  QTreeWidgetItem *sv = m_ui->m_serverTreeWidget->topLevelItem(i);
352  QString server = sv->text(0);
353  if(server != serverUri)
354  sv->setCheckState(0, Qt::Unchecked);
355  }
356  dirty = true;
357  }
358  }
359 }
360 
362 {
363  if(m_ui->m_serverFrame->isVisible())
364  {
365  m_ui->m_serverFrame->hide();
366  m_ui->m_hideToolButton->setIcon(QIcon::fromTheme("show"));
367  }
368  else
369  {
370  m_ui->m_serverFrame->show();
371  m_ui->m_hideToolButton->setIcon(QIcon::fromTheme("hide"));
372  }
373 }
374 
376 {
377 }
378 
380 {
381  QString csvFile =
382  QFileDialog::getOpenFileName(this, tr("Select a TimeSeries CSV file"),
383  te::qt::widgets::GetFilePathFromSettings("timeseriescsv"), "CSV file (*.csv)");
384 
385  if(csvFile.isEmpty())
386  return;
387 
388  QFileInfo file(csvFile);
389 
390  te::qt::widgets::AddFilePathToSettings(file.absolutePath(), "timeseriescsv");
391 
392  std::ifstream csv(csvFile.toUtf8().data());
393 
394  std::string str;
395  std::getline(csv, str);
396 
397  m_timeSeriesVec.clear();
398 
399  m_timeSeriesVec.push_back(
400  new te::st::TimeSeries(file.completeBaseName().toUtf8().data()));
401 
402  while(std::getline(csv, str))
403  {
404  QString qstr = QString::fromUtf8(str.c_str());
405  QStringList fields = qstr.split(',');
406  QStringList date = fields.front().split("/");
407 
408  te::dt::DateTime *time = new te::dt::Date(boost::gregorian::date(
409  date.at(2).toInt(), date.at(1).toInt(), date.at(0).toInt()));
410 
411  double value = fields.back().toDouble();
412 
413  m_timeSeriesVec.back()->add(time, value);
414  }
415  plotTimeSeries();
416 }
417 
419 {
420  if(m_result.query.attributes.empty())
421  return;
422 
423  QString cvName(QString::fromUtf8(m_result.coverage.name.c_str()));
424 
425  std::vector<cxx::queried_attribute_t> attributes =
426  m_result.coverage.queried_attributes;
427 
428  for(unsigned int i = 0; i < attributes.size(); i++)
429  {
430  cxx::queried_attribute_t attribute = attributes[i];
431 
432  QString csvFile = QFileDialog::getSaveFileName(
433  this, tr("Save File"),
434  te::qt::widgets::GetFilePathFromSettings("timeseriescsv") + "/" +
435  "long" + m_ui->m_longLineEdit->text() + "_" + "lat" +
436  m_ui->m_latLineEdit->text() + "_" + attribute.name.c_str() + ".csv",
437  "CSV file (*.csv)");
438 
439  if(csvFile.isEmpty())
440  return;
441 
442  QFileInfo info(csvFile);
443 
444  te::qt::widgets::AddFilePathToSettings(info.absolutePath(), "timeseriescsv");
445 
446  if(info.suffix().isEmpty())
447  csvFile.append(".csv");
448 
449  std::ofstream myfile(csvFile.toUtf8().data());
450 
451  myfile << "Timeline,Value" << std::endl;
452 
453  for(unsigned int j = 0; j < attribute.values.size(); ++j)
454  {
455  QJsonObject j_attribute =
457  QString::fromUtf8(m_lastQueriedServer.c_str()), cvName,
458  QString::fromUtf8(attribute.name.c_str()));
459 
460  cxx::date d = m_result.coverage.timeline[j];
461 
462  double value =
463  attribute.values[j] * j_attribute["scale_factor"].toDouble();
464 
465  myfile << d.day << "/" << d.month << "/" << d.year << "," << value
466  << std::endl;
467  }
468  myfile.close();
469  }
470 }
471 
473 {
474  cxx::timeseries_query_t query;
475 
476  if(m_ui->m_latLineEdit->text().isEmpty() &&
477  m_ui->m_longLineEdit->text().isEmpty())
478  {
479  QMessageBox::warning(this, tr("Web Time Series"),
480  tr("Input the latitude and longitude coordinate."));
481  return;
482  }
483  else if(m_ui->m_latLineEdit->text().isEmpty())
484  {
485  QMessageBox::warning(this, tr("Web Time Series"),
486  tr("Input the latitude coordinate."));
487  return;
488  }
489  else if(m_ui->m_longLineEdit->text().isEmpty())
490  {
491  QMessageBox::warning(this, tr("Web Time Series"),
492  tr("Input the longitude coordinate."));
493  return;
494  }
495 
496  query.latitude = m_ui->m_latLineEdit->text().toDouble();
497  query.longitude = m_ui->m_longLineEdit->text().toDouble();
498 
499  QDate startDate = m_ui->m_startDateEdit->date();
500  QDate endDate = m_ui->m_endDateEdit->date();
501 
502  if(!startDate.operator<=(endDate))
503  {
504  QMessageBox::warning(this, tr("Web Time Series"),
505  tr("The date informed is invalid."));
506  return;
507  }
508 
510  startDate.toString("dd/MM/yyyy"), endDate.toString("dd/MM/yyyy"));
511 
512  query.start_date = startDate.toString("yyyy-MM-dd").toUtf8().data();
513  query.end_date = endDate.toString("yyyy-MM-dd").toUtf8().data();
514 
515  doTimeseriesQuery(query);
516 
517  addMarker(query.longitude, query.latitude);
518 }
519 
521  QListWidgetItem *coordSelected)
522 {
523  cxx::timeseries_query_t query;
524 
525  //Get coordinate
526  QStringList selectedCoord = coordSelected->text().split(",");
527 
528  query.longitude = selectedCoord.front().toDouble();
529  query.latitude = selectedCoord.back().toDouble();
530 
531  //Get date
532  QDate startDate = m_ui->m_startDateEdit->date();
533  QDate endDate = m_ui->m_endDateEdit->date();
534 
535  if(!startDate.operator<=(endDate))
536  {
537  QMessageBox::warning(this, tr("Web Time Series"),
538  tr("The date informed is invalid."));
539  return;
540  }
541 
543  startDate.toString("dd/MM/yyyy"), endDate.toString("dd/MM/yyyy"));
544 
545  query.start_date = startDate.toString("yyyy-MM-dd").toUtf8().data();
546  query.end_date = endDate.toString("yyyy-MM-dd").toUtf8().data();
547 
548  doTimeseriesQuery(query);
549 
550  std::unique_ptr<te::srs::Converter> converter(new te::srs::Converter());
551 
552  converter->setSourceSRID(4326);
553  converter->setTargetSRID(m_mapDisplay->getSRID());
554 
555  te::gm::Coord2D coord;
556 
557  converter->convert(query.longitude, query.latitude, coord.x, coord.y);
558 
559  const te::gm::Envelope& currEnv = m_mapDisplay->getExtent();
560 
561  double auxX = (currEnv.m_urx - currEnv.m_llx) / 2;
562  double auxY = (currEnv.m_ury - currEnv.m_lly) / 2;
563 
564  te::gm::Envelope env;
565 
566  env.m_llx = coord.x - auxX;
567  env.m_lly = coord.y - auxY;
568  env.m_urx = coord.x + auxX;
569  env.m_ury = coord.y + auxY;
570 
571  m_mapDisplay->setExtent(env, true);
572 
573  addMarker(query.longitude, query.latitude);
574 }
575 
577 {
578  std::unique_ptr<te::srs::Converter> converter(new te::srs::Converter());
579 
580  try
581  {
582  converter->setSourceSRID(m_mapDisplay->getSRID());
583  converter->setTargetSRID(4326);
584  }
585  catch(...)
586  {
587  QMessageBox::warning(this, tr("Web Time Series"), tr("The display SRS is unknown."));
588  return;
589  }
590 
591  te::gm::Coord2D c;
592 
593  converter->convert(coord.x(), coord.y(), c.x, c.y);
594 
595  cxx::timeseries_query_t query;
596 
597  query.longitude = c.x;
598  query.latitude = c.y;
599 
600  QDate startDate = m_ui->m_startDateEdit->date();
601  QDate endDate = m_ui->m_endDateEdit->date();
602 
603  if(!startDate.operator <=(endDate))
604  {
605  QMessageBox::warning(this, tr("Web Time Series"),
606  tr("The date informed is invalid."));
607  return;
608  }
609 
611  startDate.toString("dd/MM/yyyy"), endDate.toString("dd/MM/yyyy"));
612 
613  query.start_date = startDate.toString("yyyy-MM-dd").toUtf8().data();
614  query.end_date = endDate.toString("yyyy-MM-dd").toUtf8().data();
615 
616  if(m_ui->m_serverTreeWidget->topLevelItemCount() > 0)
617  {
618  doTimeseriesQuery(query);
619 
620  addMarker(query.longitude, query.latitude);
621  }
622 }
623 
625 {
626  if(!checked)
627  return;
628 
629  if(!m_actionGroup->actions().contains(m_pickerAction))
630  m_actionGroup->addAction(m_ui->m_pointToolButton->defaultAction());
631 
634 
635  connect(pp, SIGNAL(pointPicked(QPointF&)), this, SLOT(onGetPointCoordinate(QPointF&)));
636 }
637 
639 {
640  try
641  {
642  //Define chartStyle
644  chartStyle->setTitle(QString::fromUtf8("Web Time Series"));
645  chartStyle->setAxisX(QString::fromUtf8("Timeline"));
646  chartStyle->setAxisY(QString::fromUtf8("Value"));
647 
649  m_ui->m_timeSeriesFrame, QString::fromUtf8("Web Time Series"),
650  chartStyle);
651 
652  QGridLayout *m_layout = new QGridLayout(m_ui->m_timeSeriesFrame);
653  m_layout->addWidget(m_chartDisplay, 0, 0);
654  m_layout->setContentsMargins(0, 0, 0, 0);
655 
656  //Define marker
657  te::se::Stroke *stroke = te::se::CreateStroke("#000000", "1");
658  te::se::Fill *fill = te::se::CreateFill("#000000", "1.0");
659  te::se::Mark* marker = te::se::CreateMark("cross", stroke, fill);
660  m_rgbaMarker =
661  te::map::MarkRendererManager::getInstance().render(marker, 12);
662 
663  //Get server settings
665  .loadSettings()
666  .object();
667 
668  QJsonObject j_servers = j_config.find("servers").value().toObject();
669 
670  if(j_servers.isEmpty())
671  return;
672 
673  for(QJsonObject::iterator it = j_servers.begin(); it != j_servers.end(); ++it)
674  addServer(it.key());
675 
676  //Get date settings
677  QJsonObject j_datefilter = j_config.find("date_filter").value().toObject();
678 
679  if(j_datefilter.isEmpty())
680  return;
681 
682  QString startDate = j_datefilter.find("start_date").value().toString();
683 
684  QString endDate = j_datefilter.find("end_date").value().toString();
685 
686  m_ui->m_startDateEdit->setDate(QDate::fromString(startDate, "dd/MM/yyyy"));
687 
688  m_ui->m_endDateEdit->setDate(QDate::fromString(endDate, "dd/MM/yyyy"));
689  }
690  catch(...)
691  {
692  QMessageBox::warning(this, tr("Web Time Series"),
693  tr("An error has occurred, "
694  "when try to load settings."));
695  }
696 }
697 
699 {
700  QJsonObject j_servers = j_config.find("servers").value().toObject();
701 
702  QJsonObject j_server = j_servers.find(server).value().toObject();
703 
704  QTreeWidgetItem *serverItem =
705  new QTreeWidgetItem(m_ui->m_serverTreeWidget, treeItemType::server);
706 
707  serverItem->setText(0, server);
708 
709  serverItem->setFlags(serverItem->flags() | Qt::ItemIsUserCheckable);
710 
711  bool active = j_server.find("active").value().toBool();
712 
713  if(active)
714  serverItem->setCheckState(0, Qt::Checked);
715  else
716  serverItem->setCheckState(0, Qt::Unchecked);
717 
718  addCoverage(serverItem, j_server);
719 }
720 
722  QTreeWidgetItem *serverItem, QJsonObject j_server)
723 {
724  QJsonObject j_coverages = j_server["coverages"].toObject();
725 
726  for(QJsonObject::iterator it = j_coverages.begin(); it != j_coverages.end();
727  it++)
728  {
729  bool active = it.value().toObject().find("active").value().toBool();
730  QTreeWidgetItem *coverageItem =
732 
733  coverageItem->setText(0, it.key());
734 
735  coverageItem->setFlags(coverageItem->flags() | Qt::ItemIsUserCheckable);
736 
737  if(active)
738  coverageItem->setCheckState(0, Qt::Checked);
739  else
740  coverageItem->setCheckState(0, Qt::Unchecked);
741 
742  serverItem->addChild(coverageItem);
743 
744  addAtributes(coverageItem, it.value().toObject());
745  }
746 }
747 
749  QTreeWidgetItem *coverageItem, QJsonObject j_coverage)
750 {
751  QJsonObject j_attributes = j_coverage.find("attributes").value().toObject();
752 
753  for(QJsonObject::iterator it = j_attributes.begin(); it != j_attributes.end();
754  it++)
755  {
756  QString attribute = it.key();
757 
758  bool active = it.value().toObject().find("active").value().toBool();
759  QTreeWidgetItem *attributeItem =
761 
762  attributeItem->setText(0, attribute);
763  attributeItem->setFlags(attributeItem->flags() | Qt::ItemIsUserCheckable);
764 
765  if(active)
766  attributeItem->setCheckState(0, Qt::Checked);
767  else
768  attributeItem->setCheckState(0, Qt::Unchecked);
769 
770  coverageItem->addChild(attributeItem);
771  }
772 }
773 
775 {
776  if(!m_checkServer)
777  {
778  QMessageBox::warning(this, tr("Web Time Series"),
779  tr("Please, select a server"));
780  return false;
781  }
782  if(!m_checkCoverage)
783  {
784  QMessageBox::warning(this, tr("Web Time Series"),
785  tr("Please, select a coverage."));
786  return false;
787  }
788  if(!m_checkAttribute)
789  {
790  QMessageBox::warning(this, tr("Web Time Series"),
791  tr("Please, select an attribute."));
792  return false;
793  }
794 
795  return true;
796 }
797 
799  cxx::timeseries_query_t query)
800 {
801  clearCanvas();
802 
803  m_ui->m_latLineEdit->setText(QString::number(query.latitude));
804  m_ui->m_longLineEdit->setText(QString::number(query.longitude));
805 
806  te::qt::widgets::ScopedCursor c(Qt::WaitCursor);
807 
809  .loadSettings()
810  .object();
811 
812  if(j_object.isEmpty())
813  return;
814 
815  QJsonObject j_servers = j_object.find("servers").value().toObject();
816 
817  QJsonObject j_server;
818 
819  m_checkServer = false;
820  m_checkCoverage = false;
821  m_checkAttribute = false;
822 
823  for(QJsonObject::iterator it_server = j_servers.begin();
824  it_server != j_servers.end(); ++it_server)
825  {
826  j_server = it_server.value().toObject();
827 
828  if(j_server.find("active").value().toBool())
829  {
830  std::string serverUri = it_server.key().toStdString();
831 
832  QJsonObject j_coverages = j_server["coverages"].toObject();
833 
834  for(QJsonObject::iterator it_coverages = j_coverages.begin();
835  it_coverages != j_coverages.end(); it_coverages++)
836  {
837  if(it_coverages.value().toObject().find("active").value().toBool())
838  {
839  cxx::timeseries_query_t new_q;
840 
841  new_q.latitude = query.latitude;
842  new_q.longitude = query.longitude;
843  new_q.coverage_name = it_coverages.key().toUtf8().data();
844  new_q.start_date = query.start_date;
845  new_q.end_date = query.end_date;
846 
847  QJsonObject j_attributes = it_coverages.value()
848  .toObject()
849  .find("attributes")
850  .value()
851  .toObject();
852 
853  for(QJsonObject::iterator it_attributes = j_attributes.begin();
854  it_attributes != j_attributes.end(); it_attributes++)
855  {
856  QJsonObject j_attribute = it_attributes.value().toObject();
857 
858  if(j_attribute["active"].toBool() == true)
859  {
860  new_q.attributes.push_back(it_attributes.key().toUtf8().data());
861  m_checkAttribute = true;
862  }
863  }
864 
865  if(new_q.attributes.size() > 0)
866  {
867  cxx::client remote(serverUri);
868 
869  try
870  {
871  m_result = remote.time_series(new_q);
872  m_lastQueriedServer = it_server.key().toUtf8().data();
874  }
875  catch(const std::exception&)
876  {
877  QMessageBox::warning(this, tr("Web Time Series"),
878  tr("The coordinates "
879  "informed are invalid."));
880  return;
881  }
882  }
883  m_checkCoverage = true;
884  }
885  }
886  m_checkServer = true;
887  }
888  }
889 
890  if(!validateQuery())
891  {
893  return;
894  }
895 
896  addLocation(query.longitude, query.latitude);
897 
898  plotTimeSeries();
899 }
900 
902  cxx::timeseries_query_result_t result)
903 {
904  QString cvName(QString::fromUtf8(result.coverage.name.c_str()));
905 
906  std::vector<cxx::queried_attribute_t> attributes =
907  result.coverage.queried_attributes;
908 
909  m_timeSeriesVec.clear();
910 
911  for(unsigned int i = 0; i < attributes.size(); i++)
912  {
913  cxx::queried_attribute_t attribute = attributes[i];
914 
915  m_timeSeriesVec.push_back(new te::st::TimeSeries(attribute.name));
916 
917  for(unsigned int j = 0; j < attribute.values.size(); ++j)
918  {
919  QJsonObject j_attribute =
921  QString::fromUtf8(m_lastQueriedServer.c_str()), cvName,
922  QString::fromUtf8(attribute.name.c_str()));
923 
924  cxx::date d = result.coverage.timeline[j];
925  te::dt::DateTime *time =
926  new te::dt::Date(boost::gregorian::date(d.year, d.month, d.day));
927 
928  double value =
929  attribute.values[j] * j_attribute["scale_factor"].toDouble();
930 
931  m_timeSeriesVec.at(i)->add(time, value);
932  }
933  }
934 }
935 
937 {
938  if(m_timeSeriesVec.empty())
939  return;
940 
941  for(unsigned int i = 0; i < m_timeSeriesVec.size(); ++i)
942  {
943  te::qt::widgets::TimeSeriesChart* timeSeriesChart =
945 
946  timeSeriesChart->setTitle(tr(m_timeSeriesVec.at(i)->getId().c_str()));
947 
948  if(!m_timeSeriesChartVec.empty())
949  {
950  for(int j = 0; j < m_timeSeriesChartVec.size(); ++j)
951  {
952  if(std::string(m_timeSeriesVec.at(i)->getId()) ==
953  std::string(m_timeSeriesChartVec.at(j)->getTimeSeries()->getId()))
954  {
955  m_timeSeriesChartVec.at(j)->detach();
956  m_timeSeriesChartVec.removeAt(j);
957  }
958  }
959  }
960 
961  m_timeSeriesChartVec.push_back(timeSeriesChart);
962  }
963 
964  for(int i = 0; i < m_timeSeriesChartVec.size(); ++i)
965  {
966  m_timeSeriesChartVec.at(i)->setPen(QPen(randomColor()));
967  m_timeSeriesChartVec.at(i)->attach(m_chartDisplay);
968 
969  m_chartDisplay->insertLegend(new QwtLegend(), QwtPlot::RightLegend);
971  m_chartDisplay->show();
972  }
973 }
974 
976 {
977  const te::gm::Envelope &env = m_mapDisplay->getExtent();
978 
980 
981  canvas.setWindow(env.m_llx, env.m_lly, env.m_urx, env.m_ury);
982  canvas.setPointPattern(m_rgbaMarker, 12, 12);
983 
984  std::unique_ptr<te::srs::Converter> converter(new te::srs::Converter());
985 
986  converter->setSourceSRID(4326);
987  converter->setTargetSRID(m_mapDisplay->getSRID());
988 
989  te::gm::Coord2D coord;
990 
991  converter->convert(x, y, coord.x, coord.y);
992 
993  te::gm::Point point(coord.x, coord.y);
994 
995  canvas.setPointColor(te::color::RGBAColor(0, 0, 0, 0));
996  canvas.draw(&point);
997 
998  m_mapDisplay->repaint();
999 }
1000 
1002 {
1003  int r = rand() % 255;
1004  int g = rand() % 255;
1005  int b = rand() % 255;
1006  return QColor(r, g, b);
1007 }
1008 
1010 {
1011  QList<QListWidgetItem *> coord = m_ui->m_coordSListWidget->findItems(
1012  QString::number(x) + "," + QString::number(y), Qt::MatchExactly);
1013  if(coord.length() != 0)
1014  return;
1015 
1016  m_ui->m_coordSListWidget->addItem(QString::number(x) + "," +
1017  QString::number(y));
1018 }
1019 
1021 {
1023 
1024  canvas.clear();
1025 
1026  m_mapDisplay->refresh();
1027 }
1028 
1030 {
1032 
1033  m_ui->m_coordSListWidget->clear();
1034 
1035  m_ui->m_latLineEdit->clear();
1036  m_ui->m_longLineEdit->clear();
1037 
1038  clearCanvas();
1039 
1040  m_mapDisplay->setCursor(Qt::ArrowCursor);
1041  m_mapDisplay->setCurrentTool(nullptr, false);
1042 
1043  emit close();
1044 }
virtual void setCurrentTool(te::qt::widgets::AbstractTool *tool, const bool &delPrevious=true)
Updates the current tool being used on te::qt::widgets::MapDisplay.
virtual void refresh(bool redraw=false)
It updates the contents in the map display.
void clear()
It clears the canvas content and fills with the background color.
void doTimeseriesQuery(cxx::timeseries_query_t query)
Definition: WtssDialog.cpp:798
void onGetPointCoordinate(QPointF &coord)
Definition: WtssDialog.cpp:576
cxx::timeseries_query_result_t m_result
Definition: WtssDialog.h:175
void adjustDisplay()
Updates the general display settings according to the ChartStyle. The adjusted properties are: Title;...
void addServer(const QString &server_uri)
void addServer(QString server)
Definition: WtssDialog.cpp:698
double y
y-coordinate.
Definition: Coord2D.h:114
QJsonObject getAttribute(const QString &server_uri, const QString &cv_name, const QString &attribute)
A Mark specifies a geometric shape and applies coloring to it.
Definition: Mark.h:84
std::vector< te::st::TimeSeries * > m_timeSeriesVec
Definition: WtssDialog.h:185
double x
x-coordinate.
Definition: Coord2D.h:113
TEQTWIDGETSEXPORT void AddFilePathToSettings(const QString &path, const QString &typeFile)
Save last used path in QSettings.
te::qt::widgets::ChartDisplay * m_chartDisplay
Definition: WtssDialog.h:181
void addCoverage(QTreeWidgetItem *serverItem, QJsonObject j_server)
Definition: WtssDialog.cpp:721
void addLocation(double x, double y)
double m_urx
Upper right corner x-coordinate.
void changeStatusAttribute(const QString &server_uri, const QString &cv_name, const QString &attribute)
void convertToTimeSeries(cxx::timeseries_query_result_t result)
Definition: WtssDialog.cpp:901
Base Exception class Exceptions in WTSS.TL.
A widget to control the display of a set of layers.
An utility struct for representing 2D coordinates.
Definition: Coord2D.h:40
void setMapDisplay(te::qt::widgets::MapDisplay *mapDisplay)
Definition: WtssDialog.cpp:123
void setActionGroup(QActionGroup *actionGroup)
Definition: WtssDialog.cpp:130
void setTitle(QString newTitle)
It sets the style&#39;s title.
Definition: ChartStyle.cpp:71
void onPointPickerToggled(bool checked)
Definition: WtssDialog.cpp:624
Manage the JSON file for services configuration of the Web Time Series Services plugin.
void removeServer(const QString &server_uri)
int b
Definition: TsRtree.cpp:32
void setWindow(const double &llx, const double &lly, const double &urx, const double &ury)
It sets the world (or window) coordinates area (supposing a cartesian reference system).
double m_llx
Lower left corner x-coordinate.
static MarkRendererManager & getInstance()
It returns a reference to the singleton instance.
A point with x and y coordinate values.
Definition: Point.h:50
te::qt::widgets::MapDisplay * m_mapDisplay
Definition: WtssDialog.h:179
An Envelope defines a 2D rectangular region.
A base class for date data types.
Definition: Date.h:53
void setAxisY(QString newAxisY)
It sets the style&#39;s y axis label.
Definition: ChartStyle.cpp:101
virtual int getSRID() const
It return the Spatial Reference System used by the Map Display.
static te::dt::DateTime d(2010, 8, 9, 15, 58, 39)
void addMarker(double x, double y)
Definition: WtssDialog.cpp:975
virtual const te::gm::Envelope & getExtent() const
It returns the world extent showned by the MapDisplay.
A class to represent a chart display.
Definition: ChartDisplay.h:65
void setAxisX(QString newAxisX)
It sets the style&#39;s x axis label.
Definition: ChartStyle.cpp:91
void changeStatusServer(const QString &server_uri)
A Fill specifies the pattern for filling an area geometry.
Definition: Fill.h:59
TESEEXPORT Mark * CreateMark(const std::string &wellKnownName, Stroke *stroke, Fill *fill)
Creates a mark.
std::unique_ptr< Ui::WtssDialogForm > m_ui
Definition: WtssDialog.h:163
void onItemChecked(QTreeWidgetItem *item)
Definition: WtssDialog.cpp:276
double m_lly
Lower left corner y-coordinate.
void refreshServer(const QString &server_uri)
A Converter is responsible for the conversion of coordinates between different Coordinate Systems (CS...
Definition: Converter.h:53
TESEEXPORT Stroke * CreateStroke(const std::string &color, const std::string &width)
Creates a stroke.
virtual QPixmap * getDraftPixmap() const
It returns the map display draft pixmap.
double m_ury
Upper right corner y-coordinate.
te::color::RGBAColor ** m_rgbaMarker
Definition: WtssDialog.h:187
A Stroke specifies the appearance of a linear geometry.
Definition: Stroke.h:67
A class to represent time series.
Definition: TimeSeries.h:66
void closeEvent(QCloseEvent *e)
A helper class for 32-bit RGBA (Red-Green-Blue-Alpha channel) color.
Definition: RGBAColor.h:57
void addDateFilter(const QString startDate, const QString endDate)
This class implements a concrete tool to geographic coordinate picker on mouse click operation...
Definition: PointPicker.h:50
WtssDialog(QWidget *parent=0, Qt::WindowFlags f=0)
Definition: WtssDialog.cpp:66
TEQTWIDGETSEXPORT QString GetFilePathFromSettings(const QString &typeFile)
Returns the value of the last saved file path for the typeFile required.
QVector< te::qt::widgets::TimeSeriesChart * > m_timeSeriesChartVec
Definition: WtssDialog.h:183
Configuration dialog for Web Time Series Services plugin.
A class to represent a timeSeries chart.
virtual void setExtent(te::gm::Envelope &e, bool doRefresh=true)
It sets the world visible area and refreshes the contents in the map display.
void changeStatusCoverage(const QString &server_uri, const QString &cv_name)
static ServerManager & getInstance()
Definition: ServerManager.h:52
void onAddCoordToList(QListWidgetItem *coordSelected)
Definition: WtssDialog.cpp:520
file(WRITE ${CMAKE_BINARY_DIR}/config_qhelp.cmake"configure_file (${TERRALIB_ABSOLUTE_ROOT_DIR}/doc/qhelp/help.qhcp.in ${CMAKE_BINARY_DIR}/share/terraview/help/help.qhcp @ONLY)") add_custom_command(OUTPUT del_dir COMMAND $
void addAtributes(QTreeWidgetItem *coverageItem, QJsonObject j_coverage)
Definition: WtssDialog.cpp:748
An object that when created shows a cursor during its scope.
Definition: ScopedCursor.h:48
TESEEXPORT Fill * CreateFill(const std::string &color, const std::string &opacity)
Creates a fill.