UnionDialog.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/vp/qt/UnionDialog.cpp
22 
23  \brief Union operation dialog.
24 */
25 
26 // TerraLib
27 #include "../../core/filesystem/FileSystem.h"
28 #include "../../common/StringUtils.h"
29 #include "../../dataaccess/dataset/DataSetAdapter.h"
30 #include "../../dataaccess/dataset/DataSetTypeConverter.h"
31 #include "../../dataaccess/dataset/ObjectIdSet.h"
32 #include "../../dataaccess/datasource/DataSourceInfoManager.h"
33 #include "../../dataaccess/datasource/DataSourceManager.h"
34 #include "../../dataaccess/datasource/DataSourceFactory.h"
35 #include "../../dataaccess/query/And.h"
36 #include "../../dataaccess/query/DataSetName.h"
37 #include "../../dataaccess/query/Expression.h"
38 #include "../../dataaccess/query/Field.h"
39 #include "../../dataaccess/query/Fields.h"
40 #include "../../dataaccess/query/From.h"
41 #include "../../dataaccess/query/FromItem.h"
42 #include "../../dataaccess/query/LiteralInt32.h"
43 #include "../../dataaccess/query/PropertyName.h"
44 #include "../../dataaccess/query/ST_SetSRID.h"
45 #include "../../dataaccess/query/ST_Transform.h"
46 #include "../../dataaccess/query/Where.h"
47 #include "../../dataaccess/utils/Utils.h"
48 #include "../../datatype/SimpleData.h"
49 #include "../../geometry/GeometryProperty.h"
50 #include "../../maptools/QueryLayer.h"
51 #include "../../qt/widgets/datasource/selector/DataSourceSelectorDialog.h"
52 #include "../../qt/widgets/layer/utils/DataSet2Layer.h"
53 #include "../../qt/widgets/utils/DoubleListWidget.h"
54 #include "../../qt/widgets/utils/FileDialog.h"
55 
56 #include "../ComplexData.h"
57 #include "../Union.h"
58 
59 #include "UnionDialog.h"
60 #include "ui_UnionDialogForm.h"
61 
62 // Qt
63 #include <QFileDialog>
64 #include <QGridLayout>
65 #include <QMessageBox>
66 
67 // BOOST
68 #include <boost/filesystem.hpp>
69 #include <boost/uuid/random_generator.hpp>
70 #include <boost/uuid/uuid_io.hpp>
71 
73 
74 te::vp::UnionDialog::UnionDialog(QWidget* parent, Qt::WindowFlags f)
75  : QDialog(parent, f),
76  m_ui(new Ui::UnionDialogForm),
77  m_layers(std::list<te::map::AbstractLayerPtr>())
78 {
79 // add controls
80  m_ui->setupUi(this);
81 
82  m_ui->m_imgLabel->setPixmap(
83  QIcon::fromTheme("vp-union-hint").pixmap(112, 48));
84 
85  m_ui->m_targetDatasourceToolButton->setIcon(QIcon::fromTheme("datasource"));
86 
87  //add double list widget to this form
88  m_doubleListWidget.reset(new te::qt::widgets::DoubleListWidget(
89  m_ui->m_specificParamsTabWidget->widget(0)));
90  m_doubleListWidget->setLeftLabel("");
91  m_doubleListWidget->setRightLabel("");
92 
93  QGridLayout* layout =
94  new QGridLayout(m_ui->m_specificParamsTabWidget->widget(0));
95  layout->addWidget(m_doubleListWidget.get());
96  layout->setContentsMargins(0, 0, 0, 0);
97 
98  QSize iconSize(96, 48);
99 
100  m_ui->m_singleRadioButton->setIconSize(iconSize);
101  m_ui->m_singleRadioButton->setIcon(QIcon::fromTheme("vp-single-objects"));
102 
103  m_ui->m_multiRadioButton->setIconSize(iconSize);
104  m_ui->m_multiRadioButton->setIcon(QIcon::fromTheme("vp-multi-objects"));
105 
106  connect(m_ui->m_firstLayerComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onFirstLayerComboBoxChanged(int)));
107 
108  connect(m_ui->m_secondLayerComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onSecondLayerComboBoxChanged(int)));
109 
110  connect(m_ui->m_targetDatasourceToolButton, SIGNAL(pressed()), this, SLOT(onTargetDatasourceToolButtonPressed()));
111 
112  connect(m_ui->m_targetFileToolButton, SIGNAL(pressed()), this, SLOT(onTargetFileToolButtonPressed()));
113 
114  connect(m_ui->m_okPushButton, SIGNAL(clicked()), this, SLOT(onOkPushButtonClicked()));
115 
116  connect(m_ui->m_cancelPushButton, SIGNAL(clicked()), this, SLOT(onCancelPushButtonClicked()));
117 
118  m_ui->m_helpPushButton->setNameSpace("dpi.inpe.br.plugins");
119  m_ui->m_helpPushButton->setPageReference("plugins/vp/vp_union.html");
120 }
121 
123 
124 void te::vp::UnionDialog::setLayers(std::list<te::map::AbstractLayerPtr> layers)
125 {
126  std::list<te::map::AbstractLayerPtr>::iterator it = layers.begin();
127 
128  while (it != layers.end())
129  {
130  std::unique_ptr<te::da::DataSetType> dsType =
131  std::move(it->get()->getSchema());
132 
133  if (dsType->hasGeom())
134  {
135  m_layers.push_back(*it);
136  }
137 
138  ++it;
139  }
140 
142 
144 
146 }
147 
149 {
150  return m_outputLayer;
151 }
152 
153 std::vector<std::pair<std::string, std::string> >
155 {
156  std::vector<std::string> outVec = m_doubleListWidget->getOutputValues();
157  std::vector<std::pair<std::string, std::string> > result;
158 
159  for (std::size_t i = 0; i < outVec.size(); ++i)
160  {
161  std::vector<std::string> tok;
162  te::common::Tokenize(outVec[i], tok, ": ");
163 
164  std::pair<std::string, std::string> p;
165 
166  if (tok[0] == m_firstSelectedLayer->getTitle())
167  {
168  p.first = "FIRST";
169  }
170  else
171  {
172  p.first = "SECOND";
173  }
174 
175  p.second = tok[1];
176 
177  result.push_back(p);
178  }
179 
180  return result;
181 }
182 
184 {
185  std::list<te::map::AbstractLayerPtr>::iterator it = m_layers.begin();
186 
187  disconnect(m_ui->m_firstLayerComboBox, SIGNAL(currentIndexChanged(int)), this,
188  SLOT(onFirstLayerComboBoxChanged(int)));
189 
190  while (it != m_layers.end())
191  {
192  m_ui->m_firstLayerComboBox->addItem(QString(it->get()->getTitle().c_str()),
193  QVariant::fromValue(*it));
194  ++it;
195  }
196 
197  connect(m_ui->m_firstLayerComboBox, SIGNAL(currentIndexChanged(int)), this,
198  SLOT(onFirstLayerComboBoxChanged(int)));
199 
200  QVariant varLayer = m_ui->m_firstLayerComboBox->itemData(
201  m_ui->m_firstLayerComboBox->currentIndex(), Qt::UserRole);
202 
203  te::map::AbstractLayerPtr layer = varLayer.value<te::map::AbstractLayerPtr>();
204 
205  m_firstSelectedLayer = layer;
206 }
207 
209 {
210  int currIndex = m_ui->m_firstLayerComboBox->currentIndex();
211 
212  std::list<te::map::AbstractLayerPtr>::iterator it = m_layers.begin();
213 
214  disconnect(m_ui->m_secondLayerComboBox, SIGNAL(currentIndexChanged(int)),
215  this, SLOT(onSecondLayerComboBoxChanged(int)));
216 
217  while (it != m_layers.end())
218  {
219  m_ui->m_secondLayerComboBox->addItem(QString(it->get()->getTitle().c_str()),
220  QVariant::fromValue(*it));
221  ++it;
222  }
223 
224  m_ui->m_secondLayerComboBox->removeItem(currIndex);
225 
226  connect(m_ui->m_secondLayerComboBox, SIGNAL(currentIndexChanged(int)), this,
227  SLOT(onSecondLayerComboBoxChanged(int)));
228 
229  QVariant varLayer = m_ui->m_secondLayerComboBox->itemData(
230  m_ui->m_secondLayerComboBox->currentIndex(), Qt::UserRole);
231 
232  te::map::AbstractLayerPtr layer = varLayer.value<te::map::AbstractLayerPtr>();
233 
234  m_secondSelectedLayer = layer;
235 }
236 
238 {
239  std::vector<std::string> inputValues;
240 
241  std::unique_ptr<te::da::DataSetType> firstSchema;
242  std::unique_ptr<te::da::DataSetType> secondSchema;
243 
245  firstSchema = std::move(m_firstSelectedLayer->getSchema());
246  else
247  return;
248 
250  secondSchema = std::move(m_secondSelectedLayer->getSchema());
251  else
252  return;
253 
254  std::vector<te::dt::Property*> firstProps = firstSchema->getProperties();
255  for (std::size_t i = 0; i < firstProps.size(); ++i)
256  {
257  if (firstProps[i]->getType() != te::dt::GEOMETRY_TYPE)
258  {
259  std::string name = firstSchema->getTitle();
260 
261  if (name.empty())
262  name = firstSchema->getName();
263 
264  inputValues.push_back(name + ": " + firstProps[i]->getName());
265  }
266  }
267 
268  std::vector<te::dt::Property*> secondProps = secondSchema->getProperties();
269  for (std::size_t i = 0; i < secondProps.size(); ++i)
270  {
271  if (secondProps[i]->getType() != te::dt::GEOMETRY_TYPE)
272  {
273  std::string name = secondSchema->getTitle();
274 
275  if (name.empty())
276  name = secondSchema->getName();
277 
278  inputValues.push_back(secondSchema->getTitle() + ": " +
279  secondProps[i]->getName());
280  }
281  }
282 
283  m_doubleListWidget->setInputValues(inputValues);
284 }
285 
287 {
288  QVariant varLayer = m_ui->m_firstLayerComboBox->itemData(index, Qt::UserRole);
289  te::map::AbstractLayerPtr layer = varLayer.value<te::map::AbstractLayerPtr>();
290 
291  m_ui->m_secondLayerComboBox->clear();
292 
293  m_firstSelectedLayer = layer;
294 
296 
298 }
299 
301 {
302  QVariant varLayer =
303  m_ui->m_secondLayerComboBox->itemData(index, Qt::UserRole);
304 
305  te::map::AbstractLayerPtr layer = varLayer.value<te::map::AbstractLayerPtr>();
306 
307  m_secondSelectedLayer = layer;
308 
310 }
311 
313 {
314  m_ui->m_newLayerNameLineEdit->clear();
315  m_ui->m_newLayerNameLineEdit->setEnabled(true);
317  dlg.exec();
318 
319  std::list<te::da::DataSourceInfoPtr> dsPtrList = dlg.getSelecteds();
320 
321  if (dsPtrList.empty())
322  return;
323 
324  std::list<te::da::DataSourceInfoPtr>::iterator it = dsPtrList.begin();
325 
326  m_ui->m_repositoryLineEdit->setText(QString(it->get()->getTitle().c_str()));
327 
328  m_outputDatasource = *it;
329 
330  m_toFile = false;
331 }
332 
334 {
335  m_ui->m_newLayerNameLineEdit->clear();
336  m_ui->m_repositoryLineEdit->clear();
337 
339 
340  try {
341  fileDialog.exec();
342  }
343  catch (te::common::Exception& ex) {
344  QMessageBox::warning(this, tr("File information"), ex.what());
345  return;
346  }
347 
348  m_ui->m_repositoryLineEdit->setText(fileDialog.getPath().c_str());
349  m_ui->m_newLayerNameLineEdit->setText(fileDialog.getFileName().c_str());
350 
351  m_toFile = true;
352  m_ui->m_newLayerNameLineEdit->setEnabled(false);
353 }
354 
356 {
357  if(m_ui->m_firstLayerComboBox->currentText().isEmpty() ||
358  m_ui->m_secondLayerComboBox->currentText().isEmpty())
359  {
360  QMessageBox::information(
361  this, tr("Union"), tr("It is necessary at least two layer to operat!"));
362  return;
363  }
364 
365  // Checking consistency of output paramenters
366  if (m_ui->m_repositoryLineEdit->text().isEmpty())
367  {
368  QMessageBox::information(
369  this, tr("Union"), tr("Select a repository for the resulting layer!"));
370 
371  return;
372  }
373 
374  if (m_ui->m_newLayerNameLineEdit->text().isEmpty())
375  {
376  QMessageBox::information(this, tr("Union"),
377  tr("Define a name for the resulting layer!"));
378  return;
379  }
380 
381  int firstSrid = m_firstSelectedLayer->getSRID();
382  int secondSrid = m_secondSelectedLayer->getSRID();
383 
384  if (firstSrid <= 0 || secondSrid <= 0)
385  {
386  QMessageBox::information(this, tr("Union"),
387  tr("All layers must have SRID!"));
388  return;
389  }
390 
391  std::string outputdataset =
392  m_ui->m_newLayerNameLineEdit->text().toUtf8().data();
393 
394  std::string firstSourceId = m_firstSelectedLayer->getDataSourceId();
395  std::string secondSourceId = m_secondSelectedLayer->getDataSourceId();
396 
397  te::da::DataSourcePtr firstSource =
398  te::da::DataSourceManager::getInstance().find(firstSourceId);
399 
400  te::da::DataSourcePtr secondSource =
401  te::da::DataSourceManager::getInstance().find(secondSourceId);
402 
403  std::unique_ptr<te::da::DataSetTypeConverter> firstConverter(
404  new te::da::DataSetTypeConverter(m_firstSelectedLayer->getSchema().get(),
405  firstSource->getCapabilities(),
406  firstSource->getEncoding()));
407 
408  te::da::AssociateDataSetTypeConverterSRID(firstConverter.get(),
409  m_firstSelectedLayer->getSRID());
410 
411  std::unique_ptr<te::da::DataSetTypeConverter> secondConverter(
413  secondSource->getCapabilities(),
414  secondSource->getEncoding()));
415 
416  te::da::AssociateDataSetTypeConverterSRID(secondConverter.get(),
417  m_secondSelectedLayer->getSRID(),
418  m_firstSelectedLayer->getSRID());
419 
420  te::da::DataSetType* firstDst(firstConverter->getResult());
421  te::da::DataSetType* secondDst(secondConverter->getResult());
422 
424  m_firstSelectedLayer->getData().release(), firstConverter.get());
425 
427  m_secondSelectedLayer->getData().release(), secondConverter.get());
428 
429  std::unique_ptr<te::da::DataSet> firstDs(firstAdapter);
430  std::unique_ptr<te::da::DataSet> secondDs(secondAdapter);
431 
432  try
433  {
434  te::vp::InputParams inputParam;
435  inputParam.m_inputDataSet = firstDs.get();
436  inputParam.m_inputDataSetType = firstDst;
437  inputParam.m_inputDataSource = firstSource;
438 
439  te::vp::InputParams mergeParam;
440  mergeParam.m_inputDataSet = secondDs.get();
441  mergeParam.m_inputDataSetType = secondDst;
442  mergeParam.m_inputDataSource = secondSource;
443 
444  std::vector<te::vp::InputParams> params;
445  params.push_back(inputParam);
446  params.push_back(mergeParam);
447 
449  attrs = new te::vp::ComplexData<
450  std::vector<std::pair<std::string, std::string> > >(
452 
453  std::map<std::string, te::dt::AbstractData*> specificParams;
454  specificParams["ATTRIBUTES"] = attrs;
455 
456  specificParams["IS_COLLECTION"] =
458  !m_ui->m_singleRadioButton->isChecked());
459 
461  aParams->setInputParams(params);
462  aParams->setOutputDataSetName(outputdataset);
463  aParams->setSpecificParams(specificParams);
464 
465  te::da::DataSourcePtr auxSource;
466  std::string ogrDsinfo("file://");
467  boost::filesystem::path ogrUri;
468 
469  if (m_toFile)
470  {
471  ogrUri = m_ui->m_repositoryLineEdit->text().toUtf8().data();
472 
473  if (te::core::FileSystem::exists(ogrUri.string()))
474  {
475  QMessageBox::information(this, tr("Union"),
476  tr("Output file already exists. Remove it or "
477  "select a new name and try again."));
478  return;
479  }
480 
481  std::size_t idx = outputdataset.find(".");
482  if (idx != std::string::npos)
483  outputdataset = outputdataset.substr(0, idx);
484 
485  aParams->setOutputDataSetName(outputdataset);
486 
487  ogrDsinfo += ogrUri.string();
488 
489  auxSource.reset(
490  te::da::DataSourceFactory::make("OGR", ogrDsinfo).release());
491  auxSource->open();
492 
493  if (auxSource->dataSetExists(outputdataset))
494  {
495  QMessageBox::information(
496  this, tr("Union"),
497  tr("There is already a dataset with the requested name in the "
498  "output data source. Remove it or select a new name and try "
499  "again."));
500  return;
501  }
502  }
503  else
504  {
505  auxSource = te::da::GetDataSource(m_outputDatasource->getId());
506  if (!auxSource)
507  {
508  QMessageBox::information(
509  this, tr("Union"),
510  tr("The selected output datasource can not be accessed."));
511  return;
512  }
513  if (auxSource->dataSetExists(outputdataset))
514  {
515  QMessageBox::information(this, tr("Union"),
516  tr("Dataset already exists. Remove it or "
517  "select a new name and try again."));
518  return;
519  }
520  }
521 
522  aParams->setOutputDataSource(auxSource);
523 
524  te::vp::Union uni;
525  uni.executeMemory(aParams);
526 
527  delete aParams;
528 
529  if (m_toFile)
530  {
531  // let's include the new datasource in the managers
532  boost::uuids::basic_random_generator<boost::mt19937> gen;
533  boost::uuids::uuid u = gen();
534  std::string id = boost::uuids::to_string(u);
535 
537  ds->setConnInfo(ogrDsinfo);
538  ds->setTitle(ogrUri.stem().string());
539  ds->setAccessDriver("OGR");
540  ds->setType("OGR");
541  ds->setDescription(ogrUri.string());
542  ds->setId(id);
543 
544  te::da::DataSourcePtr newds =
546  ds->getConnInfo());
547  newds->open();
550  }
551 
552  // creating a layer for the result
553  te::da::DataSourcePtr outDataSource =
555 
557 
559  outDataSource->getDataSetType(outputdataset).release());
560  m_outputLayer = converter(dt);
561  }
562  catch (const te::common::Exception& e)
563  {
564  QMessageBox::warning(this, tr("Union"), e.what());
565  return;
566  }
567  catch (const std::exception& e)
568  {
569  QMessageBox::warning(this, tr("Union"), e.what());
570  return;
571  }
572 
573  accept();
574 }
575 
577 {
578  reject();
579 }
580 
TEDATAACCESSEXPORT DataSourcePtr GetDataSource(const std::string &datasourceId, const bool opened=true)
Search for a data source with the informed id in the DataSourceManager.
void push_back(Curve *ring)
It adds the curve to the curve polygon.
static std::unique_ptr< DataSource > make(const std::string &driver, const te::core::URI &connInfo)
A structure to hold the input parameters of vector processing.
Definition: InputParams.h:50
Defines a component for choose a file.
Definition: FileDialog.h:52
te::map::AbstractLayerPtr m_firstSelectedLayer
Input layer selected.
Definition: UnionDialog.h:122
static bool exists(const std::string &path)
Checks if a given path in UTF-8 exists.
Definition: FileSystem.cpp:142
boost::shared_ptr< DataSetType > DataSetTypePtr
Definition: DataSetType.h:653
te::map::AbstractLayerPtr m_outputLayer
Generated Layer.
Definition: UnionDialog.h:129
boost::shared_ptr< DataSource > DataSourcePtr
bool m_toFile
The result is in a file?
Definition: UnionDialog.h:131
TEDATAACCESSEXPORT void AssociateDataSetTypeConverterSRID(DataSetTypeConverter *converter, const int &inputSRID, const int &outputSRID=TE_UNKNOWN_SRS)
A class that models the description of a dataset.
Definition: DataSetType.h:72
std::vector< std::pair< std::string, std::string > > getSelectedProperties()
virtual const char * what() const
It outputs the exception message.
void onTargetDatasourceToolButtonPressed()
Union operation dialog.
static te::dt::Date ds(2010, 01, 01)
te::da::DataSourceInfoPtr m_outputDatasource
DataSource information.
Definition: UnionDialog.h:128
void updateFirstLayerComboBox()
te::da::DataSourcePtr m_inputDataSource
Is Required.
Definition: InputParams.h:81
void onSecondLayerComboBoxChanged(int index)
An converter for DataSetType.
void Tokenize(const std::string &str, std::vector< std::string > &tokens, const std::string &delimiters=" ")
It tokenizes a given string with a delimiter of your own choice.
Definition: StringUtils.h:221
te::map::AbstractLayerPtr getLayer()
A template for complex data types.
Definition: ComplexData.h:52
static DataSourceManager & getInstance()
It returns a reference to the singleton instance.
std::unique_ptr< te::qt::widgets::DoubleListWidget > m_doubleListWidget
Definition: UnionDialog.h:133
void exec()
This method will open the dialog of file selection and populate the class members with the chosen fil...
Definition: FileDialog.cpp:54
URI C++ Library.
Definition: Attributes.h:37
static te::dt::TimeDuration dt(20, 30, 50, 11)
te::gm::Polygon * p
std::unique_ptr< Ui::UnionDialogForm > m_ui
Definition: UnionDialog.h:120
te::da::DataSetType * m_inputDataSetType
Is required.
Definition: InputParams.h:82
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
Q_DECLARE_METATYPE(te::map::AbstractLayerPtr) te
Definition: UnionDialog.cpp:72
te::map::AbstractLayerPtr m_secondSelectedLayer
Union layer selected.
Definition: UnionDialog.h:123
void onTargetFileToolButtonPressed()
std::string getPath()
This method will return the chosen path.
Definition: FileDialog.cpp:103
te::da::DataSet * m_inputDataSet
Is required for operations in memory.
Definition: InputParams.h:84
const std::list< te::da::DataSourceInfoPtr > & getSelecteds() const
void onFirstLayerComboBoxChanged(int index)
std::list< te::map::AbstractLayerPtr > m_layers
The vector layers in Layer Explorer.
Definition: UnionDialog.h:121
A dialog for selecting a data source.
A class that represents a data source component.
void updateSecondLayerComboBox()
bool executeMemory(te::vp::AlgorithmParams *mainParams)
std::string getFileName()
This method will return the file name.
Definition: FileDialog.cpp:113
void setLayers(std::list< te::map::AbstractLayerPtr > layers)
Set the layer that can be used.
A template for atomic data types (integers, floats, strings and others).
Definition: SimpleData.h:59
TEDATAACCESSEXPORT DataSetAdapter * CreateAdapter(DataSet *ds, DataSetTypeConverter *converter, bool isOwner=false)
boost::intrusive_ptr< AbstractLayer > AbstractLayerPtr
void onCancelPushButtonClicked()
An adapter for DataSet.
boost::shared_ptr< DataSourceInfo > DataSourceInfoPtr