All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
IntersectionDialog.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2011-2012 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/IntersectionDialog.cpp
22 
23  \brief A dialog for intersection operation
24 */
25 
26 // TerraLib
27 #include "../../common/progress/ProgressManager.h"
28 #include "../../common/Translator.h"
29 #include "../../dataaccess/dataset/DataSetType.h"
30 #include "../../dataaccess/datasource/DataSourceInfo.h"
31 #include "../../dataaccess/datasource/DataSourceInfoManager.h"
32 #include "../../dataaccess/datasource/DataSourceManager.h"
33 #include "../../dataaccess/datasource/DataSourceFactory.h"
34 #include "../../dataaccess/utils/Utils.h"
35 #include "../../datatype/Property.h"
36 #include "../../qt/widgets/datasource/selector/DataSourceSelectorDialog.h"
37 #include "../../qt/widgets/progress/ProgressViewerDialog.h"
38 #include "../../srs/Config.h"
39 #include "../Exception.h"
40 #include "../Intersection.h"
41 #include "../qt/widgets/layer/utils/DataSet2Layer.h"
42 #include "IntersectionDialog.h"
43 #include "LayerTreeModel.h"
44 #include "ui_IntersectionDialogForm.h"
45 #include "VectorProcessingConfig.h"
46 #include "Utils.h"
47 
48 // Qt
49 #include <QtGui/QFileDialog>
50 #include <QtGui/QMessageBox>
51 #include <QtGui/QTreeWidget>
52 
53 // BOOST
54 #include <boost/filesystem.hpp>
55 #include <boost/uuid/random_generator.hpp>
56 #include <boost/uuid/uuid_io.hpp>
57 
58 te::vp::IntersectionDialog::IntersectionDialog(QWidget* parent, Qt::WindowFlags f)
59  : QDialog(parent, f),
60  m_ui(new Ui::IntersectionDialogForm),
61  m_layers(std::list<te::map::AbstractLayerPtr>())
62 {
63 // add controls
64  m_ui->setupUi(this);
65 
66  m_ui->m_imgLabel->setPixmap(QIcon::fromTheme(VP_IMAGES"/vp-intersection-hint").pixmap(48,48));
67  m_ui->m_targetDatasourceToolButton->setIcon(QIcon::fromTheme("datasource"));
68 
69  connect(m_ui->m_firstLayerComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onFirstLayerComboBoxChanged(int)));
70  connect(m_ui->m_secondLayerComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onSecondLayerComboBoxChanged(int)));
71  //connect(m_ui->m_helpPushButton, SIGNAL(clicked()), this, SLOT(onHelpPushButtonClicked()));
72  connect(m_ui->m_okPushButton, SIGNAL(clicked()), this, SLOT(onOkPushButtonClicked()));
73  connect(m_ui->m_targetDatasourceToolButton, SIGNAL(pressed()), this, SLOT(onTargetDatasourceToolButtonPressed()));
74  connect(m_ui->m_targetFileToolButton, SIGNAL(pressed()), this, SLOT(onTargetFileToolButtonPressed()));
75 
76  m_ui->m_helpPushButton->setNameSpace("dpi.inpe.br.plugins");
77  m_ui->m_helpPushButton->setPageReference("plugins/vp/vp_intersection.html");
78 }
79 
81 {
82 }
83 
84 void te::vp::IntersectionDialog::setLayers(std::list<te::map::AbstractLayerPtr> layers)
85 {
86  m_layers = layers;
87 
88  std::list<te::map::AbstractLayerPtr>::iterator it = m_layers.begin();
89 
90  while(it != m_layers.end())
91  {
92  std::auto_ptr<te::da::DataSetType> dsType = it->get()->getSchema();
93  if(dsType->hasGeom())
94  m_ui->m_firstLayerComboBox->addItem(QString(it->get()->getTitle().c_str()), QVariant(it->get()->getId().c_str()));
95  ++it;
96  }
97 }
98 
100 {
101  return m_layerResult;
102 }
103 
105 {
106  std::list<te::map::AbstractLayerPtr>::iterator it = m_layers.begin();
107  std::string layerID = m_ui->m_firstLayerComboBox->itemData(index, Qt::UserRole).toString().toStdString();
108 
109  m_ui->m_secondLayerComboBox->clear();
110  while(it != m_layers.end())
111  {
112  if(layerID != it->get()->getId().c_str())
113  {
114  std::auto_ptr<te::da::DataSetType> dsType = it->get()->getSchema();
115  if(dsType->hasGeom())
116  m_ui->m_secondLayerComboBox->addItem(QString(it->get()->getTitle().c_str()), QVariant(it->get()->getId().c_str()));
117  }
118  else
119  {
120  te::map::AbstractLayerPtr selectedLayer = it->get();
121  m_firstSelectedLayer = selectedLayer;
122  }
123 
124  ++it;
125  }
126 }
127 
129 {
130  std::list<te::map::AbstractLayerPtr>::iterator it = m_layers.begin();
131  std::string layerID = m_ui->m_secondLayerComboBox->itemData(index, Qt::UserRole).toString().toStdString();
132 
133  while(it != m_layers.end())
134  {
135  if(layerID == it->get()->getId().c_str())
136  {
137  te::map::AbstractLayerPtr selectedLayer = it->get();
138  m_secondSelectedLayer = selectedLayer;
139  }
140 
141  ++it;
142  }
143 }
144 
146 {
147  QMessageBox::information(this, "Intersection Operation", "Under development");
148 }
149 
151 {
152  if(m_ui->m_firstLayerComboBox->currentText().isEmpty())
153  {
154  QMessageBox::warning(this, TR_VP("Intersection"), TR_VP("Select a first input layer."));
155  return;
156  }
157 
158  te::map::DataSetLayer* firstDataSetLayer = dynamic_cast<te::map::DataSetLayer*>(m_firstSelectedLayer.get());
159  if(!firstDataSetLayer)
160  {
161  QMessageBox::information(this, "Intersection", "Can not execute this operation on this type of first layer.");
162  return;
163  }
164 
165  te::da::DataSourcePtr firstDataSource = te::da::GetDataSource(firstDataSetLayer->getDataSourceId(), true);
166  if (!firstDataSource.get())
167  {
168  QMessageBox::information(this, "Intersection", "The selected first input data source can not be accessed.");
169  return;
170  }
171 
172  if(m_ui->m_secondLayerComboBox->currentText().isEmpty())
173  {
174  QMessageBox::warning(this, TR_VP("Intersection"), TR_VP("Select a second input layer."));
175  return;
176  }
177 
178  te::map::DataSetLayer* secondDataSetLayer = dynamic_cast<te::map::DataSetLayer*>(m_secondSelectedLayer.get());
179  if(!secondDataSetLayer)
180  {
181  QMessageBox::information(this, "Intersection", "Can not execute this operation on this type of second layer.");
182  return;
183  }
184 
185  te::da::DataSourcePtr secondDataSource = te::da::GetDataSource(secondDataSetLayer->getDataSourceId(), true);
186  if (!secondDataSource.get())
187  {
188  QMessageBox::information(this, "Intersection", "The selected second input data source can not be accessed.");
189  return;
190  }
191 
192  if(m_ui->m_repositoryLineEdit->text().isEmpty())
193  {
194  QMessageBox::warning(this, TR_VP("Intersection"), TR_VP("Select a repository for the resulting layer."));
195  return;
196  }
197 
198  if(m_ui->m_newLayerNameLineEdit->text().isEmpty())
199  {
200  QMessageBox::warning(this, TR_VP("Intersection"), TR_VP("Define a name for the resulting layer."));
201  return;
202  }
203 
204  if ((firstDataSetLayer->getSRID() == TE_UNKNOWN_SRS && secondDataSetLayer->getSRID() != TE_UNKNOWN_SRS) ||
205  (firstDataSetLayer->getSRID() != TE_UNKNOWN_SRS && secondDataSetLayer->getSRID() == TE_UNKNOWN_SRS))
206  {
207  int ret = QMessageBox::question(this, "Intersection", "The two layers have incompatible SRS. The result might be incorrect. Do you wish to continue?", QMessageBox::No, QMessageBox::Yes);
208  if (ret == QMessageBox::No)
209  return;
210  }
211 
212  //progress
214  int id = te::common::ProgressManager::getInstance().addViewer(&v);
215 
216  try
217  {
218  bool copyInputColumns = m_ui->m_copyColumnsCheckBox->isChecked();
219  std::string outputdataset = m_ui->m_newLayerNameLineEdit->text().toStdString();
220 
221  bool res;
222  if (m_toFile)
223  {
224  boost::filesystem::path uri(m_ui->m_repositoryLineEdit->text().toStdString());
225 
226  if (boost::filesystem::exists(uri))
227  {
228  QMessageBox::information(this, "Intersection", "Output file already exists. Remove it and try again. ");
229  return;
230  }
231 
232  std::size_t idx = outputdataset.find(".");
233  if(idx != std::string::npos)
234  outputdataset = outputdataset.substr(0, idx);
235 
236  std::map<std::string, std::string> dsinfo;
237  dsinfo["URI"] = uri.string();
238 
239  std::auto_ptr<te::da::DataSource> dsOGR = te::da::DataSourceFactory::make("OGR");
240  dsOGR->setConnectionInfo(dsinfo);
241  dsOGR->open();
242  if(dsOGR->dataSetExists(outputdataset))
243  {
244  QMessageBox::information(this, "Intersection", "Output file already exists. Remove it or select a new name and try again.");
245  return;
246  }
247 
248  this->setCursor(Qt::WaitCursor);
249  res = te::vp::Intersection( firstDataSetLayer->getDataSetName(),
250  firstDataSource.get(),
251  secondDataSetLayer->getDataSetName(),
252  secondDataSource.get(),
253  copyInputColumns,
254  outputdataset,
255  dsOGR.get());
256 
257  if(!res)
258  {
259  dsOGR->close();
260  QMessageBox::information(this, "Intersection", "Error: could not generate the intersection.");
261  reject();
262  }
263  dsOGR->close();
264 
265  // let's include the new datasource in the managers
266  boost::uuids::basic_random_generator<boost::mt19937> gen;
267  boost::uuids::uuid u = gen();
268  std::string id = boost::uuids::to_string(u);
269 
271  ds->setConnInfo(dsinfo);
272  ds->setTitle(uri.stem().string());
273  ds->setAccessDriver("OGR");
274  ds->setType("OGR");
275  ds->setDescription(uri.string());
276  ds->setId(id);
277 
278  te::da::DataSourcePtr newds = te::da::DataSourceManager::getInstance().get(id, "OGR", ds->getConnInfo());
279  newds->open();
281  m_outputDatasource = ds;
282  }
283  else
284  {
285  te::da::DataSourcePtr aux = te::da::GetDataSource(m_outputDatasource->getId());
286  if (!aux.get())
287  {
288  QMessageBox::information(this, "Intersection", "The output data source can not be accessed.");
289  return;
290  }
291  if (aux->dataSetExists(outputdataset))
292  {
293  QMessageBox::information(this, "Intersection", "Dataset already exists. Remove it or select a new name and try again. ");
294  return;
295  }
296  this->setCursor(Qt::WaitCursor);
297  res = te::vp::Intersection(firstDataSetLayer->getDataSetName(),
298  firstDataSource.get(),
299  secondDataSetLayer->getDataSetName(),
300  secondDataSource.get(),
301  copyInputColumns,
302  outputdataset,
303  aux.get());
304  if(!res)
305  {
306  this->setCursor(Qt::ArrowCursor);
307  QMessageBox::information(this, "Intersection", "Error: could not generate the intersection.");
308  reject();
309  }
310  }
311 
312  // creating a layer for the result
313  te::da::DataSourcePtr outDataSource = te::da::GetDataSource(m_outputDatasource->getId());
314 
315  te::qt::widgets::DataSet2Layer converter(m_outputDatasource->getId());
316 
317  te::da::DataSetTypePtr dt(outDataSource->getDataSetType(outputdataset).release());
318  m_layerResult = converter(dt);
319  }
320  catch(const std::exception& e)
321  {
322  this->setCursor(Qt::ArrowCursor);
323  QMessageBox::warning(this, TR_VP("Intersection"), e.what());
324  te::common::ProgressManager::getInstance().removeViewer(id);
325  return;
326  }
327 
328  te::common::ProgressManager::getInstance().removeViewer(id);
329  this->setCursor(Qt::ArrowCursor);
330  accept();
331 }
332 
334 {
335  m_ui->m_newLayerNameLineEdit->clear();
336  m_ui->m_newLayerNameLineEdit->setEnabled(true);
338  dlg.exec();
339 
340  std::list<te::da::DataSourceInfoPtr> dsPtrList = dlg.getSelecteds();
341 
342  if(dsPtrList.size() <= 0)
343  return;
344 
345  std::list<te::da::DataSourceInfoPtr>::iterator it = dsPtrList.begin();
346 
347  m_ui->m_repositoryLineEdit->setText(QString(it->get()->getTitle().c_str()));
348 
349  m_outputDatasource = *it;
350 
351  m_toFile = false;
352 }
353 
355 {
356  m_ui->m_newLayerNameLineEdit->clear();
357  m_ui->m_repositoryLineEdit->clear();
358 
359  QString fileName = QFileDialog::getSaveFileName(this, tr("Save as..."),
360  QString(), tr("Shapefile (*.shp *.SHP);;"),0, QFileDialog::DontConfirmOverwrite);
361 
362  if (fileName.isEmpty())
363  return;
364 
365  boost::filesystem::path outfile(fileName.toStdString());
366  std::string aux = outfile.leaf().string();
367  m_ui->m_newLayerNameLineEdit->setText(aux.c_str());
368  aux = outfile.string();
369  m_ui->m_repositoryLineEdit->setText(aux.c_str());
370 
371  m_toFile = true;
372  m_ui->m_newLayerNameLineEdit->setEnabled(false);
373 }
A layer with reference to a dataset.
Definition: DataSetLayer.h:47
const std::string & getDataSetName() const
A dialog for selecting a data source.
TEDATAACCESSEXPORT DataSourcePtr GetDataSource(const std::string &datasourceId, const bool opened=true)
Search for a data source with the informed id in the DataSourceManager.
Definition: Utils.cpp:258
IntersectionDialog(QWidget *parent=0, Qt::WindowFlags f=0)
A class that represents a data source component.
const std::list< te::da::DataSourceInfoPtr > & getSelecteds() const
static std::auto_ptr< DataSource > make(const std::string &dsType)
void onFirstLayerComboBoxChanged(int index)
const std::string & getDataSourceId() const
#define TE_UNKNOWN_SRS
A numeric value to represent a unknown SRS identification in TerraLib.
Definition: Config.h:72
A dialog intersection operation.
TEVPEXPORT bool Intersection(const std::string &inFirstDataSetName, te::da::DataSource *inFirstDataSource, const std::string &inSecondDataSetName, te::da::DataSource *inSecondDataSource, const bool &copyInputColumns, const std::string &outDataSetName, te::da::DataSource *outDataSource)
void setLayers(std::list< te::map::AbstractLayerPtr > layers)
Set the layer that can be used.
Utility functions for the data access module.
The class that defines the model used in the Qt Model/View architecture.
void onSecondLayerComboBoxChanged(int index)
std::auto_ptr< Ui::IntersectionDialogForm > m_ui
boost::shared_ptr< DataSource > DataSourcePtr
Definition: DataSource.h:1395
te::map::AbstractLayerPtr getLayer()
boost::shared_ptr< DataSetType > DataSetTypePtr
Definition: DataSetType.h:653
boost::intrusive_ptr< AbstractLayer > AbstractLayerPtr
static T & getInstance()
It returns a reference to the singleton instance.
Definition: Singleton.h:120
boost::shared_ptr< DataSourceInfo > DataSourceInfoPtr
virtual int getSRID() const
It returns the Spatial Reference System ID associated to the Layer.
#define TR_VP(message)
It marks a string in order to get translated. This is a special mark used in the Terrralib Vector Pro...
Definition: Config.h:58