All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
GeometricOpWizard.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/GeometricOpWizard.cpp
22 
23  \brief A Qt dialog that allows users to run the basic geographic operations defined by VP module.
24 */
25 
26 // TerraLib
27 #include "../Enums.h"
28 #include "../../common/Logger.h"
29 #include "../../common/progress/ProgressManager.h"
30 #include "../../dataaccess/dataset/DataSet.h"
31 #include "../../dataaccess/dataset/DataSetType.h"
32 #include "../../dataaccess/datasource/DataSourceCapabilities.h"
33 #include "../../dataaccess/datasource/DataSourceInfo.h"
34 #include "../../dataaccess/datasource/DataSourceInfoManager.h"
35 #include "../../dataaccess/datasource/DataSourceFactory.h"
36 #include "../../dataaccess/datasource/DataSourceManager.h"
37 #include "../../dataaccess/utils/Utils.h"
38 
39 #include "../../maptools/AbstractLayer.h"
40 
41 #include "../../qt/widgets/help/HelpPushButton.h"
42 #include "../../qt/widgets/progress/ProgressViewerDialog.h"
43 #include "../../qt/widgets/layer/search/LayerSearchWidget.h"
44 #include "../../qt/widgets/layer/search/LayerSearchWizardPage.h"
45 #include "../../qt/widgets/layer/utils/DataSet2Layer.h"
46 
47 #include "../Config.h"
48 #include "../Exception.h"
49 
50 #include "GeometricOpWizard.h"
51 #include "GeometricOpWizardPage.h"
53 #include "../GeometricOp.h"
54 #include "../GeometricOpMemory.h"
55 #include "../GeometricOpQuery.h"
56 //#include "Utils.h"
57 
58 // STL
59 #include <cassert>
60 
61 // Qt
62 #include <QMessageBox>
63 
64 // Boost
65 #include <boost/filesystem.hpp>
66 #include <boost/uuid/random_generator.hpp>
67 #include <boost/uuid/uuid_io.hpp>
68 
70  : QWizard(parent)
71 {
72  //configure the wizard
73  this->setWizardStyle(QWizard::ModernStyle);
74  this->setWindowTitle(tr("Geometric Operation"));
75 
76  this->setOption(QWizard::HaveHelpButton, true);
77  this->setOption(QWizard::HelpButtonOnRight, false);
78 
80 
81  this->setButton(QWizard::HelpButton, helpButton);
82 
83  helpButton->setPageReference("plugins/vp/vp_geometricOper.html");
84 
85  addPages();
86 }
87 
89 {
90 
91 }
92 
94 {
95  if(currentPage() == m_layerSearchPage.get())
96  {
97  std::list<te::map::AbstractLayerPtr> list = m_layerSearchPage->getSearchWidget()->getSelecteds();
98 
99  if(list.empty() == false)
100  {
101  te::map::AbstractLayerPtr l = *list.begin();
102  m_geomOpPage->setLayer(l);
103  m_inLayer = l;
104 
105  std::auto_ptr<te::da::DataSetType> dsType = l->getSchema();
106  std::vector<te::dt::Property*> vecProp = dsType->getProperties();
107  std::vector<std::string> vecPropName;
108 
109  for(std::size_t i = 0; i < vecProp.size(); ++i)
110  {
111  if(vecProp[i]->getType() != te::dt::GEOMETRY_TYPE)
112  vecPropName.push_back(vecProp[i]->getName());
113  }
114 
115  m_geomOpOutputPage->setAttributes(vecPropName);
116  }
117 
118  return m_layerSearchPage->isComplete();
119  }
120  else if(currentPage() == m_geomOpOutputPage.get())
121  {
122  if(!m_geomOpOutputPage->getToFile())
123  {
124  if(!m_geomOpOutputPage->getDsInfoPtr())
125  {
126  QMessageBox::information(this,
127  "Basic Geographic Operation",
128  "Set the output data source before execute the operation.");
129  return false;
130  }
131  if(m_geomOpOutputPage->getOutDsName() == "")
132  {
133  QMessageBox::information(this,
134  "Basic Geographic Operation",
135  "Set a Name for the output dataset before execute the operation.");
136  return false;
137  }
138  }
139 
140  return execute();
141  }
142 
143  return true;
144 }
145 
146 void te::vp::GeometricOpWizard::setList(std::list<te::map::AbstractLayerPtr>& layerList)
147 {
148  m_layerSearchPage->getSearchWidget()->setList(layerList);
149  m_layerSearchPage->getSearchWidget()->filterOnlyByGeom();
150 }
151 
153 {
154  removePage(m_layerSearchId);
155  m_geomOpPage->setLayer(layer);
156 }
157 
159 {
160  return m_inLayer;
161 }
162 
163 std::vector<te::map::AbstractLayerPtr> te::vp::GeometricOpWizard::getOutLayer()
164 {
165  return m_outLayer;
166 }
167 
169 {
170  m_layerSearchPage.reset(new te::qt::widgets::LayerSearchWizardPage(this));
171  m_geomOpPage.reset(new te::vp::GeometricOpWizardPage(this));
172  m_geomOpOutputPage.reset(new te::vp::GeometricOpOutputWizardPage(this));
173 
174  m_layerSearchId = addPage(m_layerSearchPage.get());
175  addPage(m_geomOpPage.get());
176  addPage(m_geomOpOutputPage.get());
177 
178  //for contrast only one layer can be selected
179  m_layerSearchPage->getSearchWidget()->enableMultiSelection(false);
180 }
181 
183 {
184  bool result;
185 
186 // progress
189 
190  try
191  {
192  te::map::DataSetLayer* dsLayer = dynamic_cast<te::map::DataSetLayer*>(m_inLayer.get());
193  te::da::DataSourcePtr inDataSource = te::da::GetDataSource(dsLayer->getDataSourceId(), true);
194 
195  m_ops.clear();
196 
197  //Params
198  if(m_geomOpOutputPage->hasConvexHull())
199  m_ops.push_back(te::vp::CONVEX_HULL);
200 
201  if(m_geomOpOutputPage->hasCentroid())
202  m_ops.push_back(te::vp::CENTROID);
203 
204  if(m_geomOpOutputPage->hasMBR())
205  m_ops.push_back(te::vp::MBR);
206 
207  if(m_geomOpOutputPage->hasArea())
208  m_ops.push_back(te::vp::AREA);
209 
210  if(m_geomOpOutputPage->hasLine())
211  m_ops.push_back(te::vp::LINE);
212 
213  if(m_geomOpOutputPage->hasPerimeter())
214  m_ops.push_back(te::vp::PERIMETER);
215 
216 // get the selected properties of input layer
217  std::vector<std::string> geoProps = m_geomOpPage->getSelectedProps();
218 
219  std::string outputdataset = m_geomOpOutputPage->getOutDsName();
220  std::vector<std::string> outputDSetNames;
221 
222 //get the selected property if the operation is by attribute
223  m_attribute = m_geomOpOutputPage->getAttribute();
224 
225 // Verify output datasource
226  if(m_geomOpOutputPage->getToFile())
227  {
228  boost::filesystem::path uri(m_geomOpOutputPage->getPath());
229 
230  bool ops_selected = false;
231 
232  if(m_geomOpOutputPage->hasConvexHull())
233  {
234  boost::filesystem::path uri_file(m_geomOpOutputPage->getPath() + "/" + outputdataset + "_convex_hull.shp");
235  if (boost::filesystem::exists(uri_file))
236  {
237  QMessageBox::information(this, "Geographic Operation", "The convex hull output file already exists. Remove it or select a new name and try again.");
238  return false;
239  }
240 
241  ops_selected = true;
242  }
243  if(m_geomOpOutputPage->hasCentroid())
244  {
245  boost::filesystem::path uri_file(m_geomOpOutputPage->getPath() + "/" + outputdataset + "_centroid.shp");
246  if (boost::filesystem::exists(uri_file))
247  {
248  QMessageBox::information(this, "Geographic Operation", "The centroid output file already exists. Remove it or select a new name and try again.");
249  return false;
250  }
251 
252  ops_selected = true;
253  }
254  if(m_geomOpOutputPage->hasMBR())
255  {
256  boost::filesystem::path uri_file(m_geomOpOutputPage->getPath() + "/" + outputdataset + "_mbr.shp");
257  if (boost::filesystem::exists(uri_file))
258  {
259  QMessageBox::information(this, "Geographic Operation", "The mbr output file already exists. Remove it or select a new name and try again.");
260  return false;
261  }
262 
263  ops_selected = true;
264  }
265  if(!ops_selected)
266  {
267  boost::filesystem::path uri_file(m_geomOpOutputPage->getPath() + "/" + outputdataset + ".shp");
268  if (boost::filesystem::exists(uri_file))
269  {
270  QMessageBox::information(this, "Geographic Operation", "Output file already exists. Remove it or select a new name and try again.");
271  return false;
272  }
273  }
274 
275  std::size_t idx = outputdataset.find(".");
276 
277  if (idx != std::string::npos)
278  outputdataset=outputdataset.substr(0,idx);
279 
280  std::map<std::string, std::string> dsinfo;
281  dsinfo["URI"] = uri.string();
282  dsinfo["DRIVER"] = "ESRI Shapefile";
283 
284  std::auto_ptr<te::da::DataSource> dsOGR = te::da::DataSourceFactory::make("OGR");
285  dsOGR->setConnectionInfo(dsinfo);
286  dsOGR->open();
287  if (dsOGR->dataSetExists(outputdataset))
288  {
289  QMessageBox::information(this, "Basic Geographic Operation", "There is already a dataset with the requested name in the output data source. Remove it or select a new name and try again.");
290  return false;
291  }
292 
293  this->setCursor(Qt::WaitCursor);
294 
295  // sera feito por algum tipo de factory
296  te::vp::GeometricOp* geomOp = 0;
297 
298  // select a strategy based on the capabilities of the input datasource
299  const te::da::DataSourceCapabilities dsCapabilities = inDataSource->getCapabilities();
300 
301  if(dsCapabilities.supportsPreparedQueryAPI() && dsCapabilities.getQueryCapabilities().supportsSpatialSQLDialect())
302  {
303  geomOp = new te::vp::GeometricOpQuery();
304  }
305  else
306  {
307  geomOp = new te::vp::GeometricOpMemory();
308  }
309 
310  geomOp->setInput(inDataSource, dsLayer->getDataSetName(), dsLayer->getSchema());
311  geomOp->setOutput(dsOGR, outputdataset);
312  geomOp->setParams(geoProps,
313  m_ops,
314  m_geomOpOutputPage->getObjectStrategy(),
315  m_attribute,
316  m_geomOpOutputPage->hasOutputLayer());
317 
318  if (!geomOp->paramsAreValid())
319  result = false;
320  else
321  result = geomOp->run();
322 
323  if (!result)
324  {
325  this->setCursor(Qt::ArrowCursor);
326  QMessageBox::information(this, "Geometric Operation", "Error: could not generate the operation, check the log file.");
327  return false;
328  }
329 
330  outputDSetNames = geomOp->GetOutputDSetNames();
331 
332  delete geomOp;
333 
334  // let's include the new datasource in the managers
335  boost::uuids::basic_random_generator<boost::mt19937> gen;
336  boost::uuids::uuid u = gen();
337  std::string id = boost::uuids::to_string(u);
338 
340  ds->setConnInfo(dsinfo);
341  ds->setTitle(uri.stem().string());
342  ds->setAccessDriver("OGR");
343  ds->setType("OGR");
344  ds->setDescription(uri.string());
345  ds->setId(id);
346 
347  te::da::DataSourcePtr newds = te::da::DataSourceManager::getInstance().get(id, "OGR", ds->getConnInfo());
348  newds->open();
350  m_outputDatasource = ds;
351  }
352  else
353  {
354  m_outputDatasource = m_geomOpOutputPage->getDsInfoPtr();
355  std::auto_ptr<te::da::DataSource> trgDs = te::da::DataSourceFactory::make(m_outputDatasource->getType());
356  trgDs->setConnectionInfo(m_outputDatasource->getConnInfo());
357  trgDs->open();
358 
359  if (!trgDs.get())
360  {
361  QMessageBox::information(this, "Geometric Operation", "The selected output datasource can not be accessed.");
362  return false;
363  }
364 
365  if (trgDs->dataSetExists(outputdataset))
366  {
367  QMessageBox::information(this, "Geometric Operation", "Dataset already exists. Remove it or select a new name and try again.");
368  return false;
369  }
370 
371  te::vp::GeometricOp* geomOp = 0;
372 
373  // select a strategy based on the capabilities of the input datasource
374  const te::da::DataSourceCapabilities dsCapabilities = inDataSource->getCapabilities();
375 
376  if(dsCapabilities.supportsPreparedQueryAPI() && dsCapabilities.getQueryCapabilities().supportsSpatialSQLDialect())
377  {
378  geomOp = new te::vp::GeometricOpQuery();
379  }
380  else
381  {
382  geomOp = new te::vp::GeometricOpMemory();
383  }
384 
385  geomOp->setInput(inDataSource, dsLayer->getDataSetName(), dsLayer->getSchema());
386  geomOp->setOutput(trgDs, outputdataset);
387  geomOp->setParams(geoProps,
388  m_ops,
389  m_geomOpOutputPage->getObjectStrategy(),
390  m_attribute,
391  m_geomOpOutputPage->hasOutputLayer());
392 
393  if (!geomOp->paramsAreValid())
394  result = false;
395  else
396  result = geomOp->run();
397 
398  if (!result)
399  {
400  this->setCursor(Qt::ArrowCursor);
401  QMessageBox::information(this, "Geometric Operation", "Error: could not generate the operation.");
402  return false;
403  }
404 
405  outputDSetNames = geomOp->GetOutputDSetNames();
406 
407  delete geomOp;
408  }
409 
410 // creating a layer for the result
411  te::da::DataSourcePtr outDataSource = te::da::GetDataSource(m_outputDatasource->getId());
412  te::qt::widgets::DataSet2Layer converter(m_outputDatasource->getId());
413 
414  for(std::size_t i = 0; i < outputDSetNames.size(); ++i)
415  {
416  te::da::DataSetTypePtr dt(outDataSource->getDataSetType(outputDSetNames[i]).release());
417  if(dt)
418  m_outLayer.push_back(converter(dt));
419  }
420  }
421  catch(const std::exception& e)
422  {
423  this->setCursor(Qt::ArrowCursor);
424  QMessageBox::information(this, "Greographic Operation", e.what());
425 
426 #ifdef TERRALIB_LOGGER_ENABLED
427  std::string str = "Greographic Operation - ";
428  str += e.what();
429  te::common::Logger::logDebug("vp", str.c_str());
430 #endif
431 
433  return false;
434  }
435 
437  this->setCursor(Qt::ArrowCursor);
438 
439  return true;
440 }
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
void setList(std::list< te::map::AbstractLayerPtr > &layerList)
const std::string & getDataSetName() const
std::vector< std::string > GetOutputDSetNames()
Definition: GeometricOp.cpp:90
boost::shared_ptr< DataSetType > DataSetTypePtr
Definition: DataSetType.h:653
The geographic operation Line.
Definition: Enums.h:106
boost::shared_ptr< DataSource > DataSourcePtr
Definition: DataSource.h:1435
The geographic operation Minimum Bounding Rectangle.
Definition: Enums.h:104
void setLayer(te::map::AbstractLayerPtr layer)
void setPageReference(const QString &ref)
Sets the documentation page reference.
A class that represents the known capabilities of a specific data source, i.e. this class informs all...
This class is GUI used to define the basic geometric operator parameters for the VP operation...
const QueryCapabilities & getQueryCapabilities() const
The geographic operation Area.
Definition: Enums.h:105
void removeViewer(int viewerId)
Dettach a progress viewer.
static ProgressManager & getInstance()
It returns a reference to the singleton instance.
const std::string & getDataSourceId() const
static std::auto_ptr< DataSource > make(const std::string &dsType)
A Qt dialog that allows users to run the basic geometric operations defined by VP module...
The geographic operation Perimeter.
Definition: Enums.h:107
bool supportsSpatialSQLDialect() const
void setOutput(std::auto_ptr< te::da::DataSource > outDsrc, std::string dsname)
Definition: GeometricOp.cpp:70
The geographic operation Centroid.
Definition: Enums.h:103
std::vector< te::map::AbstractLayerPtr > getOutLayer()
This file defines a class for Basic Geometric Operation Wizard Page.
int addViewer(AbstractProgressViewer *apv)
Attach a progress viewer.
Push button that uses te::qt::widgets::HelpManager on its mouse pressed implementation.
virtual bool paramsAreValid()
Definition: GeometricOp.cpp:76
te::map::AbstractLayerPtr getInLayer()
The geographic operation Convex Hull.
Definition: Enums.h:102
A class that represents a data source component.
A layer with reference to a dataset.
Definition: DataSetLayer.h:47
std::auto_ptr< LayerSchema > getSchema() const
It returns the layer schema.
void setInput(te::da::DataSourcePtr inDsrc, std::string inDsetName, std::auto_ptr< te::da::DataSetType > inDsetType)
Definition: GeometricOp.cpp:48
void setParams(std::vector< std::string > selectedProps, std::vector< te::vp::GeometricOperation > operations, te::vp::GeometricOpObjStrategy objStrategy, std::string attribute, bool outputLayer)
Definition: GeometricOp.cpp:57
boost::intrusive_ptr< AbstractLayer > AbstractLayerPtr
GeometricOpWizard(QWidget *parent)
boost::shared_ptr< DataSourceInfo > DataSourceInfoPtr
virtual bool run()=0