src/terralib/qt/plugins/datasource/ogr/Utils.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/plugins/datasource/ogr/Utils.cpp
22 
23  \brief Utility functions for the OGR data source widget plugin.
24 */
25 
26 // TerraLib
27 #include "../../../../dataaccess/dataset/DataSetType.h"
28 #include "../../../../dataaccess/datasource/DataSourceInfoManager.h"
29 #include "../../../../dataaccess/datasource/DataSourceManager.h"
30 #include "../../../../dataaccess/utils/Utils.h"
31 #include "../../../../maptools/AbstractLayer.h"
32 #include "../../../../srs/SpatialReferenceSystemManager.h"
33 #include "../../../widgets/layer/utils/DataSet2Layer.h"
34 #include "../../../af/ApplicationController.h"
35 #include "../../../af/events/LayerEvents.h"
36 #include "Utils.h"
37 
38 // Qt
39 #include <QApplication>
40 #include <QDir>
41 #include <QFileInfo>
42 #include <QMessageBox>
43 
44 // STL
45 #include <cassert>
46 
47 // Boost
48 #include <boost/uuid/random_generator.hpp>
49 #include <boost/uuid/uuid_io.hpp>
50 #include <boost/filesystem.hpp>
51 
52 std::list<te::da::DataSetTypePtr> GetDataSetsInfo(const te::da::DataSourceInfoPtr& info)
53 {
54  std::list<te::da::DataSetTypePtr> res;
55 
56  te::da::DataSourcePtr ds = te::da::DataSourceManager::getInstance().get(info->getId(), info->getType(), info->getConnInfo());
57  if (!ds->isOpened())
58  ds->open();
59 
60  std::vector<std::string> dsets = ds->getDataSetNames();
61 
62  std::vector<std::string>::iterator it;
63 
64  for (it = dsets.begin(); it != dsets.end(); ++it)
65  res.push_back(te::da::DataSetTypePtr(ds->getDataSetType(*it).release()));
66 
67  return res;
68 }
69 
70 void GetLayers(const te::da::DataSourceInfoPtr& info, std::list<te::map::AbstractLayerPtr>& layers)
71 {
72  std::list<te::map::AbstractLayerPtr> res;
73  std::list<te::da::DataSetTypePtr> dss = GetDataSetsInfo(info);
74 
75  std::transform(dss.begin(), dss.end(), std::back_inserter(layers), te::qt::widgets::DataSet2Layer(info->getId()));
76 }
77 
78 bool te::qt::plugins::ogr::IsShapeFile(const QString& path)
79 {
80  QFileInfo fileInfo(path);
81 
82  if(!fileInfo.isFile())
83  return false;
84 
85  if(fileInfo.suffix().toLower() == "shp")
86  return true;
87 
88  return false;
89 }
90 
92 {
93  assert(IsShapeFile(path));
94 
95  QFileInfo fileInfo(path);
96 
97  // Gets the ShapeFile name
98  QString fileName = fileInfo.fileName();
99 
100  // Builds the ShapeFile directory
101  QDir dir(fileInfo.absolutePath());
102 
103  // Looking for .qix file
104  QString qixFile = fileName;
105  qixFile.replace(".shp", ".qix");
106  if(dir.exists(qixFile))
107  return true;
108 
109  // Looking for .sbn file
110  QString sbnFile = fileName;
111  sbnFile.replace(".shp", ".sbn");
112  if(dir.exists(sbnFile))
113  return true;
114 
115  return false;
116 }
117 
118 void te::qt::plugins::ogr::CreateLayers(QStringList fileNames, std::list<te::map::AbstractLayerPtr>& layers)
119 {
120  QApplication::setOverrideCursor(Qt::WaitCursor);
121 
122  // The selected shapefiles without spatial index
123  std::map<std::string, std::string> shpWithoutSpatialIndex;
124 
125  bool hasErrors = false;
126  QString errorMsg = QObject::tr("Error occurred trying to create layer(s):\n\n");
127 
128  for (QStringList::iterator it = fileNames.begin(); it != fileNames.end(); ++it)
129  {
131 
132  ds->setAccessDriver("OGR");
133 
134  std::string fpath = it->toUtf8().data();
135 
136  ds->setConnInfo("file://" + fpath);
137 
138  std::string desc("A single vector file: ");
139  desc += fpath;
140  ds->setDescription(desc);
141 
142  boost::filesystem::path mpath(fpath);
143 
144  std::string fileBaseName = mpath.leaf().string();
145 
146  ds->setTitle(fileBaseName);
147 
148  ds->setType("OGR");
149 
150  boost::uuids::basic_random_generator<boost::mt19937> gen;
151  boost::uuids::uuid u = gen();
152  std::string id = boost::uuids::to_string(u);
153 
154  ds->setId(id);
156  ds = te::da::DataSourceInfoManager::getInstance().getByConnInfo(ds->getConnInfoAsString());
157 
158  id = ds->getId();
159 
160  if (IsShapeFile(*it) && !HasShapeFileSpatialIndex(*it))
161  {
162  QString datasetName(fileBaseName.c_str());
163  datasetName.remove(".shp", Qt::CaseInsensitive);
164  shpWithoutSpatialIndex[id] = datasetName.toUtf8().data();
165  }
166 
167  try
168  {
169  GetLayers(ds, layers);
170  }
171  catch (const te::common::Exception&)
172  {
173  hasErrors = true;
174  errorMsg.append(" - ");
175  errorMsg.append(fileBaseName.c_str());
176  errorMsg.append("\n");
177 
178  }
179  catch (std::exception&)
180  {
181  hasErrors = true;
182  errorMsg.append(" - ");
183  errorMsg.append(fileBaseName.c_str());
184  errorMsg.append("\n");
185  }
186  }
187 
188  QApplication::restoreOverrideCursor();
189 
190  if (hasErrors)
191  {
192  QMessageBox::warning(te::qt::af::AppCtrlSingleton::getInstance().getMainWindow(), QObject::tr("Add Layer"), errorMsg);
193 
194  return;
195  }
196 
197  if (!shpWithoutSpatialIndex.empty())
198  {
199  if (QMessageBox::question(te::qt::af::AppCtrlSingleton::getInstance().getMainWindow(),
200  QObject::tr("Spatial Index"), QObject::tr("Do you want create spatial index to the selected ESRI ShapeFiles?"),
201  QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes)
202  {
203  QApplication::setOverrideCursor(Qt::WaitCursor);
204 
205  std::map<std::string, std::string>::iterator it;
206  for (it = shpWithoutSpatialIndex.begin(); it != shpWithoutSpatialIndex.end(); ++it)
207  {
208  te::da::DataSourcePtr driver;
209 
210  try
211  {
212  driver = te::da::GetDataSource(it->first, true);
213 
214  std::string command = "CREATE SPATIAL INDEX ON " + it->second;
215 
216  driver->execute(command);
217 
218  QApplication::restoreOverrideCursor();
219  }
220  catch (const te::common::Exception&)
221  {
222  QMessageBox::information(te::qt::af::AppCtrlSingleton::getInstance().getMainWindow(), QObject::tr("Spatial Index"), "Error creating spatial index.");
223 
224  QApplication::restoreOverrideCursor();
225 
226  }
227  catch (std::exception&)
228  {
229  QMessageBox::information(te::qt::af::AppCtrlSingleton::getInstance().getMainWindow(), QObject::tr("Spatial Index"), "Error creating spatial index.");
230 
231  QApplication::restoreOverrideCursor();
232  }
233  }
234  }
235  }
236 
237  te::map::AbstractLayerPtr parentLayer(nullptr);
238 
239  std::list<te::map::AbstractLayerPtr>::iterator it;
240  for (it = layers.begin(); it != layers.end(); ++it)
241  {
242  if ((*it)->getSRID() != TE_UNKNOWN_SRS)
243  {
244  if (!te::srs::SpatialReferenceSystemManager::getInstance().recognizes((*it)->getSRID()))
245  {
246  QString msgErr(QObject::tr("Layer %1 has SRID %2 that is not recognized by TerraLib. Setting it to unknown."));
247  msgErr = msgErr.arg((*it)->getTitle().c_str());
248  msgErr = msgErr.arg((*it)->getSRID());
249 
250  QMessageBox::warning(te::qt::af::AppCtrlSingleton::getInstance().getMainWindow(),
251  QObject::tr("Layer SRS check"), msgErr);
252  (*it)->setSRID(TE_UNKNOWN_SRS);
253  }
254  }
255  }
256 
257  te::qt::af::evt::LayersAdded added(layers, parentLayer);
259 }
TEDATAACCESSEXPORT DataSourcePtr GetDataSource(const std::string &datasourceId, const bool opened=true)
Search for a data source with the informed id in the DataSourceManager.
boost::shared_ptr< DataSetType > DataSetTypePtr
Definition: DataSetType.h:653
boost::shared_ptr< DataSource > DataSourcePtr
#define TE_UNKNOWN_SRS
A numeric value to represent a unknown SRS identification in TerraLib.
This event signals that a list of layers have been created.
Definition: LayerEvents.h:95
std::list< te::da::DataSetTypePtr > GetDataSetsInfo(const te::da::DataSourceInfoPtr &info)
static te::dt::Date ds(2010, 01, 01)
void CreateLayers(QStringList fileNames, std::list< te::map::AbstractLayerPtr > &layers)
static DataSourceManager & getInstance()
It returns a reference to the singleton instance.
Utility functions for the data access module.
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
A class that represents a data source component.
void GetLayers(const te::da::DataSourceInfoPtr &info, std::list< te::map::AbstractLayerPtr > &layers)
boost::intrusive_ptr< AbstractLayer > AbstractLayerPtr
boost::shared_ptr< DataSourceInfo > DataSourceInfoPtr