Plugin.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/Plugin.cpp
22 
23  \brief Plugin implementation for the OGR data source widget.
24 */
25 
26 // TerraLib
27 #include "../../../../common/Config.h"
28 #include "../../../../common/Logger.h"
29 #include "../../../../common/Translator.h"
30 #include "../../../../srs/Config.h"
31 #include "../../../../srs/SpatialReferenceSystemManager.h"
32 #include "../../../../dataaccess/dataset/DataSetType.h"
33 #include "../../../../dataaccess/datasource/DataSourceInfoManager.h"
34 #include "../../../../dataaccess/datasource/DataSourceManager.h"
35 #include "../../../../dataaccess/utils/Utils.h"
36 #include "../../../../maptools/AbstractLayer.h"
37 #include "../../../widgets/layer/utils/DataSet2Layer.h"
38 #include "../../../widgets/datasource/core/DataSourceTypeManager.h"
39 #include "../../../widgets/Utils.h"
40 #include "../../../af/ApplicationController.h"
41 #include "../../../af/Project.h"
42 #include "../../../af/Utils.h"
43 #include "../../../af/events/LayerEvents.h"
44 #include "OGRType.h"
45 #include "Plugin.h"
46 #include "Utils.h"
47 
48 // OGR
49 #include <ogrsf_frmts.h>
50 
51 // Boost
52 #include <boost/uuid/random_generator.hpp>
53 #include <boost/uuid/uuid_io.hpp>
54 #include <boost/filesystem.hpp>
55 
56 // Qt
57 #include <QFileInfo>
58 #include <QAction>
59 #include <QApplication>
60 #include <QFileDialog>
61 #include <QMenu>
62 #include <QMessageBox>
63 
64 std::list<te::da::DataSetTypePtr> GetDataSetsInfo(const te::da::DataSourceInfoPtr& info)
65 {
66  std::list<te::da::DataSetTypePtr> res;
67 
68  te::da::DataSourcePtr ds = te::da::DataSourceManager::getInstance().get(info->getId(), info->getType(), info->getConnInfo());
69  if (!ds->isOpened())
70  ds->open();
71 
72  std::vector<std::string> dsets = ds->getDataSetNames();
73 
74  std::vector<std::string>::iterator it;
75 
76  for(it = dsets.begin(); it != dsets.end(); ++it)
77  res.push_back(te::da::DataSetTypePtr(ds->getDataSetType(*it).release()));
78 
79  return res;
80 }
81 
82 void GetLayers(const te::da::DataSourceInfoPtr& info, std::list<te::map::AbstractLayerPtr>& layers)
83 {
84  std::list<te::map::AbstractLayerPtr> res;
85  std::list<te::da::DataSetTypePtr> dss = GetDataSetsInfo(info);
86 
87  std::transform(dss.begin(), dss.end(), std::back_inserter(layers), te::qt::widgets::DataSet2Layer(info->getId()));
88 }
89 
90 QString GetFileExtensionName(const std::string& type)
91 {
92  if(type.compare("ESRI Shapefile") == 0)
93  return QObject::tr("ESRI Shapefile (*.shp *.SHP)");
94  else if(type.compare("MapInfo File") == 0)
95  return QObject::tr("MapInfo File (*.mif *.MIF)");
96  else if(type.compare("DGN") == 0)
97  return QObject::tr("DGN File (*.dgn *.DGN)");
98 // else if(type.compare("CSV") == 0)
99 // return QObject::tr("CSV File (*.csv *.CSV)");
100  else if(type.compare("GML") == 0)
101  return QObject::tr("GML File (*.gml *.GML)");
102  else if(type.compare("KML") == 0)
103  return QObject::tr("KML File (*.kml *.KML)");
104  else if(type.compare("GeoJSON") == 0)
105  return QObject::tr("GeoJSON File (*.geojson *.GEOJSON)");
106  else if(type.compare("DXF") == 0)
107  return QObject::tr("DXF File (*.dxf *.DXF)");
108 
109  return "";
110 }
111 
113 {
114  QString res;
115  OGRSFDriverRegistrar* dMgr = OGRSFDriverRegistrar::GetRegistrar();
116 
117  int count = dMgr->GetDriverCount();
118 
119  for(int i=0; i<count; i++)
120  {
121  std::string dName = dMgr->GetDriver(i)->GetName();
122 
123  QString drv = GetFileExtensionName(dName);
124 
125  if(!drv.isEmpty())
126  res += drv + ";;";
127  }
128 
129  return res;
130 }
131 
133 QObject(),
134 te::plugin::Plugin(pluginInfo),
135 m_showWindow(0)
136 {
137 }
138 
140 {
141 }
142 
144 {
145  if(m_initialized)
146  return;
147 
149 
150  TE_LOG_TRACE(TE_TR("TerraLib Qt OGR widget startup!"));
151 
152  m_initialized = true;
153 
154  //Initializing action
155  QAction* act = te::qt::af::ApplicationController::getInstance().findAction("Project.Add Layer.Tabular File");
156  QMenu* mnu = te::qt::af::ApplicationController::getInstance().findMenu("Project.Add Layer");
157 
158  if(act != 0 && mnu != 0)
159  {
160  QWidget* parent = act->parentWidget();
161  m_showWindow = new QAction(QIcon::fromTheme("file-vector"), tr("Vector File..."), parent);
162  m_showWindow->setObjectName("Project.Add Layer.Vector File");
163  mnu->insertAction(act, m_showWindow);
164  //mnu->addAction(m_showWindow);
165 
167 
168  connect (m_showWindow, SIGNAL(triggered()), SLOT(showWindow()));
169  }
170 }
171 
173 {
174  if(!m_initialized)
175  return;
176 
177  te::da::DataSourceInfoManager::getInstance().removeByType("OGR");
179 
180  TE_LOG_TRACE(TE_TR("TerraLib Qt OGR widget shutdown!"));
181 
182  delete m_showWindow;
183 
184  m_initialized = false;
185 }
186 
188 {
189 // QString filter = GetSupportedFiles();
190 // QStringList fileNames = QFileDialog::getOpenFileNames(te::qt::af::ApplicationController::getInstance().getMainWindow(), tr("Open Vector File"), te::qt::af::GetFilePathFromSettings("vector"), filter);
191 
193 
194  if(proj == 0)
195  {
196  QMessageBox::warning(te::qt::af::ApplicationController::getInstance().getMainWindow(), tr("Vector File"), tr("Error: there is no opened project!"));
197  return;
198  }
199 
200  QStringList fileNames = QFileDialog::getOpenFileNames(te::qt::af::ApplicationController::getInstance().getMainWindow(), tr("Open Vector File"), te::qt::widgets::GetFilePathFromSettings("vector"), tr("Esri Shapefile (*.shp *.SHP);; Mapinfo File (*.mif *.MIF);; GeoJSON (*.geojson *.GeoJSON);; GML (*.gml *.GML);; KML (*.kml *.KML);; All Files (*.*)"));
201 
202  if(fileNames.isEmpty())
203  return;
204 
205  QApplication::setOverrideCursor(Qt::WaitCursor);
206 
207  QFileInfo info(fileNames.value(0));
208 
209  te::qt::widgets::AddFilePathToSettings(info.absolutePath(), "vector");
210 
211  // The selected shapefiles without spatial index
212  std::map<std::string, std::string> shpWithoutSpatialIndex;
213 
214  std::list<te::map::AbstractLayerPtr> layers;
215 
216  bool hasErrors = false;
217  QString errorMsg = tr("Error occurred trying to create layer(s):\n\n");
218 
219  for(QStringList::iterator it = fileNames.begin(); it != fileNames.end(); ++it)
220  {
222 
223  ds->setAccessDriver("OGR");
224 
225  std::string fpath = it->toStdString();
226  std::map<std::string, std::string> dsinfo;
227  dsinfo["URI"] = fpath;
228 
229  ds->setConnInfo(dsinfo);
230 
231  std::string desc("A single vector file: ");
232  desc += fpath;
233  ds->setDescription(desc);
234 
235  boost::filesystem::path mpath(dsinfo["URI"]);
236 
237  std::string fileBaseName = mpath.leaf().string();
238 
239  ds->setTitle(fileBaseName);
240 
241  ds->setType("OGR");
242 
243  boost::uuids::basic_random_generator<boost::mt19937> gen;
244  boost::uuids::uuid u = gen();
245  std::string id = boost::uuids::to_string(u);
246 
247  ds->setId(id);
249  ds = te::da::DataSourceInfoManager::getInstance().getByConnInfo(ds->getConnInfoAsString());
250 
251  if(IsShapeFile(*it) && !HasShapeFileSpatialIndex(*it))
252  {
253  QString datasetName(fileBaseName.c_str());
254  datasetName.remove(".shp", Qt::CaseInsensitive);
255  shpWithoutSpatialIndex[id] = datasetName.toStdString();
256  }
257 
258  try
259  {
260  GetLayers(ds, layers);
261  }
262  catch (const te::common::Exception& e)
263  {
264  hasErrors = true;
265  errorMsg.append(" - ");
266  errorMsg.append(fileBaseName.c_str());
267  errorMsg.append("\n");
268 
269  }
270  catch (std::exception& e)
271  {
272  hasErrors = true;
273  errorMsg.append(" - ");
274  errorMsg.append(fileBaseName.c_str());
275  errorMsg.append("\n");
276  }
277  }
278 
279  QApplication::restoreOverrideCursor();
280 
281  if (hasErrors)
282  {
283  QMessageBox::warning(te::qt::af::ApplicationController::getInstance().getMainWindow(), tr("Add Layer"), errorMsg);
284  }
285 
286  if(!shpWithoutSpatialIndex.empty())
287  {
288  if(QMessageBox::question(te::qt::af::ApplicationController::getInstance().getMainWindow(),
289  tr("Spatial Index"), tr("Do you want create spatial index to the selected ESRI ShapeFiles?"),
290  QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes)
291  {
292  QApplication::setOverrideCursor(Qt::WaitCursor);
293 
294  std::map<std::string, std::string>::iterator it;
295  for(it = shpWithoutSpatialIndex.begin(); it != shpWithoutSpatialIndex.end(); ++it)
296  {
297  te::da::DataSourcePtr driver = te::da::GetDataSource(it->first, true);
298 
299  std::string command = "CREATE SPATIAL INDEX ON " + it->second;
300 
301  driver->execute(command);
302  }
303 
304  QApplication::restoreOverrideCursor();
305 
306  QMessageBox::information(te::qt::af::ApplicationController::getInstance().getMainWindow(), tr("Spatial Index"), "Spatial index created with successfully!");
307  }
308  }
309 
310  // If there is only a parent folder layer that is selected, get it as the parent of the layer to be added;
311  // otherwise, add the layer as a top level layer
312  te::map::AbstractLayerPtr parentLayer(0);
313 
314  std::list<te::map::AbstractLayerPtr> selectedLayers = te::qt::af::ApplicationController::getInstance().getProject()->getSelectedLayers();
315 
316  if(selectedLayers.size() == 1 && selectedLayers.front()->getType() == "FOLDERLAYER")
317  parentLayer = selectedLayers.front();
318 
319  std::list<te::map::AbstractLayerPtr>::iterator it;
320  for(it = layers.begin(); it != layers.end(); ++it)
321  {
322  if ((*it)->getSRID() != TE_UNKNOWN_SRS)
323  {
324  if (!te::srs::SpatialReferenceSystemManager::getInstance().recognizes((*it)->getSRID()))
325  {
326  QString msgErr(tr("Layer %1 has SRID %2 that is not recognized by TerraLib. Setting it to unknown."));
327  msgErr = msgErr.arg((*it)->getTitle().c_str());
328  msgErr = msgErr.arg((*it)->getSRID());
329 
330  QMessageBox::warning(te::qt::af::ApplicationController::getInstance().getMainWindow(),
331  tr("Layer SRS check"), msgErr);
332  (*it)->setSRID(TE_UNKNOWN_SRS);
333  }
334  }
335 
336  te::qt::af::evt::LayerAdded evt(*it, parentLayer);
338  }
339 }
340 
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
#define TE_LOG_TRACE(msg)
Use this tag in order to log a message to a specified logger with the TRACE level.
Definition: Logger.h:137
This event signals that a new layer was created.
Definition: LayerEvents.h:66
Utility functions for the data access module.
boost::shared_ptr< DataSetType > DataSetTypePtr
Definition: DataSetType.h:653
boost::shared_ptr< DataSource > DataSourcePtr
Definition: DataSource.h:1435
TEQTWIDGETSEXPORT void AddFilePathToSettings(const QString &path, const QString &typeFile)
Save last used path in QSettings.
Definition: Utils.cpp:367
bool IsShapeFile(const QString &path)
Definition: Utils.cpp:36
OGR data source type.
void GetLayers(const te::da::DataSourceInfoPtr &info, std::list< te::map::AbstractLayerPtr > &layers)
Definition: Plugin.cpp:78
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:346
#define PLUGIN_CALL_BACK_IMPL(PLUGIN_CLASS_NAME)
This macro should be used by C++ plugins in order to declare the exportable/callable DLL function...
Definition: Config.h:54
TEQTAFEXPORT void AddActionToCustomToolbars(QAction *act)
Check QSettings for existance of act and adds it if necessary.
Definition: Utils.cpp:767
static DataSourceManager & getInstance()
It returns a reference to the singleton instance.
#define TE_UNKNOWN_SRS
A numeric value to represent a unknown SRS identification in TerraLib.
Definition: Config.h:41
~Plugin()
Virtual destructor.
Definition: Plugin.cpp:139
URI C++ Library.
void shutdown()
Do nothing! Just set plugin as stopped.
Definition: Plugin.cpp:172
void startup()
Do nothing! Just set plugin as started.
Definition: Plugin.cpp:143
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
Definition: Exception.h:58
This class models the concept of a project for the TerraLib Application Framework.
Definition: Project.h:50
A class that represents a data source component.
QString GetSupportedFiles()
Definition: Plugin.cpp:112
TEQTWIDGETSEXPORT QString GetFilePathFromSettings(const QString &typeFile)
Returns the value of the last saved file path for the typeFile required.
Definition: Utils.cpp:376
The basic information about a plugin.
Definition: PluginInfo.h:61
QString GetFileExtensionName(const std::string &type)
Definition: Plugin.cpp:90
boost::intrusive_ptr< AbstractLayer > AbstractLayerPtr
Plugin implementation for the OGR data source widget.
bool HasShapeFileSpatialIndex(const QString &path)
Definition: Utils.cpp:49
Plugin(const te::plugin::PluginInfo &pluginInfo)
Definition: Plugin.cpp:132
std::list< te::da::DataSetTypePtr > GetDataSetsInfo(const te::da::DataSourceInfoPtr &info)
Definition: Plugin.cpp:62
boost::shared_ptr< DataSourceInfo > DataSourceInfoPtr