All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
QueryDataSourceDialog.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 terralib/qt/widgets/query/QueryDataSourceDialog.cpp
22 
23  \brief This file defines a class for a Query DataSource Dialog Dialog.
24 */
25 
26 // TerraLib
27 #include "../../../dataaccess/dataset/DataSet.h"
28 #include "../../../dataaccess/dataset/DataSetType.h"
29 #include "../../../dataaccess/dataset/ObjectIdSet.h"
30 #include "../../../dataaccess/datasource/DataSourceCapabilities.h"
31 #include "../../../dataaccess/datasource/DataSourceInfoManager.h"
32 #include "../../../dataaccess/datasource/DataSourceInfo.h"
33 #include "../../../dataaccess/query/SQLDialect.h"
34 #include "../../../dataaccess/query/SQLFunctionEncoder.h"
35 #include "../../../dataaccess/utils/Utils.h"
36 #include "../../../maptools/DataSetLayer.h"
37 #include "QueryDataSourceDialog.h"
38 #include "ui_QueryDataSourceDialogForm.h"
39 
40 // Qt
41 #include <QCursor>
42 #include <QFileDialog>
43 #include <QGridLayout>
44 #include <QMessageBox>
45 #include <QTextStream>
46 
47 // STL
48 #include <cassert>
49 #include <memory>
50 
52 
54  : QDialog(parent, f),
55  m_ui(new Ui::QueryDataSourceDialogForm)
56 {
57  m_ui->setupUi(this);
58 
59  m_ui->m_applyToolButton->setIcon(QIcon::fromTheme("media-playback-start-green"));
60  m_ui->m_clearToolButton->setIcon(QIcon::fromTheme("edit-clear"));
61  m_ui->m_applySelToolButton->setIcon(QIcon::fromTheme("check"));
62  m_ui->m_applyQueryLayerToolButton->setIcon(QIcon::fromTheme("check"));
63 
64  m_ui->m_saveSqlToolButton->setIcon(QIcon::fromTheme("document-save-as"));
65  m_ui->m_openSqlToolButton->setIcon(QIcon::fromTheme("document-open"));
66 
67  //table view
69  m_ui->m_tableView->setModel(m_tableModel);
70 
71  //dataset display
73 
74  QGridLayout* displayGridLayout = new QGridLayout(m_ui->m_displayWidget);
75  displayGridLayout->setContentsMargins(0, 0, 0, 0);
76  displayGridLayout->addWidget(m_dataSetDisplay);
77 
78  // Signals¨& slots
79  connect(m_ui->m_dataSourceComboBox, SIGNAL(activated(int)), this, SLOT(onDataSourceSelected(int)));
80  connect(m_ui->m_baseDataSetComboBox, SIGNAL(activated(int)), this, SLOT(onBaseDataSetSelected(int)));
81  connect(m_ui->m_dataSetListWidget, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(onDataSetItemClicked(QListWidgetItem*)));
82  connect(m_ui->m_applyToolButton, SIGNAL(clicked()), this, SLOT(onApplyPushButtonClicked()));
83  connect(m_ui->m_clearToolButton, SIGNAL(clicked()), this, SLOT(onClearPushButtonClicked()));
84  connect(m_ui->m_saveSqlToolButton, SIGNAL(clicked()), this, SLOT(onSaveSqlToolButtonClicked()));
85  connect(m_ui->m_openSqlToolButton, SIGNAL(clicked()), this, SLOT(onOpenSqlToolButtonClicked()));
86  connect(m_ui->m_sqlEditorTextEdit, SIGNAL(textChanged()), this, SLOT(onSQLEditorTextChanged()));
87  connect(m_ui->m_applySelToolButton, SIGNAL(clicked()), this, SLOT(onApplySelToolButtonClicked()));
88 
89  //load data sources information
91 }
92 
94 {
95  m_keyWords.clear();
96 }
97 
98 void te::qt::widgets::QueryDataSourceDialog::setLayerList(std::list<te::map::AbstractLayerPtr> layerList)
99 {
100  m_layerList = layerList;
101 
102  if(m_ui->m_baseDataSetComboBox->count() > 0)
103  onBaseDataSetSelected(0);
104 }
105 
107 {
108  m_ui->m_dataSourceComboBox->clear();
109 
110  std::map<std::string, te::da::DataSourceInfoPtr>::const_iterator it = te::da::DataSourceInfoManager::getInstance().begin();
111  std::map<std::string, te::da::DataSourceInfoPtr>::const_iterator itend =te::da::DataSourceInfoManager::getInstance().end();
112 
113  while(it != itend)
114  {
115  if(it->second->getType() != "GDAL")
116  m_ui->m_dataSourceComboBox->addItem(it->second->getTitle().c_str(), QVariant(it->second->getId().c_str()));
117 
118  ++it;
119  }
120 
121  if(m_ui->m_dataSourceComboBox->count() != 0)
122  onDataSourceSelected(m_ui->m_dataSourceComboBox->currentIndex());
123 }
124 
126 {
127  m_keyWords.clear();
128 
129  // add defaul SQL key words
130  m_keyWords.insert(std::map<std::string, Qt::GlobalColor>::value_type("SELECT", Qt::blue));
131  m_keyWords.insert(std::map<std::string, Qt::GlobalColor>::value_type("FROM", Qt::blue));
132  m_keyWords.insert(std::map<std::string, Qt::GlobalColor>::value_type("WHERE", Qt::blue));
133  m_keyWords.insert(std::map<std::string, Qt::GlobalColor>::value_type("JOIN", Qt::blue));
134  m_keyWords.insert(std::map<std::string, Qt::GlobalColor>::value_type("INNER", Qt::blue));
135  m_keyWords.insert(std::map<std::string, Qt::GlobalColor>::value_type("LEFT", Qt::blue));
136  m_keyWords.insert(std::map<std::string, Qt::GlobalColor>::value_type("RIGHT", Qt::blue));
137  m_keyWords.insert(std::map<std::string, Qt::GlobalColor>::value_type("AS", Qt::blue));
138  m_keyWords.insert(std::map<std::string, Qt::GlobalColor>::value_type("GROUP", Qt::blue));
139  m_keyWords.insert(std::map<std::string, Qt::GlobalColor>::value_type("ORDER", Qt::blue));
140  m_keyWords.insert(std::map<std::string, Qt::GlobalColor>::value_type("BY", Qt::blue));
141 
142  //add data source specific key words
143  std::string dataSourceId = m_ui->m_dataSourceComboBox->itemData(m_ui->m_dataSourceComboBox->currentIndex()).toString().toStdString();
144 
145  te::da::DataSourcePtr ds = te::da::GetDataSource(dataSourceId);
146 
147  const te::da::SQLDialect* dialect = ds->getDialect();
148 
149  std::vector<std::string> names = dialect->getRegisteredNames();
150 
151  for(std::size_t t = 0; t < names.size(); ++t)
152  {
153  QString s = names[t].c_str();
154  QString sUpper = s.toUpper();
155 
156  m_keyWords.insert(std::map<std::string, Qt::GlobalColor>::value_type(sUpper.toStdString(), Qt::red));
157  }
158 
159 }
160 
162 {
163  m_ui->m_baseDataSetComboBox->clear();
164  m_ui->m_dataSetListWidget->clear();
165  m_ui->m_attrDataSetListWidget->clear();
166 
167  std::string dataSourceId = m_ui->m_dataSourceComboBox->itemData(index).toString().toStdString();
168 
169  te::da::DataSourcePtr ds = te::da::GetDataSource(dataSourceId);
170 
171  if(!ds->isOpened())
172  ds->open();
173 
174  std::vector<std::string> dataSetNames;
175  te::da::GetDataSetNames(dataSetNames, dataSourceId);
176 
177  for(std::size_t t = 0; t < dataSetNames.size(); ++t)
178  {
179  m_ui->m_baseDataSetComboBox->addItem(dataSetNames[t].c_str());
180  m_ui->m_dataSetListWidget->addItem(dataSetNames[t].c_str());
181  }
182 
183  if(m_ui->m_baseDataSetComboBox->count() > 0)
184  onBaseDataSetSelected(0);
185 
186  buildMap();
187 }
188 
190 {
191  std::string dataSet = m_ui->m_baseDataSetComboBox->itemText(index).toStdString();
192 
193  m_ui->m_layerComboBox->clear();
194 
195  std::list<te::map::AbstractLayerPtr>::iterator it = m_layerList.begin();
196 
197  while(it != m_layerList.end())
198  {
200 
201  std::auto_ptr<te::da::DataSetType> dsType = l->getSchema();
202 
203  te::map::DataSetLayer* dsLayer = dynamic_cast<te::map::DataSetLayer*>(l.get());
204 
205  if(dsLayer && dsType->getName() == dataSet)
206  m_ui->m_layerComboBox->addItem(l->getTitle().c_str(), QVariant::fromValue(l));
207 
208  ++it;
209  }
210 }
211 
213 {
214  m_ui->m_attrDataSetListWidget->clear();
215 
216  if(!item)
217  return;
218 
219  std::string dataSourceId = m_ui->m_dataSourceComboBox->itemData(m_ui->m_dataSourceComboBox->currentIndex()).toString().toStdString();
220 
221  std::string dataSetName = item->text().toStdString();
222 
223  te::da::DataSetType* dsType = te::da::GetDataSetType(dataSetName, dataSourceId);
224 
225  std::vector<te::dt::Property*> propVec = dsType->getProperties();
226 
227  for(std::size_t t = 0; t < propVec.size(); ++t)
228  {
229  m_ui->m_attrDataSetListWidget->addItem(propVec[t]->getName().c_str());
230  }
231 
232  delete dsType;
233 }
234 
236 {
237  if(m_ui->m_sqlEditorTextEdit->toPlainText().isEmpty())
238  return;
239 
240  std::string dataSourceId = m_ui->m_dataSourceComboBox->itemData(m_ui->m_dataSourceComboBox->currentIndex()).toString().toStdString();
241 
242  te::da::DataSourcePtr ds = te::da::GetDataSource(dataSourceId);
243 
244  std::string dataSetName = m_ui->m_baseDataSetComboBox->currentText().toStdString();
245 
246  te::da::DataSetTypePtr dsType(te::da::GetDataSetType(dataSetName, dataSourceId));
247 
248  std::string sql = "";
249 
250  if(m_ui->m_sqlEditorTextEdit->textCursor().selectedText().isEmpty())
251  sql = m_ui->m_sqlEditorTextEdit->toPlainText().toStdString();
252  else
253  sql = m_ui->m_sqlEditorTextEdit->textCursor().selectedText().toStdString();
254 
255  //get dataset
256  std::auto_ptr<te::da::DataSet> dataSet;
257 
258  try
259  {
260  dataSet = ds->query(sql);
261  }
262  catch(const std::exception& e)
263  {
264  m_dataSetDisplay->clear();
265  m_tableModel->setDataSet(0);
266 
267  std::string errorMessage = "SQL Error: ";
268  errorMessage += e.what();
269  errorMessage += "\n";
270  errorMessage += "-------------------------------------------------------------------------\n";
271 
272  m_ui->m_logPlainTextEdit->appendPlainText(errorMessage.c_str());
273 
274  m_ui->m_tabWidget->setCurrentIndex(1);
275 
276  return;
277  }
278 
279  std::string message = "SQL Done: ";
280  message += sql;
281  message += "\n";
282  message += "-------------------------------------------------------------------------\n";
283 
284  m_ui->m_logPlainTextEdit->appendPlainText(message.c_str());
285 
286  //draw dataset
287  m_dataSetDisplay->clear();
288 
289  bool draw = false;
290  for(std::size_t t = 0; t < dataSet->getNumProperties(); ++t)
291  {
292  int type = dataSet->getPropertyDataType(t);
293 
294  if(type == te::dt::GEOMETRY_TYPE)
295  {
296  draw = true;
297  break;
298  }
299  }
300 
301  if(draw)
302  m_dataSetDisplay->draw(dsType, ds, dataSet.get());
303  else
304  m_dataSetDisplay->clear();
305 
306  //show dataset on table
307  m_tableModel->setDataSet(dataSet.release());
308 
309  m_ui->m_tabWidget->setCurrentIndex(0);
310 }
311 
313 {
314  m_ui->m_sqlEditorTextEdit->clear();
315 
316  m_dataSetDisplay->clear();
317 
318  m_tableModel->setDataSet(0);
319 }
320 
322 {
323  disconnect(m_ui->m_sqlEditorTextEdit, SIGNAL(textChanged()), this, SLOT(onSQLEditorTextChanged()));
324 
325  QString sql = m_ui->m_sqlEditorTextEdit->toPlainText();
326 
327  int curPos = m_ui->m_sqlEditorTextEdit->textCursor().position();
328 
329  disconnect(m_ui->m_sqlEditorTextEdit, SIGNAL(textChanged()), this, SLOT(onSQLEditorTextChanged()));
330 
331  m_ui->m_sqlEditorTextEdit->clear();
332 
333  QStringList words = sql.split(' ');
334 
335  bool isAttrValue = false;
336 
337  for(int i = 0; i < words.size(); ++i)
338  {
339  QString w = words.value(i).toUpper();
340 
341  std::string strW = w.toStdString();
342 
343  std::map<std::string, Qt::GlobalColor>::iterator it = m_keyWords.find(strW);
344 
345  bool removeAttrValue = false;
346 
347  if(it != m_keyWords.end())
348  {
349  m_ui->m_sqlEditorTextEdit->setFontWeight(QFont::Bold);
350  m_ui->m_sqlEditorTextEdit->setTextColor(it->second);
351  }
352  else
353  {
354  bool okNum = false;
355 
356  words.value(i).toDouble(&okNum);
357 
358  m_ui->m_sqlEditorTextEdit->setFontWeight(QFont::Normal);
359 
360  if(okNum)
361  m_ui->m_sqlEditorTextEdit->setTextColor(Qt::darkGreen);
362  else
363  {
364  if(!strW.empty())
365  {
366  std::string initChar = strW.substr(0, 1);
367  if(!isAttrValue && (initChar == "'" || initChar == "\""))
368  isAttrValue = true;
369 
370  if(strW.size() > 1)
371  {
372  std::string lastChar = strW.substr(strW.size() - 1, 1);
373  if(isAttrValue && (lastChar == "'" || lastChar == "\""))
374  removeAttrValue = true;
375  }
376  }
377 
378  if(isAttrValue)
379  m_ui->m_sqlEditorTextEdit->setTextColor(Qt::magenta);
380  else
381  m_ui->m_sqlEditorTextEdit->setTextColor(Qt::black);
382  }
383  }
384 
385  m_ui->m_sqlEditorTextEdit->insertPlainText(words.value(i));
386 
387  if(removeAttrValue)
388  isAttrValue = false;
389 
390  if(i < words.size() - 1)
391  m_ui->m_sqlEditorTextEdit->insertPlainText(" ");
392  }
393 
394  QTextCursor c = m_ui->m_sqlEditorTextEdit->textCursor();
395  c.setPosition(curPos);
396  m_ui->m_sqlEditorTextEdit->setTextCursor(c);
397 
398  connect(m_ui->m_sqlEditorTextEdit, SIGNAL(textChanged()), this, SLOT(onSQLEditorTextChanged()));
399 }
400 
402 {
403  //select file
404  QString path = QFileDialog::getSaveFileName(this, tr("Set a SQL file..."), "", tr("SQL File *.sql"));
405 
406  if(path.isNull())
407  return;
408 
409  //open file
410  QFile file(path);
411 
412  if(!file.open(QIODevice::WriteOnly | QIODevice::Text))
413  {
414  QMessageBox::warning(this, tr("Query DataSource"), file.errorString());
415  return;
416  }
417 
418  // save to file
419  QTextStream out(&file);
420 
421  out << m_ui->m_sqlEditorTextEdit->toPlainText();
422 
423  file.close();
424 }
425 
427 {
428  //select file
429  QString path = QFileDialog::getOpenFileName(this, tr("Select a SQL file..."), "", tr("SQL File *.sql"));
430 
431  if(path.isNull())
432  return;
433 
434  //open file
435  QFile file(path);
436 
437  if(!file.open(QIODevice::ReadOnly))
438  {
439  QMessageBox::warning(this, tr("Query DataSource"), file.errorString());
440  return;
441  }
442 
443  // show file
444  QTextStream in(&file);
445 
446  m_ui->m_sqlEditorTextEdit->clear();
447 
448  while(!in.atEnd())
449  {
450  QString line = in.readLine();
451 
452  m_ui->m_sqlEditorTextEdit->append(line);
453  }
454 
455  file.close();
456 }
457 
459 {
460  if(m_ui->m_sqlEditorTextEdit->toPlainText().isEmpty())
461  return;
462 
463  QVariant varLayer = m_ui->m_layerComboBox->itemData(m_ui->m_layerComboBox->currentIndex(), Qt::UserRole);
464  te::map::AbstractLayerPtr layer = varLayer.value<te::map::AbstractLayerPtr>();
465 
466  if(!layer.get())
467  {
468  QMessageBox::warning(this, tr("Query DataSource"), tr("No layer selected."));
469  return;
470  }
471 
472  std::string dataSourceId = m_ui->m_dataSourceComboBox->itemData(m_ui->m_dataSourceComboBox->currentIndex()).toString().toStdString();
473 
474  te::da::DataSourcePtr ds = te::da::GetDataSource(dataSourceId);
475 
476  std::string dataSetName = m_ui->m_baseDataSetComboBox->currentText().toStdString();
477 
478  te::da::DataSetTypePtr dsType(te::da::GetDataSetType(dataSetName, dataSourceId));
479 
480  std::string sql = "";
481 
482  if(m_ui->m_sqlEditorTextEdit->textCursor().selectedText().isEmpty())
483  sql = m_ui->m_sqlEditorTextEdit->toPlainText().toStdString();
484  else
485  sql = m_ui->m_sqlEditorTextEdit->textCursor().selectedText().toStdString();
486 
487  //get dataset
488  std::auto_ptr<te::da::DataSet> dataSet;
489 
490  try
491  {
492  dataSet = ds->query(sql);
493  }
494  catch(...)
495  {
496  QMessageBox::warning(this, tr("Query DataSource"), tr("Error executing SQL."));
497  return;
498  }
499 
500  try
501  {
502  if(m_ui->m_newSelRadioButton->isChecked())
503  {
504  // Generates the oids
505  dataSet->moveBeforeFirst();
506  te::da::ObjectIdSet* oids = te::da::GenerateOIDSet(dataSet.get(), dsType.get());
507 
508  layer->clearSelected();
509  layer->select(oids);
510  }
511  else if(m_ui->m_addSelRadioButton->isChecked())
512  {
513  // Generates the oids
514  dataSet->moveBeforeFirst();
515  te::da::ObjectIdSet* oids = te::da::GenerateOIDSet(dataSet.get(), dsType.get());
516 
517  layer->select(oids);
518  }
519  }
520  catch(te::common::Exception& e)
521  {
522  QMessageBox::warning(this, tr("Query DataSource"), tr("Error selecting objects: ") + e.what());
523  return;
524  }
525 
526  QMessageBox::information(this, tr("Query DataSource"), tr("Selection done."));
527 }
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:259
te::da::SQLDialect * dialect
Definition: WFSDialect.h:1
boost::shared_ptr< DataSetType > DataSetTypePtr
Definition: DataSetType.h:653
boost::shared_ptr< DataSource > DataSourcePtr
Definition: DataSource.h:1435
A class that models the description of a dataset.
Definition: DataSetType.h:72
virtual const char * what() const
It outputs the exception message.
Definition: Exception.cpp:58
QueryDataSourceDialog(QWidget *parent=0, Qt::WindowFlags f=0)
It represents the SQL query dialect accepted by a given data source.
Definition: SQLDialect.h:55
te::qt::widgets::DataSetDisplay * m_dataSetDisplay
std::auto_ptr< Ui::QueryDataSourceDialogForm > m_ui
const std::vector< Property * > & getProperties() const
It returns the list of properties describing the CompositeProperty.
static DataSourceInfoManager & getInstance()
It returns a reference to the singleton instance.
This class represents a set of unique ids created in the same context. i.e. from the same data set...
Definition: ObjectIdSet.h:53
te::qt::widgets::DataSetTableModel * m_tableModel
A map display for a dataset.
TEDATAACCESSEXPORT ObjectIdSet * GenerateOIDSet(DataSet *dataset, const DataSetType *type)
Definition: Utils.cpp:363
TEDATAACCESSEXPORT void GetDataSetNames(std::vector< std::string > &datasetNames, const std::string &datasourceId)
Definition: Utils.cpp:150
Q_DECLARE_METATYPE(te::map::AbstractLayerPtr)
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
Definition: Exception.h:58
void setLayerList(std::list< te::map::AbstractLayerPtr > layerList)
This method is used to set the list of layers.
std::vector< std::string > getRegisteredNames() const
It gets the all registered names from registed functions.
Definition: SQLDialect.cpp:51
TEDATAACCESSEXPORT DataSetType * GetDataSetType(const std::string &name, const std::string &datasourceId)
Definition: Utils.cpp:225
A layer with reference to a dataset.
Definition: DataSetLayer.h:47
void onDataSetItemClicked(QListWidgetItem *item)
A table model representing a te::da::DataSet.
boost::intrusive_ptr< AbstractLayer > AbstractLayerPtr
This file defines a class for a Query DataSource Dialog Dialog.