PostGISConnectorDialog.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/plugins/datasource/pgis/PostGISConnectorDialog.cpp
22 
23  \brief A dialog window for showing the PostGIS connector widget.
24 */
25 
26 // TerraLib
27 #include "../../../../core/translator/Translator.h"
28 #include "../../../../core/uri/URI.h"
29 #include "../../../../core/uri/Utils.h"
30 #include "../../../../dataaccess/datasource/DataSource.h"
31 #include "../../../../dataaccess/datasource/DataSourceFactory.h"
32 #include "../../../../dataaccess/datasource/DataSourceManager.h"
33 #include "../../../../dataaccess/datasource/DataSourceInfo.h"
34 #include "../../../widgets/Exception.h"
35 #include "PostGISConnectorDialog.h"
36 #include "ui_PostGISConnectorDialogForm.h"
37 
38 // Boost
39 #include <boost/algorithm/string/case_conv.hpp>
40 #include <boost/uuid/random_generator.hpp>
41 #include <boost/uuid/uuid_io.hpp>
42 #include <boost/lexical_cast.hpp>
43 
44 // Qt
45 #include <QMessageBox>
46 
48  : QDialog(parent, f),
49  m_ui(new Ui::PostGISConnectorDialogForm)
50 {
51 // add controls
52  m_ui->setupUi(this);
53 
54 // init controls
55  m_ui->m_advancedConnectionOptionsGroupBox->hide();
56 
57 // connect signal and slots
58  connect(m_ui->m_openPushButton, SIGNAL(pressed()), this, SLOT(openPushButtonPressed()));
59  connect(m_ui->m_testPushButton, SIGNAL(pressed()), this, SLOT(testPushButtonPressed()));
60  connect(m_ui->m_userNameLineEdit, SIGNAL(editingFinished()), this, SLOT(passwordLineEditEditingFinished()));
61  connect(m_ui->m_passwordLineEdit, SIGNAL(editingFinished()), this, SLOT(passwordLineEditEditingFinished()));
62  connect(m_ui->m_advancedConnectionOptionsCheckBox, SIGNAL(toggled(bool)), this, SLOT(advancedConnectionOptionsCheckBoxToggled(bool)));
63 
64  m_ui->m_portLineEdit->setValidator(new QIntValidator(0, 99999, this));
65 
66  m_ui->m_helpPushButton->setNameSpace("dpi.inpe.br.plugins");
67  m_ui->m_helpPushButton->setPageReference("plugins/pgis/pgis.html");
68 }
69 
71  default;
72 
74 {
75  return m_datasource;
76 }
77 
79 {
80  return m_driver;
81 }
82 
84 {
85  m_datasource = ds;
86 
87  if(m_datasource.get() != nullptr)
88  {
89  setConnectionInfo(m_datasource->getConnInfoAsString());
90 
91  m_ui->m_datasourceTitleLineEdit->setText(QString::fromUtf8(m_datasource->getTitle().c_str()));
92 
93  m_ui->m_datasourceDescriptionTextEdit->setText(QString::fromUtf8(m_datasource->getDescription().c_str()));
94  }
95 }
96 
98 {
99  try
100  {
101  // Check if driver is loaded
102  if(te::da::DataSourceFactory::find("POSTGIS") == 0)
103  throw te::qt::widgets::Exception(TE_TR("No data access driver loaded for PostgreSQL + PostGIS data sources!"));
104 
105  // Perform connection
106  std::unique_ptr<te::da::DataSource> ds = te::da::DataSourceFactory::make("POSTGIS", getConnectionInfo(true));
107  ds->open();
108  m_driver.reset(ds.release());
109 
110  if(m_driver.get() == nullptr)
111  throw te::qt::widgets::Exception(TE_TR("Could not open PostgreSQL + PostGIS data source due to an unknown error!"));
112 
113  QString title = m_ui->m_datasourceTitleLineEdit->text().trimmed();
114 
115  if(title.isEmpty())
116  title = m_ui->m_hostNameLineEdit->text().trimmed() + QString::fromUtf8("@") + m_ui->m_databaseComboBox->currentText().trimmed() + QString::fromUtf8("@") + m_ui->m_userNameLineEdit->text().trimmed();
117 
118  if(m_datasource.get() == nullptr)
119  {
120  // Create a new data source based on the form data
122 
123  m_datasource->setConnInfo(getConnectionInfo(m_ui->m_savePasswordCheckBox->isChecked()));
124 
125  boost::uuids::basic_random_generator<boost::mt19937> gen;
126  boost::uuids::uuid u = gen();
127  std::string dsId = boost::uuids::to_string(u);
128 
129  m_datasource->setId(dsId);
130  m_driver->setId(dsId);
131  m_datasource->setTitle(title.toUtf8().data());
132  m_datasource->setDescription(m_ui->m_datasourceDescriptionTextEdit->toPlainText().toUtf8().data());
133  m_datasource->setAccessDriver("POSTGIS");
134  m_datasource->setType("POSTGIS");
135  }
136  else
137  {
138  m_driver->setId(m_datasource->getId());
139  m_datasource->setConnInfo(getConnectionInfo(m_ui->m_savePasswordCheckBox->isChecked()));
140  m_datasource->setTitle(title.toUtf8().data());
141  m_datasource->setDescription(m_ui->m_datasourceDescriptionTextEdit->toPlainText().toUtf8().data());
142  }
143  }
144  catch(const std::exception& e)
145  {
146  QMessageBox::warning(this,
147  tr("TerraLib Qt Components"),
148  tr(e.what()));
149  return;
150  }
151  catch(...)
152  {
153  QMessageBox::warning(this,
154  tr("TerraLib Qt Components"),
155  tr("Unknown error while opening PostgreSQL database!"));
156  return;
157  }
158 
159  accept();
160 }
161 
163 {
164  try
165  {
166  // Check if driver is loaded
167  if(te::da::DataSourceFactory::find("POSTGIS") == 0)
168  throw te::qt::widgets::Exception(TE_TR("Sorry! No data access driver loaded for PostgreSQL + PostGIS data sources!"));
169 
170  // Perform connection
171  std::unique_ptr<te::da::DataSource> ds = te::da::DataSourceFactory::make("POSTGIS", getConnectionInfo(true));
172  if(ds.get() == nullptr)
173  throw te::qt::widgets::Exception(TE_TR("Could not open PostgreSQL + PostGIS database!"));
174 
175  ds->open();
176 
177  QMessageBox::information(this,
178  tr("TerraLib Qt Components"),
179  tr("Data source is ok!"));
180 
181  ds->close();
182  }
183  catch(const std::exception& e)
184  {
185  QMessageBox::warning(this,
186  tr("TerraLib Qt Components"),
187  tr(e.what()));
188  }
189  catch(...)
190  {
191  QMessageBox::warning(this,
192  tr("TerraLib Qt Components"),
193  tr("Unknown error while testing PostgreSQL + PostGIS data source!"));
194  }
195 }
196 
197 const std::string te::qt::plugins::pgis::PostGISConnectorDialog::getConnectionInfo(bool getPrivateKeys) const
198 {
199  QString qstr; // Auxiliary string used to hold temporary data
200 
201  std::string strURI = "pgsql://"; // The base of the URI
202 
203  // get user
204  qstr = m_ui->m_userNameLineEdit->text().trimmed();
205  strURI += qstr.toUtf8().data();
206  strURI += ":";
207 
208  //get password
209  if(getPrivateKeys)
210  {
211  qstr = m_ui->m_passwordLineEdit->text().trimmed();
212  strURI += qstr.toUtf8().data();
213  }
214 
215  //get host
216  strURI += "@";
217  qstr = m_ui->m_hostNameLineEdit->text().trimmed();
218  strURI += qstr.isEmpty() ? "localhost" : qstr.toUtf8().data();
219  strURI += ":";
220 
221  //get port
222  qstr = m_ui->m_portLineEdit->text().trimmed();
223  strURI += qstr.isEmpty() ? "5432" : qstr.toUtf8().data();
224  strURI += "/";
225 
226  //get db name
227  qstr = m_ui->m_databaseComboBox->currentText().trimmed();
228  if (qstr.isEmpty())
229  strURI += "template1";
230  else
231  strURI += qstr.toUtf8().data();
232 
233  //query section
234  strURI += "?";
235 
236  qstr = m_ui->m_tablesToHideLineEdit->text().trimmed();
237  if (!qstr.isEmpty())
238  {
239  strURI += "PG_HIDE_TABLES=";
240  strURI += qstr.toUtf8().data();
241  strURI += "&";
242  }
243 
244  strURI += "PG_CONNECT_TIMEOUT=";
245  qstr = qstr.isEmpty() ? "4" : m_ui->m_connectTimeoutSpinBox->text().trimmed();
246  strURI += qstr.toUtf8().data();
247 
248  // get MaxPoolSize
249  strURI += "&PG_MAX_POOL_SIZE=";
250  qstr = qstr.isEmpty() ? "50" : m_ui->m_maxPoolSizeSpinBox->text().trimmed();
251  strURI += qstr.toUtf8().data();
252 
253  // get MinPoolSize
254  strURI += "&PG_MIN_POOL_SIZE=";
255  qstr = qstr.isEmpty() ? "2" : m_ui->m_minPoolSizeSpinBox->text().trimmed();
256  strURI += qstr.toUtf8().data();
257 
258  // hide spatial metadata tables?
259  strURI += "&PG_HIDE_SPATIAL_METADATA_TABLES=";
260  strURI += m_ui->m_hideMetadataTablesCheckBox->isChecked() ? "TRUE" : "FALSE";
261 
262  // hide raster tables?
263  strURI += "&PG_HIDE_RASTER_TABLES=";
264  strURI += m_ui->m_hideRasterTablesCheckBox->isChecked() ? "TRUE" : "FALSE";
265 
266  qstr = m_ui->m_optionsLineEdit->text().trimmed();
267  if(!qstr.isEmpty())
268  {
269  strURI += "&PG_OPTIONS=";
270  strURI += qstr.toUtf8().data();
271  }
272 
273  return strURI;
274 }
275 
277 {
278  te::core::URI uri(connInfo);
279  std::map<std::string, std::string> kvp = te::core::Expand(uri.query());
280  std::map<std::string, std::string>::const_iterator it = kvp.begin();
281  std::map<std::string, std::string>::const_iterator itend = kvp.end();
282 
283  std::string host = uri.host();
284  if (!host.empty())
285  m_ui->m_hostNameLineEdit->setText(QString::fromUtf8(host.c_str()));
286 
287  std::string port = uri.port();
288  if(!port.empty())
289  m_ui->m_portLineEdit->setText(QString::fromUtf8(port.c_str()));
290 
291  std::string dbName = uri.path().substr(1, uri.path().length());
292  if(!dbName.empty())
293  {
294  int pos = m_ui->m_databaseComboBox->findText(QString::fromUtf8(dbName.c_str()));
295 
296  if(pos != -1)
297  m_ui->m_databaseComboBox->setCurrentIndex(pos);
298  else
299  {
300  m_ui->m_databaseComboBox->addItem(QString::fromUtf8(dbName.c_str()));
301  m_ui->m_databaseComboBox->setCurrentIndex(0);
302  }
303  }
304 
305  std::string user = uri.user();
306  if(!user.empty())
307  m_ui->m_userNameLineEdit->setText(QString::fromUtf8(user.c_str()));
308 
309  std::string pass = uri.password();
310  if (!pass.empty())
311  m_ui->m_passwordLineEdit->setText(QString::fromUtf8(pass.c_str()));
312 
313  it = kvp.find("PG_CONNECT_TIMEOUT");
314  if (it != itend && !it->second.empty())
315  m_ui->m_connectTimeoutSpinBox->setValue(boost::lexical_cast<int>(it->second.c_str()));
316 
317  it = kvp.find("PG_MIN_POOL_SIZE");
318  if (it != itend && !it->second.empty())
319  m_ui->m_minPoolSizeSpinBox->setValue(boost::lexical_cast<int>(it->second.c_str()));
320 
321  it = kvp.find("PG_MAX_POOL_SIZE");
322  if (it != itend && !it->second.empty())
323  m_ui->m_maxPoolSizeSpinBox->setValue(boost::lexical_cast<int>(it->second.c_str()));
324 
325  it = kvp.find("PG_OPTIONS");
326  if (it != itend && !it->second.empty())
327  m_ui->m_optionsLineEdit->setText(QString::fromUtf8(it->second.c_str()));
328 
329  it = kvp.find("PG_HIDE_SPATIAL_METADATA_TABLES");
330  m_ui->m_hideMetadataTablesCheckBox->setChecked((it != itend && !it->second.empty()) && (boost::to_upper_copy(it->second) == "TRUE"));
331 
332  it = kvp.find("PG_HIDE_RASTER_TABLES");
333  m_ui->m_hideRasterTablesCheckBox->setChecked((it != itend && !it->second.empty()) && (boost::to_upper_copy(it->second) == "TRUE"));
334 
335  it = kvp.find("PG_HIDE_TABLES");
336  if(it != itend && !it->second.empty())
337  m_ui->m_tablesToHideLineEdit->setText(QString::fromUtf8(it->second.c_str()));
338 }
339 
341 {
342  m_ui->m_advancedConnectionOptionsGroupBox->setVisible(t);
343 }
344 
346 {
347  if(m_ui->m_userNameLineEdit->text() != "" || m_ui->m_passwordLineEdit->text() != "")
348  {
349  try{
350  std::string connInfo = getConnectionInfo(true);
351 
352  //get current informations
353  std::string curDb;
354 
355  if(!m_ui->m_databaseComboBox->currentText().isEmpty())
356  curDb = m_ui->m_databaseComboBox->currentText().toUtf8().data();
357 
358  m_ui->m_databaseComboBox->clear();
359 
360  // Get DataSources
361  std::vector<std::string> dbNames =
362  te::da::DataSource::getDataSourceNames("POSTGIS", connInfo);
363 
364  if(!dbNames.empty())
365  {
366  setDatabasesNames(dbNames);
367 
368  if(!curDb.empty())
369  {
370  int idx = m_ui->m_databaseComboBox->findText(curDb.c_str(),
371  Qt::MatchExactly);
372 
373  if(idx != -1)
374  m_ui->m_databaseComboBox->setCurrentIndex(idx);
375  }
376  }
377  }
378  catch(...)
379  {
380  }
381  }
382 }
383 
385 {
386  std::sort(names.begin(), names.end());
387 
388  for(std::size_t i = 0; i < names.size(); ++i)
389  {
390  m_ui->m_databaseComboBox->addItem(names[i].c_str());
391  }
392 }
std::string path() const
Retrieving the path.
Definition: URI.cpp:118
static std::unique_ptr< DataSource > make(const std::string &driver, const te::core::URI &connInfo)
void set(const te::da::DataSourceInfoPtr &ds)
boost::shared_ptr< DataSource > DataSourcePtr
std::unique_ptr< Ui::PostGISConnectorDialogForm > m_ui
const te::da::DataSourcePtr & getDriver() const
std::string password() const
Retrieving the password information.
Definition: URI.cpp:103
static te::dt::Date ds(2010, 01, 01)
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:242
std::string query() const
Retrieving the query.
Definition: URI.cpp:123
static std::vector< std::string > getDataSourceNames(const std::string &dsType, const std::string &connInfo)
It returns the data source names available in the driver.
std::string port() const
Retrieving the port.
Definition: URI.cpp:113
std::string host() const
Retrieving the host.
Definition: URI.cpp:108
const te::da::DataSourceInfoPtr & getDataSource() const
A class for representing an Uniform Resource Identifier (URI).
Definition: URI.h:49
const std::string getConnectionInfo(bool getPrivateKeys) const
PostGISConnectorDialog(QWidget *parent=0, Qt::WindowFlags f=0)
TECOREEXPORT std::map< std::string, std::string > Expand(const std::string &query_str)
Split a query string into its components.
A class that represents a data source component.
A dialog window for showing the PostGIS connector widget.
void setDatabasesNames(std::vector< std::string > names)
void setConnectionInfo(const std::string &connInfo)
std::string user() const
Retrieving the user information.
Definition: URI.cpp:98
boost::shared_ptr< DataSourceInfo > DataSourceInfoPtr