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").toStdString()));
69  typeMap.insert(std::map<int, std::string>::value_type(te::dt::BYTE_ARRAY_TYPE, QObject::tr("Byte Array").toStdString()));
70  typeMap.insert(std::map<int, std::string>::value_type(te::dt::DATETIME_TYPE, QObject::tr("Date and Time").toStdString()));
71  typeMap.insert(std::map<int, std::string>::value_type(te::dt::DOUBLE_TYPE, QObject::tr("Double").toStdString()));
72  typeMap.insert(std::map<int, std::string>::value_type(te::dt::GEOMETRY_TYPE, QObject::tr("Geometry").toStdString()));
73  typeMap.insert(std::map<int, std::string>::value_type(te::dt::INT32_TYPE, QObject::tr("Int 32").toStdString()));
74  typeMap.insert(std::map<int, std::string>::value_type(te::dt::NUMERIC_TYPE, QObject::tr("Numeric").toStdString()));
75  typeMap.insert(std::map<int, std::string>::value_type(te::dt::STRING_TYPE, QObject::tr("String").toStdString()));
76 }
77 
78 te::dt::SimpleProperty* getConvertedproperty(std::string name, int dataType, std::string defaultValue = "", bool isRequired = false, bool isAutoNumber = true)
79 {
80  te::dt::SimpleProperty* newProperty;
81 
82  switch(dataType)
83  {
85  case te::dt::CHAR_TYPE:
87  case te::dt::FLOAT_TYPE:
88  case te::dt::INT16_TYPE:
89  case te::dt::INT32_TYPE:
90  case te::dt::INT64_TYPE:
91  case te::dt::UCHAR_TYPE:
95  {
96  newProperty = new te::dt::SimpleProperty(name, dataType, isRequired, new std::string(defaultValue));
97  newProperty->setAutoNumber(isAutoNumber);
98  break;
99  }
100 
101  case te::dt::STRING_TYPE:
102  {
103  newProperty = new te::dt::StringProperty(name, te::dt::STRING, 0, isRequired, new std::string(defaultValue));
104  break;
105  }
106 
108  {
109  newProperty = new te::dt::NumericProperty(name, 0, 0, isRequired, new std::string(defaultValue));
110  newProperty->setAutoNumber(isAutoNumber);
111  break;
112  }
113 
115  {
116  newProperty = new te::dt::DateTimeProperty(name, te::dt::DATE, isRequired, new std::string(defaultValue));
117  break;
118  }
119 
121  {
122  newProperty = new te::gm::GeometryProperty(name, isRequired, new std::string(defaultValue));
123  break;
124  }
125 
126  default:
127  {
128  newProperty = 0;
129  return false;
130  }
131  }
132  return newProperty;
133 }
134 
135 void fillComboBox(std::map<int, std::string> typeMap, QComboBox* box)
136 {
137  for(std::map<int, std::string>::iterator it = typeMap.begin(); it != typeMap.end(); ++it)
138  {
139  box->addItem(QString::fromStdString(it->second), QVariant(it->first));
140  }
141 }
142 
144  : QWidget(parent, f),
145  m_ui(new Ui::DataPropertiesWidgetForm)
146 {
147  m_ui->setupUi(this);
148 
149  //preparing the Type Map
151 
152  m_mapper = new QSignalMapper(this);
153 
154  //Adjusting the dataSetTableView that will be used to display the dataset's data
155  m_tblView.reset(new DataSetTableView(m_ui->m_dataPreviewFrame));
156  QGridLayout* dataPreviewLayout = new QGridLayout(m_ui->m_dataPreviewFrame);
157  dataPreviewLayout->addWidget(m_tblView.get());
158  dataPreviewLayout->setContentsMargins(0, 0, 0, 0);
159 
160  m_tblView->setAlternatingRowColors(true);
161  m_tblView->verticalHeader()->setVisible(false);
162  m_tblView->setSelectionMode(QAbstractItemView::NoSelection);
163 
164  m_ui->m_dataPropertiesTableWidget->setSelectionMode(QAbstractItemView::NoSelection);
165 
166  //add icon
167  m_ui->m_imgLabel->setPixmap(QIcon::fromTheme("tabular-import-hint").pixmap(112,48));
168  m_ui->m_sridPushButton->setIcon(QIcon::fromTheme("srs"));
169 
170  //Connecting signals and slots
171  connect(m_ui->m_inputDataToolButton, SIGNAL(clicked()), this, SLOT(onInputDataToolButtonTriggered()));
172  connect(m_ui->m_sridPushButton, SIGNAL(clicked()), this, SLOT(onSridPushButtonCLicked()));
173  connect(m_mapper, SIGNAL(mapped(int)), this, SLOT(onPropertyTypeChanged(int)));
174 }
175 
177 {
178  m_typeMap.clear();
179 }
180 
181 Ui::DataPropertiesWidgetForm* te::qt::widgets::DatapPropertiesWidget::getForm() const
182 {
183  return m_ui.get();
184 }
185 
186 std::auto_ptr<te::da::DataSetTypeConverter> te::qt::widgets::DatapPropertiesWidget::getConverter()
187 {
188  //Searching for properties that the user selected to adapt
189  te::da::PrimaryKey* pk = new te::da::PrimaryKey(m_dsConverter->getResult());
190  te::da::PrimaryKey* pkIn = m_dataType->getPrimaryKey();
191  for (int i = 0; i < m_ui->m_dataPropertiesTableWidget->rowCount(); ++i)
192  {
193  if(dynamic_cast<QCheckBox*>(m_ui->m_dataPropertiesTableWidget->cellWidget(i, 0))->isChecked())
194  {
195  QComboBox* box = dynamic_cast<QComboBox*>(m_ui->m_dataPropertiesTableWidget->cellWidget(i, 1));
196  int type = box->itemData(box->currentIndex()).toInt();
197 
198  m_dsConverter->add(m_dataType->getProperty(i)->getName(), getConvertedproperty(m_dataType->getProperty(i)->getName(), type));
199 
200  if(pkIn)
201  {
202  std::vector<te::dt::Property*> props = pkIn->getProperties();
203 
204  for(std::size_t t= 0; t < props.size(); ++t)
205  {
206  if(props[t]->getName() == m_dataType->getProperty(i)->getName())
207  {
208  te::dt::SimpleProperty* sp = getConvertedproperty(m_dataType->getProperty(i)->getName(), type);
209  pk->add(sp);
210 
211  break;
212  }
213  }
214  }
215  }
216  }
217 
218  //Configuring a new geometry if the user requested it.
219  if(m_ui->m_geometryGroupBox->isCheckable() && m_ui->m_geometryGroupBox->isChecked())
220  {
221  te::gm::GeometryProperty* newGeom;
222 
223  std::vector<std::string> names;
224  names.push_back(m_ui->m_xAxisComboBox->currentText().toStdString());
225  names.push_back(m_ui->m_yAxisComboBox->currentText().toStdString());
226  newGeom = new te::gm::GeometryProperty("OGR_POINT", true, new std::string());
228 
229  m_dsConverter->add(names, newGeom, "XYToPointConverter");
230  }
231 
232  te::gm::GeometryProperty* gp = te::da::GetFirstGeomProperty(m_dsConverter->getResult());
233 
234  if(gp && !m_ui->m_sridLineEdit->text().isEmpty())
235  gp->setSRID(boost::lexical_cast<int>(m_ui->m_sridLineEdit->text().trimmed().toStdString()));
236 
237  te::da::DataSourceManager::getInstance().insert(m_dataSource);
238  return m_dsConverter;
239 }
240 
242 {
243  return m_dataType.get();
244 }
245 
247 {
248  return m_dataSource.get();
249 }
250 
252 {
253  try
254  {
255  QString fileName = QFileDialog::getOpenFileName(this, tr("Open Textual File"), te::qt::widgets::GetFilePathFromSettings("tabular"), tr("Comma Separated Value (*.csv *.CSV);; dBASE (*.dbf *.DBF)"),
256  0, QFileDialog::ReadOnly);
257 
258  if(fileName.isEmpty())
259  return;
260 
261  QFileInfo info(fileName);
262 
263  te::qt::widgets::AddFilePathToSettings(info.absolutePath(), "tabular");
264 
265  //Getting the connection info
266  std::string ogrInfo("connection_string=" + fileName.toStdString());
267  std::map<std::string, std::string> connInfo;
268  connInfo["URI"] = fileName.toStdString();
269 
270  boost::filesystem::path uri(fileName.toStdString());
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.toStdString());
281  dsInfo->setDescription("");
282  dsInfo->setAccessDriver("OGR");
283  dsInfo->setType("OGR");
284 
286 
287  m_dataSource = te::da::DataSourceFactory::make(dsInfo->getAccessDriver());
288  m_dataSource->setConnectionInfo(dsInfo->getConnInfo());
289 
290  m_dataSource->setId(boost::uuids::to_string(u));
291  m_dataSource->open();
292 
293  //Creating the DataSet and DataType
294  std::auto_ptr<te::da::DataSet> dataset = m_dataSource->getDataSet(file);
295  std::vector<std::string> datasetNames = m_dataSource->getDataSetNames();
296 
297  if(!datasetNames.empty())
298  m_dataType = m_dataSource->getDataSetType(datasetNames[0]);
299  else
300  {
301  QMessageBox::critical( this, tr("Error"),tr("The file could not be read!"));
302  return;
303  }
304 
305  m_ui->m_inputDataLineEdit->setText(fileName);
306 
307  //Creating the DataSetConverter
308  m_dsConverter.reset(new te::da::DataSetTypeConverter(m_dataType.get()));
309 
310  //Filling the data preview table
311  std::vector<std::size_t> properties;
312  for (std::size_t i = 0; i < dataset->getNumProperties(); ++i)
313  properties.push_back(i);
314 
315  //The table will display 5 rows of the data for previewing purposes
316  std::auto_ptr<te::mem::DataSet> memFeature((new te::mem::DataSet(*dataset.get(), properties, 5)));
317 
318  m_tblView->setDataSet(memFeature.release(), m_dataSource->getEncoding());
319  m_tblView->resizeColumnsToContents();
320  m_tblView->show();
321 
322  m_ui->m_dataPropertiesTableWidget->setRowCount(0);
323 
324  //Filling the properties table widget
325  for(size_t t = 0; t < m_dataType->size(); ++t)
326  {
327  int newrow = m_ui->m_dataPropertiesTableWidget->rowCount();
328  m_ui->m_dataPropertiesTableWidget->insertRow(newrow);
329 
330  //The Property name item
331  std::string propName = m_dataType->getProperty(t)->getName();
332 
333  //A checkbox used to know if the user wants to import that row's property
334  QCheckBox* impCheck = new QCheckBox();
335  impCheck->setText(QString::fromStdString(propName));
336  impCheck->setCheckState(Qt::Checked);
337 
338  if(m_dataType->getProperty(t)->getType() == te::dt::GEOMETRY_TYPE)
339  connect(impCheck, SIGNAL(stateChanged (int )), this, SLOT(onGeomPropertyChecked(int)));
340 
341  m_ui->m_dataPropertiesTableWidget->setCellWidget(newrow, 0, impCheck);
342 
343  //The property type item
344  QComboBox* typeCB = new QComboBox();
345  fillComboBox(m_typeMap, typeCB);
346  typeCB->setCurrentIndex(typeCB->findText(m_typeMap[m_dataType->getProperty(t)->getType()].c_str()));
347 
348  m_mapper->setMapping(typeCB, newrow);
349  connect(typeCB, SIGNAL(currentIndexChanged (int)), m_mapper, SLOT(map()));
350 
351  m_ui->m_dataPropertiesTableWidget->setCellWidget(newrow, 1, typeCB);
352 
353  //check geom
354  if(m_dataType->hasGeom())
355  {
357 
358  if(gp && gp->getName() == propName)
359  {
360  QString srid;
361  srid.setNum(gp->getSRID());
362  m_ui->m_sridLineEdit->setText(srid);
363 
364  typeCB->setEnabled(false);
365  break;
366  }
367  }
368 
369  //check pk
370  te::da::PrimaryKey* pk = m_dataType->getPrimaryKey();
371 
372  if(pk)
373  {
374  std::vector<te::dt::Property*> props = pk->getProperties();
375 
376  for(std::size_t t= 0; t < props.size(); ++t)
377  {
378  if(props[t]->getName() == propName)
379  {
380  typeCB->setEnabled(false);
381  impCheck->setEnabled(false);
382  break;
383  }
384  }
385  }
386  }
387 
388  m_ui->m_dataPropertiesTableWidget->resizeColumnsToContents();
389  m_ui->m_dataPropertiesTableWidget->resizeRowsToContents();
390 #if (QT_VERSION >= 0x050000)
391  m_ui->m_dataPropertiesTableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
392 #else
393  m_ui->m_dataPropertiesTableWidget->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
394 #endif
395 
396  //Clearing the Comboxes if they aren't empty
397  m_ui->m_xAxisComboBox->clear();
398  m_ui->m_yAxisComboBox->clear();
399 
400  if(m_dataType->hasGeom())
401  {
402  m_ui->m_geometryGroupBox->setCheckable(false);
403  m_ui->m_xAxisComboBox->setEnabled(false);
404  m_ui->m_yAxisComboBox->setEnabled(false);
405  m_ui->m_geometryGroupBox->setChecked(true);
406  }
407  else
408  {
409  m_ui->m_geometryGroupBox->setCheckable(true);
410  m_ui->m_xAxisComboBox->setEnabled(true);
411  m_ui->m_yAxisComboBox->setEnabled(true);
412  m_ui->m_geometryGroupBox->setChecked(false);
413  }
414 
415  //Filling the ComboBoxes that will be used to configure the resulting geometries
416  for(size_t t = 0; t < m_dataType->size(); ++t)
417  {
418  std::string propName = m_dataType->getProperty(t)->getName();
419  int type = m_dataType->getProperty(t)->getType();
420  if((type >= te::dt::INT16_TYPE && type <= te::dt::UINT64_TYPE) ||
421  type == te::dt::FLOAT_TYPE || type == te::dt::DOUBLE_TYPE)
422  {
423  m_ui->m_xAxisComboBox->addItem(QString::fromStdString(propName));
424  m_ui->m_yAxisComboBox->addItem(QString::fromStdString(propName));
425  }
426  }
427  emit itemChanged();
428  }
429  catch(const std::exception& e)
430  {
431  QMessageBox::warning(this, tr("Tabular File"), e.what());
432  }
433 }
434 
436 {
437  te::qt::widgets::SRSManagerDialog srsDialog(this);
438  srsDialog.setWindowTitle(tr("Choose the SRS"));
439 
440  if(srsDialog.exec() != QDialog::Rejected)
441  {
442  std::pair<int, std::string> srid = srsDialog.getSelectedSRS();
443  m_ui->m_sridLineEdit->setText(QString::number(srid.first));
444  }
445 }
446 
448 {
449  if(checked == Qt::Unchecked)
450  {
451  m_ui->m_geometryGroupBox->setCheckable(true);
452  m_ui->m_xAxisComboBox->setEnabled(true);
453  m_ui->m_yAxisComboBox->setEnabled(true);
454  m_ui->m_geometryGroupBox->setChecked(true);
455  }
456  else
457  {
458  m_ui->m_geometryGroupBox->setCheckable(false);
459  m_ui->m_xAxisComboBox->setEnabled(false);
460  m_ui->m_yAxisComboBox->setEnabled(false);
461  m_ui->m_geometryGroupBox->setChecked(false);
462  }
463 }
464 
466 {
467  //Acquiring the name of the cconfigured property and it's new type.
468  QCheckBox* check = dynamic_cast<QCheckBox*>(m_ui->m_dataPropertiesTableWidget->cellWidget(row, 0));
469  QComboBox* box = dynamic_cast<QComboBox*>(m_ui->m_dataPropertiesTableWidget->cellWidget(row, 1));
470  std::string propName = check->text().toStdString();
471  int type = box->itemData(box->currentIndex()).toInt();
472 
473  //Searching the property to see if it is already in the comboBoxes
474  int xyAxis = m_ui->m_xAxisComboBox->findText(QString::fromStdString(propName));
475 
476  //Checking wheather the property needs to be added to or removed from the xAxisoOmboBox and yAxisoCOmboBox.
477  //Their values will always be the same.
478  if(xyAxis == -1)
479  {
480  if((type >= te::dt::INT16_TYPE && type <= te::dt::UINT64_TYPE) || type == te::dt::FLOAT_TYPE || type == te::dt::DOUBLE_TYPE)
481  {
482  m_ui->m_xAxisComboBox->addItem(QString::fromStdString(propName));
483  m_ui->m_yAxisComboBox->addItem(QString::fromStdString(propName));
484  }
485  }
486  else
487  {
488  if((type <= te::dt::INT16_TYPE && type >= te::dt::UINT64_TYPE) || type != te::dt::FLOAT_TYPE || type != te::dt::DOUBLE_TYPE)
489  {
490  m_ui->m_xAxisComboBox->removeItem(xyAxis);
491  m_ui->m_yAxisComboBox->removeItem(xyAxis);
492  }
493  }
494 }
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.
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'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.
std::auto_ptr< Ui::DataPropertiesWidgetForm > m_ui
The widget's form.
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.
Definition: Utils.cpp:367
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. ...
Definition: DataSource.h:118
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.
std::auto_ptr< te::da::DataSetTypeConverter > getConverter()
Returns a pointer to the generated DataSetTypeConverter.
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...
Definition: DataSet.h:65
int getSRID() const
It returns the spatial reference system identifier associated to this property.
static DataSourceManager & getInstance()
It returns a reference to the singleton instance.
static std::auto_ptr< DataSource > make(const std::string &dsType)
void fillComboBox(std::map< int, std::string > typeMap, QComboBox *box)
The type for string types: FIXED_STRING, VAR_STRING or STRING.
DatapPropertiesWidget(QWidget *parent=0, Qt::WindowFlags f=0)
Constructor.
It describes a primary key (pk) constraint.
Definition: PrimaryKey.h:52
std::auto_ptr< DataSetTableView > m_tblView
The widget used to preview the data of the new dataset.
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.
Definition: Utils.cpp:376
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)
Definition: Utils.cpp:557
A class used to configure the properties of a new textual file based layer.
te::da::DataSource * getDataSource()
Returns a pointer to the widget's dataSource.
const std::pair< int, std::string > & getSelectedSRS() const
Returns the selected SRS in the window.
boost::shared_ptr< DataSourceInfo > DataSourceInfoPtr
const std::string & getName() const
It returns the property name.
Definition: Property.h:127
void buidTypeMap(std::map< int, std::string > &typeMap)