PostGISCreatorDialog.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/PostGISCreatorDialog.cpp
22 
23  \brief A dialog window for showing the PostgreSQL creator widget.
24 */
25 
26 // TerraLib
27 #include "PostGISCreatorDialog.h"
28 #include "../../../../core/translator/Translator.h"
29 #include "../../../../core/uri/URI.h"
30 #include "../../../../core/uri/Utils.h"
31 #include "../../../../dataaccess/datasource/DataSource.h"
32 #include "../../../../dataaccess/datasource/DataSourceFactory.h"
33 #include "../../../../dataaccess/datasource/DataSourceInfo.h"
34 #include "../../../../dataaccess/datasource/DataSourceManager.h"
35 #include "../../../widgets/Exception.h"
36 #include "../../../widgets/utils/ScopedCursor.h"
37 #include "ui_PostGISCreatorDialogForm.h"
38 
39 // Boost
40 #include <boost/algorithm/string/case_conv.hpp>
41 #include <boost/lexical_cast.hpp>
42 #include <boost/uuid/random_generator.hpp>
43 #include <boost/uuid/uuid_io.hpp>
44 
45 // Qt
46 #include <QMessageBox>
47 
49  : QDialog(parent, f),
50  m_ui(new Ui::PostGISCreatorDialogForm)
51 {
52  // add controls
53  m_ui->setupUi(this);
54 
55 // init controls
56  m_ui->m_advancedOptionsGroupBox->hide();
57 
58 // connect signal and slots
59  connect(m_ui->m_advancedOptionsCheckBox, SIGNAL(toggled(bool)), this, SLOT(onAdvancedCreationOptionsCheckBoxToggled(bool)));
60  connect(m_ui->m_applyPushButton, SIGNAL(pressed()), this, SLOT(onApplyPushButtonPressed()));
61  connect(m_ui->m_closePushButton, SIGNAL(pressed()), this, SLOT(onClosePushButtonPressed()));
62  connect(m_ui->m_userNameLineEdit, SIGNAL(editingFinished()), this, SLOT(onLineEditEditingFinished()));
63  connect(m_ui->m_passwordLineEdit, SIGNAL(editingFinished()), this, SLOT(onLineEditEditingFinished()));
64  connect(m_ui->m_hostNameLineEdit, SIGNAL(editingFinished()), this, SLOT(onLineEditEditingFinished()));
65  connect(m_ui->m_portLineEdit, SIGNAL(editingFinished()), this, SLOT(onLineEditEditingFinished()));
66 
67  m_ui->m_portLineEdit->setValidator(new QIntValidator(0, 99999, this));
68 
69  m_ui->m_helpPushButton->setNameSpace("dpi.inpe.br.plugins");
70  m_ui->m_helpPushButton->setPageReference("plugins/pgis/pgis_creator.html");
71 }
72 
74 
76 {
77  QApplication::setOverrideCursor(Qt::WaitCursor);
78 
79  try
80  {
81 // check if driver is loaded
82  if(te::da::DataSourceFactory::find("POSTGIS") == 0)
83  {
84  QApplication::restoreOverrideCursor();
85  throw te::qt::widgets::Exception(TE_TR("Sorry! No data access driver loaded for PostgreSQL data sources!"));
86  }
87 
88 // get data source connection info based on form data
89  std::string connInfo = getConnectionInfo(true);
90 
91 // create database
92  te::da::DataSource::create("POSTGIS", connInfo);
93 
94  {
95  // Connect
96  const te::core::URI aux(connInfo);
97 
98  std::map<std::string, std::string> kvp = te::core::Expand(aux.query());
99 
100  std::string strURI = "pgsql://";
101  strURI += aux.user() + ":";
102  strURI += aux.password() + "@";
103  strURI += aux.host() + ":";
104  strURI += aux.port() + "/";
105  strURI += kvp["PG_NEWDB_NAME"] + "?";
106 
107  strURI += "PG_CLIENT_ENCODING=";
109 
110  std::unique_ptr<te::da::DataSource> ds = te::da::DataSourceFactory::make("POSTGIS", strURI);
111  ds->open();
112 
113  m_driver.reset(ds.release());
114  }
115 
116  if(m_driver.get() == nullptr)
117  {
118  QApplication::restoreOverrideCursor();
119  throw te::qt::widgets::Exception(TE_TR("Could not open POSTGIS data source due to an unknown error!"));
120  }
121 
122  QString title = m_ui->m_hostNameLineEdit->text().trimmed() + QString::fromUtf8("@") + m_ui->m_newDatabaseNameLineEdit->text().trimmed() + QString::fromUtf8("@") + m_ui->m_userNameLineEdit->text().trimmed();
123 
124  if(m_datasource.get() == nullptr)
125  {
126 // create a new data source based on form data
128 
129  m_datasource->setConnInfo(m_driver->getConnectionInfo());
130 
131  boost::uuids::basic_random_generator<boost::mt19937> gen;
132  boost::uuids::uuid u = gen();
133  std::string dsId = boost::uuids::to_string(u);
134 
135  m_datasource->setId(dsId);
136  m_driver->setId(dsId);
137  m_datasource->setTitle(title.toUtf8().data());
138  m_datasource->setDescription("");
139  m_datasource->setAccessDriver("POSTGIS");
140  m_datasource->setType("POSTGIS");
141  }
142  else
143  {
144  m_driver->setId(m_datasource->getId());
145  m_datasource->setConnInfo(m_driver->getConnectionInfo());
146  m_datasource->setTitle(title.toUtf8().data());
147  m_datasource->setDescription("");
148  }
149  }
150  catch(const std::exception& e)
151  {
152  QApplication::restoreOverrideCursor();
153  QMessageBox::warning(this,
154  tr("TerraLib Qt Components"),
155  tr(e.what()));
156  return;
157  }
158  catch(...)
159  {
160  QApplication::restoreOverrideCursor();
161  QMessageBox::warning(this,
162  tr("TerraLib Qt Components"),
163  tr("Unknown error while opening PostgreSQL database!"));
164  return;
165  }
166 
167  QApplication::restoreOverrideCursor();
168  accept();
169 }
170 
172 {
173  reject();
174 }
175 
177 {
178  m_ui->m_advancedOptionsGroupBox->setVisible(t);
179 }
180 
181 const std::string te::qt::plugins::pgis::PostGISCreatorDialog::getConnectionInfo(bool getPrivateKeys) const
182 {
183  QString qstr; // Auxiliary string used to hold temporary data
184 
185  std::string strURI = "pgsql://"; // THe base of the URI
186 
187  // get user
188  qstr = m_ui->m_userNameLineEdit->text().trimmed();
189  strURI += qstr.toUtf8().data();
190  strURI += ":";
191 
192  //get password
193  if (getPrivateKeys)
194  {
195  qstr = m_ui->m_passwordLineEdit->text().trimmed();
196  strURI += qstr.toUtf8().data();
197  }
198 
199  //get host
200  strURI += "@";
201  qstr = m_ui->m_hostNameLineEdit->text().trimmed();
202  strURI += qstr.isEmpty() ? "localhost" : qstr.toUtf8().data();
203  strURI += ":";
204 
205  //get port
206  qstr = m_ui->m_portLineEdit->text().trimmed();
207  strURI += qstr.isEmpty() ? "5432" : qstr.toUtf8().data();
208  strURI += "/";
209 
210  //query section
211  strURI += "?";
212 
213  qstr = m_ui->m_newDatabaseNameLineEdit->text().trimmed();
214  if (!qstr.isEmpty())
215  {
216  strURI += "PG_NEWDB_NAME=";
217  strURI += qstr.toUtf8().data();
218  strURI += "&";
219  }
220 
221  // get Template
222  qstr = m_ui->m_templateComboBox->currentText().trimmed();
223  if (!qstr.isEmpty())
224  {
225  strURI += "PG_NEWDB_TEMPLATE=";
226  strURI += qstr.toUtf8().data();
227  strURI += "&";
228  }
229 
230 // get Owner
231  qstr = m_ui->m_ownerComboBox->currentText().trimmed();
232  if (!qstr.isEmpty())
233  {
234  strURI += "PG_NEWDB_OWNER=";
235  strURI += qstr.toUtf8().data();
236  strURI += "&";
237  }
238 
239 // get Tablespace
240  qstr = m_ui->m_tablespaceLineEdit->text().trimmed();
241  if (!qstr.isEmpty())
242  {
243  strURI += "PG_NEWDB_TABLESPACE=";
244  strURI += qstr.toUtf8().data();
245  strURI += "&";
246  }
247 
248 // get Connections limit
249  if(!m_ui->m_noLimitConnectionsGroupBox->isChecked())
250  {
251 
252  strURI += "PG_NEWDB_CONN_LIMIT=";
253  qstr = m_ui->m_connectionsLimitSpinBox->text().trimmed();
254 
255  if(!qstr.isEmpty())
256  {
257  if(boost::lexical_cast<int>(qstr.toUtf8().data()) >= 1)
258  strURI += qstr.toUtf8().data();
259  else
260  strURI += "-1";
261  }
262  }
263 
264  strURI += "&PG_CONNECT_TIMEOUT=";
265  strURI += "4";
266 
267  // get MaxPoolSize
268  strURI += "&PG_MAX_POOL_SIZE=";
269  strURI += "50";
270 
271  // get MinPoolSize
272  strURI += "&PG_MIN_POOL_SIZE=";
273  strURI += "2";
274 
275  // get Encoding
276  strURI += "&PG_NEWDB_ENCODING=";
278 
279  return strURI;
280 }
281 
283 {
284  return m_datasource;
285 }
286 
288 {
289  return m_driver;
290 }
291 
293 {
294  try
295  {
296  if(m_ui->m_userNameLineEdit->text() != "" && m_ui->m_passwordLineEdit->text() != "")
297  {
298  std::string connInfo = getConnectionInfo(true);
299 
300  // Get Templates/Databases
301  std::vector<std::string> templates = te::da::DataSource::getDataSourceNames("POSTGIS", connInfo);
302  if (!templates.empty())
303  {
304  m_ui->m_templateComboBox->clear();
305 
306  for (std::size_t i = 0; i < templates.size(); i++)
307  m_ui->m_templateComboBox->addItem(templates[i].c_str());
308  }
309 
310  m_ui->m_templateComboBox->setCurrentIndex(m_ui->m_templateComboBox->findText("postgis"));
311 
312  // Try to go the owners
313  m_ui->m_ownerComboBox->clear();
314 
315  std::unique_ptr<te::da::DataSource> auxDs = te::da::DataSourceFactory::make("POSTGIS", getConnectionInfo(true));
316  auxDs->open();
317 
318  std::unique_ptr<te::da::DataSet> dsRoles = auxDs->query("select * from pg_roles");
319 
320  while(dsRoles->moveNext())
321  m_ui->m_ownerComboBox->addItem(dsRoles->getString("rolname").c_str());
322 
323  auxDs->close();
324  }
325  }
326  catch(...)
327  {
328  return;
329  }
330 }
static std::unique_ptr< DataSource > create(const std::string &dsType, const std::string &connInfo)
It creates a new repository for a data source.
std::unique_ptr< Ui::PostGISCreatorDialogForm > m_ui
static std::unique_ptr< DataSource > make(const std::string &driver, const te::core::URI &connInfo)
boost::shared_ptr< DataSource > DataSourcePtr
std::string password() const
Retrieving the password information.
Definition: URI.cpp:103
static te::dt::Date ds(2010, 01, 01)
const te::da::DataSourceInfoPtr & getDataSource() const
#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.
static std::string getEncodingName(EncodingType et)
Retrive a string from a given character encoding type enum.
const std::string getConnectionInfo(bool getPrivateKeys) const
std::string port() const
Retrieving the port.
Definition: URI.cpp:113
PostGISCreatorDialog(QWidget *parent=0, Qt::WindowFlags f=0)
std::string host() const
Retrieving the host.
Definition: URI.cpp:108
A class for representing an Uniform Resource Identifier (URI).
Definition: URI.h:49
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.
const te::da::DataSourcePtr & getDriver() const
std::string user() const
Retrieving the user information.
Definition: URI.cpp:98
boost::shared_ptr< DataSourceInfo > DataSourceInfoPtr