All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
DirectExchangerDialog.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/qt/widgets/exchanger/DirectExchangerDialog.h
22 
23  \brief A direct exchanger dialog for ADO, POSTGIS and SHP data sources
24 */
25 
26 // TerraLib
27 #include "../../../common/StringUtils.h"
28 #include "../../../dataaccess/dataset/DataSetAdapter.h"
29 #include "../../../dataaccess/dataset/PrimaryKey.h"
30 #include "../../../dataaccess/dataset/DataSetTypeConverter.h"
31 #include "../../../dataaccess/datasource/DataSourceFactory.h"
32 #include "../../../dataaccess/datasource/DataSourceInfo.h"
33 #include "../../../dataaccess/datasource/DataSourceInfoManager.h"
34 #include "../../../dataaccess/datasource/DataSourceManager.h"
35 #include "../../../dataaccess/datasource/DataSourceTransactor.h"
36 #include "../../../dataaccess/utils/Utils.h"
37 #include "../../../geometry/GeometryProperty.h"
38 #include "../../../maptools/DataSetLayer.h"
39 #include "../../widgets/datasource/selector/DataSourceExplorerDialog.h"
40 #include "../../widgets/srs/SRSManagerDialog.h"
41 #include "DirectExchangerDialog.h"
42 #include "ui_DirectExchangerDialogForm.h"
43 
44 // Qt
45 #include <QFileDialog>
46 #include <QMessageBox>
47 
48 // Boost
49 #include <boost/algorithm/string/replace.hpp>
50 #include <boost/filesystem.hpp>
51 #include <boost/lexical_cast.hpp>
52 #include <boost/uuid/random_generator.hpp>
53 #include <boost/uuid/uuid_io.hpp>
54 
55 
58 
60  : QDialog(parent, f),
61  m_ui(new Ui::DirectExchangerDialogForm)
62 {
63 // setup widget
64  m_ui->setupUi(this);
65 
66 // add icons
67  m_ui->m_imgLabel->setPixmap(QIcon::fromTheme("data-exchange-direct-hint").pixmap(112,48));
68  m_ui->m_dsToolButton->setIcon(QIcon::fromTheme("datasource"));
69 
70 //connectors
71  connect(m_ui->m_okPushButton, SIGNAL(clicked()), this, SLOT(onOkPushButtonClicked()));
72  connect(m_ui->m_dirToolButton, SIGNAL(clicked()), this, SLOT(onDirToolButtonClicked()));
73  connect(m_ui->m_dsToolButton, SIGNAL(clicked()), this, SLOT(onDataSoruceToolButtonClicked()));
74  connect(m_ui->m_dsTypeComboBox, SIGNAL(activated(int)), this, SLOT(onDataSourceTypeActivated(int)));
75  connect(m_ui->m_inputLayerComboBox, SIGNAL(activated(QString)), this, SLOT(onInputLayerActivated(QString)));
76 
77  m_ui->m_helpPushButton->setPageReference("widgets/exchanger_direct/exchanger_direct.html");
78 
79  //starup interface
81  m_exchangeToFile = false;
82  m_lastDsType = "";
83 
85 }
86 
88 {
89 }
90 
91 void te::qt::widgets::DirectExchangerDialog::setLayers(std::list<te::map::AbstractLayerPtr> layers)
92 {
93  m_layers = layers;
94 
95  m_ui->m_inputLayerComboBox->clear();
96 
97  std::list<te::map::AbstractLayerPtr>::iterator it = m_layers.begin();
98 
99  while(it != m_layers.end())
100  {
102 
103  std::auto_ptr<te::da::DataSetType> dsType = l->getSchema();
104 
105  if(dsType.get() && !dsType->hasRaster())
106  m_ui->m_inputLayerComboBox->addItem(l->getTitle().c_str(), QVariant::fromValue(l));
107 
108  ++it;
109  }
110 
111  if(m_ui->m_inputLayerComboBox->count() > 0)
112  {
113  QString s = m_ui->m_inputLayerComboBox->currentText();
114 
115  onInputLayerActivated(s);
116  }
117 
118  if(m_ui->m_inputLayerComboBox->count() > 1)
119  m_ui->m_inputLayerComboBox->setEnabled(true);
120 }
121 
123 {
124  m_lastDsType = dataSource;
125 }
126 
128 {
129  m_ui->m_outputDataSourceComboBox->clear();
130 
131  std::vector<te::da::DataSourceInfoPtr> datasources;
132 
133  te::da::DataSourceInfoManager::getInstance().getByType(m_outputDataSourceType, datasources);
134 
135  for(std::size_t i = 0; i < datasources.size(); ++i)
136  {
137  const te::da::DataSourceInfoPtr& datasource = datasources[i];
138 
139  if(datasource.get() == 0)
140  continue;
141 
142  const std::string& title = datasource->getTitle();
143 
144  m_ui->m_outputDataSourceComboBox->addItem(title.c_str(), QVariant::fromValue(datasource));
145  }
146 }
147 
149 {
150  int idxLayer = m_ui->m_inputLayerComboBox->currentIndex();
151 
152  if(idxLayer == -1)
153  {
154  QMessageBox::warning(this, tr("Warning"), tr("Input layer not selected."));
155  return false;
156  }
157 
158  QVariant varLayer = m_ui->m_inputLayerComboBox->itemData(idxLayer, Qt::UserRole);
159  te::map::AbstractLayerPtr layer = varLayer.value<te::map::AbstractLayerPtr>();
160 
161  if(!layer.get())
162  {
163  QMessageBox::warning(this, tr("Warning"), tr("Error getting selected layer."));
164  return false;
165  }
166 
167  if(m_ui->m_dataSetLineEdit->text().isEmpty())
168  {
169  QMessageBox::warning(this, tr("Warning"), tr("Output File Name not defined."));
170  return false;
171  }
172 
173  try
174  {
175  //create adapter
176  std::auto_ptr<te::da::DataSetType> dsType = layer->getSchema();
177 
178  //create data source
179  std::map<std::string, std::string> connInfo;
180  connInfo["URI"] = m_ui->m_dataSetLineEdit->text().toStdString();
181 
182  std::auto_ptr<te::da::DataSource> dsOGR = te::da::DataSourceFactory::make(m_outputDataSourceType);
183  dsOGR->setConnectionInfo(connInfo);
184  dsOGR->open();
185 
186  te::da::DataSetTypeConverter* converter = new te::da::DataSetTypeConverter(dsType.get(), dsOGR->getCapabilities(), dsOGR->getEncoding());
187 
188  te::da::DataSetType* dsTypeResult = converter->getResult();
189 
191 
192  //check srid
193  if(p && (p->getSRID() != layer->getSRID()))
194  {
195  p->setSRID(layer->getSRID());
196  }
197 
198  boost::filesystem::path uri(m_ui->m_dataSetLineEdit->text().toStdString());
199 
200  std::string val = uri.stem().string();
201 
202  dsTypeResult->setName(val);
203 
204  // Check dataset name
205  if(!dsOGR->isDataSetNameValid(dsTypeResult->getName()))
206  {
207  int r = QMessageBox::question(this, tr("Exchanger"), tr("Layer name invalid for output datasource. Would you like to normalize the name?"), QMessageBox::Yes, QMessageBox::No);
208 
209  if(r == QMessageBox::Yes)
210  {
211  bool aux;
212  std::string newName = te::common::ReplaceSpecialChars(dsTypeResult->getName(), aux);
213  dsTypeResult->setName(newName);
214  }
215  else
216  {
217  throw te::common::Exception(tr("Layer name invalid for output datasource!").toStdString());
218  }
219  }
220 
221  // Check properties names
222  std::vector<te::dt::Property* > props = dsTypeResult->getProperties();
223  std::map<std::size_t, std::string> invalidNames;
224  for(std::size_t i = 0; i < props.size(); ++i)
225  {
226  if(!dsOGR->isPropertyNameValid(props[i]->getName()))
227  {
228  invalidNames[i] = props[i]->getName();
229  }
230  }
231 
232  if(!invalidNames.empty())
233  {
234  int r = QMessageBox::question(this, tr("Exchanger"), tr("Some property name is invalid for output datasource. Would you like to normalize the name?"), QMessageBox::Yes, QMessageBox::No);
235 
236  if(r == QMessageBox::Yes)
237  {
238  std::map<std::size_t, std::string>::iterator it = invalidNames.begin();
239 
240  while(it != invalidNames.end())
241  {
242  bool aux;
243  std::string newName = te::common::ReplaceSpecialChars(it->second, aux);
244 
245  props[it->first]->setName(newName);
246 
247  ++it;
248  }
249  }
250  else
251  {
252  QString err(tr("Some property name is invalid for output datasource:\n\n"));
253 
254  std::map<std::size_t, std::string>::iterator it = invalidNames.begin();
255 
256  while(it != invalidNames.end())
257  {
258  err.append(" - ");
259  err.append(it->second.c_str());
260 
261  ++it;
262  }
263 
264  throw te::common::Exception(err.toStdString());
265  }
266  }
267 
268  //exchange
269  std::map<std::string,std::string> nopt;
270 
271  std::auto_ptr<te::da::DataSet> dataset = layer->getData();
272 
273  dsOGR->createDataSet(dsTypeResult, nopt);
274 
275  std::auto_ptr<te::da::DataSetAdapter> dsAdapter(te::da::CreateAdapter(dataset.get(), converter));
276 
277  dsAdapter->setSRID(layer->getSRID());
278 
279  if(dataset->moveBeforeFirst())
280  dsOGR->add(dsTypeResult->getName(), dsAdapter.get(), dsOGR->getConnectionInfo());
281 
282  dsOGR->close();
283 
284  QMessageBox::information(this, tr("Exchanger"), tr("Layer exported successfully."));
285  }
286  catch(const std::exception& e)
287  {
288  QString errMsg(tr("Error during exchanger. The reported error is: %1"));
289 
290  errMsg = errMsg.arg(e.what());
291 
292  QMessageBox::information(this, tr("Exchanger"), errMsg);
293 
294  return false;
295  }
296 
297  return true;
298 }
299 
301 {
302  int idxLayer = m_ui->m_inputLayerComboBox->currentIndex();
303 
304  if(idxLayer == -1)
305  {
306  QMessageBox::warning(this, tr("Warning"), tr("Input layer not selected."));
307  return false;
308  }
309 
310  QVariant varLayer = m_ui->m_inputLayerComboBox->itemData(idxLayer, Qt::UserRole);
311  te::map::AbstractLayerPtr layer = varLayer.value<te::map::AbstractLayerPtr>();
312 
313  if(!layer.get())
314  {
315  QMessageBox::warning(this, tr("Warning"), tr("Error getting selected layer."));
316  return false;
317  }
318 
319  int idxDataSource = m_ui->m_outputDataSourceComboBox->currentIndex();
320 
321  if(idxLayer == -1)
322  {
323  QMessageBox::warning(this, tr("Warning"), tr("Output data source not selected."));
324  return false;
325  }
326 
327  QVariant varDataSource = m_ui->m_outputDataSourceComboBox->itemData(idxDataSource, Qt::UserRole);
328  te::da::DataSourceInfoPtr dsInfo = varDataSource.value<te::da::DataSourceInfoPtr>();
329 
330  if(!dsInfo.get())
331  {
332  QMessageBox::warning(this, tr("Warning"), tr("Error getting selected data source."));
333  return false;
334  }
335 
336  if(m_ui->m_dataSetLineEdit->text().isEmpty())
337  {
338  QMessageBox::warning(this, tr("Warning"), tr("Data Set name not defined."));
339  return false;
340  }
341 
342  std::auto_ptr<te::da::DataSourceTransactor> transactor;
343 
344  try
345  {
346  setCursor(Qt::WaitCursor);
347 
348  //create adapter
349  std::auto_ptr<te::da::DataSetType> dsType = layer->getSchema();
350 
351  te::da::DataSourcePtr targetDSPtr = te::da::DataSourceManager::getInstance().get(dsInfo->getId(), dsInfo->getType(), dsInfo->getConnInfo());
352 
353  transactor = targetDSPtr->getTransactor();
354 
355  te::da::DataSetTypeConverter* converter = new te::da::DataSetTypeConverter(dsType.get(), targetDSPtr->getCapabilities(), targetDSPtr->getEncoding());
356 
357  te::da::DataSetType* dsTypeResult = converter->getResult();
358 
359  dsTypeResult->setName(m_ui->m_dataSetLineEdit->text().toStdString());
360 
361  // Check dataset name
362  if(!targetDSPtr->isDataSetNameValid(dsTypeResult->getName()))
363  {
364  int r = QMessageBox::question(this, tr("Exchanger"), tr("Layer name invalid for output datasource. Would you like to normalize the name?"), QMessageBox::Yes, QMessageBox::No);
365 
366  if(r == QMessageBox::Yes)
367  {
368  bool aux;
369  std::string newName = te::common::ReplaceSpecialChars(dsTypeResult->getName(), aux);
370  dsTypeResult->setName(newName);
371  }
372  else
373  {
374  throw te::common::Exception(tr("Layer name invalid for output datasource!").toStdString());
375  }
376  }
377 
378  // Check properties names
379  std::vector<te::dt::Property* > props = dsTypeResult->getProperties();
380  std::map<std::size_t, std::string> invalidNames;
381  for(std::size_t i = 0; i < props.size(); ++i)
382  {
383  if(!targetDSPtr->isPropertyNameValid(props[i]->getName()))
384  {
385  invalidNames[i] = props[i]->getName();
386  }
387  }
388 
389  if(!invalidNames.empty())
390  {
391  int r = QMessageBox::question(this, tr("Exchanger"), tr("Some property name is invalid for output datasource. Would you like to normalize the name?"), QMessageBox::Yes, QMessageBox::No);
392 
393  if(r == QMessageBox::Yes)
394  {
395  std::map<std::size_t, std::string>::iterator it = invalidNames.begin();
396 
397  while(it != invalidNames.end())
398  {
399  bool aux;
400  std::string newName = te::common::ReplaceSpecialChars(it->second, aux);
401 
402  props[it->first]->setName(newName);
403 
404  ++it;
405  }
406  }
407  else
408  {
409  QString err(tr("Some property name is invalid for output datasource:\n\n"));
410 
411  std::map<std::size_t, std::string>::iterator it = invalidNames.begin();
412 
413  while(it != invalidNames.end())
414  {
415  err.append(" - ");
416  err.append(it->second.c_str());
417 
418  ++it;
419  }
420 
421  throw te::common::Exception(err.toStdString());
422  }
423  }
424 
425  //create index
426  if(m_ui->m_spatialIndexCheckBox->isChecked())
427  {
429 
430  //check srid
431  if(p && (p->getSRID() != layer->getSRID()))
432  {
433  p->setSRID(layer->getSRID());
434  }
435 
436  if(p)
437  {
438  te::da::Index* idx = new te::da::Index(dsTypeResult);
439 
440  std::string name = m_ui->m_dataSetLineEdit->text().toStdString() + "_" + p->getName() + "_idx";
441 
442  boost::replace_all(name, ".", "_");
443 
444  idx->setName(name);
446 
447  te::dt::Property* pClone = p->clone();
448 
449  idx->add(pClone);
450  }
451  }
452 
453  //create primary key
454  if(dsType->getPrimaryKey())
455  {
456  te::da::PrimaryKey* pk = new te::da::PrimaryKey(dsTypeResult);
457 
458  std::string name = m_ui->m_dataSetLineEdit->text().toStdString() + "_" + dsType->getPrimaryKey()->getName() + "_pk";
459 
460  boost::replace_all(name, ".", "_");
461 
462  pk->setName(name);
463 
464  std::vector<te::dt::Property*> props = dsType->getPrimaryKey()->getProperties();
465 
466  for(size_t t = 0; t < props.size(); ++ t)
467  {
468  te::dt::Property* p = props[t]->clone();
469 
470  pk->add(p);
471  }
472  }
473 
474  //exchange
475  std::map<std::string,std::string> nopt;
476 
477  std::auto_ptr<te::da::DataSet> dataset = layer->getData();
478 
479  transactor->begin();
480 
481  transactor->createDataSet(dsTypeResult, nopt);
482 
483  std::auto_ptr<te::da::DataSetAdapter> dsAdapter(te::da::CreateAdapter(dataset.get(), converter));
484 
485  dsAdapter->setSRID(layer->getSRID());
486 
487  if(dataset->moveBeforeFirst())
488  transactor->add(dsTypeResult->getName(), dsAdapter.get(), targetDSPtr->getConnectionInfo());
489 
490  transactor->commit();
491 
492  setCursor(Qt::ArrowCursor);
493  QMessageBox::information(this, tr("Exchanger"), tr("Layer exported successfully."));
494  }
495  catch(const std::exception& e)
496  {
497  setCursor(Qt::ArrowCursor);
498 
499  transactor->rollBack();
500 
501  QString errMsg(tr("Error during exchanger. The reported error is: %1"));
502 
503  errMsg = errMsg.arg(e.what());
504 
505  QMessageBox::information(this, tr("Exchanger"), errMsg);
506 
507  return false;
508  }
509 
510  return true;
511 }
512 
514 {
515  QString value = m_ui->m_dsTypeComboBox->itemData(index).toString();
516 
517  m_outputDataSourceType = value.toStdString();
518 
519  if(m_outputDataSourceType == "POSTGIS")
520  {
521  m_exchangeToFile = false;
522 
523  m_ui->m_outputDataSourceComboBox->setEnabled(true);
524  m_ui->m_dsToolButton->setEnabled(true);
525  m_ui->m_dataSetLineEdit->clear();
526  m_ui->m_dataSetLineEdit->setEnabled(true);
527  m_ui->m_dirToolButton->setEnabled(false);
528  m_ui->m_spatialIndexCheckBox->setEnabled(true);
529  m_ui->m_spatialIndexCheckBox->setChecked(true);
530 
531  setDataSources();
532  }
533  else if(m_outputDataSourceType == "ADO")
534  {
535  m_exchangeToFile = false;
536 
537  m_ui->m_outputDataSourceComboBox->setEnabled(true);
538  m_ui->m_dsToolButton->setEnabled(true);
539  m_ui->m_dataSetLineEdit->clear();
540  m_ui->m_dataSetLineEdit->setEnabled(true);
541  m_ui->m_dirToolButton->setEnabled(false);
542  m_ui->m_spatialIndexCheckBox->setEnabled(false);
543  m_ui->m_spatialIndexCheckBox->setChecked(false);
544 
545  setDataSources();
546  }
547  else if(m_outputDataSourceType == "OGR")
548  {
549  m_exchangeToFile = true;
550 
551  m_ui->m_outputDataSourceComboBox->clear();
552  m_ui->m_outputDataSourceComboBox->setEnabled(false);
553  m_ui->m_dsToolButton->setEnabled(false);
554  m_ui->m_dataSetLineEdit->clear();
555  m_ui->m_dataSetLineEdit->setEnabled(false);
556  m_ui->m_dirToolButton->setEnabled(true);
557  m_ui->m_spatialIndexCheckBox->setEnabled(false);
558  m_ui->m_spatialIndexCheckBox->setChecked(false);
559  }
560 }
561 
563 {
564  onDataSourceTypeActivated(m_ui->m_dsTypeComboBox->currentIndex());
565 
566  if(m_ui->m_dataSetLineEdit->isEnabled())
567  m_ui->m_dataSetLineEdit->setText(value);
568 }
569 
571 {
572  QString fileName = QFileDialog::getSaveFileName(this, tr("Save as..."),
573  QString(), tr("Shapefile (*.shp *.SHP);;Mapinfo File (*.mif *.MIF);;KML (*.kml *.KML);;GeoJSON (*.geojson *.GEOJSON);;GML (*.gml *.GML);;DXF (*.dxf *.DXF);;DGN (*.dgn *.DGN);;"),0, QFileDialog::DontConfirmOverwrite);
574 
575  if (fileName.isEmpty())
576  return;
577 
578  m_ui->m_dataSetLineEdit->setText(fileName);
579 }
580 
582 {
583  std::auto_ptr<te::qt::widgets::DataSourceExplorerDialog> dExplorer(new te::qt::widgets::DataSourceExplorerDialog(this));
584 
585  if(!m_lastDsType.empty())
586  dExplorer->setDataSourceToUse(m_lastDsType.c_str());
587 
588  dExplorer->exec();
589 
590  setDataSources();
591 }
592 
594 {
595  bool res = false;
596 
597  if(m_exchangeToFile)
598  res = exchangeToFile();
599  else
600  res = exchangeToDatabase();
601 
602  if(res)
603  accept();
604 }
605 
607 {
608  m_ui->m_dsTypeComboBox->clear();
609 
610  m_ui->m_dsTypeComboBox->addItem(QIcon::fromTheme("datasource-postgis"), tr("PostGIS"), QVariant("POSTGIS"));
611  m_ui->m_dsTypeComboBox->addItem(QIcon::fromTheme("datasource-ado"), tr("Microsoft Access"), QVariant("ADO"));
612  m_ui->m_dsTypeComboBox->addItem(QIcon::fromTheme("datasource-ogr"), tr("File - OGR Formats"), QVariant("OGR"));
613 }
virtual void setName(const std::string &name)
It sets the constraint name.
Definition: Constraint.h:126
void setDataSources()
Set the list of data sources that can be used.
Geometric property.
void add(te::dt::Property *p)
It adds a property to the list of properties of the primary key.
Definition: PrimaryKey.h:123
void setSRID(int srid)
It sets the spatial reference system identifier associated to this property.
A dialog for selecting a data source.
boost::shared_ptr< DataSource > DataSourcePtr
Definition: DataSource.h:1435
A class that models the description of a dataset.
Definition: DataSetType.h:72
Q_DECLARE_METATYPE(te::map::AbstractLayerPtr)
virtual Property * clone() const =0
It returns a clone of the object.
void setIndexType(IndexType t)
It sets the index type.
Definition: Index.h:176
void add(te::dt::Property *p)
It adds the property to the list of properties of the index.
Definition: Index.h:197
te::dt::Property * clone() const
It returns a clone of the object.
std::string ReplaceSpecialChars(const std::string &str, bool &changed)
It replace special characters of a string.
Definition: StringUtils.h:537
It models a property definition.
Definition: Property.h:59
DirectExchangerDialog(QWidget *parent=0, Qt::WindowFlags f=0)
An converter for DataSetType.
void setName(const std::string &name)
It sets the property name.
Definition: Property.h:137
int getSRID() const
It returns the spatial reference system identifier associated to this property.
static DataSourceInfoManager & getInstance()
It returns a reference to the singleton instance.
static std::auto_ptr< DataSource > make(const std::string &dsType)
void setLayers(std::list< te::map::AbstractLayerPtr > layers)
Set the layer that can be used.
std::auto_ptr< Ui::DirectExchangerDialogForm > m_ui
A direct exchanger dialog for ADO, POSTGIS and SHP data sources.
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
Definition: Exception.h:58
void setLastDataSource(std::string dataSource)
Function used to set the last data source used.
It describes a primary key (pk) constraint.
Definition: PrimaryKey.h:52
void setName(const std::string &name)
It sets the index name.
Definition: Index.h:162
TEDATAACCESSEXPORT te::gm::GeometryProperty * GetFirstGeomProperty(const DataSetType *dt)
Definition: Utils.cpp:557
TEDATAACCESSEXPORT DataSetAdapter * CreateAdapter(DataSet *ds, DataSetTypeConverter *converter, bool isOwner=false)
Definition: Utils.cpp:644
boost::intrusive_ptr< AbstractLayer > AbstractLayerPtr
It describes an index associated to a DataSetType.
Definition: Index.h:54
boost::shared_ptr< DataSourceInfo > DataSourceInfoPtr
const std::string & getName() const
It returns the property name.
Definition: Property.h:127