MultipartToSinglepartDialog.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/MultipartToSinglepartDialog.cpp
22 
23  \brief A Multipart to Singlepart operation dialog
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/ObjectIdSet.h"
34 #include "../../dataaccess/datasource/DataSourceCapabilities.h"
35 #include "../../dataaccess/datasource/DataSourceInfo.h"
36 #include "../../dataaccess/datasource/DataSourceInfoManager.h"
37 #include "../../dataaccess/datasource/DataSourceFactory.h"
38 #include "../../dataaccess/datasource/DataSourceManager.h"
39 #include "../../dataaccess/utils/Utils.h"
40 #include "../../datatype/Enums.h"
41 #include "../../datatype/Property.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 "../../qt/widgets/utils/FileDialog.h"
48 #include "../../statistics/core/Utils.h"
49 #include "../Config.h"
50 #include "../Exception.h"
51 #include "../MultipartToSinglepart.h"
53 #include "ui_MultipartToSinglepartDialogForm.h"
54 #include "Utils.h"
55 
56 // Qt
57 #include <QFileDialog>
58 #include <QList>
59 #include <QListWidget>
60 #include <QListWidgetItem>
61 #include <QMessageBox>
62 #include <QTreeWidget>
63 
64 // Boost
65 #include <boost/algorithm/string.hpp>
66 #include <boost/filesystem.hpp>
67 #include <boost/uuid/random_generator.hpp>
68 #include <boost/uuid/uuid_io.hpp>
69 
71 
72 te::vp::MultipartToSinglepartDialog::MultipartToSinglepartDialog(QWidget* parent, Qt::WindowFlags f)
73  : QDialog(parent, f),
74  m_ui(new Ui::MultipartToSinglepartDialogForm),
75  m_layers(std::list<te::map::AbstractLayerPtr>()),
76  m_selectedLayer(nullptr),
77  m_toFile(false)
78 {
79 // add controls
80  m_ui->setupUi(this);
81 
82 // add icons
83  m_ui->m_imgLabel->setPixmap(QIcon::fromTheme("vp-multiparttosinglepart-hint").pixmap(112,48));
84  m_ui->m_targetDatasourceToolButton->setIcon(QIcon::fromTheme("datasource"));
85 
86  connect(m_ui->m_layersComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onLayerComboBoxChanged(int)));
87  connect(m_ui->m_targetDatasourceToolButton, SIGNAL(pressed()), this, SLOT(onTargetDatasourceToolButtonPressed()));
88  connect(m_ui->m_targetFileToolButton, SIGNAL(pressed()), this, SLOT(onTargetFileToolButtonPressed()));
89  connect(m_ui->m_okPushButton, SIGNAL(clicked()), this, SLOT(onOkPushButtonClicked()));
90  connect(m_ui->m_cancelPushButton, SIGNAL(clicked()), this, SLOT(onCancelPushButtonClicked()));
91 
92  m_ui->m_helpPushButton->setNameSpace("dpi.inpe.br.plugins");
93  m_ui->m_helpPushButton->setPageReference("plugins/vp/vp_multiparttosinglepart.html");
94 
95  m_outputDatasource = te::da::DataSourceInfoPtr();
96  m_ui->m_newLayerNameLineEdit->setEnabled(true);
97 }
98 
100 
101 void te::vp::MultipartToSinglepartDialog::setLayers(std::list<te::map::AbstractLayerPtr> layers)
102 {
103  m_layers = layers;
104 
105  std::list<te::map::AbstractLayerPtr>::iterator it = m_layers.begin();
106 
107  while(it != m_layers.end())
108  {
109  std::unique_ptr<te::da::DataSetType> dsType = it->get()->getSchema();
110  if(dsType->hasGeom())
111  m_ui->m_layersComboBox->addItem(it->get()->getTitle().c_str(), QVariant(QVariant::fromValue(*it)));
112 
113  ++it;
114  }
115 }
116 
118 {
119  return m_layer;
120 }
121 
123 {
124  QVariant varLayer = m_ui->m_layersComboBox->itemData(index, Qt::UserRole);
125  te::map::AbstractLayerPtr layer = varLayer.value<te::map::AbstractLayerPtr>();
126 
127  m_selectedLayer = layer;
128 }
129 
131 {
132  m_ui->m_newLayerNameLineEdit->clear();
133  m_ui->m_newLayerNameLineEdit->setEnabled(true);
135  dlg.exec();
136 
137  std::list<te::da::DataSourceInfoPtr> dsPtrList = dlg.getSelecteds();
138 
139  if(dsPtrList.empty())
140  return;
141 
142  std::list<te::da::DataSourceInfoPtr>::iterator it = dsPtrList.begin();
143 
144  m_ui->m_repositoryLineEdit->setText(QString(it->get()->getTitle().c_str()));
145 
146  m_outputDatasource = *it;
147 
148  m_toFile = false;
149 }
150 
152 {
153  m_ui->m_newLayerNameLineEdit->clear();
154  m_ui->m_repositoryLineEdit->clear();
155 
157 
158  try {
159  fileDialog.exec();
160  }
161  catch (te::common::Exception& ex) {
162  QMessageBox::warning(this, tr("File information"), ex.what());
163  return;
164  }
165 
166  m_ui->m_repositoryLineEdit->setText(fileDialog.getPath().c_str());
167  m_ui->m_newLayerNameLineEdit->setText(fileDialog.getFileName().c_str());
168 
169  m_toFile = true;
170  m_ui->m_newLayerNameLineEdit->setEnabled(false);
171 }
172 
174 {
175  if(m_ui->m_layersComboBox->count() == 0)
176  {
177  QMessageBox::information(this, tr("Multipart To Singlepart"), tr("Select an input layer."));
178  return;
179  }
180 
181  te::map::DataSetLayer* dsLayer = dynamic_cast<te::map::DataSetLayer*>(m_selectedLayer.get());
182 
183  if(!dsLayer)
184  {
185  QMessageBox::information(this, tr("Multipart To Singlepart"), tr("Can not execute this operation on this type of layer."));
186  return;
187  }
188 
189  const te::da::ObjectIdSet* oidSet = nullptr;
190 
191  if(m_ui->m_onlySelectedCheckBox->isChecked())
192  {
193  oidSet = m_selectedLayer->getSelected();
194  if(!oidSet)
195  {
196  QMessageBox::information(this, tr("Multipart To Singlepart"), tr("None selected object!"));
197  return;
198  }
199  }
200 
201  te::da::DataSourcePtr inDataSource = te::da::GetDataSource(dsLayer->getDataSourceId(), true);
202  if (!inDataSource.get())
203  {
204  QMessageBox::information(this, tr("Multipart To Singlepart"), tr("The selected input data source can not be accessed."));
205  return;
206  }
207 
208  std::string outputdataset = m_ui->m_newLayerNameLineEdit->text().toUtf8().data();
209 
210  if(m_ui->m_repositoryLineEdit->text().isEmpty())
211  {
212  QMessageBox::information(this, tr("Multipart To Singlepart"), tr("Define a repository for the result."));
213  return;
214  }
215 
216  if(m_ui->m_newLayerNameLineEdit->text().isEmpty())
217  {
218  QMessageBox::information(this, tr("Multipart To Singlepart"), "Define a name for the resulting layer.");
219  return;
220  }
221 
222  //progress
224 
225  try
226  {
227  bool res;
228 
229  if (m_toFile)
230  {
231  boost::filesystem::path uri(m_ui->m_repositoryLineEdit->text().toUtf8().data());
232 
233  if (te::core::FileSystem::exists(uri.string()))
234  {
235  QMessageBox::information(this, tr("Multipart To Singlepart"), "Output file already exists. Remove it or select a new name and try again.");
236  return;
237  }
238 
239  std::size_t idx = outputdataset.find(".");
240  if (idx != std::string::npos)
241  outputdataset=outputdataset.substr(0,idx);
242 
243  std::string dsinfo("file://");
244  dsinfo += uri.string();
245 
246  te::da::DataSourcePtr dsOGR(te::da::DataSourceFactory::make("OGR", dsinfo).release());
247  dsOGR->open();
248  if (dsOGR->dataSetExists(outputdataset))
249  {
250  QMessageBox::information(this, tr("Multipart To Singlepart"), "There is already a dataset with the requested name in the output data source. Remove it or select a new name and try again.");
251  return;
252  }
253 
254  this->setCursor(Qt::WaitCursor);
255 
257 
258  m2s->setInput(inDataSource, dsLayer->getDataSetName(),dsLayer->getSchema(), oidSet);
259  m2s->setOutput(dsOGR, outputdataset);
260 
261  res = m2s->run();
262 
263  if (!res)
264  {
265  this->setCursor(Qt::ArrowCursor);
266  dsOGR->close();
267  QMessageBox::information(this, tr("Multipart To Singlepart"), tr("Error: could not operate."));
268  reject();
269  }
270  dsOGR->close();
271 
272  delete m2s;
273 
274  // let's include the new datasource in the managers
275  boost::uuids::basic_random_generator<boost::mt19937> gen;
276  boost::uuids::uuid u = gen();
277  std::string id_ds = boost::uuids::to_string(u);
278 
280  ds->setConnInfo(dsinfo);
281  ds->setTitle(uri.stem().string());
282  ds->setAccessDriver("OGR");
283  ds->setType("OGR");
284  ds->setDescription(uri.string());
285  ds->setId(id_ds);
286 
287  te::da::DataSourcePtr newds = te::da::DataSourceManager::getInstance().get(id_ds, "OGR", ds->getConnInfo());
288  newds->open();
291  }
292  else
293  {
295  if (!aux)
296  {
297  QMessageBox::information(this, tr("Multipart To Singlepart"), "The selected output datasource can not be accessed.");
298  return;
299  }
300 
301  if (aux->dataSetExists(outputdataset))
302  {
303  QMessageBox::information(this, tr("Multipart To Singlepart"), "Dataset already exists. Remove it or select a new name and try again.");
304  return;
305  }
306  this->setCursor(Qt::WaitCursor);
307 
309 
310  m2s->setInput(inDataSource, dsLayer->getDataSetName(), dsLayer->getSchema(), oidSet);
311  m2s->setOutput(aux, outputdataset);
312 
313  res = m2s->run();
314 
315  delete m2s;
316 
317  if (!res)
318  {
319  this->setCursor(Qt::ArrowCursor);
320  QMessageBox::information(this, tr("Multipart To Singlepart"), tr("Error: could not operate."));
321  reject();
322  }
323  }
324 
325  // creating a layer for the result
327 
329 
330  te::da::DataSetTypePtr dt(outDataSource->getDataSetType(outputdataset).release());
331  m_layer = converter(dt);
332  }
333  catch(const std::exception& e)
334  {
335  this->setCursor(Qt::ArrowCursor);
336 
337  QMessageBox::information(this, tr("Multipart To Singlepart"), e.what());
338 
339  std::string str = "Vector Processing - Multipart To Singlepart - ";
340  str += e.what();
341  TE_LOG_ERROR(str);
342 
343  return;
344  }
345 
346  this->setCursor(Qt::ArrowCursor);
347 
348  accept();
349 }
350 
352 {
353  reject();
354 }
355 
TEDATAACCESSEXPORT DataSourcePtr GetDataSource(const std::string &datasourceId, const bool opened=true)
Search for a data source with the informed id in the DataSourceManager.
A Multipart to Singlepart operation dialog.
static std::unique_ptr< DataSource > make(const std::string &driver, const te::core::URI &connInfo)
Defines a component for choose a file.
Definition: FileDialog.h:52
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
Q_DECLARE_METATYPE(te::map::AbstractLayerPtr) te
virtual const char * what() const
It outputs the exception message.
te::da::DataSourceInfoPtr m_outputDatasource
DataSource information.
void setLayers(std::list< te::map::AbstractLayerPtr > layers)
Set the layer that can be used.
std::unique_ptr< LayerSchema > getSchema() const
It returns the layer schema.
static te::dt::Date ds(2010, 01, 01)
static DataSourceManager & getInstance()
It returns a reference to the singleton instance.
void setOutput(te::da::DataSourcePtr outDsrc, std::string outDsName)
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 inDsName, std::unique_ptr< te::da::DataSetType > inDsType, const te::da::ObjectIdSet *oidSet=0)
te::map::AbstractLayerPtr m_layer
Generated Layer.
static te::dt::TimeDuration dt(20, 30, 50, 11)
te::map::AbstractLayerPtr getLayer()
Get the generated layer.
Utility functions for the data access module.
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
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
A dialog for selecting a data source.
std::unique_ptr< Ui::MultipartToSinglepartDialogForm > m_ui
#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::map::AbstractLayerPtr m_selectedLayer
Layer used for operation.
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
std::list< te::map::AbstractLayerPtr > m_layers
List of layers.
boost::shared_ptr< DataSourceInfo > DataSourceInfoPtr