All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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, 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_dataSet.get();
244 }
245 
247 {
248  return m_dataType.get();
249 }
250 
252 {
253  return m_dataSource.get();
254 }
255 
257 {
258  try
259  {
260  QString fileName = QFileDialog::getOpenFileName(this, tr("Open Textual File"), te::qt::widgets::GetFilePathFromSettings("tabular"), tr("Comma Separated Value (*.csv *.CSV);; dBASE (*.dbf *.DBF)"),
261  0, QFileDialog::ReadOnly);
262 
263  if(fileName.isEmpty())
264  return;
265 
266  QFileInfo info(fileName);
267 
268  te::qt::widgets::AddFilePathToSettings(info.absolutePath(), "tabular");
269 
270  //Getting the connection info
271  std::string ogrInfo("connection_string=" + fileName.toStdString());
272  std::map<std::string, std::string> connInfo;
273  connInfo["URI"] = fileName.toStdString();
274 
275  boost::filesystem::path uri(fileName.toStdString());
276  std::string file = uri.stem().string();
277 
278  //Creating a DataSource
279  static boost::uuids::basic_random_generator<boost::mt19937> gen;
280  boost::uuids::uuid u = gen();
281 
283  dsInfo->setConnInfo(connInfo);
284  dsInfo->setId(boost::uuids::to_string(u));
285  dsInfo->setTitle(fileName.toStdString());
286  dsInfo->setDescription("");
287  dsInfo->setAccessDriver("OGR");
288  dsInfo->setType("OGR");
289 
291 
292  m_dataSource = te::da::DataSourceFactory::make(dsInfo->getAccessDriver());
293  m_dataSource->setConnectionInfo(dsInfo->getConnInfo());
294 
295  m_dataSource->setId(boost::uuids::to_string(u));
296  m_dataSource->open();
297 
298  //Creating the DataSet and DataType
299  m_dataSet = m_dataSource->getDataSet(file);
300  std::vector<std::string> datasetNames = m_dataSource->getDataSetNames();
301 
302  if(!datasetNames.empty())
303  m_dataType = m_dataSource->getDataSetType(datasetNames[0]);
304  else
305  {
306  QMessageBox::critical( this, tr("Error"),tr("The file could not be read!"));
307  return;
308  }
309 
310  m_ui->m_inputDataLineEdit->setText(fileName);
311 
312  //Creating the DataSetConverter
313  m_dsConverter.reset(new te::da::DataSetTypeConverter(m_dataType.get()));
314 
315  //Filling the data preview table
316  std::vector<std::size_t> properties;
317  for(std::size_t i = 0; i < m_dataSet->getNumProperties(); ++i)
318  properties.push_back(i);
319 
320  //The table will display 5 rows of the data for previewing purposes
321  std::auto_ptr<te::mem::DataSet> memFeature((new te::mem::DataSet(*m_dataSet.get(), properties, 5)));
322 
323  m_tblView->setDataSet(memFeature.release(), m_dataSource->getEncoding());
324  m_tblView->resizeColumnsToContents();
325  m_tblView->show();
326 
327  m_ui->m_dataPropertiesTableWidget->setRowCount(0);
328 
329  //Filling the properties table widget
330  for(size_t t = 0; t < m_dataType->size(); ++t)
331  {
332  int newrow = m_ui->m_dataPropertiesTableWidget->rowCount();
333  m_ui->m_dataPropertiesTableWidget->insertRow(newrow);
334 
335  //The Property name item
336  std::string propName = m_dataType->getProperty(t)->getName();
337 
338  //A checkbox used to know if the user wants to import that row's property
339  QCheckBox* impCheck = new QCheckBox();
340  impCheck->setText(QString::fromStdString(propName));
341  impCheck->setCheckState(Qt::Checked);
342 
343  if(m_dataType->getProperty(t)->getType() == te::dt::GEOMETRY_TYPE)
344  connect(impCheck, SIGNAL(stateChanged (int )), this, SLOT(onGeomPropertyChecked(int)));
345 
346  m_ui->m_dataPropertiesTableWidget->setCellWidget(newrow, 0, impCheck);
347 
348  //The property type item
349  QComboBox* typeCB = new QComboBox();
350  fillComboBox(m_typeMap, typeCB);
351  typeCB->setCurrentIndex(typeCB->findText(m_typeMap[m_dataType->getProperty(t)->getType()].c_str()));
352 
353  m_mapper->setMapping(typeCB, newrow);
354  connect(typeCB, SIGNAL(currentIndexChanged (int)), m_mapper, SLOT(map()));
355 
356  m_ui->m_dataPropertiesTableWidget->setCellWidget(newrow, 1, typeCB);
357 
358  //check geom
359  if(m_dataType->hasGeom())
360  {
362 
363  if(gp && gp->getName() == propName)
364  {
365  QString srid;
366  srid.setNum(gp->getSRID());
367  m_ui->m_sridLineEdit->setText(srid);
368 
369  typeCB->setEnabled(false);
370  break;
371  }
372  }
373 
374  //check pk
375  te::da::PrimaryKey* pk = m_dataType->getPrimaryKey();
376 
377  if(pk)
378  {
379  std::vector<te::dt::Property*> props = pk->getProperties();
380 
381  for(std::size_t t= 0; t < props.size(); ++t)
382  {
383  if(props[t]->getName() == propName)
384  {
385  typeCB->setEnabled(false);
386  impCheck->setEnabled(false);
387  break;
388  }
389  }
390  }
391  }
392 
393  m_ui->m_dataPropertiesTableWidget->resizeColumnsToContents();
394  m_ui->m_dataPropertiesTableWidget->resizeRowsToContents();
395 #if (QT_VERSION >= 0x050000)
396  m_ui->m_dataPropertiesTableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
397 #else
398  m_ui->m_dataPropertiesTableWidget->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
399 #endif
400 
401  //Clearing the Comboxes if they aren't empty
402  m_ui->m_xAxisComboBox->clear();
403  m_ui->m_yAxisComboBox->clear();
404 
405  if(m_dataType->hasGeom())
406  {
407  m_ui->m_geometryGroupBox->setCheckable(false);
408  m_ui->m_xAxisComboBox->setEnabled(false);
409  m_ui->m_yAxisComboBox->setEnabled(false);
410  m_ui->m_geometryGroupBox->setChecked(true);
411  }
412  else
413  {
414  m_ui->m_geometryGroupBox->setCheckable(true);
415  m_ui->m_xAxisComboBox->setEnabled(true);
416  m_ui->m_yAxisComboBox->setEnabled(true);
417  m_ui->m_geometryGroupBox->setChecked(false);
418  }
419 
420  //Filling the ComboBoxes that will be used to configure the resulting geometries
421  for(size_t t = 0; t < m_dataType->size(); ++t)
422  {
423  std::string propName = m_dataType->getProperty(t)->getName();
424  int type = m_dataType->getProperty(t)->getType();
425  if((type >= te::dt::INT16_TYPE && type <= te::dt::UINT64_TYPE) ||
426  type == te::dt::FLOAT_TYPE || type == te::dt::DOUBLE_TYPE)
427  {
428  m_ui->m_xAxisComboBox->addItem(QString::fromStdString(propName));
429  m_ui->m_yAxisComboBox->addItem(QString::fromStdString(propName));
430  }
431  }
432  emit itemChanged();
433  }
434  catch(const std::exception& e)
435  {
436  QMessageBox::warning(this, tr("Tabular File"), e.what());
437  }
438 }
439 
441 {
442  te::qt::widgets::SRSManagerDialog srsDialog(this);
443  srsDialog.setWindowTitle(tr("Choose the SRS"));
444 
445  if(srsDialog.exec() != QDialog::Rejected)
446  {
447  std::pair<int, std::string> srid = srsDialog.getSelectedSRS();
448  m_ui->m_sridLineEdit->setText(QString::number(srid.first));
449  }
450 }
451 
453 {
454  if(checked == Qt::Unchecked)
455  {
456  m_ui->m_geometryGroupBox->setCheckable(true);
457  m_ui->m_xAxisComboBox->setEnabled(true);
458  m_ui->m_yAxisComboBox->setEnabled(true);
459  m_ui->m_geometryGroupBox->setChecked(true);
460  }
461  else
462  {
463  m_ui->m_geometryGroupBox->setCheckable(false);
464  m_ui->m_xAxisComboBox->setEnabled(false);
465  m_ui->m_yAxisComboBox->setEnabled(false);
466  m_ui->m_geometryGroupBox->setChecked(false);
467  }
468 }
469 
471 {
472  //Acquiring the name of the cconfigured property and it's new type.
473  QCheckBox* check = dynamic_cast<QCheckBox*>(m_ui->m_dataPropertiesTableWidget->cellWidget(row, 0));
474  QComboBox* box = dynamic_cast<QComboBox*>(m_ui->m_dataPropertiesTableWidget->cellWidget(row, 1));
475  std::string propName = check->text().toStdString();
476  int type = box->itemData(box->currentIndex()).toInt();
477 
478  //Searching the property to see if it is already in the comboBoxes
479  int xyAxis = m_ui->m_xAxisComboBox->findText(QString::fromStdString(propName));
480 
481  //Checking wheather the property needs to be added to or removed from the xAxisoOmboBox and yAxisoCOmboBox.
482  //Their values will always be the same.
483  if(xyAxis == -1)
484  {
485  if((type >= te::dt::INT16_TYPE && type <= te::dt::UINT64_TYPE) || type == te::dt::FLOAT_TYPE || type == te::dt::DOUBLE_TYPE)
486  {
487  m_ui->m_xAxisComboBox->addItem(QString::fromStdString(propName));
488  m_ui->m_yAxisComboBox->addItem(QString::fromStdString(propName));
489  }
490  }
491  else
492  {
493  if((type <= te::dt::INT16_TYPE && type >= te::dt::UINT64_TYPE) || type != te::dt::FLOAT_TYPE || type != te::dt::DOUBLE_TYPE)
494  {
495  m_ui->m_xAxisComboBox->removeItem(xyAxis);
496  m_ui->m_yAxisComboBox->removeItem(xyAxis);
497  }
498  }
499 }
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
te::da::DataSet * getDataSet()
Returns a pointer to the widget's dataSet.
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.
A dataset is the unit of information manipulated by the data access module of TerraLib.
Definition: DataSet.h:112
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)