PolygonToLineDialog.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/PolygonToLineDialog.cpp
22 
23  \brief A dialog for polygon to line operation
24 */
25 
26 // TerraLib
27 #include "../../common/progress/ProgressManager.h"
28 #include "../../core/filesystem/FileSystem.h"
29 #include "../../core/logger/Logger.h"
30 #include "../../core/translator/Translator.h"
31 #include "../../common/STLUtils.h"
32 #include "../../dataaccess/dataset/DataSetType.h"
33 #include "../../dataaccess/dataset/DataSetTypeConverter.h"
34 #include "../../dataaccess/dataset/ObjectIdSet.h"
35 #include "../../dataaccess/datasource/DataSourceCapabilities.h"
36 #include "../../dataaccess/datasource/DataSourceInfo.h"
37 #include "../../dataaccess/datasource/DataSourceInfoManager.h"
38 #include "../../dataaccess/datasource/DataSourceFactory.h"
39 #include "../../dataaccess/datasource/DataSourceManager.h"
40 #include "../../dataaccess/utils/Utils.h"
41 #include "../../datatype/Enums.h"
42 #include "../../datatype/Property.h"
43 #include "../../geometry/GeometryProperty.h"
44 #include "../../maptools/AbstractLayer.h"
45 #include "../../qt/af/Utils.h"
46 #include "../../qt/widgets/datasource/selector/DataSourceSelectorDialog.h"
47 #include "../../qt/widgets/layer/utils/DataSet2Layer.h"
48 #include "../../qt/widgets/progress/ProgressViewerDialog.h"
49 #include "../../qt/widgets/utils/FileDialog.h"
50 #include "../Config.h"
51 #include "../Exception.h"
52 #include "../PolygonToLineMemory.h"
53 #include "../PolygonToLineOp.h"
54 #include "../PolygonToLineQuery.h"
55 #include "PolygonToLineDialog.h"
56 #include "ui_PolygonToLineDialogForm.h"
57 
58 // Qt
59 #include <QFileDialog>
60 #include <QMessageBox>
61 #include <QSize>
62 
63 // Boost
64 #include <boost/algorithm/string.hpp>
65 #include <boost/filesystem.hpp>
66 #include <boost/uuid/random_generator.hpp>
67 #include <boost/uuid/uuid_io.hpp>
68 
70  : QDialog(parent, f),
71  m_ui(new Ui::PolygonToLineDialogForm),
72  m_layers(std::list<te::map::AbstractLayerPtr>()),
73  m_selectedLayer(nullptr),
74  m_toFile(false)
75 {
76 // add controls
77  m_ui->setupUi(this);
78 
79 // add icons
80  m_ui->m_imgLabel->setPixmap(QIcon::fromTheme("vp-polygon-line-hint").pixmap(112,48));
81  m_ui->m_targetDatasourceToolButton->setIcon(QIcon::fromTheme("datasource"));
82 
83 //signals
84 
85  connect(m_ui->m_layersComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onLayerComboBoxChanged(int)));
86 
87  connect(m_ui->m_targetDatasourceToolButton, SIGNAL(pressed()), this, SLOT(onTargetDatasourceToolButtonPressed()));
88  connect(m_ui->m_targetFileToolButton, SIGNAL(pressed()), this, SLOT(onTargetFileToolButtonPressed()));
89 
90  connect(m_ui->m_okPushButton, SIGNAL(clicked()), this, SLOT(onOkPushButtonClicked()));
91  connect(m_ui->m_cancelPushButton, SIGNAL(clicked()), this, SLOT(onCancelPushButtonClicked()));
92 
93  m_ui->m_helpPushButton->setNameSpace("dpi.inpe.br.plugins");
94  m_ui->m_helpPushButton->setPageReference("plugins/vp/vp_polygonToLine.html");
95 }
96 
98 
99 void te::vp::PolygonToLineDialog::setLayers(std::list<te::map::AbstractLayerPtr> layers)
100 {
101  m_layers = layers;
102 
103  std::list<te::map::AbstractLayerPtr>::iterator it = m_layers.begin();
104 
105  while(it != m_layers.end())
106  {
107  std::unique_ptr<te::map::LayerSchema> layerSchema = it->get()->getSchema();
108  te::gm::GeometryProperty* prop = static_cast<te::gm::GeometryProperty*>(layerSchema->findFirstPropertyOfType(te::dt::GEOMETRY_TYPE));
109 
110  if(!prop)
111  {
112  ++it;
113  continue;
114  }
115 
116  te::gm::GeomType geomType = prop->getGeometryType();
117 
118  if( geomType == te::gm::PolygonMType || geomType == te::gm::PolygonType || geomType == te::gm::PolygonZMType || geomType == te::gm::PolygonZType ||
119  geomType == te::gm::MultiPolygonMType || geomType == te::gm::MultiPolygonType || geomType == te::gm::MultiPolygonZMType || geomType == te::gm::MultiPolygonZType)
120  m_ui->m_layersComboBox->addItem(QString(it->get()->getTitle().c_str()), QVariant(it->get()->getId().c_str()));
121 
122  ++it;
123  }
124 }
125 
127 {
128  return m_outLayer;
129 }
130 
132 {
133  std::list<te::map::AbstractLayerPtr>::iterator it = m_layers.begin();
134 
135  std::string layerID = m_ui->m_layersComboBox->itemData(index, Qt::UserRole).toString().toUtf8().data();
136 
137  while(it != m_layers.end())
138  {
139  if(layerID == it->get()->getId())
140  {
141  te::map::AbstractLayerPtr selectedLayer = it->get();
142  m_selectedLayer = selectedLayer;
143 
144  return;
145  }
146  ++it;
147  }
148 }
149 
151 {
152  m_ui->m_newLayerNameLineEdit->clear();
153  m_ui->m_newLayerNameLineEdit->setEnabled(true);
155  dlg.exec();
156 
157  std::list<te::da::DataSourceInfoPtr> dsPtrList = dlg.getSelecteds();
158 
159  if(dsPtrList.empty())
160  return;
161 
162  std::list<te::da::DataSourceInfoPtr>::iterator it = dsPtrList.begin();
163 
164  m_ui->m_repositoryLineEdit->setText(QString(it->get()->getTitle().c_str()));
165 
166  m_outputDatasource = *it;
167 
168  m_toFile = false;
169 }
170 
172 {
173  m_ui->m_newLayerNameLineEdit->clear();
174  m_ui->m_repositoryLineEdit->clear();
175 
177 
178  try {
179  fileDialog.exec();
180  }
181  catch (te::common::Exception& ex) {
182  QMessageBox::warning(this, tr("File information"), ex.what());
183  return;
184  }
185  m_ui->m_repositoryLineEdit->setText(fileDialog.getPath().c_str());
186  m_ui->m_newLayerNameLineEdit->setText(fileDialog.getFileName().c_str());
187 
188  m_toFile = true;
189  m_ui->m_newLayerNameLineEdit->setEnabled(false);
190 }
191 
193 {
194  if(m_ui->m_layersComboBox->count() == 0)
195  {
196  QMessageBox::information(this, "Polygon to line", "Select input layer.");
197  return;
198  }
199 
200  te::map::DataSetLayer* dsLayer = dynamic_cast<te::map::DataSetLayer*>(m_selectedLayer.get());
201  if(!dsLayer)
202  {
203  QMessageBox::information(this, "Polygon to line", "Can not execute this operation on this type of layer.");
204  }
205 
206  const te::da::ObjectIdSet* oidSet = nullptr;
207  if(m_ui->m_onlySelectedCheckBox->isChecked())
208  {
209  oidSet = m_selectedLayer->getSelected();
210  if(!oidSet)
211  {
212  QMessageBox::information(this, "Polygon to line", "Select the layer objects to perform the polygon to line operation.");
213  return;
214  }
215  }
216 
217  te::da::DataSourcePtr inDataSource = te::da::GetDataSource(dsLayer->getDataSourceId(), true);
218  if(!inDataSource.get())
219  {
220  QMessageBox::information(this, "Polygon to line", "The selected input data source can not be accessed.");
221  return;
222  }
223 
224  if(m_ui->m_repositoryLineEdit->text().isEmpty())
225  {
226  QMessageBox::information(this, "Polygon to line", "Define a repository for the result.");
227  return;
228  }
229 
230  std::string outputDataSet = m_ui->m_newLayerNameLineEdit->text().toUtf8().data();
231  if(outputDataSet.empty())
232  {
233  QMessageBox::information(this, "Polygon to line", "Define a name for the resulting layer.");
234  return;
235  }
236 
237  bool res;
238 
239  //progress
241 
242  try
243  {
244  if(m_toFile)
245  {
246  boost::filesystem::path uri(m_ui->m_repositoryLineEdit->text().toUtf8().data());
247  if (te::core::FileSystem::exists(uri.string()))
248  {
249  QMessageBox::information(this, "Polygon to line", "Output file already exists. Remove it or select a new name and try again.");
250  return;
251  }
252 
253  std::size_t idx = outputDataSet.find(".");
254  if (idx != std::string::npos)
255  outputDataSet=outputDataSet.substr(0,idx);
256 
257  std::string dsinfo("file://");
258  dsinfo += uri.string();
259 
260  te::da::DataSourcePtr dsOGR(te::da::DataSourceFactory::make("OGR", dsinfo).release());
261 
262  dsOGR->open();
263  if (dsOGR->dataSetExists(outputDataSet))
264  {
265  QMessageBox::information(this, "Polygon to Line", "There is already a dataset with the requested name in the output data source. Remove it or select a new name and try again.");
266  return;
267  }
268 
269  std::unique_ptr<te::da::DataSetTypeConverter> converter(new te::da::DataSetTypeConverter(dsLayer->getSchema().get(), dsOGR->getCapabilities(), dsOGR->getEncoding()));
270 
271  te::da::AssociateDataSetTypeConverterSRID(converter.get(), dsLayer->getSRID());
272 
273  this->setCursor(Qt::WaitCursor);
274 
275  te::vp::PolygonToLineOp* pol2LineOp = nullptr;
276 
277  // select a strategy based on the capabilities of the input datasource
278  const te::da::DataSourceCapabilities dsCapabilities = inDataSource->getCapabilities();
279 
280  if(dsCapabilities.supportsPreparedQueryAPI() && dsCapabilities.getQueryCapabilities().supportsSpatialSQLDialect())
281  pol2LineOp = new te::vp::PolygonToLineQuery();
282  else
283  pol2LineOp = new te::vp::PolygonToLineMemory();
284 
285  pol2LineOp->setInput(inDataSource, dsLayer->getDataSetName(), std::move(converter), oidSet);
286  pol2LineOp->setOutput(dsOGR, outputDataSet);
287 
288  if(!pol2LineOp->paramsAreValid())
289  res = false;
290  else
291  res = pol2LineOp->run();
292 
293  if(!res)
294  {
295  this->setCursor(Qt::ArrowCursor);
296  dsOGR->close();
297  QMessageBox::information(this, "Polygon to Line", "Error: Error in operation.");
298  reject();
299  }
300  dsOGR->close();
301 
302  delete pol2LineOp;
303 
304  // let's include the new datasource in the managers
305  boost::uuids::basic_random_generator<boost::mt19937> gen;
306  boost::uuids::uuid u = gen();
307  std::string id_ds = boost::uuids::to_string(u);
308 
310  ds->setConnInfo(dsinfo);
311  ds->setTitle(uri.stem().string());
312  ds->setAccessDriver("OGR");
313  ds->setType("OGR");
314  ds->setDescription(uri.string());
315  ds->setId(id_ds);
316 
317  te::da::DataSourcePtr newds = te::da::DataSourceManager::getInstance().get(id_ds, "OGR", ds->getConnInfo());
318  newds->open();
321 
322  }
323  else
324  {
326  if(!dsOGR)
327  {
328  QMessageBox::information(this, "Polygon to Line", "The selected output datasource can not be accessed.");
329  return;
330  }
331 
332  if(dsOGR->dataSetExists(outputDataSet))
333  {
334  QMessageBox::information(this, "Polygon to Line", "Dataset already exists. Remove ir or select a new name and try again.");
335  return;
336  }
337 
338  std::unique_ptr<te::da::DataSetTypeConverter> converter(new te::da::DataSetTypeConverter(dsLayer->getSchema().get(), dsOGR->getCapabilities(), dsOGR->getEncoding()));
339 
340  te::da::AssociateDataSetTypeConverterSRID(converter.get(), dsLayer->getSRID());
341 
342  this->setCursor(Qt::WaitCursor);
343 
344  te::vp::PolygonToLineOp* pol2LineOp = nullptr;
345 
346  const te::da::DataSourceCapabilities dsCapabilities = inDataSource->getCapabilities();
347 
348  if(dsCapabilities.supportsPreparedQueryAPI() && dsCapabilities.getQueryCapabilities().supportsSpatialSQLDialect())
349  pol2LineOp = new te::vp::PolygonToLineQuery();
350  else
351  pol2LineOp = new te::vp::PolygonToLineMemory();
352 
353  pol2LineOp->setInput(inDataSource, dsLayer->getDataSetName(), std::move(converter), oidSet);
354  pol2LineOp->setOutput(dsOGR, outputDataSet);
355 
356  if(!pol2LineOp->paramsAreValid())
357  res = false;
358  else
359  res = pol2LineOp->run();
360 
361  delete pol2LineOp;
362 
363  if(!res)
364  {
365  this->setCursor(Qt::ArrowCursor);
366  QMessageBox::information(this, "Polygon to Line", "Error in operation.");
367  reject();
368  }
369  }
370 
373  te::da::DataSetTypePtr dt(outDataSource->getDataSetType(outputDataSet).release());
374 
375  m_outLayer = converter(dt);
376  }
377  catch(const std::exception& e)
378  {
379  this->setCursor(Qt::ArrowCursor);
380 
381  QMessageBox::information(this, "Polygon to Line", e.what());
382 
383  std::string str = "Vector Processing - Polygon to Line - ";
384  str += e.what();
385  TE_LOG_ERROR(str);
386 
387  return;
388  }
389 
390  this->setCursor(Qt::ArrowCursor);
391 
392  accept();
393 }
394 
396 {
397  reject();
398 }
TEDATAACCESSEXPORT DataSourcePtr GetDataSource(const std::string &datasourceId, const bool opened=true)
Search for a data source with the informed id in the DataSourceManager.
static std::unique_ptr< DataSource > make(const std::string &driver, const te::core::URI &connInfo)
Geometric property.
Defines a component for choose a file.
Definition: FileDialog.h:52
GeomType
Each enumerated type is compatible with a Well-known Binary (WKB) type code.
A dialog for polygon to line operation.
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
boost::shared_ptr< DataSource > DataSourcePtr
TEDATAACCESSEXPORT void AssociateDataSetTypeConverterSRID(DataSetTypeConverter *converter, const int &inputSRID, const int &outputSRID=TE_UNKNOWN_SRS)
virtual const char * what() const
It outputs the exception message.
te::map::AbstractLayerPtr m_selectedLayer
Layer used for operation.
std::unique_ptr< Ui::PolygonToLineDialogForm > m_ui
std::list< te::map::AbstractLayerPtr > m_layers
List of layers.
virtual bool run()=0
std::unique_ptr< LayerSchema > getSchema() const
It returns the layer schema.
A class that represents the known capabilities of a specific data source, i.e. this class informs all...
static te::dt::Date ds(2010, 01, 01)
const QueryCapabilities & getQueryCapabilities() const
void setLayers(std::list< te::map::AbstractLayerPtr > layers)
Set the layer that can be used.
An converter for DataSetType.
te::map::AbstractLayerPtr m_outLayer
Resulting layer.
PolygonToLineDialog(QWidget *parent=0, Qt::WindowFlags f=0)
static DataSourceManager & getInstance()
It returns a reference to the singleton instance.
This class represents a set of unique ids created in the same context. i.e. from the same data set...
Definition: ObjectIdSet.h:55
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
void setInput(te::da::DataSourcePtr inDsrc, std::string inDsetName, std::unique_ptr< te::da::DataSetTypeConverter > converter, const te::da::ObjectIdSet *oidSet=0)
GeomType getGeometryType() const
It returns the geometry subtype allowed for the property.
static te::dt::TimeDuration dt(20, 30, 50, 11)
bool supportsSpatialSQLDialect() const
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
te::map::AbstractLayerPtr getLayer()
std::string getPath()
This method will return the chosen path.
Definition: FileDialog.cpp:103
const std::string & getDataSetName() const
const std::list< te::da::DataSourceInfoPtr > & getSelecteds() const
void setOutput(te::da::DataSourcePtr outDsrc, std::string dsname)
A dialog for selecting a data source.
#define TE_LOG_ERROR(message)
Use this tag in order to log a message to the TerraLib default logger with the ERROR level...
Definition: Logger.h:337
A class that represents a data source component.
te::da::DataSourceInfoPtr m_outputDatasource
DataSource information.
virtual int getSRID() const
It returns the Spatial Reference System ID associated to the Layer.
A layer with reference to a dataset.
Definition: DataSetLayer.h:47
std::string getFileName()
This method will return the file name.
Definition: FileDialog.cpp:113
boost::intrusive_ptr< AbstractLayer > AbstractLayerPtr
virtual const std::string & getDataSourceId() const
boost::shared_ptr< DataSourceInfo > DataSourceInfoPtr