DataPropertiesWidget.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/externalTable/DataPropertiesWidget.h
22 
23  \brief A class used to configure the properties of a new textual file based layer
24 */
25 
26 //Terralib
27 #include "../../../dataaccess/dataset/DataSetAdapter.h"
28 #include "../../../dataaccess/dataset/DataSetType.h"
29 #include "../../../dataaccess/dataset/DataSetTypeConverter.h"
30 #include "../../../dataaccess/dataset/PrimaryKey.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/utils/Utils.h"
36 #include "../../../datatype/Property.h"
37 #include "../../../datatype/DateTimeProperty.h"
38 #include "../../../datatype/NumericProperty.h"
39 #include "../../../datatype/SimpleProperty.h"
40 #include "../../../datatype/StringProperty.h"
41 #include "../../../geometry/GeometryProperty.h"
42 #include "../../../memory/DataSet.h"
43 #include "../property/DataSetAdapterWidget.h"
44 #include "../srs/SRSManagerDialog.h"
45 #include "../table/DataSetTableView.h"
46 #include "../Utils.h"
47 #include "DataPropertiesWidget.h"
48 #include "ui_DataPropertiesWidgetForm.h"
49 
50 // Qt
51 #include <QCheckBox>
52 #include <QComboBox>
53 #include <QFileDialog>
54 #include <QFileInfo>
55 #include <QMessageBox>
56 
57 // Boost
58 #include <boost/filesystem.hpp>
59 #include <boost/lexical_cast.hpp>
60 #include <boost/uuid/random_generator.hpp>
61 #include <boost/uuid/uuid_io.hpp>
62 
63 //Utility functions used mainly to populate ui elements.
64 void buidTypeMap(std::map<int, std::string>& typeMap)
65 {
66  typeMap.clear();
67 
68  typeMap.insert(std::map<int, std::string>::value_type(te::dt::ARRAY_TYPE, QObject::tr("Array").toUtf8().data()));
69  typeMap.insert(std::map<int, std::string>::value_type(te::dt::BYTE_ARRAY_TYPE, QObject::tr("Byte Array").toUtf8().data()));
70  typeMap.insert(std::map<int, std::string>::value_type(te::dt::DATETIME_TYPE, QObject::tr("Date and Time").toUtf8().data()));
71  typeMap.insert(std::map<int, std::string>::value_type(te::dt::DOUBLE_TYPE, QObject::tr("Double").toUtf8().data()));
72  typeMap.insert(std::map<int, std::string>::value_type(te::dt::GEOMETRY_TYPE, QObject::tr("Geometry").toUtf8().data()));
73  typeMap.insert(std::map<int, std::string>::value_type(te::dt::INT32_TYPE, QObject::tr("Int 32").toUtf8().data()));
74  typeMap.insert(std::map<int, std::string>::value_type(te::dt::INT64_TYPE, QObject::tr("Int 64").toUtf8().data()));
75  typeMap.insert(std::map<int, std::string>::value_type(te::dt::NUMERIC_TYPE, QObject::tr("Numeric").toUtf8().data()));
76  typeMap.insert(std::map<int, std::string>::value_type(te::dt::STRING_TYPE, QObject::tr("String").toUtf8().data()));
77 }
78 
79 te::dt::SimpleProperty* getConvertedproperty(std::string name, int dataType, std::string defaultValue = "", bool isRequired = false, bool isAutoNumber = true)
80 {
81  te::dt::SimpleProperty* newProperty;
82 
83  switch(dataType)
84  {
86  case te::dt::CHAR_TYPE:
88  case te::dt::FLOAT_TYPE:
89  case te::dt::INT16_TYPE:
90  case te::dt::INT32_TYPE:
91  case te::dt::INT64_TYPE:
92  case te::dt::UCHAR_TYPE:
96  {
97  newProperty = new te::dt::SimpleProperty(name, dataType, isRequired, new std::string(defaultValue));
98  newProperty->setAutoNumber(isAutoNumber);
99  break;
100  }
101 
102  case te::dt::STRING_TYPE:
103  {
104  newProperty = new te::dt::StringProperty(name, te::dt::STRING, 0, isRequired, new std::string(defaultValue));
105  break;
106  }
107 
109  {
110  newProperty = new te::dt::NumericProperty(name, 0, 0, isRequired, new std::string(defaultValue));
111  newProperty->setAutoNumber(isAutoNumber);
112  break;
113  }
114 
116  {
117  newProperty = new te::dt::DateTimeProperty(name, te::dt::DATE, 0, isRequired, new std::string(defaultValue));
118  break;
119  }
120 
122  {
123  newProperty = new te::gm::GeometryProperty(name, isRequired, new std::string(defaultValue));
124  break;
125  }
126 
127  default:
128  {
129  newProperty = nullptr;
130  return nullptr;
131  }
132  }
133  return newProperty;
134 }
135 
136 void fillComboBox(std::map<int, std::string> typeMap, QComboBox* box)
137 {
138  for(std::map<int, std::string>::iterator it = typeMap.begin(); it != typeMap.end(); ++it)
139  {
140  box->addItem(QString::fromUtf8(it->second.c_str()), QVariant(it->first));
141  }
142 }
143 
145  : QWidget(parent, f),
146  m_ui(new Ui::DataPropertiesWidgetForm)
147 {
148  m_ui->setupUi(this);
149 
150  //preparing the Type Map
152 
153  m_mapper = new QSignalMapper(this);
154 
155  //Adjusting the dataSetTableView that will be used to display the dataset's data
156  m_tblView.reset(new DataSetTableView(m_ui->m_dataPreviewFrame));
157  QGridLayout* dataPreviewLayout = new QGridLayout(m_ui->m_dataPreviewFrame);
158  dataPreviewLayout->addWidget(m_tblView.get());
159  dataPreviewLayout->setContentsMargins(0, 0, 0, 0);
160 
161  m_tblView->setAlternatingRowColors(true);
162  m_tblView->verticalHeader()->setVisible(false);
163  m_tblView->setSelectionMode(QAbstractItemView::NoSelection);
164 
165  m_ui->m_dataPropertiesTableWidget->setSelectionMode(QAbstractItemView::NoSelection);
166 
167  //add icon
168  m_ui->m_imgLabel->setPixmap(QIcon::fromTheme("tabular-import-hint").pixmap(112,48));
169  m_ui->m_sridPushButton->setIcon(QIcon::fromTheme("srs"));
170 
171  //Connecting signals and slots
172  connect(m_ui->m_inputDataToolButton, SIGNAL(clicked()), this, SLOT(onInputDataToolButtonTriggered()));
173  connect(m_ui->m_sridPushButton, SIGNAL(clicked()), this, SLOT(onSridPushButtonCLicked()));
174  connect(m_mapper, SIGNAL(mapped(int)), this, SLOT(onPropertyTypeChanged(int)));
175 }
176 
178 {
179  m_typeMap.clear();
180 }
181 
182 Ui::DataPropertiesWidgetForm* te::qt::widgets::DatapPropertiesWidget::getForm() const
183 {
184  return m_ui.get();
185 }
186 
187 std::unique_ptr<te::da::DataSetTypeConverter> te::qt::widgets::DatapPropertiesWidget::getConverter()
188 {
189  std::unique_ptr<te::da::DataSetTypeConverter> result = std::move(m_dsConverter);
190 
191  //Searching for properties that the user selected to adapt
192  te::da::PrimaryKey* pk = new te::da::PrimaryKey(result->getResult());
193  te::da::PrimaryKey* pkIn = m_dataType->getPrimaryKey();
194  for (int i = 0; i < m_ui->m_dataPropertiesTableWidget->rowCount(); ++i)
195  {
196  if(dynamic_cast<QCheckBox*>(m_ui->m_dataPropertiesTableWidget->cellWidget(i, 0))->isChecked())
197  {
198  QComboBox* box = dynamic_cast<QComboBox*>(m_ui->m_dataPropertiesTableWidget->cellWidget(i, 1));
199  int type = box->itemData(box->currentIndex()).toInt();
200 
201  result->add(m_dataType->getProperty(i)->getName(), getConvertedproperty(m_dataType->getProperty(i)->getName(), type));
202  if(pkIn)
203  {
204  std::vector<te::dt::Property*> props = pkIn->getProperties();
205 
206  for(std::size_t t= 0; t < props.size(); ++t)
207  {
208  if(props[t]->getName() == m_dataType->getProperty(i)->getName())
209  {
210  te::dt::SimpleProperty* sp = getConvertedproperty(m_dataType->getProperty(i)->getName(), type);
211  pk->add(sp);
212 
213  break;
214  }
215  }
216  }
217  }
218  }
219 
220  //Configuring a new geometry if the user requested it.
221  if(m_ui->m_geometryGroupBox->isCheckable() && m_ui->m_geometryGroupBox->isChecked())
222  {
223  te::gm::GeometryProperty* newGeom;
224 
225  std::vector<std::string> names;
226  names.push_back(m_ui->m_xAxisComboBox->currentText().toUtf8().data());
227  names.push_back(m_ui->m_yAxisComboBox->currentText().toUtf8().data());
228  newGeom = new te::gm::GeometryProperty("OGR_POINT", true, new std::string());
230 
231  result->add(names, newGeom, "XYToPointConverter");
232  }
233 
234  te::gm::GeometryProperty* gp = te::da::GetFirstGeomProperty(result->getResult());
235 
236  if(gp && !m_ui->m_sridLineEdit->text().isEmpty())
237  gp->setSRID(boost::lexical_cast<int>(m_ui->m_sridLineEdit->text().trimmed().toUtf8().data()));
238 
239  return result;
240 }
241 
243 {
244  return m_dataType.get();
245 }
246 
248 {
249  return m_dataSource.get();
250 }
251 
253 {
254  try
255  {
256  QString fileName = QFileDialog::getOpenFileName(this, tr("Open Textual File"), te::qt::widgets::GetFilePathFromSettings("tabular"), tr("Comma Separated Value (*.csv *.CSV);; dBASE (*.dbf *.DBF)"),
257  nullptr, QFileDialog::ReadOnly);
258 
259  if(fileName.isEmpty())
260  return;
261 
262  QFileInfo info(fileName);
263 
264  te::qt::widgets::AddFilePathToSettings(info.absolutePath(), "tabular");
265 
266  //Getting the connection info
267  std::string ogrInfo("connection_string=" + std::string(fileName.toUtf8().data()));
268  const std::string connInfo("file://" + std::string(fileName.toUtf8().data()));
269 
270  boost::filesystem::path uri(fileName.toUtf8().data());
271  std::string file = uri.stem().string();
272 
273  //Creating a DataSource
274  static boost::uuids::basic_random_generator<boost::mt19937> gen;
275  boost::uuids::uuid u = gen();
276 
278  dsInfo->setConnInfo(connInfo);
279  dsInfo->setId(boost::uuids::to_string(u));
280  dsInfo->setTitle(fileName.toUtf8().data());
281  dsInfo->setDescription("");
282  dsInfo->setAccessDriver("OGR");
283  dsInfo->setType("OGR");
284 
285  m_dataSource = te::da::DataSourceFactory::make(dsInfo->getAccessDriver(), connInfo);
286 
288  {
289  m_dataSource->setId(boost::uuids::to_string(u));
291  }
292  else
293  {
294  dsInfo = te::da::DataSourceInfoManager::getInstance().getByConnInfo(dsInfo->getConnInfoAsString());
295  m_dataSource->setId(dsInfo->getId());
296  }
297 
298  m_dataSource->open();
299 
300  //Creating the DataSet and DataType
301  std::unique_ptr<te::da::DataSet> dataset = m_dataSource->getDataSet(file);
302  std::vector<std::string> datasetNames = m_dataSource->getDataSetNames();
303 
304  if(!datasetNames.empty())
305  m_dataType = m_dataSource->getDataSetType(datasetNames[0]);
306  else
307  {
308  QMessageBox::critical( this, tr("Error"),tr("The file could not be read!"));
309  return;
310  }
311 
312  m_ui->m_inputDataLineEdit->setText(fileName);
313 
314  //Creating the DataSetConverter
316 
317  //Filling the data preview table
318  std::vector<std::size_t> properties;
319  for (std::size_t i = 0; i < dataset->getNumProperties(); ++i)
320  properties.push_back(i);
321 
322  //The table will display up to 5 rows of the data for previewing purposes
323  std::unique_ptr<te::mem::DataSet> memFeature;
324 
325  size_t count = dataset->size();
326  if(count > 5)
327  memFeature.reset((new te::mem::DataSet(*dataset.get(), properties, 5)));
328  else
329  memFeature.reset((new te::mem::DataSet(*dataset.get(), properties, count)));
330 
331  m_tblView->setDataSet(memFeature.release());
332  m_tblView->resizeColumnsToContents();
333  m_tblView->show();
334 
335  m_ui->m_dataPropertiesTableWidget->setRowCount(0);
336 
337  //Filling the properties table widget
338  for(size_t t = 0; t < m_dataType->size(); ++t)
339  {
340  //ignoring the geometry
341  if (m_dataType->getProperty(t)->getType() == te::dt::GEOMETRY_TYPE)
342  continue;
343 
344  int newrow = m_ui->m_dataPropertiesTableWidget->rowCount();
345  m_ui->m_dataPropertiesTableWidget->insertRow(newrow);
346 
347  //The Property name item
348  std::string propName = m_dataType->getProperty(t)->getName();
349 
350  //A checkbox used to know if the user wants to import that row's property
351  QCheckBox* impCheck = new QCheckBox();
352  impCheck->setText(QString::fromUtf8(propName.c_str()));
353  impCheck->setCheckState(Qt::Checked);
354 
355  m_ui->m_dataPropertiesTableWidget->setCellWidget(newrow, 0, impCheck);
356 
357  //The property type item
358  QComboBox* typeCB = new QComboBox();
359  fillComboBox(m_typeMap, typeCB);
360  typeCB->setCurrentIndex(typeCB->findText(m_typeMap[m_dataType->getProperty(t)->getType()].c_str()));
361 
362  m_mapper->setMapping(typeCB, newrow);
363  connect(typeCB, SIGNAL(currentIndexChanged (int)), m_mapper, SLOT(map()));
364 
365  m_ui->m_dataPropertiesTableWidget->setCellWidget(newrow, 1, typeCB);
366 
367  //check pk
368  te::da::PrimaryKey* pk = m_dataType->getPrimaryKey();
369 
370  if(pk)
371  {
372  std::vector<te::dt::Property*> props = pk->getProperties();
373 
374  for(std::size_t t= 0; t < props.size(); ++t)
375  {
376  if(props[t]->getName() == propName)
377  {
378  typeCB->setEnabled(false);
379  impCheck->setEnabled(false);
380  break;
381  }
382  }
383  }
384  }
385 
386  m_ui->m_dataPropertiesTableWidget->resizeColumnsToContents();
387  m_ui->m_dataPropertiesTableWidget->resizeRowsToContents();
388 #if (QT_VERSION >= 0x050000)
389  m_ui->m_dataPropertiesTableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
390 #else
391  m_ui->m_dataPropertiesTableWidget->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
392 #endif
393 
394  //Clearing the Comboxes if they aren't empty
395  m_ui->m_xAxisComboBox->clear();
396  m_ui->m_yAxisComboBox->clear();
397  m_ui->m_xAxisComboBox->setEnabled(true);
398  m_ui->m_yAxisComboBox->setEnabled(true);
399  m_ui->m_geometryGroupBox->setCheckable(true);
400  m_ui->m_geometryGroupBox->setChecked(false);
401 
402  //Filling the ComboBoxes that will be used to configure the resulting geometries
403  for(size_t t = 0; t < m_dataType->size(); ++t)
404  {
405  std::string propName = m_dataType->getProperty(t)->getName();
406  int type = m_dataType->getProperty(t)->getType();
407  if((type >= te::dt::INT16_TYPE && type <= te::dt::UINT64_TYPE) ||
408  type == te::dt::FLOAT_TYPE || type == te::dt::DOUBLE_TYPE)
409  {
410  m_ui->m_xAxisComboBox->addItem(QString::fromUtf8(propName.c_str()));
411  m_ui->m_yAxisComboBox->addItem(QString::fromUtf8(propName.c_str()));
412  }
413  }
414  emit itemChanged();
415  }
416  catch(const std::exception& e)
417  {
418  QMessageBox::warning(this, tr("Tabular File"), e.what());
419  }
420 }
421 
423 {
424  te::qt::widgets::SRSManagerDialog srsDialog(this);
425  srsDialog.setWindowTitle(tr("Choose the SRS"));
426 
427  if(srsDialog.exec() != QDialog::Rejected)
428  {
429  std::pair<int, std::string> srid = srsDialog.getSelectedSRS();
430  m_ui->m_sridLineEdit->setText(QString::number(srid.first));
431  }
432 }
433 
435 {
436  //Acquiring the name of the cconfigured property and it's new type.
437  QCheckBox* check = dynamic_cast<QCheckBox*>(m_ui->m_dataPropertiesTableWidget->cellWidget(row, 0));
438  QComboBox* box = dynamic_cast<QComboBox*>(m_ui->m_dataPropertiesTableWidget->cellWidget(row, 1));
439  std::string propName = check->text().toUtf8().data();
440  int type = box->itemData(box->currentIndex()).toInt();
441 
442  //Searching the property to see if it is already in the comboBoxes
443  int xyAxis = m_ui->m_xAxisComboBox->findText(QString::fromUtf8(propName.c_str()));
444 
445  //Checking wheather the property needs to be added to or removed from the xAxisoOmboBox and yAxisoCOmboBox.
446  //Their values will always be the same.
447  if(xyAxis == -1)
448  {
449  if((type >= te::dt::INT16_TYPE && type <= te::dt::UINT64_TYPE) || type == te::dt::FLOAT_TYPE || type == te::dt::DOUBLE_TYPE)
450  {
451  m_ui->m_xAxisComboBox->addItem(QString::fromUtf8(propName.c_str()));
452  m_ui->m_yAxisComboBox->addItem(QString::fromUtf8(propName.c_str()));
453  }
454  }
455  else
456  {
457  if((type <= te::dt::INT16_TYPE || type >= te::dt::UINT64_TYPE) && type != te::dt::FLOAT_TYPE && type != te::dt::DOUBLE_TYPE)
458  {
459  m_ui->m_xAxisComboBox->removeItem(xyAxis);
460  m_ui->m_yAxisComboBox->removeItem(xyAxis);
461  }
462  }
463 }
void setAutoNumber(bool a)
It tells if the property is an autonumber or not.
std::map< int, std::string > m_typeMap
A map that correlates a terralib type with a label.
static std::unique_ptr< DataSource > make(const std::string &driver, const te::core::URI &connInfo)
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
te::da::DataSetType * getDataSetType()
Returns a pointer to the widget&#39;s dataSetType.
void setSRID(int srid)
It sets the spatial reference system identifier associated to this property.
void setGeometryType(GeomType t)
It sets the geometry subtype.
An atomic property like an integer or double.
A class that models the description of a dataset.
Definition: DataSetType.h:72
TEQTWIDGETSEXPORT void AddFilePathToSettings(const QString &path, const QString &typeFile)
Save last used path in QSettings.
te::dt::SimpleProperty * getConvertedproperty(std::string name, int dataType, std::string defaultValue="", bool isRequired=false, bool isAutoNumber=true)
An abstract class for data providers like a DBMS, Web Services or a regular file. ...
const std::vector< te::dt::Property * > & getProperties() const
It returns the properties that take part of the primary key.
Definition: PrimaryKey.h:109
An converter for DataSetType.
The type for arbitrary precison numbers, like numeric(p, q).
Implementation of a random-access dataset class for the TerraLib In-Memory Data Access driver...
static DataSourceInfoManager & getInstance()
It returns a reference to the singleton instance.
void fillComboBox(std::map< int, std::string > typeMap, QComboBox *box)
te::da::DataSourcePtr m_dataSource
The DataSource that will be generated by this widget.
std::unique_ptr< te::da::DataSetType > m_dataType
The DataSetType that will be generated by this widget.
The type for string types: FIXED_STRING, VAR_STRING or STRING.
std::unique_ptr< Ui::DataPropertiesWidgetForm > m_ui
The widget&#39;s form.
DatapPropertiesWidget(QWidget *parent=0, Qt::WindowFlags f=0)
Constructor.
std::unique_ptr< te::da::DataSetTypeConverter > getConverter()
Returns a pointer to the generated DataSetTypeConverter.
std::unique_ptr< DataSetTableView > m_tblView
The widget used to preview the data of the new dataset.
std::unique_ptr< te::da::DataSetTypeConverter > m_dsConverter
The DataSetConverter that will be configured by this widget.
It describes a primary key (pk) constraint.
Definition: PrimaryKey.h:52
Ui::DataPropertiesWidgetForm * getForm() const
The type for date and time types: date, date period, date duration, time duration, time instant, time period, time instant with time zone or time period with time zone.
A customized table view for te::map::AbstractLayer objects. Uses a te::qt::widgets::DataSetModel as i...
A class that represents a data source component.
TEQTWIDGETSEXPORT QString GetFilePathFromSettings(const QString &typeFile)
Returns the value of the last saved file path for the typeFile required.
QSignalMapper * m_mapper
The mapper used to know which property was configured.
A dialog used to build a SRSManagerDialog element.
TEDATAACCESSEXPORT te::gm::GeometryProperty * GetFirstGeomProperty(const DataSetType *dt)
A class used to configure the properties of a new textual file based layer.
te::da::DataSource * getDataSource()
Returns a pointer to the widget&#39;s dataSource.
const std::pair< int, std::string > & getSelectedSRS() const
Returns the selected SRS in the window.
file(WRITE ${CMAKE_BINARY_DIR}/config_qhelp.cmake"configure_file (${TERRALIB_ABSOLUTE_ROOT_DIR}/doc/qhelp/help.qhcp.in ${CMAKE_BINARY_DIR}/share/terraview/help/help.qhcp @ONLY)") add_custom_command(OUTPUT del_dir COMMAND $
boost::shared_ptr< DataSourceInfo > DataSourceInfoPtr
void buidTypeMap(std::map< int, std::string > &typeMap)