All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 "../../common/Logger.h"
29 #include "../../common/Translator.h"
30 #include "../../common/STLUtils.h"
31 #include "../../dataaccess/dataset/DataSetType.h"
32 #include "../../dataaccess/dataset/ObjectIdSet.h"
33 #include "../../dataaccess/datasource/DataSourceCapabilities.h"
34 #include "../../dataaccess/datasource/DataSourceInfo.h"
35 #include "../../dataaccess/datasource/DataSourceInfoManager.h"
36 #include "../../dataaccess/datasource/DataSourceFactory.h"
37 #include "../../dataaccess/datasource/DataSourceManager.h"
38 #include "../../dataaccess/utils/Utils.h"
39 #include "../../datatype/Enums.h"
40 #include "../../datatype/Property.h"
41 #include "../../geometry/GeometryProperty.h"
42 #include "../../maptools/AbstractLayer.h"
43 #include "../../qt/af/Utils.h"
44 #include "../../qt/widgets/datasource/selector/DataSourceSelectorDialog.h"
45 #include "../../qt/widgets/layer/utils/DataSet2Layer.h"
46 #include "../../qt/widgets/progress/ProgressViewerDialog.h"
47 #include "../Config.h"
48 #include "../Exception.h"
49 #include "../PolygonToLineMemory.h"
50 #include "../PolygonToLineOp.h"
51 #include "../PolygonToLineQuery.h"
52 #include "PolygonToLineDialog.h"
53 #include "ui_PolygonToLineDialogForm.h"
54 
55 // Qt
56 #include <QFileDialog>
57 #include <QMessageBox>
58 #include <QSize>
59 
60 // Boost
61 #include <boost/algorithm/string.hpp>
62 #include <boost/filesystem.hpp>
63 #include <boost/uuid/random_generator.hpp>
64 #include <boost/uuid/uuid_io.hpp>
65 
66 te::vp::PolygonToLineDialog::PolygonToLineDialog(QWidget* parent, Qt::WindowFlags f)
67  : QDialog(parent, f),
68  m_ui(new Ui::PolygonToLineDialogForm),
69  m_layers(std::list<te::map::AbstractLayerPtr>()),
70  m_selectedLayer(0),
71  m_toFile(false)
72 {
73 // add controls
74  m_ui->setupUi(this);
75 
76 // add icons
77  m_ui->m_imgLabel->setPixmap(QIcon::fromTheme("vp-polygon-line-hint").pixmap(112,48));
78  m_ui->m_targetDatasourceToolButton->setIcon(QIcon::fromTheme("datasource"));
79 
80 //signals
81 
82  connect(m_ui->m_layersComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onLayerComboBoxChanged(int)));
83 
84  connect(m_ui->m_targetDatasourceToolButton, SIGNAL(pressed()), this, SLOT(onTargetDatasourceToolButtonPressed()));
85  connect(m_ui->m_targetFileToolButton, SIGNAL(pressed()), this, SLOT(onTargetFileToolButtonPressed()));
86 
87  connect(m_ui->m_okPushButton, SIGNAL(clicked()), this, SLOT(onOkPushButtonClicked()));
88  connect(m_ui->m_cancelPushButton, SIGNAL(clicked()), this, SLOT(onCancelPushButtonClicked()));
89 
90  m_ui->m_helpPushButton->setNameSpace("dpi.inpe.br.plugins");
91  m_ui->m_helpPushButton->setPageReference("plugins/vp/vp_polygonToLine.html");
92 }
93 
95 {
96 }
97 
98 void te::vp::PolygonToLineDialog::setLayers(std::list<te::map::AbstractLayerPtr> layers)
99 {
100  m_layers = layers;
101 
102  std::list<te::map::AbstractLayerPtr>::iterator it = m_layers.begin();
103 
104  while(it != m_layers.end())
105  {
106  std::auto_ptr<te::map::LayerSchema> layerSchema = it->get()->getSchema();
107  te::gm::GeometryProperty* prop = static_cast<te::gm::GeometryProperty*>(layerSchema->findFirstPropertyOfType(te::dt::GEOMETRY_TYPE));
108 
109  if(!prop)
110  {
111  ++it;
112  continue;
113  }
114 
115  te::gm::GeomType geomType = prop->getGeometryType();
116 
117  if( geomType == te::gm::PolygonMType || geomType == te::gm::PolygonType || geomType == te::gm::PolygonZMType || geomType == te::gm::PolygonZType ||
118  geomType == te::gm::MultiPolygonMType || geomType == te::gm::MultiPolygonType || geomType == te::gm::MultiPolygonZMType || geomType == te::gm::MultiPolygonZType)
119  m_ui->m_layersComboBox->addItem(QString(it->get()->getTitle().c_str()), QVariant(it->get()->getId().c_str()));
120 
121  ++it;
122  }
123 }
124 
126 {
127  return m_outLayer;
128 }
129 
131 {
132  std::list<te::map::AbstractLayerPtr>::iterator it = m_layers.begin();
133 
134  std::string layerID = m_ui->m_layersComboBox->itemData(index, Qt::UserRole).toString().toStdString();
135 
136  while(it != m_layers.end())
137  {
138  if(layerID == it->get()->getId().c_str())
139  {
140  te::map::AbstractLayerPtr selectedLayer = it->get();
141  m_selectedLayer = selectedLayer;
142 
143  return;
144  }
145  ++it;
146  }
147 }
148 
150 {
151  m_ui->m_newLayerNameLineEdit->clear();
152  m_ui->m_newLayerNameLineEdit->setEnabled(true);
154  dlg.exec();
155 
156  std::list<te::da::DataSourceInfoPtr> dsPtrList = dlg.getSelecteds();
157 
158  if(dsPtrList.size() <= 0)
159  return;
160 
161  std::list<te::da::DataSourceInfoPtr>::iterator it = dsPtrList.begin();
162 
163  m_ui->m_repositoryLineEdit->setText(QString(it->get()->getTitle().c_str()));
164 
165  m_outputDatasource = *it;
166 
167  m_toFile = false;
168 }
169 
171 {
172  m_ui->m_newLayerNameLineEdit->clear();
173  m_ui->m_repositoryLineEdit->clear();
174 
175  QString fileName = QFileDialog::getSaveFileName(this, tr("Save as..."),
176  QString(), tr("Shapefile (*.shp *.SHP);;"),0, QFileDialog::DontConfirmOverwrite);
177 
178  if (fileName.isEmpty())
179  return;
180 
181  boost::filesystem::path outfile(fileName.toStdString());
182  std::string aux = outfile.leaf().string();
183  m_ui->m_newLayerNameLineEdit->setText(aux.c_str());
184  aux = outfile.string();
185  m_ui->m_repositoryLineEdit->setText(aux.c_str());
186 
187  m_toFile = true;
188  m_ui->m_newLayerNameLineEdit->setEnabled(false);
189 }
190 
192 {
193  if(m_ui->m_layersComboBox->count() == 0)
194  {
195  QMessageBox::information(this, "Polygon to line", "Select input layer.");
196  return;
197  }
198 
199  te::map::DataSetLayer* dsLayer = dynamic_cast<te::map::DataSetLayer*>(m_selectedLayer.get());
200  if(!dsLayer)
201  {
202  QMessageBox::information(this, "Polygon to line", "Can not execute this operation on this type of layer.");
203  }
204 
205  const te::da::ObjectIdSet* oidSet = 0;
206  if(m_ui->m_onlySelectedCheckBox->isChecked())
207  {
208  oidSet = m_selectedLayer->getSelected();
209  if(!oidSet)
210  {
211  QMessageBox::information(this, "Polygon to line", "Select the layer objects to perform the polygon to line operation.");
212  return;
213  }
214  }
215 
216  te::da::DataSourcePtr inDataSource = te::da::GetDataSource(dsLayer->getDataSourceId(), true);
217  if(!inDataSource.get())
218  {
219  QMessageBox::information(this, "Polygon to line", "The selected input data source can not be accessed.");
220  return;
221  }
222 
223  if(m_ui->m_repositoryLineEdit->text().isEmpty())
224  {
225  QMessageBox::information(this, "Polygon to line", "Define a repository for the result.");
226  return;
227  }
228 
229  std::string outputDataSet = m_ui->m_newLayerNameLineEdit->text().toStdString();
230  if(outputDataSet.empty())
231  {
232  QMessageBox::information(this, "Polygon to line", "Define a name for the resulting layer.");
233  return;
234  }
235 
236  bool res;
237 
238  //progress
241 
242  try
243  {
244  if(m_toFile)
245  {
246  boost::filesystem::path uri(m_ui->m_repositoryLineEdit->text().toStdString());
247  if (boost::filesystem::exists(uri))
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::map<std::string, std::string> dsinfo;
258  dsinfo["URI"] = uri.string();
259 
261  dsOGR->setConnectionInfo(dsinfo);
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  this->setCursor(Qt::WaitCursor);
270 
271  te::vp::PolygonToLineOp* pol2LineOp = 0;
272 
273  // select a strategy based on the capabilities of the input datasource
274  const te::da::DataSourceCapabilities dsCapabilities = inDataSource->getCapabilities();
275 
276  if(dsCapabilities.supportsPreparedQueryAPI() && dsCapabilities.getQueryCapabilities().supportsSpatialSQLDialect())
277  pol2LineOp = new te::vp::PolygonToLineQuery();
278  else
279  pol2LineOp = new te::vp::PolygonToLineMemory();
280 
281  pol2LineOp->setInput(inDataSource, dsLayer->getDataSetName(), oidSet);
282  pol2LineOp->setOutput(dsOGR, outputDataSet);
283 
284  if(!pol2LineOp->paramsAreValid())
285  res = false;
286  else
287  res = pol2LineOp->run();
288 
289  if(!res)
290  {
291  this->setCursor(Qt::ArrowCursor);
292  dsOGR->close();
293  QMessageBox::information(this, "Polygon to Line", "Error: Error in operation.");
294  reject();
295  }
296  dsOGR->close();
297 
298  delete pol2LineOp;
299 
300  // let's include the new datasource in the managers
301  boost::uuids::basic_random_generator<boost::mt19937> gen;
302  boost::uuids::uuid u = gen();
303  std::string id_ds = boost::uuids::to_string(u);
304 
306  ds->setConnInfo(dsinfo);
307  ds->setTitle(uri.stem().string());
308  ds->setAccessDriver("OGR");
309  ds->setType("OGR");
310  ds->setDescription(uri.string());
311  ds->setId(id_ds);
312 
313  te::da::DataSourcePtr newds = te::da::DataSourceManager::getInstance().get(id_ds, "OGR", ds->getConnInfo());
314  newds->open();
316  m_outputDatasource = ds;
317 
318  }
319  else
320  {
321  te::da::DataSourcePtr dsOGR = te::da::GetDataSource(m_outputDatasource->getId());
322  if(!dsOGR)
323  {
324  QMessageBox::information(this, "Polygon to Line", "The selected output datasource can not be accessed.");
325  return;
326  }
327 
328  if(dsOGR->dataSetExists(outputDataSet))
329  {
330  QMessageBox::information(this, "Polygon to Line", "Dataset already exists. Remove ir or select a new name and try again.");
331  return;
332  }
333 
334  this->setCursor(Qt::WaitCursor);
335 
336  te::vp::PolygonToLineOp* pol2LineOp = 0;
337 
338  const te::da::DataSourceCapabilities dsCapabilities = inDataSource->getCapabilities();
339 
340  if(dsCapabilities.supportsPreparedQueryAPI() && dsCapabilities.getQueryCapabilities().supportsSpatialSQLDialect())
341  pol2LineOp = new te::vp::PolygonToLineQuery();
342  else
343  pol2LineOp = new te::vp::PolygonToLineMemory();
344 
345  pol2LineOp->setInput(inDataSource, dsLayer->getDataSetName(), oidSet);
346  pol2LineOp->setOutput(dsOGR, outputDataSet);
347 
348  if(!pol2LineOp->paramsAreValid())
349  res = false;
350  else
351  res = pol2LineOp->run();
352 
353  delete pol2LineOp;
354 
355  if(!res)
356  {
357  this->setCursor(Qt::ArrowCursor);
358  QMessageBox::information(this, "Polygon to Line", "Error in operation.");
359  reject();
360  }
361  }
362 
363  te::da::DataSourcePtr outDataSource = te::da::GetDataSource(m_outputDatasource->getId());
364  te::qt::widgets::DataSet2Layer converter(m_outputDatasource->getId());
365  te::da::DataSetTypePtr dt(outDataSource->getDataSetType(outputDataSet).release());
366 
367  m_outLayer = converter(dt);
368  }
369  catch(const std::exception& e)
370  {
371  this->setCursor(Qt::ArrowCursor);
372 
373  QMessageBox::information(this, "Polygon to Line", e.what());
374 
375 #ifdef TERRALIB_LOGGER_ENABLED
376  std::string str = "Polygon to Line - ";
377  str += e.what();
378  te::common::Logger::logDebug("vp", str.c_str());
379 #endif
380 
382  return;
383  }
384 
386  this->setCursor(Qt::ArrowCursor);
387 
388  accept();
389 }
390 
392 {
393  reject();
394 }
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:262
Geometric property.
GeomType
Each enumerated type is compatible with a Well-known Binary (WKB) type code.
Definition: Enums.h:41
const std::string & getDataSetName() const
A dialog for polygon to line operation.
boost::shared_ptr< DataSetType > DataSetTypePtr
Definition: DataSetType.h:653
boost::shared_ptr< DataSource > DataSourcePtr
Definition: DataSource.h:1435
virtual bool run()=0
A class that represents the known capabilities of a specific data source, i.e. this class informs all...
std::auto_ptr< Ui::PolygonToLineDialogForm > m_ui
const QueryCapabilities & getQueryCapabilities() const
void setLayers(std::list< te::map::AbstractLayerPtr > layers)
Set the layer that can be used.
PolygonToLineDialog(QWidget *parent=0, Qt::WindowFlags f=0)
void removeViewer(int viewerId)
Dettach a progress viewer.
static ProgressManager & getInstance()
It returns a reference to the singleton instance.
const std::string & getDataSourceId() const
This class represents a set of unique ids created in the same context. i.e. from the same data set...
Definition: ObjectIdSet.h:55
static std::auto_ptr< DataSource > make(const std::string &dsType)
GeomType getGeometryType() const
It returns the geometry subtype allowed for the property.
bool supportsSpatialSQLDialect() const
void setInput(te::da::DataSourcePtr inDsrc, std::string inDsetName, const te::da::ObjectIdSet *oidSet=0)
te::map::AbstractLayerPtr getLayer()
int addViewer(AbstractProgressViewer *apv)
Attach a progress viewer.
const std::list< te::da::DataSourceInfoPtr > & getSelecteds() const
void setOutput(te::da::DataSourcePtr outDsrc, std::string dsname)
A dialog for selecting a data source.
A class that represents a data source component.
A layer with reference to a dataset.
Definition: DataSetLayer.h:47
boost::intrusive_ptr< AbstractLayer > AbstractLayerPtr
boost::shared_ptr< DataSourceInfo > DataSourceInfoPtr