GeoPackageBuilderWizard.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2011-2012 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 src/terraMobilePlugin/qt/GeoPackageBuilderWizard.h
22 
23 \brief This interface is used to get the input parameters for GeoPackage Builder wizard operation.
24 */
25 
26 // TerraLib
27 #include "../../../../common/StringUtils.h"
28 #include "../../../../dataaccess/utils/Utils.h"
29 #include "../../../../dataaccess/datasource/DataSourceInfoManager.h"
30 #include "../../../../dataaccess/datasource/DataSourceManager.h"
31 #include "../../../../geometry/GeometryProperty.h"
32 #include "../../../../maptools/DataSetLayer.h"
33 #include "../../../widgets/utils/DoubleListWidget.h"
34 #include "../../../widgets/utils/ScopedCursor.h"
35 #include "../core/form/Serializer.h"
36 #include "../utils/Utils.h"
39 #include "BuilderFormsWizardPage.h"
42 
43 // Qt
44 #include <QMessageBox>
45 
46 //Boost
47 #include <boost/date_time/posix_time/posix_time.hpp>
48 #include <boost/date_time/posix_time/posix_time_io.hpp>
49 #include <boost/lexical_cast.hpp>
50 #include <boost/uuid/random_generator.hpp>
51 #include <boost/uuid/uuid_io.hpp>
52 
54 : QWizard(parent, f)
55 {
56  //configure the wizard
57  this->setWizardStyle(QWizard::ModernStyle);
58  this->setFixedSize(640, 480);
59  this->setWindowTitle(tr("GeoPackage Builder Wizard"));
60 
61  addPages();
63 }
64 
66 {
67 
68 }
69 
70 void te::qt::plugins::terramobile::GeoPackageBuilderWizard::setLayerList(std::list<te::map::AbstractLayerPtr> list)
71 {
72  m_list = list;
73 
74  //clear lists
75  m_inputLayersPage->getWidget()->clearInputValues();
76  m_inputLayersPage->getWidget()->clearOutputValues();
77 
78  m_gatheringLayersPage->getWidget()->clearInputValues();
79  m_gatheringLayersPage->getWidget()->clearOutputValues();
80 
81  std::vector<std::string> inputLayerNames;
82  std::vector<std::string> gatheringLayerNames;
83 
84 
85  //fill combos
86  std::list<te::map::AbstractLayerPtr>::iterator it = list.begin();
87 
88  while (it != list.end())
89  {
91 
92  if (l->isValid())
93  {
94  std::auto_ptr<te::da::DataSetType> dsType = l->getSchema();
95 
96  if (dsType->hasGeom())
97  {
98  inputLayerNames.push_back(l->getTitle());
99 
100  //if this layer has point as geom type, add this layer to gatherer list
101  te::gm::GeometryProperty* geomProp = te::da::GetFirstGeomProperty(dsType.get());
102 
103  if (geomProp && (geomProp->getGeometryType() == te::gm::PointType || geomProp->getGeometryType() == te::gm::MultiPointType))
104  {
105  gatheringLayerNames.push_back(l->getTitle());
106  }
107  }
108  else if (dsType->hasRaster())
109  {
110  inputLayerNames.push_back(l->getTitle());
111  }
112  }
113  ++it;
114  }
115 
116  m_inputLayersPage->getWidget()->setInputValues(inputLayerNames);
117  m_gatheringLayersPage->setLayerList(gatheringLayerNames);
118 }
119 
121 {
122  m_extent = extent;
123 }
124 
126 {
127  m_srid = srid;
128 }
129 
131 {
132  if (currentPage() == m_inputLayersPage.get())
133  {
134  bool res = m_inputLayersPage->isComplete();
135 
136  if (res)
137  {
138  std::vector<std::string> names = m_inputLayersPage->getWidget()->getOutputValues();
139 
140  m_gatheringLayersPage->setSelectedLayers(names);
141  }
142 
143  return res;
144  }
145  else if (currentPage() == m_gatheringLayersPage.get())
146  {
147  bool res = m_gatheringLayersPage->isComplete();
148 
149  if (res)
150  {
151  std::list<te::map::AbstractLayerPtr> layers = getGatheringLayers();
152 
153  m_formsPage->setLayerList(layers);
154  }
155 
156  return res;
157  }
158  else if (currentPage() == m_formsPage.get())
159  {
160  return m_formsPage->isComplete();
161  }
162  else if (currentPage() == m_outputPage.get())
163  {
164  return execute();
165  }
166 
167  return false;
168 }
169 
171 {
176 
177  addPage(m_inputLayersPage.get());
178  addPage(m_gatheringLayersPage.get());
179  addPage(m_formsPage.get());
180  addPage(m_outputPage.get());
181 }
182 
184 {
185  std::string gpkgName = m_outputPage->getGeoPackageFilePath();
186 
187  if (gpkgName.empty())
188  {
189  QMessageBox::warning(this, tr("GeoPackage Builder"), "The name for the output geopackage can not be empty.");
190  return false;
191  }
192 
193  //get forms
194  std::map<std::string, Section*> sectionsMap = m_formsPage->getSections();
195 
196  std::auto_ptr<te::da::DataSource> dsGPKG = te::qt::plugins::terramobile::createGeopackage(gpkgName);
197 
198  std::list<te::map::AbstractLayerPtr> gatheringLayers = getGatheringLayers();
199  std::list<te::map::AbstractLayerPtr> inputLayers = getInputLayers();
200 
201  std::list<te::map::AbstractLayerPtr>::iterator it;
202 
203  //Exporting the selected input and gathering layers
204  size_t pos = 1;
205  bool visible = false;
206 
207  try
208  {
209  te::qt::widgets::ScopedCursor c(Qt::WaitCursor);
210 
211  for (it = gatheringLayers.begin(); it != gatheringLayers.end(); ++it)
212  {
213  std::auto_ptr<te::da::DataSetType> dsType = (*it)->getSchema();
214  std::string dataSourceId = (*it)->getDataSourceId();
217  std::string dataSetName = dsType->getName();
218 
219  //check and add status column
220  te::dt::Property* statusProp = dsType->getProperty(LAYER_GATHERING_STATUS_COLUMN);
221 
222  if (!statusProp)
223  {
224  statusProp = new te::dt::SimpleProperty(LAYER_GATHERING_STATUS_COLUMN, te::dt::INT32_TYPE, true, new std::string("0"));
225 
226  ds->addProperty(dsType->getName(), statusProp);
227  }
228 
229  //check and add obj_id column
230  te::dt::Property* objIdProp = dsType->getProperty(LAYER_GATHERING_OBJID_COLUMN);
231 
232  if (!objIdProp)
233  {
235 
236  ds->addProperty(dsType->getName(), objIdProp);
237  }
238 
239  //get updated dstype
240  te::map::DataSetLayer* dsLayer = dynamic_cast<te::map::DataSetLayer*>((*it).get());
241 
242  if (dsLayer)
243  dsLayer->loadSchema();
244 
245  dsType = (*it)->getSchema();
246 
247  bool aux = false;
248 
249  if (!visible && !aux)
250  {
251  visible = (*it)->getVisibility();
252  aux = (*it)->getVisibility();
253  }
254 
255  //fill obj_id and tm_status
256  te::qt::plugins::terramobile::fillExtraColumns(ds.get(), dataSetName);
257 
258  //export
259  te::qt::plugins::terramobile::exportToGPKG(*it, dsGPKG.get(), gpkgName, m_extent);
260 
261  m_outputPage->appendLogMesssage("Exporting gathering layer " + dsType->getName());
262 
263  std::string insert = "INSERT INTO tm_layer_settings ('layer_name', 'enabled', 'position', 'datasource_uri') values('" + dsType->getName() + "', " +
264  boost::lexical_cast<std::string>(aux)+", " + boost::lexical_cast<std::string>(pos)+", '" + dsInfo->getConnInfoAsString() + "'); ";
265  te::qt::plugins::terramobile::queryGPKG(insert, dsGPKG.get());
266  ++pos;
267 
268  m_outputPage->appendLogMesssage("Gathering layer " + dsType->getName() + " successfuly exported.");
269  }
270 
271  for (it = inputLayers.begin(); it != inputLayers.end(); ++it)
272  {
273  std::string dataSourceId = (*it)->getDataSourceId();
275 
276  visible = (*it)->getVisibility();
277 
278  std::auto_ptr<te::da::DataSetType> dsType = (*it)->getSchema();
279  std::string name = dsType->getName();
280 
281  //Checking if the layer contains a raster property to adjust it's name removing the extension
282  if (dsType->hasRaster())
283  {
284  std::vector<std::string> values;
285  te::common::Tokenize(name, values, ".");
286  name = "";
287  for (size_t i = 0; i < values.size() - 1; ++i)
288  name += values[i];
289  }
290 
291  m_outputPage->appendLogMesssage("Exporting input layer " + name);
292 
293  std::string insert = "INSERT INTO tm_layer_settings ('layer_name', 'enabled', 'position', 'datasource_uri') values('" + name + "', " + boost::lexical_cast<std::string>(visible)+", " +
294  boost::lexical_cast<std::string>(pos)+", '" + dsInfo->getConnInfoAsString() + "'); ";
295  te::qt::plugins::terramobile::exportToGPKG(*it, dsGPKG.get(), gpkgName, m_extent);
296  te::qt::plugins::terramobile::queryGPKG("select * from sqlite_master", dsGPKG.get());
297  te::qt::plugins::terramobile::queryGPKG(insert, dsGPKG.get());
298  ++pos;
299 
300  m_outputPage->appendLogMesssage("Input layer " + name + " successfuly exported.");
301  }
302 
303  //Exporting the forms used to collect data on the field
304  std::map<std::string, Section*>::iterator itb = sectionsMap.begin();
305  std::map<std::string, Section*>::iterator ite = sectionsMap.end();
306 
307  while (itb != ite)
308  {
309  std::string jsonStr = te::qt::plugins::terramobile::Write(itb->second);
310 
311  std::string insert = "INSERT INTO tm_layer_form ('gpkg_layer_identify', 'tm_form', 'tm_media_table') values('" + itb->first + "', '" + jsonStr + "', '" + "" + "');";
312  te::qt::plugins::terramobile::queryGPKG(insert, dsGPKG.get());
313  ++itb;
314  }
315 
316  //Settings - Exporting the visible area if it is valid
317  if (m_outputPage->useVisibleArea() && m_extent.isValid() && m_srid != 0)
318  {
319  m_extent.transform(m_srid, 4326);
320 
321  std::string minX, minY, maxX, maxY;
322  minX = boost::lexical_cast<std::string>(m_extent.getLowerLeftX());
323  minY = boost::lexical_cast<std::string>(m_extent.getLowerLeftY());
324  maxX = boost::lexical_cast<std::string>(m_extent.getUpperRightX());
325  maxY = boost::lexical_cast<std::string>(m_extent.getUpperRightY());
326 
327  std::string insert1 = "INSERT INTO tm_settings ('key', 'value') values ('default_xmin', '" + minX + "');";
328  std::string insert2 = "INSERT INTO tm_settings ('key', 'value') values ('default_ymin', '" + minY + "');";
329  std::string insert3 = "INSERT INTO tm_settings ('key', 'value') values ('default_xmax', '" + maxX + "');";
330  std::string insert4 = "INSERT INTO tm_settings ('key', 'value') values ('default_ymax', '" + maxY + "');";
331 
332  te::qt::plugins::terramobile::queryGPKG(insert1, dsGPKG.get());
333  te::qt::plugins::terramobile::queryGPKG(insert2, dsGPKG.get());
334  te::qt::plugins::terramobile::queryGPKG(insert3, dsGPKG.get());
335  te::qt::plugins::terramobile::queryGPKG(insert4, dsGPKG.get());
336  }
337 
338  //Generating a unique id for the geopackage file
339  boost::uuids::basic_random_generator<boost::mt19937> gen;
340  boost::uuids::uuid u = gen();
341  std::string id_ds = boost::uuids::to_string(u);
342 
343  std::string insPrjId = "INSERT INTO tm_settings ('key', 'value') values ('project_id', '" + id_ds + "');";
344  te::qt::plugins::terramobile::queryGPKG(insPrjId, dsGPKG.get());
345 
346  std::string insProjStatus = "INSERT INTO tm_settings ('key', 'value') values ('project_status', '" + boost::lexical_cast<std::string>(0) + "');";
347  te::qt::plugins::terramobile::queryGPKG(insProjStatus, dsGPKG.get());
348 
349  std::string insGpkgVrs = "INSERT INTO tm_settings ('key', 'value') values ('gpkg_version', '1.0');";
350  te::qt::plugins::terramobile::queryGPKG(insGpkgVrs, dsGPKG.get());
351 
352  boost::gregorian::date current_date(boost::gregorian::day_clock::local_day());
353  std::locale fmt(std::locale::classic(), new boost::gregorian::date_facet("%d/%m/%Y"));
354  std::ostringstream os;
355  os.imbue(fmt);
356  os << current_date;
357 
358  std::string insDate = "INSERT INTO tm_settings ('key', 'value') values ('creation_date','" + os.str() + "'); ";
359  te::qt::plugins::terramobile::queryGPKG(insDate, dsGPKG.get());
360 
361  std::string gpkgDesc = m_outputPage->getGeoPackageDescription();
362  if (!gpkgDesc.empty())
363  {
364  std::string insDesc = "INSERT INTO tm_settings ('key', 'value') values ('description','" + gpkgDesc + "'); ";
365  te::qt::plugins::terramobile::queryGPKG(insDesc, dsGPKG.get());
366  }
367 
368  //Removing trigggers and tables that could generate problems on the mobile application
369  std::vector<std::string> triggers = te::qt::plugins::terramobile::getItemNames("trigger", dsGPKG.get());
370 
371  for (size_t i = 0; i < triggers.size(); ++i)
372  {
373  std::string drop = "drop trigger " + triggers[i] + ";";
374  te::qt::plugins::terramobile::queryGPKG(drop, dsGPKG.get());
375  }
376 
377  std::vector<std::string> tables = te::qt::plugins::terramobile::getItemNames("table", dsGPKG.get());
378 
379  for (size_t i = 0; i < tables.size(); ++i)
380  {
381  std::string drop = "drop table " + tables[i] + ";";
382  te::qt::plugins::terramobile::queryGPKG(drop, dsGPKG.get());
383  }
384  }
385  catch (std::exception& e)
386  {
387  QMessageBox::warning(this, tr("Warning"), e.what());
388  return false;
389  }
390  catch (...)
391  {
392  QMessageBox::warning(this, tr("Warning"), tr("Internal error generating geopackage file."));
393  return false;
394  }
395 
396  QMessageBox::information(this, tr("Information"), tr("Generated Geopackage File Successfully."));
397 
398  return true;
399 }
400 
402 {
403  std::list<te::map::AbstractLayerPtr> list;
404 
405  //get gathering layers names
406  std::vector<std::string> names = m_gatheringLayersPage->getWidget()->getOutputValues();
407 
408  for (std::size_t t = 0; t < names.size(); ++t)
409  {
410  std::list<te::map::AbstractLayerPtr>::iterator it;
411 
412  for (it = m_list.begin(); it != m_list.end(); ++it)
413  {
414  if (names[t] == it->get()->getTitle())
415  {
416  list.push_back(it->get());
417  }
418  }
419  }
420 
421  return list;
422 }
423 
425 {
426  std::list<te::map::AbstractLayerPtr> list;
427 
428  //get gathering layers names
429  std::vector<std::string> names = m_inputLayersPage->getWidget()->getOutputValues();
430 
431  for (std::size_t t = 0; t < names.size(); ++t)
432  {
433  std::list<te::map::AbstractLayerPtr>::iterator it;
434 
435  for (it = m_list.begin(); it != m_list.end(); ++it)
436  {
437  if (names[t] == it->get()->getTitle())
438  {
439  list.push_back(it->get());
440  }
441  }
442  }
443 
444  return list;
445 }
TEDATAACCESSEXPORT DataSourcePtr GetDataSource(const std::string &datasourceId, const bool opened=true)
Search for a data source with the informed id in the DataSourceManager.
Geometric property.
void makeInvalid()
It will invalidated the envelope.
std::list< te::map::AbstractLayerPtr > getGatheringLayers()
An atomic property like an integer or double.
boost::shared_ptr< DataSource > DataSourcePtr
void queryGPKG(std::string query, te::da::DataSource *dsGPKG)
std::vector< std::string > getItemNames(std::string type, te::da::DataSource *dsGPKG)
const double & getUpperRightX() const
It returns a constant refernce to the x coordinate of the upper right corner.
GeoPackageBuilderWizard(QWidget *parent=0, Qt::WindowFlags f=0)
const double & getLowerLeftY() const
It returns a constant refernce to the y coordinate of the lower left corner.
static te::dt::Date ds(2010, 01, 01)
const double & getUpperRightY() const
It returns a constant refernce to the x coordinate of the upper right corner.
This interface is used to get the gathering layers parameters for GeoPackage Builder wizard operation...
std::auto_ptr< te::da::DataSource > createGeopackage(std::string gpkgName)
It models a property definition.
Definition: Property.h:59
void Tokenize(const std::string &str, std::vector< std::string > &tokens, const std::string &delimiters=" ")
It tokenizes a given string with a delimiter of your own choice.
Definition: StringUtils.h:221
void exportToGPKG(te::map::AbstractLayerPtr layer, te::da::DataSource *dsGPKG, std::string outFileName, const te::gm::Envelope extent)
static DataSourceInfoManager & getInstance()
It returns a reference to the singleton instance.
An Envelope defines a 2D rectangular region.
std::auto_ptr< te::qt::plugins::terramobile::BuilderFormsWizardPage > m_formsPage
mydialect insert("+", new te::da::BinaryOpEncoder("+"))
GeomType getGeometryType() const
It returns the geometry subtype allowed for the property.
void fillExtraColumns(te::da::DataSource *ds, std::string dataSetName)
#define LAYER_GATHERING_STATUS_COLUMN
const double & getLowerLeftX() const
It returns a constant reference to the x coordinate of the lower left corner.
std::string Write(te::qt::plugins::terramobile::Section *section)
#define LAYER_GATHERING_OBJID_COLUMN
std::auto_ptr< te::qt::plugins::terramobile::BuilderOutputWizardPage > m_outputPage
A layer with reference to a dataset.
Definition: DataSetLayer.h:47
This interface is used to configure the form json file for GeoPackage Builder wizard operation...
void loadSchema() const
This interface is used to get the output parameters for GeoPackage Builder wizard operation...
std::auto_ptr< te::qt::plugins::terramobile::BuilderInputLayersWizardPage > m_inputLayersPage
TEDATAACCESSEXPORT te::gm::GeometryProperty * GetFirstGeomProperty(const DataSetType *dt)
boost::intrusive_ptr< AbstractLayer > AbstractLayerPtr
void transform(int oldsrid, int newsrid)
It will transform the coordinates of the Envelope from the old SRS to the new one.
std::auto_ptr< te::qt::plugins::terramobile::BuilderGatheringLayersWizardPage > m_gatheringLayersPage
void setLayerList(std::list< te::map::AbstractLayerPtr > list)
This interface is used to get the input layers parameters for GeoPackage Builder wizard operation...
bool isValid() const
It tells if the rectangle is valid or not.
std::list< te::map::AbstractLayerPtr > getInputLayers()
boost::shared_ptr< DataSourceInfo > DataSourceInfoPtr
An object that when created shows a cursor during its scope.
Definition: ScopedCursor.h:48